commit
c9ee8af20c
174
defos/defos.lua
174
defos/defos.lua
|
@ -11,10 +11,20 @@ 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([[
|
||||
|
||||
|
||||
typedef long LONG;
|
||||
typedef int BOOL;
|
||||
typedef unsigned long DWORD;
|
||||
|
@ -32,7 +42,7 @@ if ffi.os == "Windows" then
|
|||
typedef HANDLE HWND;
|
||||
typedef HICON HCURSOR;
|
||||
typedef BYTE BCHAR;
|
||||
|
||||
|
||||
static const int CCHDEVICENAME = 32;
|
||||
static const int CCHFORMNAME = 32;
|
||||
|
||||
|
@ -49,7 +59,7 @@ if ffi.os == "Windows" then
|
|||
LONG x;
|
||||
LONG y;
|
||||
} POINT, *PPOINT, *NPPOINT, *LPPOINT;
|
||||
|
||||
|
||||
typedef struct _POINTL
|
||||
{
|
||||
LONG x;
|
||||
|
@ -75,7 +85,7 @@ if ffi.os == "Windows" then
|
|||
HCURSOR hCursor;
|
||||
POINT ptScreenPos;
|
||||
} CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
|
||||
|
||||
|
||||
typedef struct _devicemode {
|
||||
BCHAR dmDeviceName[CCHDEVICENAME];
|
||||
WORD dmSpecVersion;
|
||||
|
@ -98,7 +108,7 @@ if ffi.os == "Windows" then
|
|||
DWORD dmDisplayOrientation;
|
||||
DWORD dmDisplayFixedOutput;
|
||||
};
|
||||
|
||||
|
||||
short dmColor;
|
||||
short dmDuplex;
|
||||
short dmYResolution;
|
||||
|
@ -123,8 +133,17 @@ if ffi.os == "Windows" then
|
|||
DWORD dmPanningWidth;
|
||||
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);
|
||||
|
||||
|
@ -151,8 +170,14 @@ if ffi.os == "Windows" then
|
|||
BOOL GetMonitorInfoW(HMONITOR hMonitor, LPMONITORINFO lpmi);
|
||||
|
||||
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
|
||||
|
||||
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))
|
||||
|
||||
local dhwnd = C.GetDesktopWindow()
|
||||
C.GetWindowRect(dhwnd, rc)
|
||||
|
||||
-- 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