commit
c9ee8af20c
146
defos/defos.lua
146
defos/defos.lua
|
@ -11,6 +11,16 @@ according to the document, we do not need to load user32.dll manually:
|
|||
local C = ffi.C
|
||||
|
||||
if ffi.os == "Windows" then
|
||||
local GWL_STYLE = -16
|
||||
local WS_POPUP = 0x80000000
|
||||
local WS_CAPTION = 0x00C00000
|
||||
local WS_SYSMENU = 0x00080000
|
||||
local WS_SIZEBOX = 0x00040000
|
||||
local WS_MAXIMIZEBOX = 0x00010000
|
||||
local WS_MINIMIZEBOX = 0x00020000
|
||||
local SWP_NOZORDER = 0x0004
|
||||
local SW_MAXIMIZE = 3
|
||||
|
||||
-- add definitions here,
|
||||
-- to make it clear and avoid re-define exception (for struct) when calling a method more than 1 time
|
||||
ffi.cdef([[
|
||||
|
@ -124,6 +134,15 @@ if ffi.os == "Windows" then
|
|||
DWORD dmPanningHeight;
|
||||
} DEVMODE, *PDEVMODE;
|
||||
|
||||
typedef struct tagWINDOWPLACEMENT {
|
||||
UINT length;
|
||||
UINT flags;
|
||||
UINT showCmd;
|
||||
POINT ptMinPosition;
|
||||
POINT ptMaxPosition;
|
||||
RECT rcNormalPosition;
|
||||
} WINDOWPLACEMENT, *PWINDOWPLACEMENT, *LPWINDOWPLACEMENT;
|
||||
|
||||
|
||||
|
||||
int GetSystemMetrics(int nIndex);
|
||||
|
@ -153,6 +172,12 @@ if ffi.os == "Windows" then
|
|||
BOOL MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
|
||||
|
||||
HWND GetDesktopWindow(void);
|
||||
|
||||
BOOL GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT *lpwndpl);
|
||||
|
||||
BOOL SetWindowPlacement(HWND hWnd,const WINDOWPLACEMENT *lpwndpl);
|
||||
|
||||
BOOL ShowWindow(HWND hWnd,int nCmdShow);
|
||||
]])
|
||||
|
||||
|
||||
|
@ -189,8 +214,6 @@ if ffi.os == "Windows" then
|
|||
-- @usage set_window_style(bit.band(bit.bnot(WS_MAXIMIZEBOX), bit.bnot(WS_MINIMIZEBOX))) or set_window_style(bit.bnot(WS_SIZEBOX))
|
||||
-- @return true if success to change style, or false
|
||||
local function set_window_style(style)
|
||||
|
||||
local GWL_STYLE = -16
|
||||
local ptr = C.GetActiveWindow()
|
||||
local value = C.GetWindowLongPtrA(ptr, GWL_STYLE)
|
||||
|
||||
|
@ -202,12 +225,12 @@ if ffi.os == "Windows" then
|
|||
local function get_monitor_info()
|
||||
--https://blogs.msdn.microsoft.com/oldnewthing/20050505-04/?p=35703/
|
||||
|
||||
local MONITOR_DEFAULTTONULL = 0x00000000 -- Returns NULL.
|
||||
local MONITOR_DEFAULTTOPRIMARY = 0x00000001 -- Returns a handle to the primary display monitor.
|
||||
--local MONITOR_DEFAULTTONULL = 0x00000000 -- Returns NULL.
|
||||
--local MONITOR_DEFAULTTOPRIMARY = 0x00000001 -- Returns a handle to the primary display monitor.
|
||||
local MONITOR_DEFAULTTONEAREST = 0x00000002 -- Returns a handle to the display monitor that is nearest to the window.
|
||||
|
||||
local hwnd = C.GetActiveWindow()
|
||||
local monitor = C.MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)
|
||||
local monitor = C.MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST)
|
||||
local mi = ffi.new("MONITORINFO")
|
||||
|
||||
mi.cbSize = ffi.sizeof("MONITORINFO")
|
||||
|
@ -217,10 +240,53 @@ if ffi.os == "Windows" then
|
|||
return (success and mi) or nil
|
||||
end
|
||||
|
||||
-- https://github.com/glfw/glfw-legacy/tree/master/lib
|
||||
-- https://github.com/luapower/winapi/blob/master/winapi/window.lua
|
||||
--http://www.glfw.org/GLFWReference27.pdf
|
||||
function M.get_mouse_pos()
|
||||
-- Retrieves the show state and the restored, minimized, and maximized positions of window.
|
||||
-- @return WINDOWPLACEMENT if success, or nil
|
||||
local function get_window_placement(hwnd)
|
||||
local placement = ffi.new("WINDOWPLACEMENT")
|
||||
placement.length = ffi.sizeof("WINDOWPLACEMENT")
|
||||
|
||||
local successed = C.GetWindowPlacement(hwnd, placement)
|
||||
|
||||
return (successed > 0 and placement) or nil
|
||||
end
|
||||
|
||||
-- set the window placement, always used to restore window state
|
||||
local function set_window_placement(hwnd, placement)
|
||||
if hwnd and placement then
|
||||
C.SetWindowPlacement(hwnd, placement)
|
||||
end
|
||||
end
|
||||
|
||||
local is_maximize = false
|
||||
local is_fullscreen = false;
|
||||
local previous_state = {style = nil, placement=nil}
|
||||
|
||||
function M.is_maximize()
|
||||
return is_maximize
|
||||
end
|
||||
|
||||
function M.toggle_maximize()
|
||||
if is_fullscreen then
|
||||
M.toggle_fullscreen()
|
||||
end
|
||||
|
||||
local hwnd = C.GetActiveWindow()
|
||||
|
||||
if is_maximize then
|
||||
set_window_placement(hwnd, previous_state.placement)
|
||||
is_maximize = false
|
||||
else
|
||||
previous_state.placement = get_window_placement(hwnd)
|
||||
C.ShowWindow(hwnd, SW_MAXIMIZE)
|
||||
is_maximize = true
|
||||
end
|
||||
end
|
||||
|
||||
-- https://github.com/glfw/glfw-legacy/tree/master/lib
|
||||
-- https://github.com/luapower/winapi/blob/master/winapi/window.lua
|
||||
--http://www.glfw.org/GLFWReference27.pdf
|
||||
function M.get_mouse_pos()
|
||||
-- definitions
|
||||
|
||||
--ffi.cdef[[
|
||||
|
@ -238,69 +304,57 @@ function M.get_mouse_pos()
|
|||
return {x = pci.ptScreenPos.x, y = pci.ptScreenPos.y}
|
||||
end
|
||||
|
||||
local is_fullscreen = false;
|
||||
local previous_state = {style = nil, rect = nil}
|
||||
|
||||
function M.is_fullscreen()
|
||||
return is_fullscreen
|
||||
end
|
||||
|
||||
function M.toggle_fullscreen()
|
||||
|
||||
-- TODO: shall we move const to out to make it re-usable?
|
||||
local GWL_STYLE = -16
|
||||
local WS_POPUP = 0x80000000
|
||||
local WS_CAPTION = 0x00C00000
|
||||
local WS_SYSMENU = 0x00080000
|
||||
local WS_MINIMIZEBOX = 0x00020000
|
||||
local WS_MAXIMIZEBOX = 0x00010000
|
||||
local SWP_NOZORDER = 0x0004
|
||||
if is_maximize then
|
||||
-- if itis maximized, then we need to restore it then toggle fullscreen
|
||||
M.toggle_maximize()
|
||||
end
|
||||
|
||||
local hwnd = C.GetActiveWindow()
|
||||
|
||||
if not is_fullscreen then
|
||||
|
||||
-- first remember current style and rect
|
||||
local prect = ffi.new("RECT")
|
||||
|
||||
C.GetWindowRect(hwnd, prect)
|
||||
|
||||
-- TODO: exception handle?
|
||||
previous_state.rect = prect
|
||||
previous_state.style = C.GetWindowLongPtrA(hwnd, GWL_STYLE)
|
||||
previous_state.placement = get_window_placement(hwnd)
|
||||
|
||||
-- get desktop rect, or we can use get_monitor_info?
|
||||
local rc = ffi.new("RECT")
|
||||
local dhwnd = C.GetDesktopWindow() -- get desktop handle, or we can use get_monitor_info
|
||||
local dhwnd = C.GetDesktopWindow()
|
||||
C.GetWindowRect(dhwnd, rc)
|
||||
|
||||
C.GetWindowRect(dhwnd, rc) -- get desktop rect
|
||||
|
||||
local windowed_fullscreen_style = bit.band(bit.bnot(WS_CAPTION), bit.bnot(WS_SYSMENU), bit.bnot(WS_MINIMIZEBOX), bit.bnot(WS_MAXIMIZEBOX))
|
||||
-- for fullscreen, we remove these styles
|
||||
local windowed_fullscreen_style = bit.band(
|
||||
bit.bnot(WS_CAPTION),
|
||||
bit.bnot(WS_SYSMENU),
|
||||
bit.bnot(WS_MINIMIZEBOX),
|
||||
bit.bnot(WS_MAXIMIZEBOX),
|
||||
bit.bnot(WS_SIZEBOX))
|
||||
|
||||
if set_window_style(windowed_fullscreen_style) then
|
||||
if C.SetWindowPos(hwnd, nil, 0, 0, rc.right, rc.bottom, SWP_NOZORDER) then
|
||||
if C.SetWindowPos(hwnd, nil, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER) then
|
||||
-- we are in fullscreen mode
|
||||
is_fullscreen = true
|
||||
end
|
||||
end
|
||||
else
|
||||
-- TODO: exception handle?
|
||||
-- restore the style
|
||||
-- restore the style and position/size
|
||||
C.SetWindowLongPtrA(hwnd, GWL_STYLE, previous_state.style)
|
||||
C.SetWindowPos(hwnd,
|
||||
nil,
|
||||
previous_state.rect.left,
|
||||
previous_state.rect.top,
|
||||
previous_state.rect.right - previous_state.rect.left,
|
||||
previous_state.rect.bottom - previous_state.rect.top,
|
||||
SWP_NOZORDER)
|
||||
set_window_placement(hwnd, previous_state.placement)
|
||||
|
||||
is_fullscreen = false
|
||||
end
|
||||
end
|
||||
|
||||
function M.set_window_size(pos_x, pos_y, width, height)
|
||||
local HWND_TOP = 0
|
||||
local SWP_NOMOVE = 0x0002
|
||||
local SWP_NOZORDER = 0x0004
|
||||
--local HWND_TOP = 0
|
||||
--local SWP_NOMOVE = 0x0002
|
||||
--local SWP_NOZORDER = 0x0004
|
||||
local SM_CXSCREEN = 0
|
||||
local SM_CYSCREEN = 1
|
||||
|
||||
|
@ -327,22 +381,16 @@ function M.get_mouse_pos()
|
|||
|
||||
|
||||
function M.disable_window_resize()
|
||||
local WS_SIZEBOX = 0x00040000
|
||||
|
||||
set_window_style(bit.bnot(WS_SIZEBOX))
|
||||
end
|
||||
|
||||
|
||||
function M.disable_maximize_button()
|
||||
local WS_MAXIMIZEBOX = 0x00010000
|
||||
|
||||
set_window_style(bit.bnot(WS_MAXIMIZEBOX))
|
||||
end
|
||||
|
||||
|
||||
function M.disable_minimize_button()
|
||||
local WS_MINIMIZEBOX = 0x00020000
|
||||
|
||||
set_window_style(bit.bnot(WS_MINIMIZEBOX))
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue