Nine Posted December 18, 2024 Posted December 18, 2024 (edited) @MattyD Sorry if we've been hijacking your thread, but in a sense it is all your fault. Making such an innovative example will certainly attract some members of the community, right ? Anyway, here my take to solve the minimize issue : expandcollapse popup#include <guiConstants.au3> #include <winapi.au3> Opt("MustDeclareVars", True) Global Const $tagMOUSEHOOKSTRUCT = "dword X;dword Y;hwnd hwnd;uint wHitTestCode;ulong_ptr dwExtraInfo;" Global $hGUI, $idBtn, $idBtn2, $hHook Example() Func Example() $hGUI = GUICreate("WM_NCHITTEST", 300, 200, -1, -1, $WS_OVERLAPPEDWINDOW) $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80, $WS_CLIPSIBLINGS) $idBtn2 = GUICtrlCreateButton("Button 2", 90, 4, 80, 80, $WS_CLIPSIBLINGS) Local $idLockButtons = GUICtrlCreateCheckbox("Lock Buttons", 200, 20, 80, 20) Local $hDll = DllCallbackRegister(ButtonMoveProc, 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr') _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn) _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2) Local $hStub = DllCallbackRegister(WM_MOUSE, "LRESULT", "int;wparam;lparam") $hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE, DllCallbackGetPtr($hStub), 0, _WinAPI_GetCurrentThreadId()) GUISetState() Local $iMsg While True $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE ExitLoop Case $idLockButtons If GUICtrlRead($iMsg) = $GUI_CHECKED Then _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn) _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2) _WinAPI_UnhookWindowsHookEx($hHook) Else _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn, 0) _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2, 0) $hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE, DllCallbackGetPtr($hStub), 0, _WinAPI_GetCurrentThreadId()) EndIf Case $idBtn, $idBtn2 ConsoleWrite("Click " & GUICtrlRead($iMsg) & @CRLF) EndSwitch WEnd GUIDelete() _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn) _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2) DllCallbackFree($hDll) _WinAPI_UnhookWindowsHookEx($hHook) DllCallbackFree($hStub) EndFunc ;==>Example Func ButtonMoveProc($hWnd, $iMsg, $wParam, $lParam, $iID, $iData) Local $aPos, $iRet, $aPoint[2], $iSrc, $iEvent, $hCursor Switch $iMsg Case $WM_NCHITTEST $aPos = WinGetPos($hWnd) $aPoint[0] = BitAND($lParam, 0xFFFF) $aPoint[1] = BitShift($lParam, 16) $iRet = $HTCAPTION If $aPoint[0] - $aPos[0] < 10 Then $iRet = $HTLEFT If $aPoint[0] - $aPos[0] > ($aPos[2] - 10) Then $iRet = $HTRIGHT If $aPoint[1] - $aPos[1] < 10 Then Switch $iRet Case $HTLEFT $iRet = $HTTOPLEFT Case $HTRIGHT $iRet = $HTTOPRIGHT Case Else $iRet = $HTTOP EndSwitch ElseIf $aPoint[1] - $aPos[1] > ($aPos[3] - 10) Then Switch $iRet Case $HTLEFT $iRet = $HTBOTTOMLEFT Case $HTRIGHT $iRet = $HTBOTTOMRIGHT Case Else $iRet = $HTBOTTOM EndSwitch EndIf Return $iRet Case $WM_SETCURSOR $iSrc = BitAND($lParam, 0xFFFF) $iEvent = BitShift($lParam, 16) If $iSrc = $HTCAPTION And $iEvent = $WM_LBUTTONDOWN Then _WinAPI_RedrawWindow($hWnd, 0, 0, $RDW_INVALIDATE + $RDW_FRAME) $hCursor = _WinAPI_LoadCursor(0, $OCR_SIZEALL) _WinAPI_SetCursor($hCursor) Return True EndIf EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>ButtonMoveProc Func WM_MOUSE($iMsg, $wParam, $lParam) If $iMsg < 0 Then Return _WinAPI_CallNextHookEx($hHook, $iMsg, $wParam, $lParam) If $wParam = $WM_LBUTTONUP Then Local $tMouse = DllStructCreate($tagMOUSEHOOKSTRUCT, $lParam) If $tMouse.hwnd = GUICtrlGetHandle($idBtn) Or $tMouse.hwnd = GUICtrlGetHandle($idBtn2) Then Local $idCtrl = _WinAPI_GetDlgCtrlID($tMouse.hwnd) Local $aPos = ControlGetPos($hGUI, "", $idCtrl) GUICtrlSetPos($idCtrl, $aPos[0], $aPos[1]) EndIf EndIf Return _WinAPI_CallNextHookEx($hHook, $iMsg, $wParam, $lParam) EndFunc ;==>WM_MOUSE ps. I converted it to subclassing Edited December 18, 2024 by Nine MattyD 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
MattyD Posted December 19, 2024 Author Posted December 19, 2024 Nah all good Its all very interesting. I might experiment some more to see if I can discover what ControlSetPos is actually doing behind the scenes . I mean calling it works a treat - but surely we shouldn't need to move everything twice.
argumentum Posted December 19, 2024 Posted December 19, 2024 (edited) ...and, making it a single function/UDF ?, so that you shift-click ( to come up with a strategy ) and make that control movable. Because writing all this for each control, what a pain. Edited December 19, 2024 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
ptrex Posted December 19, 2024 Posted December 19, 2024 @Nine When the windows is resized the mouse control to release the button to the new position doesn't work anymore ? Only when the window is not resized all is OK Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New
Nine Posted December 19, 2024 Posted December 19, 2024 8 hours ago, MattyD said: what ControlSetPos is actually doing behind the scenes Do you mean ControlMove or GUICtrlSetPos ? In any case, I tend to believe that there is an underlying bug behind all this minimize issue. 8 hours ago, MattyD said: but surely we shouldn't need to move everything twice Totally agree. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
Nine Posted December 19, 2024 Posted December 19, 2024 2 hours ago, ptrex said: When the windows is resized the mouse control to release the button to the new position doesn't work anymore ? Only when the window is not resized all is OK You mean with @pixelsearch base code ? It is working alright, just the flickers is quite annoying after resize. But with the snippet I provided, it makes it very tolerable. With @MattyD base code there is no is issue (no flickers) before or after resize. However, both codes have the same problem on minimize/restore, the controls get restored to their original places. But solutions was found in both cases. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
pixelsearch Posted December 19, 2024 Posted December 19, 2024 (edited) 39 minutes ago, Nine said: However, both codes have the same problem on minimize/restore, the controls get restored to their original places. But solutions was found in both cases. So in my case (and with your help) there is no Minimize/Restore bug when using GUICtrlSetPos() instead of ControlMove Now if we refer to this post from @Melba23 this is not a bug, here is an excerpt of his post : The 2 types of commands do not have the same "prefix" as they are used differently: Any command that begins GUICtrl* is to be used on an AutoIt GUI created by the script itself - hence the use of a ControlID only to identify the control to be actioned. Commands that begin Control* can be used on any GUI - hence the requirement to define the GUI by title and text as well as providing a ControlID. So we should have in mind to always use the GUICtrl* commands when the GUI is created by our own script (my case) and everything should be fine, fingers crossed Edited December 19, 2024 by pixelsearch typo
Nine Posted December 19, 2024 Posted December 19, 2024 (edited) I understand what you are saying. But in the original code from @MattyD there is no Control* function used at all. And the minimize/restore problem is still there. I had to set position again with GUICtrlSetPos to make it work (I do not think it is normal). Edit : Here an interesting test I just made. Local $hWnd = WinGetHandle("Express") WinActivate($hWnd) Local $hCtrl = ControlGetHandle($hWnd, "", "Button6") Local $aPos = ControlGetPos($hWnd, "", $hCtrl) ControlMove($hWnd, "", $hCtrl, $aPos[0] + 50, $aPos[1]) Using an outside window (Express Burn), when I move a button and I minimize/restore the window..... well, control returns to its original place. Just like what AutoIt GUI does. Seems it is a Windows behavior not a bug like I said. ReEdit : tried with _WinAPI_SetWindowPos. Same behavior, same result. Edited December 19, 2024 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
ioa747 Posted December 19, 2024 Posted December 19, 2024 (edited) I tried the traditional method of applying resize ... but it overflowed a little expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <WinAPI.au3> Example() Func Example() Local $hGui = GUICreate("", 300, 200, -1, -1, $WS_OVERLAPPEDWINDOW) Local $idBtn1 = GUICtrlCreateButton("Button 1", 10, 40, 80, 80, $WS_CLIPSIBLINGS) Local $idBtn2 = GUICtrlCreateButton("Button 2", 100, 40, 80, 80, $WS_CLIPSIBLINGS) Local $idInput = GUICtrlCreateInput("Test 123 Text", 10, 10, 170, 20, BitOR($ES_CENTER, $WS_CLIPSIBLINGS)) Local $idLockButtons = GUICtrlCreateCheckbox("Lock Buttons", 200, 20, 80, 20, $WS_CLIPSIBLINGS) Local $bLock = False GUISetState() Local $iMsg, $aInfo While 1 $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE Exit Case $idLockButtons $bLock = (GUICtrlRead($iMsg) = $GUI_CHECKED) ConsoleWrite("- Lock Buttons is " & _ (GUICtrlRead($iMsg) = 1 ? "Checked" : "Un-Checked") & @CRLF) Case $idBtn1 If Not $bLock Then ContinueLoop ConsoleWrite("- Button 1 is pressed" & @CRLF) Case $idBtn2 If Not $bLock Then ContinueLoop ConsoleWrite("- Button 2 is pressed" & @CRLF) Case $GUI_EVENT_PRIMARYDOWN If $bLock Then ContinueLoop $aInfo = GUIGetCursorInfo($hGui) If (Not @error) And ($aInfo[4] = $idBtn1 Or $aInfo[4] = $idBtn2 Or $aInfo[4] = $idInput) Then _Resize($hGui) EndIf EndSwitch WEnd EndFunc ;==>Example Func _Resize($hWnd, $iGrid = 5) If Not WinActive($hWnd) Then Return Local $aInfo = GUIGetCursorInfo($hWnd) Local $idControl = $aInfo[4] If $idControl = 0 Then Return If $iGrid < 1 Then $iGrid = 1 Local $iEdge = 5 Local $CtrlPos = ControlGetPos($hWnd, "", $idControl) Local $CtrlX = $CtrlPos[0] Local $CtrlY = $CtrlPos[1] Local $CtrlW = $CtrlPos[2] Local $CtrlH = $CtrlPos[3] Local $MouseX = $aInfo[0] Local $MouseY = $aInfo[1] Local $LeftEdge = Abs($MouseX - $CtrlX) < $iEdge Local $RightEdge = Abs($MouseX - ($CtrlX + $CtrlW)) < $iEdge Local $TopEdge = Abs($MouseY - $CtrlY) < $iEdge Local $BottomEdge = Abs($MouseY - ($CtrlY + $CtrlH)) < $iEdge _WinAPI_SetWindowPos(GUICtrlGetHandle($idControl), $HWND_TOP, 0, 0, 0, 0, $SWP_NOMOVE + $SWP_NOSIZE) Local $iCursorId = MouseGetCursor() Local $aInfoNew = $aInfo If $LeftEdge Or $RightEdge Or $TopEdge Or $BottomEdge Then ; ## Resizing ## Local $resizeMode = 0 If $LeftEdge Then $resizeMode += 1 If $RightEdge Then $resizeMode += 2 If $TopEdge Then $resizeMode += 4 If $BottomEdge Then $resizeMode += 8 ; Set cursor for resizing Switch $resizeMode Case 1, 2 ; Left, Right edge GUISetCursor(13, 1, $hWnd) Case 4, 8 ; Top, Bottom edge GUISetCursor(11, 1, $hWnd) Case 5, 10 ; Top-left, Bottom-right corner GUISetCursor(12, 1, $hWnd) Case 6, 9 ; Top-right, Bottom-left corner GUISetCursor(10, 1, $hWnd) EndSwitch Do $aInfo = GUIGetCursorInfo($hWnd) If $aInfoNew[0] <> $aInfo[0] Or $aInfoNew[1] <> $aInfo[1] Then $MouseX = $aInfo[0] $MouseY = $aInfo[1] Switch $resizeMode Case 1 ; Left edge $CtrlW += $CtrlX - $MouseX $CtrlX = $MouseX Case 2 ; Right edge $CtrlW = $MouseX - $CtrlX Case 4 ; Top edge $CtrlH += $CtrlY - $MouseY $CtrlY = $MouseY Case 8 ; Bottom edge $CtrlH = $MouseY - $CtrlY Case 5 ; Top-left corner $CtrlW += $CtrlX - $MouseX $CtrlX = $MouseX $CtrlH += $CtrlY - $MouseY $CtrlY = $MouseY Case 6 ; Top-right corner $CtrlW = $MouseX - $CtrlX $CtrlH += $CtrlY - $MouseY $CtrlY = $MouseY Case 9 ; Bottom-left corner $CtrlW += $CtrlX - $MouseX $CtrlX = $MouseX $CtrlH = $MouseY - $CtrlY Case 10 ; Bottom-right corner $CtrlW = $MouseX - $CtrlX $CtrlH = $MouseY - $CtrlY EndSwitch ; Snap to grid $CtrlX = Round($CtrlX / $iGrid) * $iGrid $CtrlY = Round($CtrlY / $iGrid) * $iGrid $CtrlW = Round($CtrlW / $iGrid) * $iGrid $CtrlH = Round($CtrlH / $iGrid) * $iGrid ; minimum size If $CtrlW < 15 Then $CtrlW = 15 If $CtrlH < 15 Then $CtrlH = 15 GUICtrlSetPos($idControl, $CtrlX, $CtrlY, $CtrlW, $CtrlH) EndIf Sleep(10) Until Not $aInfo[2] ElseIf $MouseX > $CtrlX + $iEdge And $MouseX < ($CtrlX + $CtrlW - $iEdge) And _ $MouseY > $CtrlY + $iEdge And $MouseY < ($CtrlY + $CtrlH - $iEdge) Then ; ## Moving ## GUISetCursor(0, 1, $hWnd) Local $OffsetX = $MouseX - $CtrlX Local $OffsetY = $MouseY - $CtrlY Do $aInfo = GUIGetCursorInfo($hWnd) If $aInfoNew[0] <> $aInfo[0] Or $aInfoNew[1] <> $aInfo[1] Then Local $NewX = Round(($aInfo[0] - $OffsetX) / $iGrid) * $iGrid Local $NewY = Round(($aInfo[1] - $OffsetY) / $iGrid) * $iGrid GUICtrlSetPos($idControl, $NewX, $NewY, $CtrlW, $CtrlH) EndIf Sleep(10) Until Not $aInfo[2] EndIf GUISetCursor($iCursorId, 0, $hWnd) EndFunc ;==>_Resize ... and since I did it, I want to share it Edit: I entered the grid parameter. Edited December 19, 2024 by ioa747 I entered the grid parameter. MattyD 1 I know that I know nothing
MattyD Posted December 20, 2024 Author Posted December 20, 2024 (edited) Ok so here's a test to see whats going on with GUICtrlSetPos. I tried inspecting whats being sent to the button - Bear with me... Spoiler expandcollapse popup#include <guiConstants.au3> #include <winapi.au3> #include <GUIButton.au3> Opt("MustDeclareVars", 1) Global Const $SC_MINIMIZE = 0xF020 Global Const $SC_RESTORE = 0xF120 Global $tagMSG = "hwnd hwnd;uint Message;wparam wParam;lparam lParam;dword time;" & $tagPoint & ";dword private" Global $tagNCCALCSIZE_PARAMS = "int rect1[4];int rect2[4];int rect3[4];ptr WinPos" Global $hGui = GUICreate("", 300, 200) ;~ Global $hBtn = _GUICtrlButton_Create($hGUI, "Button 1", 4, 4, 80, 80) ;~ Global $idBtn = _WinAPI_GetDlgCtrlID($hBtn) Global $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80) Global $hBtn = GUICtrlGetHandle($idBtn) Global $hBtnMoveProc = DllCallbackRegister("ButtonInspect", "long", "hwnd;uint;wparam;lparam") Global $pBtnMoveProc = DllCallbackGetPtr($hBtnMoveProc) Global $pOrigBtnProc = _WinAPI_SetWindowLong($hBtn, $GWL_WNDPROC, $pBtnMoveProc) GUISetState() GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND") While 1 Local $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE Exit Case $GUI_EVENT_MINIMIZE ConsoleWrite("---End Min---" & @CRLF) Case $GUI_EVENT_RESTORE ConsoleWrite("---End Restore---" & @CRLF) EndSwitch WEnd Func ButtonInspect($hWnd, $uMsg, $wParam, $lParam) Local $iRet, $aRes, $tNCCALCSIZE Switch $uMsg Case $WM_NCHITTEST $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_NCHITTEST" & @CRLF) ConsoleWrite(StringFormat("\tMouse[%d, %d]", BitShift($lParam, 16), BitAND($lParam, 0xFFFF)) & @CRLF) ConsoleWrite(StringFormat("\tRET (Area)[%d]", $iRet) & @CRLF) ConsoleWrite("----Set Pos----" & @CRLF) GUICtrlSetPos($idBtn, 80, 80, 100, 100) ;~ _WinAPI_SetWindowPos($hWnd, $HWND_TOP, 80, 80, 100, 100, $SWP_FRAMECHANGED) ConsoleWrite("---End Set Pos---" & @CRLF) Return $iRet Case $WM_GETDLGCODE $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_GETDLGCODE" & @CRLF) ConsoleWrite(StringFormat("\tvKey[0x%02x]", $wParam) & @CRLF) If $lParam Then Local $tMsg = DllStructCreate($tagMSG, $lParam) ConsoleWrite(StringFormat("\tMsg[0x%08x]", $tMsg.Message) & @CRLF) ConsoleWrite(StringFormat("\twParam[0x%08x]", $tMsg.wParam) & @CRLF) ConsoleWrite(StringFormat("\tlParam[0x%08x]", $tMsg.lParam) & @CRLF) ConsoleWrite(StringFormat("\tTime[0x%08x]", $tMsg.time) & @CRLF) ConsoleWrite(StringFormat("\tPoint[%d, %d]", $tMsg.X, $tMsg.Y) & @CRLF) EndIf ConsoleWrite(StringFormat("\tRET[0x%08x]", $iRet) & @CRLF) Return $iRet Case $WM_IME_SETCONTEXT $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_IME_SETCONTEXT" & @CRLF) ConsoleWrite(StringFormat("\tWinActive[%d]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tOptions[0x%08x]", $lParam) & @CRLF) ConsoleWrite(StringFormat("\tRET[0x%08x]", $iRet) & @CRLF) Return $iRet Case $WM_IME_NOTIFY $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_IME_NOTIFY" & @CRLF) ConsoleWrite(StringFormat("\tCommand[0x%08x]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tData[0x%08x]", $lParam) & @CRLF) ConsoleWrite(StringFormat("\tRET[0x%08x]", $iRet) & @CRLF) Return $iRet Case $WM_KILLFOCUS $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_KILLFOCUS" & @CRLF) ConsoleWrite(StringFormat("\tKBFocusHWND[0x%08x]", $wParam) & @CRLF) Return $iRet Case $WM_CHILDACTIVATE $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_CHILDACTIVATE" & @CRLF) Return $iRet Case $WM_SETCURSOR $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_SETCURSOR" & @CRLF) ConsoleWrite(StringFormat("\tCursorHwnd[0x%08x]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tCauseMsg[0x%04x]", BitShift($lParam, 16)) & @CRLF) ConsoleWrite(StringFormat("\tHitTest[%d]", BitAND($lParam, 0xFFFF)) & @CRLF) ConsoleWrite(StringFormat("\tRET[0x%08x]", $iRet) & @CRLF) Return $iRet Case $WM_WINDOWPOSCHANGING $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_WINDOWPOSCHANGING" & @CRLF) _DispWinPos($lParam) Return $iRet Case $WM_NCCALCSIZE $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) Local $tNCCALCSIZE ConsoleWrite("WM_NCCALCSIZE" & @CRLF) ConsoleWrite(StringFormat("\twParam[%d]", $wParam) & @CRLF) If $wParam Then $tNCCALCSIZE = DllStructCreate($tagNCCALCSIZE_PARAMS, $lParam) ConsoleWrite(StringFormat("\tNewPos[%d %d %d %d]", $tNCCALCSIZE.rect1(1), $tNCCALCSIZE.rect1(2), $tNCCALCSIZE.rect1(3), $tNCCALCSIZE.rect1(4)) & @CRLF) ConsoleWrite(StringFormat("\tOldPos[%d %d %d %d]", $tNCCALCSIZE.rect2(1), $tNCCALCSIZE.rect2(2), $tNCCALCSIZE.rect2(3), $tNCCALCSIZE.rect2(4)) & @CRLF) ConsoleWrite(StringFormat("\tOldClientPos[%d %d %d %d]", $tNCCALCSIZE.rect3(1), $tNCCALCSIZE.rect3(2), $tNCCALCSIZE.rect3(3), $tNCCALCSIZE.rect3(4)) & @CRLF) _DispWinPos($tNCCALCSIZE.WinPos) Else $tNCCALCSIZE = DllStructCreate($tagRect, $lParam) ;proc may change rect data. ConsoleWrite(StringFormat("\tProposed[%d %d %d %d]", $tNCCALCSIZE.Left, $tNCCALCSIZE.Top, $tNCCALCSIZE.Right, $tNCCALCSIZE.Bottom) & @CRLF) EndIf ConsoleWrite(StringFormat("\tRET[0x%08x]", $iRet) & @CRLF) Return $iRet Case $WM_MOVE $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_MOVE" & @CRLF) ConsoleWrite(StringFormat("\tPos[%d, %d]", BitShift($lParam, 16), BitAND($lParam, 0xFFFF)) & @CRLF) Return $iRet Case $WM_SIZE $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_SIZE" & @CRLF) ConsoleWrite(StringFormat("\tType[%d]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tDims[%d, %d]", BitShift($lParam, 16), BitAND($lParam, 0xFFFF)) & @CRLF) Return $iRet Case $WM_WINDOWPOSCHANGED $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_WINDOWPOSCHANGED" & @CRLF) _DispWinPos($lParam) Return $iRet Case $WM_GETOBJECT $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_GETOBJECT" & @CRLF) ConsoleWrite(StringFormat("\tFlags[0x%08x]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tObjId[0x%08x]", $lParam) & @CRLF) ConsoleWrite(StringFormat("\tRET[0x%08x]", $iRet) & @CRLF) Return $iRet Case $WM_MOUSEMOVE $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_MOUSEMOVE" & @CRLF) ConsoleWrite(StringFormat("\tvKey[0x%08x]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tPos[%d, %d]", BitShift($lParam, 16), BitAND($lParam, 0xFFFF)) & @CRLF) Return $iRet Case $WM_GETTEXTLENGTH $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_GETTEXTLENGTH" & @CRLF) ConsoleWrite(StringFormat("\tRET[%d]", $iRet) & @CRLF) Return $iRet Case $WM_GETTEXT $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ConsoleWrite("WM_GETTEXT" & @CRLF) ConsoleWrite(StringFormat("\tLenInclNull[%d]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tpBuff[0x%08x]", $lParam) & @CRLF) ConsoleWrite(StringFormat("\tRET[%d]", $iRet) & @CRLF) Return $iRet ;;;; Below affects the painting process - need Autoit proc to handle these. Case $WM_SETFOCUS $aRes = DllCallAddress("long", $pOrigBtnProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] ConsoleWrite("WM_SETFOCUS" & @CRLF) ConsoleWrite(StringFormat("\tPrevWin[0x%08x]", $wParam) & @CRLF) Return $iRet Case $WM_ERASEBKGND $aRes = DllCallAddress("long", $pOrigBtnProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] ConsoleWrite("WM_ERASEBKGND" & @CRLF) ConsoleWrite(StringFormat("\thDC[0x%08x]", $wParam) & @CRLF) ConsoleWrite(StringFormat("\tRET[%d]", $iRet) & @CRLF) Return $iRet Case $WM_NCPAINT $aRes = DllCallAddress("long", $pOrigBtnProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] ConsoleWrite("WM_NCPAINT" & @CRLF) ConsoleWrite(StringFormat("\tUpdateRegion[0x%08x]", $wParam) & @CRLF) Return $iRet Case $WM_PAINT $aRes = DllCallAddress("long", $pOrigBtnProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] ConsoleWrite("WM_PAINT" & @CRLF) Return $iRet Case $BM_SETSTATE $aRes = DllCallAddress("long", $pOrigBtnProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] ConsoleWrite("BM_SETSTATE" & @CRLF) ConsoleWrite(StringFormat("\tHilighted[%d]", $wParam) & @CRLF) Return $iRet Case Else $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) ;~ $aRes = DllCallAddress("long", $pOrigBtnProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) ;~ $iRet = $aRes[0] ConsoleWrite(StringFormat("msg: 0x%04x %-5s ret(%d) wparam( 0x%08x ) lparam( 0x%08x )", $uMsg, "(" & $uMsg & ")", $iRet, $wParam, $lParam) & @CRLF) Return $iRet EndSwitch EndFunc ;==>ButtonInspect Func _DispWinPos($pPos) Local $tPos = DllStructCreate($tagWINDOWPOS, $pPos) ConsoleWrite(StringFormat("\tInsertAfter [0x%0x8]", $tPos.InsertAfter) & @CRLF) ConsoleWrite(StringFormat("\tpos [%d %d %d %d]", $tPos.X, $tPos.Y, $tPos.CX, $tPos.CY) & @CRLF) ConsoleWrite(StringFormat("\tFlags [0x%0x8]", $tPos.InsertAfter) & @CRLF) EndFunc ;==>_DispWinPos Func WM_SYSCOMMAND($hWnd, $uMsg, $wParam, $lParam) If $wParam = $SC_MINIMIZE Then ConsoleWrite("---Start MIN---" & @CRLF) ElseIf $wParam = $SC_RESTORE Then ConsoleWrite("---Start Restore---" & @CRLF) EndIf EndFunc ;==>WM_SYSCOMMAND So run this > mouse over the control (it will jump) > then minimise > restore > esc (Exit). Next on line 58, uncomment _WinAPI_SetWindowPos & comment out GUICtrlSetPos I found the end result is near identical - except _WinAPI_SetWindowPos sends a WM_CHILDACTIVATE when moving the control (I doubt this matters) and WM_WINDOWPOSCHANGING has different coordinates after restoring. OK next uncomment 16 & 17, Comment out 19 & 20. Repeat the experiment. _WinAPI_SetWindowPos now works properly for minimize/restore (buttons now created with _GUICtrlButton_Create), and GUICtrlSetPos breaks totally. So I'm guessing Auitoit is keeping track of the controls that it creates, and is manually telling them where to go during the restore procedure. And I figure if we wanted to go deeper we could probably just wite our own restore func to test this... But I haven't got around to that just yet! Edit: Then again this seems inconsistent with what @Nine found with the external window - so maybe I'm still missing something.... Edited December 20, 2024 by MattyD clarity ioa747 1
MattyD Posted December 20, 2024 Author Posted December 20, 2024 (edited) Here's a simpler test. This time we're defining the main gui proc. When $bBypassAutoItHdlr = False then we're letting Autoit's message handler do its thing, otherwise we're bypassing it (That's my understanding anyway!). So we can see _WinAPI_SetWindowsPos() does indeed work with a minimize/restore when $bBypassAutoItHdlr = True. So I guess the next task is to find which messages introduce the behavior. expandcollapse popup#include <guiConstants.au3> #include <winapi.au3> Opt("MustDeclareVars", 1) Global Const $SC_MINIMIZE = 0xF020 Global Const $SC_RESTORE = 0xF120 Global Const $SC_CLOSE = 0xF060 Global $hGui = GUICreate("", 300, 200, 100, 100) Global $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80) Global $hBtn = GUICtrlGetHandle($idBtn) Global $hGUIProc = DllCallbackRegister("GUIProc", "long", "hwnd;uint;wparam;lparam") Global $pGUIProc = DllCallbackGetPtr($hGUIProc) Global $pOrigGUIProc = _WinAPI_SetWindowLong($hGUI, $GWL_WNDPROC, $pGUIProc) Global $bBypassAutoItHdlr = False GUISetState() _WinAPI_SetWindowPos($hBtn, $HWND_TOP, 80, 80, 100, 100, 0) ;~ GUICtrlSetPos($idBtn, 80, 80, 100, 100) While WinExists($hGUI) Sleep(10) WEnd Func guiProc($hWnd, $uMsg, $wParam, $lParam) Local $iRet, $aRes Switch $uMsg Case $WM_SYSCOMMAND Switch $wParam Case $SC_CLOSE $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) GUIDelete($hGUI) Case Else If $bBypassAutoItHdlr Then $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) Else $aRes = DllCallAddress("long", $pOrigGuiProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] EndIf EndSwitch Case $WM_DESTROY $aRes = DllCallAddress("long", $pOrigGuiProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] Case Else If $bBypassAutoItHdlr Then $iRet = _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) Else $aRes = DllCallAddress("long", $pOrigGuiProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) $iRet = $aRes[0] EndIf EndSwitch Return $iRet EndFunc Edited December 20, 2024 by MattyD
Nine Posted December 20, 2024 Posted December 20, 2024 (edited) Great investigations. Seems we can force the position of the button inside $WM_WINDOWPOSCHANGING message (by setting X, Y, CX and CY). I still haven't found the elegant way to set the right position at the right time, though. Got to go for now... Edit : this is what I got best so far... expandcollapse popup#include <guiConstants.au3> #include <winapi.au3> #include <MenuConstants.au3> Opt("MustDeclareVars", True) Global $hGUI, $bRestore Example() Func Example() $hGUI = GUICreate("WM_NCHITTEST", 300, 200, -1, -1, $WS_OVERLAPPEDWINDOW) Local $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80, $WS_CLIPSIBLINGS) Local $idBtn2 = GUICtrlCreateButton("Button 2", 90, 4, 80, 80, $WS_CLIPSIBLINGS) Local $idLockButtons = GUICtrlCreateCheckbox("Lock Buttons", 200, 20, 80, 20) Local $hDll = DllCallbackRegister(ButtonMoveProc, 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr') _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn) _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2) GUIRegisterMsg($WM_SYSCOMMAND, WM_SYSCOMMAND) GUISetState() Local $iMsg While True $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE ExitLoop Case $idLockButtons If GUICtrlRead($iMsg) = $GUI_CHECKED Then _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn) _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2) Else _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn, 0) _WinAPI_SetWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2, 0) EndIf Case $idBtn, $idBtn2 ConsoleWrite("Click " & GUICtrlRead($iMsg) & @CRLF) Case $GUI_EVENT_RESTORE $bRestore = False EndSwitch WEnd GUIDelete() _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn), DllCallbackGetPtr($hDll), $idBtn) _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($idBtn2), DllCallbackGetPtr($hDll), $idBtn2) DllCallbackFree($hDll) EndFunc ;==>Example Func ButtonMoveProc($hWnd, $iMsg, $wParam, $lParam, $iID, $iData) Local $tPos, $aPos, $iRet, $aPoint[2], $iSrc, $iEvent, $hCursor Switch $iMsg Case $WM_NCHITTEST $aPos = WinGetPos($hWnd) $aPoint[0] = BitAND($lParam, 0xFFFF) $aPoint[1] = BitShift($lParam, 16) $iRet = $HTCAPTION If $aPoint[0] - $aPos[0] < 10 Then $iRet = $HTLEFT If $aPoint[0] - $aPos[0] > ($aPos[2] - 10) Then $iRet = $HTRIGHT If $aPoint[1] - $aPos[1] < 10 Then Switch $iRet Case $HTLEFT $iRet = $HTTOPLEFT Case $HTRIGHT $iRet = $HTTOPRIGHT Case Else $iRet = $HTTOP EndSwitch ElseIf $aPoint[1] - $aPos[1] > ($aPos[3] - 10) Then Switch $iRet Case $HTLEFT $iRet = $HTBOTTOMLEFT Case $HTRIGHT $iRet = $HTBOTTOMRIGHT Case Else $iRet = $HTBOTTOM EndSwitch EndIf Return $iRet Case $WM_SETCURSOR $iSrc = BitAND($lParam, 0xFFFF) $iEvent = BitShift($lParam, 16) If $iSrc = $HTCAPTION And $iEvent = $WM_LBUTTONDOWN Then _WinAPI_RedrawWindow($hWnd, 0, 0, $RDW_INVALIDATE + $RDW_FRAME) $hCursor = _WinAPI_LoadCursor(0, $OCR_SIZEALL) _WinAPI_SetCursor($hCursor) Return True EndIf Case $WM_WINDOWPOSCHANGING If $bRestore Then ConsoleWrite("WM_WINDOWPOSCHANGING" & @CRLF) $tPos = DllStructCreate($tagWINDOWPOS, $lParam) $aPos = ControlGetPos($hGUI, "", $hWnd) ConsoleWrite($aPos[0] & "/" & $aPos[1] & "/" & $aPos[2] & "/" & $aPos[3] & @CRLF) $tPos.X = $aPos[0] $tPos.Y = $aPos[1] $tPos.CX = $aPos[2] $tPos.CY = $aPos[3] Return 0 EndIf EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>ButtonMoveProc Func WM_SYSCOMMAND($hWnd, $uMsg, $wParam, $lParam) If $wParam = $SC_RESTORE Then ConsoleWrite("---Start Restore---" & @CRLF) $bRestore = True EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_SYSCOMMAND Edited December 20, 2024 by Nine pixelsearch, ioa747 and MattyD 3 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
MattyD Posted December 20, 2024 Author Posted December 20, 2024 (edited) Nice Nine, but I'll do you one better - The trigger looks to be WM_SIZE, which makes sense. I'd say we've been fighting the mechanism behind control docking. We can ignore it though by using GuiRegisterMsg and returning anything but $GUI_RUNDEFMSG. Edit: or maybe its technically better to return _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) I've also changed the Main GUI style so you can resize the window. If you don't register $WM_SIZE you can see autoit's "default" behavior is that the button moves when you resize the window. expandcollapse popup#AutoIt3Wrapper_UseX64=N #include <guiConstants.au3> #include <winapi.au3> Opt("MustDeclareVars", 1) Global $hGui = GUICreate("", 300, 200, 100, 100, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX)) Global $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80) Global $hBtn = GUICtrlGetHandle($idBtn) Global $hBtnProc = DllCallbackRegister("btnProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $pBtnProc = DllCallbackGetPtr($hBtnProc) _WinAPI_SetWindowSubclass($hBtn, $pBtnProc, $idBtn) GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUISetState() Local $iMsg While 1 $iMsg = GUIGetMsg() switch $iMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func btnProc($hWnd, $uMsg, $wParam, $lParam, $uIdSubclasss, $dwRefData) local $iRet Switch $uMsg Case $WM_NCHITTEST $iRet = $HTCAPTION Case Else $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam) EndSwitch Return $iRet EndFunc Func WM_SIZE($hWnd, $uMsg, $wParam, $lParam) Return _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) EndFunc#include <guiConstants.au3> #include <winapi.au3> Opt("MustDeclareVars", 1) Global $hGui = GUICreate("", 300, 200, 100, 100, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX)) Global $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80) Global $hBtn = GUICtrlGetHandle($idBtn) Global $hBtnProc = DllCallbackRegister("BtnProc", "long", "hwnd;uint;wparam;lparam") Global $pBtnProc = DllCallbackGetPtr($hBtnProc) _WinAPI_SetWindowSubclass($hBtn,$pBtnProc, $idBtn) GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUISetState() Local $iMsg While 1 $iMsg = GUIGetMsg() switch $iMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func btnProc($hWnd, $uMsg, $wParam, $lParam) local $iRet Switch $uMsg Case $WM_NCHITTEST $iRet = $HTCAPTION Case Else $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam) EndSwitch Return $iRet EndFunc Func WM_SIZE($hWnd, $uMsg, $wParam, $lParam) Return _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) EndFunc Edited December 21, 2024 by MattyD
Nine Posted December 21, 2024 Posted December 21, 2024 Does not work for me : Quote !>20:19:39 AutoIt3 ended. rc:-1073740771 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
ioa747 Posted December 21, 2024 Posted December 21, 2024 neither to me !>03:32:51 AutoIt3 ended. rc:-1073740771 I know that I know nothing
MattyD Posted December 21, 2024 Author Posted December 21, 2024 (edited) Oops it was broken for Autoit x86 - I didn't register the callback correctly when I've moved from WindowSetLong to setwindowssubclass. I've updated the example. And here's one for @argumentum if I've done things correctly Hold shift to move/resize the controls. expandcollapse popup#include <guiConstants.au3> #include <winapi.au3> #include <misc.au3> Opt("MustDeclareVars", 1) Global $hGui = GUICreate("", 300, 200, 100, 100, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX)) Global $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80) Global $idBtn2 = GUICtrlCreateButton("Button 2", 90, 4, 80, 80) Global $hCursor = _WinAPI_CopyCursor(_WinAPI_LoadCursor(0, $OCR_CROSS)) Global $hBtn = GUICtrlGetHandle($idBtn) Global $hBtn2 = GUICtrlGetHandle($idBtn2) Global $hBtnProc = DllCallbackRegister("btnProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $pBtnProc = DllCallbackGetPtr($hBtnProc) _WinAPI_SetWindowSubclass($hBtn, $pBtnProc, $idBtn) _WinAPI_SetWindowSubclass($hBtn2, $pBtnProc, $idBtn2) GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUISetState() Local $iMsg While 1 $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE Exit Case $idBtn, $idBtn2 ConsoleWrite(GUICtrlRead($iMsg) & @CRLF) EndSwitch WEnd Func btnProc($hWnd, $uMsg, $wParam, $lParam, $uIdSubclasss, $dwRefData) Local $iRet Switch $uMsg Case $WM_NCHITTEST Local $aPoint[2] = [BitAND($lParam, 0xFFFF), BitShift($lParam, 16)] ;Mouse coords can be negative on edge cases! If BitAND($aPoint[0], 0x8000) Then $aPoint[0] = BitOR(0xFFFF0000, $aPoint[0]) If BitAND($aPoint[1], 0x8000) Then $aPoint[1] = BitOR(0xFFFF0000, $aPoint[1]) Local $aPos = WinGetPos($hWnd), $iMar = 10 If Not _IsPressed("10") Then $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam) Else $iRet = $HTCAPTION If $aPoint[0] - $aPos[0] < $iMar Then $iRet = $HTLEFT If $aPoint[0] - $aPos[0] > ($aPos[2] - $iMar) Then $iRet = $HTRIGHT If $aPoint[1] - $aPos[1] < $iMar Then Switch $iRet Case $HTLEFT $iRet = $HTTOPLEFT Case $HTRIGHT $iRet = $HTTOPRIGHT Case Else $iRet = $HTTOP EndSwitch ElseIf $aPoint[1] - $aPos[1] > ($aPos[3] - $iMar) Then Switch $iRet Case $HTLEFT $iRet = $HTBOTTOMLEFT Case $HTRIGHT $iRet = $HTBOTTOMRIGHT Case Else $iRet = $HTBOTTOM EndSwitch EndIf If $aPoint[0] < 0 Then $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam) If $aPoint[1] < 0 Then $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam) _WinAPI_RedrawWindow($hWnd) EndIf Case $WM_SETCURSOR Local $iSrc = BitAND($lParam, 0xFFFF), $iEvent = BitShift($lParam, 16) If $iSrc = $HTCAPTION And $iEvent = $WM_LBUTTONDOWN Then _WinAPI_SetCursor($hCursor) $iRet = 1 Else $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam) EndIf Case Else $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam) EndSwitch Return $iRet EndFunc ;==>btnProc Func WM_SIZE($hWnd, $uMsg, $wParam, $lParam) Return _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) EndFunc ;==>WM_SIZE Edited December 21, 2024 by MattyD argumentum and ioa747 2
argumentum Posted December 21, 2024 Posted December 21, 2024 1 hour ago, MattyD said: And here's one for @argumentum Thanks. My idea/wish, is to _WinAPI_SetWindowSubclass() and _WinAPI_RemoveWindowSubclass() at will, to any control. That would make it practical to use anywhere. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
Nine Posted December 21, 2024 Posted December 21, 2024 @MattyD Works great. Good job ! “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
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