pixelsearch Posted 17 hours ago Posted 17 hours ago (edited) Hello everybody I have a problem with GUIGetCursorInfo, not sure if it's a bug or not. Here is a script that shows it : expandcollapse popup#include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) Global $g_hGUI Example() Func Example() $g_hGUI = GUICreate("Main", 300, 300) WinSetTitle($g_hGUI, "", "Main " & $g_hGUI) Local $idLabel = GUICtrlCreateLabel("Label in Main", 0, 0, 150, 150, BitOr($SS_CENTERIMAGE, $SS_CENTER)) GUICtrlSetBkColor($idLabel, 0xFFFF00) ; yellow GUISetState(@SW_SHOW, $g_hGUI) Local $hChild = GUICreate("Child", 150, 150, 150, 150, $WS_CHILD, -1, $g_hGUI) GUISetBkColor(0x00FFFF, $hChild) ; blue GUISetState(@SW_SHOW, $hChild) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch _Hover() WEnd GuiDelete($hChild) GuiDelete($g_hGUI) EndFunc ;==>Example Func _Hover() Local $aInfo = GUIGetCursorInfo() If Not @error And $aInfo[4] Then Local Static $iInc2 = 0 $iInc2 +=1 If Not Mod($iInc2, 10) Then ConsoleWrite("Hovering over control #" & $aInfo[4] & " (" & $iInc2 & ")" & @crlf) EndIf EndIf EndFunc ;==>_Hover What happens when you hover over the label (yellow control) ? Nothing happens and the Console stays empty, unfortunately. But if you reverse the order of the 2 GUISetState(@SW_SHOW) like this... GUISetState(@SW_SHOW, $hChild) GUISetState(@SW_SHOW, $g_hGUI) ...now everything works and when you hover over the label, this is what you see in the Console : Hovering over control #3 (10) Hovering over control #3 (20) Hovering over control #3 (30) Hovering over control #3 (40) ... We discovered this strange behavior with @ioa747 yesterday, after this scenario in 4 acts : 1) Original script looked like this : Func Example() ... GUISetState(@SW_SHOW, $g_hGUI) GUISetState(@SW_SHOW, $hChild) ... _Hover() ... EndFunc Func _Hover() Local $aInfo = GUIGetCursorInfo($g_hGUI) ... EndFunc This works, because we indicate a [winhandle] parameter in GUIGetCursorInfo() The problem is that it works "too much" as ioa747 detected, because if you drag any external window over the GUI (try it with a small NotePad window) then the controls in the GUI keep reacting and you'll see in your Console : Hovering over control #3 (10) Hovering over control #3 (20) ... This is not acceptable, depending on the code associated to the hover process. Why are the controls in the GUI reacting when an external window is dragged over the GUI ? This is what the help file stipulates, topic GUIGetCursorInfo() If the "winhandle" parameter is used then the specified window becomes the new "current" window. This is exactly how we used GUIGetCursorInfo($g_hGUI) in our script and that's why the controls kept reacting when covered by an external window. So far, so good... 2) To quickly solve this issue, we started with this solution : Func Example() ... GUISetState(@SW_SHOW, $g_hGUI) GUISetState(@SW_SHOW, $hChild) ... If WinActive($g_hGUI) Then _Hover() ... EndFunc Func _Hover() Local $aInfo = GUIGetCursorInfo($g_hGUI) ... EndFunc This works, because the _Hover function will NOT be called when an external window is being dragged over the label control, as the external window will be active and not $g_hGUI Then I thought it was not normal to solve it that way and some digging needed to be done. 3) Let's look at the help file, to see what happens when no winhandle is used in GUIGetCursorInfo() When no winhandle, it will be successful if the GUI Windows is active That's exactly the script at the top of the post, which contains : Func Example() ... GUISetState(@SW_SHOW, $g_hGUI) GUISetState(@SW_SHOW, $hChild) ... _Hover() ... EndFunc Func _Hover() Local $aInfo = GUIGetCursorInfo() ... EndFunc But as you notice, it doesn't work, no matter the GUI is active (you can click on its title to make sure the GUI becomes active, or add WinActivate($g_hGUI) to make sure, or test with WinActive($g_hGUI) it will not work and the hover process will not be detected (tested on Windows 11 too) Maybe @jpm could read this to share his expertise : is there a bug (or not) in AutoIt, concerning this part 3 ? 4) Gladly, we found a solution, by reversing the order of the 2 GuiSetState(@SW_SHOW), like this : Func Example() ... GUISetState(@SW_SHOW, $hChild) GUISetState(@SW_SHOW, $g_hGUI) ... _Hover() ... EndFunc Func _Hover() Local $aInfo = GUIGetCursorInfo() ... EndFunc Now the hover process works and if an external window is dragged over the GUI, then the controls of the GUI don't react, great ! Of course, the issue will never happen if you got only 1 GUI in the script, as there will be only 1 GuiSetState(@SW_SHOW) . But when you got 2 Gui's or more... Thanks for reading and have a great evening Edited 16 hours ago by pixelsearch typo ioa747 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
Solution MattyD Posted 2 hours ago Solution Posted 2 hours ago (edited) Just reading through this - apologies if I've misunderstood the question!. GUIGetCursorInfo ( [winhandle] ) Parameters winhandle [optional] The handle of the window to use. If omitted the "current" window will be used. The "Current" window by default is the last GUI created no? So this fails: GUISetState(@SW_SHOW, $g_hGUI) GUISetState(@SW_SHOW, $hChild) But this should work: GUISetState(@SW_SHOW, $g_hGUI) GUISetState(@SW_SHOW, $hChild) GUISwitch($g_hGUI) Edit: I guess setting the state switches the current GUI as well - GuiSwitch returns the previous handle so it'll be easy to test! ConsoleWrite("Prev Window is the child? " & (GUISwitch($g_hGUI) = $hChild) & @CRLF) Edited 2 hours ago by MattyD pixelsearch 1
pixelsearch Posted 1 hour ago Author Posted 1 hour ago @MattyD you're right, when using GUIGetCursorInfo() without indicating a handle, then GuiSwitch() is the key to make sure that we'll use the correct "current" GUI Apparently we made it by reversing the 2 GUISetState (child before main) but it's more elegant with GuiSwitch() which should always be used in that case. Also we have to take care of what is written in the help file (remarks section of GUIGetCursorInfo) : When no winhandle it will be successful if the GUI Windows is active. So the "current" GUI must also be "active" or GUIGetCursorInfo() without handle won't react correctly. Can you imagine we went through all this, only because when you indicate a handle, e.g GUIGetCursorInfo($g_hGUI) , then any external window being dragged over the GUI triggers GUIGetCursorInfo($g_hGUI) and now... $aArray[4] = ID of the control that the mouse cursor is hovering over (or 0 if none) But we're not "directly" hovering over a control, there's an external window between the control and the mouse cursor. I wish $aArray[4] did return 0 in this case, when you're hovering "indirectly" over a control, or (why not) return... the negative value of the control MattyD 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
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