Popular Post MattyD Posted December 16 Popular Post Posted December 16 Hi all, I've just been playing with window messages that are sent to win32 controls themselves (rather than to the parent GUI), and it looks like you can do some cool stuff. So I thought I'd share some things that I found interesting. And yeah I know the code probably needs a cleanup - but I figure its good enough to get the point across... Anyway what I have is: while the "lock" checkbox is selected, the buttons behave normally. Otherwise you can drag them around and/or resize them. Because you're essentially dragging the buttons by their "Caption" bar, double clicking will also maximise them. expandcollapse popup#include <guiConstants.au3> #include <winapi.au3> Global Const $DLGC_BUTTON = 0x2000 Global Const $DLGC_WANTTAB = 0x0002 Global $hGui = GUICreate("", 300, 200) Global $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80) Global $idBtn2 = GUICtrlCreateButton("Button 2", 90, 4, 80, 80) Global $idLockButtons = GUICtrlCreateCheckbox("Lock Buttons", 200, 20, 80, 20) Global $hCursor = _WinAPI_CopyCursor(_WinAPI_LoadCursor(0, $OCR_CROSS)) Global $hBtnMoveProc = DllCallbackRegister("ButtonMoveProc", "long", "hwnd;uint;wparam;lparam") Global $pBtnMoveProc = DllCallbackGetPtr($hBtnMoveProc) Global $hBtn = GUICtrlGetHandle($idBtn) Global $hBtn2 = GUICtrlGetHandle($idBtn2) Global $pOrigBtnProc = _WinAPI_SetWindowLong($hBtn, $GWL_WNDPROC, $pBtnMoveProc) _WinAPI_SetWindowLong($hBtn2, $GWL_WNDPROC, $pBtnMoveProc) GUISetState() While 1 Local $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE Exit Case $idLockButtons _WinAPI_SetWindowLong($hBtn, $GWL_WNDPROC, (GUICtrlRead($iMsg) = $GUI_CHECKED) ? $pOrigBtnProc : $pBtnMoveProc) _WinAPI_SetWindowLong($hBtn2, $GWL_WNDPROC, (GUICtrlRead($iMsg) = $GUI_CHECKED) ? $pOrigBtnProc : $pBtnMoveProc) Case $idBtn, $idBtn2 ConsoleWrite("Click " & GUICtrlRead($iMsg) & @CRLF) EndSwitch WEnd Func ButtonMoveProc($hWnd, $uMsg, $wParam, $lParam) Local $aPos, $iRet, $aPoint[2], $iSrc, $iEvent Local $aRes = DllCallAddress("long", $pOrigBtnProc, "hwnd", $hWnd, "uint", $uMsg, "wparam", $wParam, "lparam", $lParam) Switch $uMsg 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_SetCursor($hCursor) Return True EndIf Case Else EndSwitch Return $aRes[0] ;~ Return _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam) EndFunc ;==>ButtonProc argumentum, AutoBert, Dan_555 and 3 others 6
Nine Posted Monday at 04:33 PM Posted Monday at 04:33 PM Very nice way to play with controls. Don't know if you have tried it, but FWIW it works also perfectly with _WinAPI_SetWindowSubclass. Just tested it with same result. 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
pixelsearch Posted Monday at 05:55 PM Posted Monday at 05:55 PM (edited) Very nice ! Do you guys can reproduce this : 1) Launch OP's script and drag button 2 over button 1 (first pic below) then drop (release mouse click) 2) Drag button 1 to the right (2nd pic) ... 3) ... then drop (3rd pic) I think we discussed this a couple of years ago (I'll try to find where) and there was a solution, maybe a style to add, can't remember. Edited Monday at 05:58 PM by pixelsearch typo
Nine Posted Monday at 06:42 PM Posted Monday at 06:42 PM (edited) yep got it. Here a way to solve it : 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 ps. it is not working all the times... pps. seems that solves the issue (changed code above) _WinAPI_RedrawWindow($hWnd, 0, 0, $RDW_INVALIDATE + $RDW_FRAME) Edited Monday at 07:09 PM by Nine argumentum, MattyD and pixelsearch 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
pixelsearch Posted Monday at 07:11 PM Posted Monday at 07:11 PM (edited) @Nine yes, Redraw did it. This is the part I just found in a personal script which uses Redraw too : ; Move the control until the mouse left button is released Do Sleep(10) $cInfo = GUIGetCursorInfo($hGui) ControlMove($hGui, "", $iControl, $cInfo[0] - $iSubtractX, $cInfo[1] - $iSubtractY) ; _WinAPI_RedrawWindow($hControl) DllCall($hDll, "bool", "RedrawWindow", "hwnd", $hControl, "struct*", 0, "handle", 0, "uint", 5) Until Not $cInfo[2] Edited Monday at 07:17 PM by pixelsearch typo
MattyD Posted Monday at 11:49 PM Author Posted Monday at 11:49 PM (edited) Another option is pass the message to the default message handler before returning. I'm not sure what other messages this kicks off or if they matter... Oops nevermind. this is not right! Edited Tuesday at 12:01 AM by MattyD
pixelsearch Posted Wednesday at 03:08 AM Posted Wednesday at 03:08 AM (edited) Hope this script will work for you as it works for me, no callback, no subclassing, no redraw, no nothing Both buttons seem to be draggable fluently, fingers crossed. expandcollapse popup#include <GUIConstantsEx.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Global $g_hGui Example() ;============================================== Func Example() Local $idBtn, $idBtn2, $aInfo $g_hGui = GUICreate("Drag Buttons", 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) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $GUI_EVENT_PRIMARYDOWN $aInfo = GUIGetCursorInfo($g_hGui) If (Not @error) And ($aInfo[4] = $idBtn Or $aInfo[4] = $idBtn2) Then _WinAPI_SetWindowPos(GUICtrlGetHandle($aInfo[4]), $HWND_TOP , 0, 0, 0, 0, $SWP_NOMOVE + $SWP_NOSIZE) _ControlMove() EndIf EndSwitch WEnd EndFunc ;==>Example ;============================================== Func _ControlMove() Local $aInfo, $idControl, $hControl, $aPos, $iSubtractX, $iSubtractY $aInfo = GUIGetCursorInfo($g_hGui) $idControl = $aInfo[4] ; +++ $hControl = GUICtrlGetHandle($idControl) $aPos = ControlGetPos($g_hGui, "", $idControl) $iSubtractX = $aInfo[0] - $aPos[0] $iSubtractY = $aInfo[1] - $aPos[1] Do $aInfo = GUIGetCursorInfo($g_hGui) ; ConsoleWrite($aInfo[4] & @crlf) ; varies from 3 => 4 => 3 => 4 ... while dragging ; https://www.autoitscript.com/forum/topic/211959-drag-and-drop-items-labels-vertically-among-themselves/?do=findComment&comment=1534654 ; ControlMove($g_hGui, "", $idControl, $aInfo[0] - $iSubtractX, $aInfo[1] - $iSubtractY) ; issue on Minimize GUICtrlSetPos($idControl, $aInfo[0] - $iSubtractX, $aInfo[1] - $iSubtractY) _WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0, $SWP_NOMOVE + $SWP_NOSIZE) Sleep(10) Until Not $aInfo[2] EndFunc ;==>_ControlMove Edited Wednesday at 11:48 AM by pixelsearch typo MattyD 1
Nine Posted Wednesday at 10:55 AM Posted Wednesday at 10:55 AM @pixelsearch If you move buttons, and then you minimize the GUI, when you restore the window, the buttons return to their original place...I need to remember where I saw that before. “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 Wednesday at 11:04 AM Posted Wednesday at 11:04 AM (edited) 21 minutes ago, Nine said: I need to remember where I saw that before. It was me. déjà vu Edit: Func _ControlMove() Local $aInfo, $idControl, $hControl, $aPos, $iSubtractX, $iSubtractY $aInfo = GUIGetCursorInfo($g_hGui) $idControl = $aInfo[4] ; +++ $hControl = GUICtrlGetHandle($idControl) $aPos = ControlGetPos($g_hGui, "", $idControl) $iSubtractX = $aInfo[0] - $aPos[0] $iSubtractY = $aInfo[1] - $aPos[1] Do $aInfo = GUIGetCursorInfo($g_hGui) ControlMove($g_hGui, "", $idControl, $aInfo[0] - $iSubtractX, $aInfo[1] - $iSubtractY) _WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0, $SWP_NOMOVE + $SWP_NOSIZE) Sleep(10) Until Not $aInfo[2] GUICtrlSetPos($idControl, $aInfo[0] - $iSubtractX, $aInfo[1] - $iSubtractY) EndFunc ;==>_ControlMove Edited Wednesday at 11:17 AM by ioa747 I know that I know nothing
Nine Posted Wednesday at 11:12 AM Posted Wednesday at 11:12 AM 7 minutes ago, ioa747 said: It was me Now I do ! “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 Wednesday at 11:13 AM Posted Wednesday at 11:13 AM (edited) @Nine yes I noted that inconvenience before I posted the script, but as it did same in OP's script... Another thing I noticed while scripting : if you add a ConsoleWrite inside the Do... Until loop : Do $aInfo = GUIGetCursorInfo($g_hGui) ConsoleWrite($aInfo[4] & @crlf) ; varies from 3 => 4 => 3 => 4 ... while dragging ControlMove($g_hGui, "", $idControl, $aInfo[0] - $iSubtractX, $aInfo[1] - $iSubtractY) _WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0, $SWP_NOMOVE + $SWP_NOSIZE) Sleep(10) Until Not $aInfo[2] ...then the Console display varies constantly from 3 to 4 while dragging (depending on the moment the controls overlap or not). That's why I had to ControlMove $idControl and not $aInfo[4]. It drove me nuts during the scripting phase, as I wanted to get rid of $idControl in the function (just to use $aInfo[4] everywhere) but the GUI display goes wrong when you try to ControlMove $aInfo[4] Concerning the Minimize / Restore inconvenience in both our scripts, I hope there will be a way to solve it. Edited Wednesday at 11:20 AM by pixelsearch typo
Nine Posted Wednesday at 11:19 AM Posted Wednesday at 11:19 AM Already did ! See @ioa747 thread ^^ “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 Wednesday at 11:36 AM Posted Wednesday at 11:36 AM Fantastic, thanks @Nine and @ioa747 I just updated my script above accordingly, to solve the Minimize / Restore inconvenience.
Nine Posted Wednesday at 11:38 AM Posted Wednesday at 11:38 AM (edited) Now as for @MattyD script, it is going to be harder to find an elegant solution... Edited Wednesday at 11:38 AM 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
pixelsearch Posted Wednesday at 11:58 AM Posted Wednesday at 11:58 AM (edited) I just added a $WS_OVERLAPPEDWINDOW style to the GUI (to test Maximize and Resize) $g_hGui = GUICreate("Drag Buttons", 300, 200, -1, -1, $WS_OVERLAPPEDWINDOW) ; https://www.autoitscript.com/trac/autoit/ticket/3877 : ; apply $WS_CLIPSIBLINGS style to both button controls (or $WS_EX_COMPOSITED as GUI extended style, as also suggested in Ticket 3877 ?) ; But $WS_EX_COMPOSITED worked fine until Win7 included, not sure it's 100% reliable on OS's >= Win8 $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80, $WS_CLIPSIBLINGS) $idBtn2 = GUICtrlCreateButton("Button 2", 90, 4, 80, 80, $WS_CLIPSIBLINGS) Please note how the GUI display goes wrong without the $WS_CLIPSIBLINGS style for both buttons, as discussed in Trac ticket 3877, which made @jpm add this sentence to AutoIt help file 3.3.16.1, topic GUICtrlCreateLabel If you really need to create a label that overlap other control you can set the style to $WS_CLIPSIBLINGS. In fact that has a little performance drawback [...] Edited Wednesday at 12:30 PM by pixelsearch
Nine Posted Wednesday at 12:23 PM Posted Wednesday at 12:23 PM With $WS_OVERLAPPEDWINDOW after you resize the window, moving a button makes it terribly flickering... “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 Wednesday at 12:29 PM Posted Wednesday at 12:29 PM (edited) @Nine even if you add the $WS_EX_COMPOSITED Gui extended style ? (also suggested in Ticket 3877) : $g_hGui = GUICreate("Drag Buttons", 300, 200, -1, -1, $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED) Edited Wednesday at 12:33 PM by pixelsearch
ioa747 Posted Wednesday at 12:34 PM Posted Wednesday at 12:34 PM (edited) @pixelsearch I teased it a little. Spoiler expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <WinAPISysWin.au3> #include <StaticConstants.au3> Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Example() ;============================================== Func Example() Local $hGui, $idBtn, $idBtn2, $hLbl, $aInfo $hGui = GUICreate("Drag Buttons", 300, 200, -1, -1, $WS_OVERLAPPEDWINDOW) $idBtn = GUICtrlCreateButton("Button 1", 4, 30, 80, 80, $WS_CLIPSIBLINGS) $idBtn2 = GUICtrlCreateButton("Button 2", 90, 30, 80, 80, $WS_CLIPSIBLINGS) $hLbl = GUICtrlCreateLabel("Label Test", 94, 4, 80, 15, BitOR($SS_CENTER, $WS_CLIPSIBLINGS)) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $GUI_EVENT_PRIMARYDOWN $aInfo = GUIGetCursorInfo($hGui) If (Not @error) And ($aInfo[4] = $idBtn Or $aInfo[4] = $idBtn2 Or $aInfo[4] = $hLbl) Then _ControlMove($hGui) EndIf EndSwitch WEnd EndFunc ;==>Example Func _ControlMove($hGui) If Not WinActive($hGui) Then Return Local $aInfo = GUIGetCursorInfo($hGui) Local $idControl = $aInfo[4] If $aInfo[4] = 0 Then Return ; Return if not control Local $aPos = ControlGetPos($hGui, "", $idControl) Local $iSubtractX = $aInfo[0] - $aPos[0] Local $iSubtractY = $aInfo[1] - $aPos[1] Local $iCursorId = MouseGetCursor() GUISetCursor(0, 1, $hGui) _WinAPI_SetWindowPos(GUICtrlGetHandle($idControl), $HWND_TOP, 0, 0, 0, 0, $SWP_NOMOVE + $SWP_NOSIZE) Local $aInfoNew = $aInfo Do $aInfo = GUIGetCursorInfo($hGui) If $aInfoNew[0] <> $aInfo[0] Or $aInfoNew[1] <> $aInfo[1] Then $aInfoNew = $aInfo GUICtrlSetPos($idControl, $aInfoNew[0] - $iSubtractX, $aInfoNew[1] - $iSubtractY) EndIf Sleep(10) Until Not $aInfo[2] GUISetCursor($iCursorId, 0, $hGui) EndFunc ;==>_ControlMove Edit: added GUISetCursor effect I added the Nine 's instructions, from below. Edited Wednesday at 01:16 PM by ioa747 update I know that I know nothing
Nine Posted Wednesday at 12:43 PM Posted Wednesday at 12:43 PM 7 minutes ago, pixelsearch said: even if you add the $WS_EX_COMPOSITED Gui extended style ? It is better. But it flickers quite a bit when moving slowly. This makes it very tolerable : While $aInfo[2] $aInfoNew = GUIGetCursorInfo($g_hGui) If $aInfoNew[0] <> $aInfo[0] Or $aInfoNew[1] <> $aInfo[1] Then GUICtrlSetPos($idControl, $aInfoNew[0] - $iSubtractX, $aInfoNew[1] - $iSubtractY) $aInfo = $aInfoNew EndIf WEnd “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 Wednesday at 01:53 PM Posted Wednesday at 01:53 PM (edited) At least we have now a few solutions : $WS_EX_COMPOSITED, $WS_CLIPSIBLINGS, your last code (Nine), also the fact that we won't need a resizable GUI in all cases etc... I guess if a user is interested in moving all controls inside a GUI for a display that suits him, then all controls coords and GUI coords (if resizable) should be saved before exiting the script (maybe in an ini file) When the script is run again, then : * If there is an associated ini file : use all coords for GUI & controls from the ini file. * If there isn't an associated ini file : use hard-coded default GUI & controls coords It should be easy to add a local variable $bMovingPhase to allow (or not) the controls moving phase. This variable should be present in all Case of main loop and could have its value modified through a checkbox control (as OP did), a menu option, a HotKey etc... We need it in all Case of main loop because when Case $GUI_EVENT_PRIMARYDOWN ends, then Case $idBtn2 is always triggered (if the user dragged & drop Button 2) Case $GUI_EVENT_PRIMARYDOWN If $bMovingPhase Then ; allow to move all controls when the variable is True ... EndIf Case $idBtn If $bMovingPhase Then ContinueLoop ConsoleWrite("Button 1 code" & @crlf) Case $idBtn2 If $bMovingPhase Then ContinueLoop ConsoleWrite("Button 2 code" & @crlf) Interesting thread indeed Edited Wednesday at 01:58 PM by pixelsearch typo
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