Is there a way to disable / grey out the `maximize`, `minimize` button on a window, for Windows OS?

I tried using ffi ( as suggested by a defold developer, i forgot his name ), but it doesn’t seem to work.

local ffi = package.preload.ffi()

ffi.cdef([[
        typedef unsigned int LONG;
        typedef long long LONG_PTR;
        typedef void* PVOID;
        typedef PVOID HANDLE;
        typedef HANDLE HWND;
        
        HWND GetActiveWindow();
        LONG GetWindowLongPtrA(HWND hWnd, int nIndex); 
        LONG SetWindowLongPtrA(HWND hWnd, int nIndex, LONG_PTR dwNewLong);
    ]])

    local GWL_STYLE = -16
    local WS_SYSMENU = 0x0000000000080000

    local hwnd = ffi.C.GetActiveWindow()
    local value = ffi.C.GetWindowLongPtrA(hwnd, GWL_STYLE)
    ffi.C.SetWindowLongPtrA(hwnd, GWL_STYLE, bit.band(value, bit.bnot(WS_SYSMENU)))

i just have the same question with you!:slight_smile:, and after some search, I made a simple code to do that, following is the gist, you can have a try.

3 Likes

Nice! Thank you for sharing!

I moduleified your code! Could be expanded as a general os utility module. I’ll play with it more too soon.

Edit: actually going to start that process now!

os.lua (4.3 KB)

Added hide/show mouse on Windows for anyone who wanted that, but I would strongly hesitate using this until it’s ironed out a bit more!

Also added window resizing and optional centering. Want your game to have a virtual resolution but to scale to a certain window size on launch and be centered? Now you can… on Windows!

utils/os.lua

local M = {}

local ffi = package.preload.ffi()

-- https://github.com/ffi/ffi/wiki/Types
-- https://github.com/luapower/winapi/blob/master/winapi/window.lua

function M.set_window_size(pos_x, pos_y, width, height)
	if(ffi.os == "Windows") then

	  -- definitions
	  ffi.cdef([[
			typedef unsigned int LONG;
			typedef long long LONG_PTR;
			typedef void* PVOID;
			typedef PVOID HANDLE;
			typedef HANDLE HWND;
			typedef unsigned int UINT;
			typedef bool BOOL;

			int  GetSystemMetrics(int nIndex);
			HWND GetActiveWindow();
			BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
			
		]])

		-- load User32.dll
		local user32 = ffi.load("User32")
		
		local HWND_TOP = 0
		local SWP_NOMOVE = 0x0002
		local SWP_NOZORDER = 0x0004
		local SM_CXSCREEN = 0
		local SM_CYSCREEN = 1
		
		
		local ptr = user32.GetActiveWindow()
		
		if pos_x == -1 then 
			local x_pos = (user32.GetSystemMetrics(SM_CXSCREEN) - width) / 2
			local y_pos = (user32.GetSystemMetrics(SM_CYSCREEN) - height) / 2
			user32.SetWindowPos(ptr, ptr, x_pos, y_pos, width, height, SWP_NOZORDER)
		else
			user32.SetWindowPos(ptr, ptr, pos_x, pos_y, width, height, SWP_NOZORDER)
		end
	end	
end	

function M.disable_mouse_cursor()
	if(ffi.os == "Windows") then

	  -- definitions
	  ffi.cdef([[
			typedef unsigned int LONG;
			typedef long long LONG_PTR;
			typedef void* PVOID;
			typedef PVOID HANDLE;
			typedef HANDLE HWND;
			typedef bool BOOL;

			int ShowCursor(BOOL bShow);
		]])

		-- load User32.dll
		local user32 = ffi.load("User32")

		user32.ShowCursor(false)
	end	
end

function M.enable_mouse_cursor()
	if(ffi.os == "Windows") then

	  -- definitions
	  ffi.cdef([[
			typedef unsigned int LONG;
			typedef long long LONG_PTR;
			typedef void* PVOID;
			typedef PVOID HANDLE;
			typedef HANDLE HWND;
			typedef bool BOOL;

			int ShowCursor(BOOL bShow);
		]])

		-- load User32.dll
		local user32 = ffi.load("User32")

		user32.ShowCursor(true)
	end	
end	

function M.disable_window_resize()
	if(ffi.os == "Windows") then

	  -- definitions
	  ffi.cdef([[
			typedef unsigned int LONG;
			typedef long long LONG_PTR;
			typedef void* PVOID;
			typedef PVOID HANDLE;
			typedef HANDLE HWND;

			HWND GetActiveWindow();
			LONG GetWindowLongPtrA(HWND hWnd, int nIndex);
			LONG SetWindowLongPtrA(HWND hWnd, int nIndex, LONG_PTR dwNewLong);
		]])

		local GWL_STYLE = -16

		-- styles from https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
		local WS_SIZEBOX = 0x00040000

		-- load User32.dll
		local user32 = ffi.load("User32")

		local ptr = user32.GetActiveWindow()
		local value = user32.GetWindowLongPtrA(ptr, GWL_STYLE)
		user32.SetWindowLongPtrA(ptr, GWL_STYLE, bit.band(value, bit.bnot(WS_SIZEBOX)))
	end	
end	

function M.disable_maximize_button()
	if(ffi.os == "Windows") then

	  -- definitions
	  ffi.cdef([[
			typedef unsigned int LONG;
			typedef long long LONG_PTR;
			typedef void* PVOID;
			typedef PVOID HANDLE;
			typedef HANDLE HWND;

			HWND GetActiveWindow();
			LONG GetWindowLongPtrA(HWND hWnd, int nIndex);
			LONG SetWindowLongPtrA(HWND hWnd, int nIndex, LONG_PTR dwNewLong);
		]])

		local GWL_STYLE = -16

		-- styles from https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
		local WS_MAXIMIZEBOX = 0x00010000

		-- load User32.dll
		local user32 = ffi.load("User32")

		local ptr = user32.GetActiveWindow()
		local value = user32.GetWindowLongPtrA(ptr, GWL_STYLE)
		user32.SetWindowLongPtrA(ptr, GWL_STYLE, bit.band(value, bit.bnot(WS_MAXIMIZEBOX)))
	end
end

function M.disable_minimize_button()
	if(ffi.os == "Windows") then

	  -- definitions
	  ffi.cdef([[
			typedef unsigned int LONG;
			typedef long long LONG_PTR;
			typedef void* PVOID;
			typedef PVOID HANDLE;
			typedef HANDLE HWND;

			HWND GetActiveWindow();
			LONG GetWindowLongPtrA(HWND hWnd, int nIndex);
			LONG SetWindowLongPtrA(HWND hWnd, int nIndex, LONG_PTR dwNewLong);
		]])

		local GWL_STYLE = -16

		-- styles from https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
		local WS_MINIMIZEBOX = 0x00020000

		-- load User32.dll
		local user32 = ffi.load("User32")

		local ptr = user32.GetActiveWindow()
		local value = user32.GetWindowLongPtrA(ptr, GWL_STYLE)
		user32.SetWindowLongPtrA(ptr, GWL_STYLE, bit.band(value, bit.bnot(WS_MINIMIZEBOX)))
	end
end	

return M

Usage

local os_utils = require("utils.os")

function init(self)
	os_utils.disable_maximize_button()
	os_utils.disable_minimize_button()
	os_utils.disable_window_resize()
	os_utils.disable_mouse_cursor()
	os_utils.enable_mouse_cursor()
	os_utils.set_window_size(-1,-1,800,600)
end

I love the codeblocks now being styled like editor 2’s theme! :grinning:

Here is the source for GLFW2, which is what Defold uses, but we can call the same platform specific apis in the same way.

What would still be better would interacting with GLFW2 directly and let it handle the platform specific stuff.

Defold uses GLFW 2.7 specifically but I don’t know if it’s 2.7.6 https://sourceforge.net/projects/glfw/files/glfw/2.7.6/

If we can get GLFW to work then we’ll get a lot of stuff for free as multiplatform. I’m attempting now but anyone with knowhow should for sure try and get it to work too.

Does Defold actually use GLFW 2.7 or did it fork it?

I was reminded of this thread and that unfortunately the same methods don’t work on Windows otherwise that way would be ideal for using GLFW directly. But then I tested on OSX again to confirm and it seems JIT isn’t being used for Mac engine now so this method wouldn’t work? Otherwise I would have suggested to use GLFW functions directly for OSX and maybe Linux too… anyone confirm?

It’s nice to know some things can work though. Over time I’ll add the things I need.

7 Likes

:grinning:nice work! and I love new editor too.

3 Likes

I started https://github.com/subsoap/defos and added a few people as collaborators just in case. This weekend I would like to spend some time making what’s already there cross platform for win/osx/linux and I’m pretty sure it will be a simple process of referencing the way GLFW itself does things to find the right native apis but might need some help.

5 Likes

For mac os it can be made by methods of NSWindow using native extension

2 Likes

@Pkeod I made a fork, and first realization of native extension for mac os. And made a pull request.
Until you approve it, mac os version available on my git account:
https://github.com/AGulev/defos

4 Likes

Merged - you as a contributor should be able to merge in pull requests too.

4 Likes

Thanks everyone!

3 Likes