argumentum Posted April 8, 2021 Share Posted April 8, 2021 (edited) In Win10, you can drag the TITLE BAR to the top of the monitor and the GUI will maximize. GUIGetMsg() does not trigger the event. I believe to understand why, but maybe there can be a fix for the unexpected behavior in GUIGetMsg() not triggering the event. Here is a sampler to show expected behavior via WM_WINDOWPOSCHANGING > _WinAPI_GetWindowPlacement() expandcollapse popup#include <AutoItConstants.au3> #include <GUIConstants.au3> #include <WinAPIMisc.au3> #include <WinAPIGdi.au3> #include <WinAPISysWin.au3> ; _WinAPI_GetWindowPlacement #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <SendMessage.au3> Global Const $SC_DRAGMOVE = 0xF012 Global $__g_WINDOWPOSCHANGING_iGap = 10 ; 30 pixels for "dramatic effect", 10 pixels should be good for the "magnetic pull" Global $__g_WINDOWPOSCHANGING_iEdge = BitOR(1, 2, 4, 8) ; = 15 ; Left, Top, Right, Bottom Global $__g_WINDOWPOSCHANGING_aBorderWidth[4] = [0, 0, 0, 0] ; Left, Top, Right, Bottom ; for _SetGETMINMAXINFOBorderWidth() Global $__g_aGETMINMAXINFO[4] = [0,0,0,0] ; for WM_GETMINMAXINFO() to limit GUI minimum and/or maximum size. Default of zero means disable. Global $idBtnStyle, $iTest_GUIGetMsg_ON = 1 ; <<<< set to zero to show the expected behaviour Example() Func Example() Local $hGUI = GUICreate("Snapped Window multi-monitor", 500, 300) _SetGETMINMAXINFO(300, 200, 800) ConsoleWrite('@OSVersion = ' & @OSVersion & @CRLF) If @OSVersion <> "WIN_10" Then _SetGETMINMAXINFOBorderWidth("OFF") GUISetBkColor(0x505254) Local $bNewStyle = True ; False $idBtnStyle = GUICtrlCreateButton("Undo Style", 5, 50, 200, 25) GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING") GUIRegisterMsg($WM_GETMINMAXINFO, "WM_GETMINMAXINFO") GUISetStyle(BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP)) _GUIStyleRefresh($hGUI) _SetGETMINMAXINFOBorderWidth($hGUI) _GuiCenterOnMonitorFromMousePosition($hGUI) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIDelete() ExitLoop Case $GUI_EVENT_PRIMARYDOWN _SendMessage($hGUI, $WM_SYSCOMMAND, $SC_DRAGMOVE, 0) ; Moved to WM_WINDOWPOSCHANGING() for this example. GUIGetMsg() does not act on size events when the TITLE bar is dragged. Case $GUI_EVENT_MAXIMIZE, $GUI_EVENT_RESTORE ; should not change to this style while maximized If $iTest_GUIGetMsg_ON Then GUICtrlSetState($idBtnStyle, (BitAND(WinGetState($hGUI), $WIN_STATE_MAXIMIZED) ? $GUI_DISABLE : $GUI_ENABLE)) Case $idBtnStyle $bNewStyle = Not $bNewStyle If $bNewStyle Then GUISetStyle(BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP)) Else GUISetStyle($GUI_SS_DEFAULT_GUI) ;~ GUISetStyle($WS_POPUP) EndIf GUICtrlSetData($idBtnStyle, ($bNewStyle ? 'Undo Style' : 'Change Style')) _GUIStyleRefresh($hGUI) _SetGETMINMAXINFOBorderWidth($hGUI) _GUIStyleRefresh($hGUI) ; ..with new SetGETMINMAXINFOBorderWidth EndSwitch WEnd EndFunc ;==>Example Func _SetGETMINMAXINFO($iMinTrackSizeX = Default, $iMinTrackSizeY = Default, $iMaxTrackSizeX = Default, $iMaxTrackSizeY = Default) ;~ $tagMINMAXINFO = 'struct; long ReservedX;long ReservedY;long MaxSizeX;long MaxSizeY;long MaxPositionX;long MaxPositionY;long MinTrackSizeX;long MinTrackSizeY;long MaxTrackSizeX;long MaxTrackSizeY; endstruct' If $iMinTrackSizeX <> Default Then $__g_aGETMINMAXINFO[0] = $iMinTrackSizeX ; https://www.autoitscript.com/forum/topic/144385-restricting-the-minimum-and-maximum-sizes-of-a-gui/ If $iMinTrackSizeY <> Default Then $__g_aGETMINMAXINFO[1] = $iMinTrackSizeY If $iMaxTrackSizeX <> Default Then $__g_aGETMINMAXINFO[2] = $iMaxTrackSizeX If $iMaxTrackSizeY <> Default Then $__g_aGETMINMAXINFO[3] = $iMaxTrackSizeY Return $__g_aGETMINMAXINFO EndFunc Func WM_GETMINMAXINFO($hWnd, $msg, $wParam, $lParam) Local $tagMINMAXINFO = DllStructCreate("struct;long;long;long;long;long;long;long MinTrackSizeX;long MinTrackSizeY;long MaxTrackSizeX;long MaxTrackSizeY;endstruct", $lParam) If $__g_aGETMINMAXINFO[0] Then $tagMINMAXINFO.MinTrackSizeX = $__g_aGETMINMAXINFO[0] ; DllStructSetData($tagMINMAXINFO, 7, $__g_aGETMINMAXINFO[0]) ; min X If $__g_aGETMINMAXINFO[1] Then $tagMINMAXINFO.MinTrackSizeY = $__g_aGETMINMAXINFO[1] If $__g_aGETMINMAXINFO[2] Then $tagMINMAXINFO.MaxTrackSizeX = $__g_aGETMINMAXINFO[2] If $__g_aGETMINMAXINFO[3] Then $tagMINMAXINFO.MaxTrackSizeY = $__g_aGETMINMAXINFO[3] Return $GUI_RUNDEFMSG EndFunc ;==>WM_GETMINMAXINFO Func _SetGETMINMAXINFOBorderWidth($hWnd, $iLeft = Default, $iTop = Default, $iRight = Default, $iBottom = Default ) Local Static $iAutoBorderWidthEnabled = 1 Switch $hWnd Case "ON" $iAutoBorderWidthEnabled = 1 Return SetError(0, $iAutoBorderWidthEnabled, $__g_WINDOWPOSCHANGING_aBorderWidth) Case "OFF" $iAutoBorderWidthEnabled = 0 Return SetError(0, $iAutoBorderWidthEnabled, $__g_WINDOWPOSCHANGING_aBorderWidth) Case "SET" If $iLeft <> Default Then $__g_WINDOWPOSCHANGING_aBorderWidth[0] = $iLeft If $iTop <> Default Then $__g_WINDOWPOSCHANGING_aBorderWidth[1] = $iTop If $iRight <> Default Then $__g_WINDOWPOSCHANGING_aBorderWidth[2] = $iRight If $iBottom <> Default Then $__g_WINDOWPOSCHANGING_aBorderWidth[3] = $iBottom Return SetError(0, $iAutoBorderWidthEnabled, $__g_WINDOWPOSCHANGING_aBorderWidth) Case "RESET" $__g_WINDOWPOSCHANGING_aBorderWidth[0] = 0 $__g_WINDOWPOSCHANGING_aBorderWidth[1] = 0 $__g_WINDOWPOSCHANGING_aBorderWidth[2] = 0 $__g_WINDOWPOSCHANGING_aBorderWidth[3] = 0 Return SetError(0, $iAutoBorderWidthEnabled, $__g_WINDOWPOSCHANGING_aBorderWidth) EndSwitch If Not $iAutoBorderWidthEnabled Then Return Local $aWinPos = WinGetPos($hWnd) Local $aWinClientSize = WinGetClientSize($hWnd) Local $iBorder = (($aWinPos[2] - $aWinClientSize[0]) / 2) Local $iHeader = $aWinPos[3] - $aWinClientSize[1] - $iBorder ConsoleWrite( '>>> ' & $iBorder & @TAB & $iHeader & @CRLF) If $iBorder Then $iBorder -= 1 ; auto-adjusting for Windows 10 border ; -1 or will otherwise show part in the adjacent monitor in multi-monitor setup. $__g_WINDOWPOSCHANGING_aBorderWidth[0] = - $iBorder $__g_WINDOWPOSCHANGING_aBorderWidth[2] = $iBorder $__g_WINDOWPOSCHANGING_aBorderWidth[3] = $iBorder Return SetError(0, $iAutoBorderWidthEnabled, $__g_WINDOWPOSCHANGING_aBorderWidth) EndFunc Func _GUIStyleRefresh($hWnd) Local $aWinPos = WinGetPos($hWnd) If @error Then Return SetError(@error, @extended, @error) WinMove($hWnd, "", $aWinPos[0], $aWinPos[1], $aWinPos[2] - 1, $aWinPos[3] - 1) WinMove($hWnd, "", $aWinPos[0], $aWinPos[1], $aWinPos[2], $aWinPos[3]) Return EndFunc ;==>GUIStyleRefresh Func WM_WINDOWPOSCHANGING($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam ; original code at https://www.autoitscript.com/forum/topic/24342-form-snap/ ;~ ConsoleWrite('+ WM_WINDOWPOSCHANGING(' & $hWnd & ', ' & $iMsg & ', ' & $wParam & ', ' & $lParam & ') ' & @SEC &'.'& @MSEC & @CRLF) ; The Static declaration speeds up the func. ( not much, nanoseconds ) Local Static $stWinPos, $tPos, $hMonitor, $aData, $nLeft, $nTop, $nRight, $nBottom, $iShowCmd = 0, $hTimer = 0 If TimerDiff($hTimer) > 1000 Then $hTimer = TimerInit() $tPos = _WinAPI_GetMousePos() ; These func are very time consuming and If Not @error Then $hMonitor = _WinAPI_MonitorFromPoint($tPos) ; the user is very unlikely to move the If Not @error Then $aData = _WinAPI_GetMonitorInfo($hMonitor) ; mouse into position on another monitor If @error Then Return $GUI_RUNDEFMSG ; in less than a second. EndIf ; https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-windowpos?redirectedfrom=MSDN $stWinPos = DllStructCreate("hwnd hwnd;hwnd hwndInsertAfter;int x;int y;int cx;int cy;uint flags", $lParam) ; $tagWINDOWPOS $nLeft = $aData[1].Left $nTop = $aData[1].Top ; $tagRECT = "struct;long Left;long Top;long Right;long Bottom;endstruct" $nRight = $aData[1].Right - $stWinPos.cx $nBottom = $aData[1].Bottom - $stWinPos.cy If BitAND($stWinPos.flags, 0x0020) Then ; SWP_FRAMECHANGED ; https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-windowpos Local $tRET = _WinAPI_GetWindowPlacement($hWnd) If @error = 0 Then ; https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-windowplacement $iShowCmd = $tRET.showCmd ; $tagWINDOWPLACEMENT = "uint length;uint flags;uint showCmd;long ptMinPosition[2];long ptMaxPosition[2];long rcNormalPosition[4]" Local Static $aShowCmd[10] = ["SW_HIDE","SW_SHOWNORMAL","SW_SHOWMINIMIZED","SW_MAXIMIZE","SW_SHOWNOACTIVATE","SW_SHOW","SW_MINIMIZE","SW_SHOWMINNOACTIVE","SW_SHOWNA","SW_RESTORE"] ConsoleWrite($aShowCmd[$iShowCmd] & @CRLF) ; ..just for show ; dragging the title will change state and GUIGetMsg() will not act on it, so is better running here. If $iTest_GUIGetMsg_ON = 0 Then GUICtrlSetState($idBtnStyle, $iShowCmd = @SW_MAXIMIZE ? $GUI_DISABLE : $GUI_ENABLE) EndIf EndIf If $iShowCmd = @SW_MAXIMIZE Then Return $GUI_RUNDEFMSG If BitAND($__g_WINDOWPOSCHANGING_iEdge, 1) And Abs($nLeft - $stWinPos.x) <= $__g_WINDOWPOSCHANGING_iGap Then $stWinPos.x = $nLeft + $__g_WINDOWPOSCHANGING_aBorderWidth[0] If BitAND($__g_WINDOWPOSCHANGING_iEdge, 4) And Abs($nRight - $stWinPos.x) <= $__g_WINDOWPOSCHANGING_iGap Then $stWinPos.x = $nRight + $__g_WINDOWPOSCHANGING_aBorderWidth[2] If BitAND($__g_WINDOWPOSCHANGING_iEdge, 8) And Abs($nBottom - $stWinPos.y) <= $__g_WINDOWPOSCHANGING_iGap Then $stWinPos.y = $nBottom + $__g_WINDOWPOSCHANGING_aBorderWidth[3] If BitAND($__g_WINDOWPOSCHANGING_iEdge, 2) And Abs($nTop - $stWinPos.y) <= $__g_WINDOWPOSCHANGING_iGap Then $stWinPos.y = $nTop + $__g_WINDOWPOSCHANGING_aBorderWidth[1] Return $GUI_RUNDEFMSG EndFunc ;==>WM_WINDOWPOSCHANGING Func _GuiCenterOnMonitorFromMousePosition($hForm, $sText = "") ; https://www.autoitscript.com/forum/index.php?showtopic=139260&view=findpost&p=1479329 Local $aData, $hMonitor, $tPos = _WinAPI_GetMousePos() If Not @error Then $hMonitor = _WinAPI_MonitorFromPoint($tPos) If Not @error Then $aData = _WinAPI_GetMonitorInfo($hMonitor) If @error Then Return SetError(1, -1, 1) Local $iWinState = WinGetState($hForm, $sText) If @error Then Return SetError(2, $aData[2], 2) If BitAND($iWinState, $WIN_STATE_MINIMIZED) Or _ BitAND($iWinState, $WIN_STATE_MAXIMIZED) Then WinSetState($hForm, $sText, @SW_RESTORE) Local $aWinPos = WinGetPos($hForm, $sText) If @error Then Return SetError(3, $aData[2], 3) WinMove($hForm, _ $sText, _ Int((($aData[0].Right - $aData[0].Left - $aWinPos[2]) / 2) + $aData[0].Left), _ Int((($aData[0].Bottom - $aData[0].Top - $aWinPos[3]) / 2) + $aData[0].Top)) If @error Then Return SetError(4, $aData[2], 4) If BitAND($iWinState, $WIN_STATE_MINIMIZED) Then WinSetState($hForm, $sText, @SW_MINIMIZE) If BitAND($iWinState, $WIN_STATE_MAXIMIZED) Then WinSetState($hForm, $sText, @SW_MAXIMIZE) Return SetError(0, $aData[2], 0) EndFunc ;==>GuiCenterOnMonitorFromMousePosition ...well, a sampler that is like a "example type of script" but I did not know where to post it to ask if it deserves opening a ticket or not. Tho it should.@jpm, will you give your 2 cents Edit: $GUI_EVENT_RESIZED does trigger ( OnEvent or not ). Maybe the patch can be around there in the source ?, no clue. Edited April 8, 2021 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now