baconaise Posted January 20, 2023 Share Posted January 20, 2023 Good evening, I wrote a short program intended to help me determine Control IDs, but it crashes when I change the window focus to anything else. #include <GUIConstants.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) GUICreate("ControlID Decoder",300,115) GUISetFont(12) GUISetOnEvent($GUI_EVENT_CLOSE, "Decoder_Events") GUISetOnEvent($GUI_EVENT_MINIMIZE, "Decoder_Events") GUISetOnEvent($GUI_EVENT_RESTORE, "Decoder_Events") Global $Window_Label = GUICtrlCreateLabel("Active Window:",5,5,290,24) Global $ControlID_Label = GUICtrlCreateLabel("ControlID:",5,32,290,24) Global $X_Coord_Label = GUICtrlCreateLabel("X:",5,59,290,24) Global $Y_Coord_Label = GUICtrlCreateLabel("Y:",5,86,290,24) GUISetState(@SW_SHOW) While 1 Sleep(100) Local $Cursor_Info_Array = GUIGetCursorInfo("[active]") Local $Active_Window_Title = WinGetTitle("[active]") GUICtrlSetData($Window_Label, "Active Window: " & $Active_Window_Title) GUICtrlSetData($ControlID_Label, "ControlID: " & $Cursor_Info_Array[4]) GUICtrlSetData($X_Coord_Label, "X: " & $Cursor_Info_Array[0]) GUICtrlSetData($Y_Coord_Label, "Y: " & $Cursor_Info_Array[1]) WEnd Func Decoder_Events() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE Case @GUI_CtrlId = $GUI_EVENT_RESTORE EndSelect EndFunc If I comment out the CUICtrlSetData lines which contain $Cursor_Info_Array, the program does not crash. Scite doesn't seem to find any errors. Any ideas what I did wrong? Link to comment Share on other sites More sharing options...
pixelsearch Posted January 20, 2023 Share Posted January 20, 2023 Hi baconaise As you're not testing a possible @error returned by GUIGetCursorInfo, then I suggest this : expandcollapse popup#include <GUIConstants.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) Local $hGUI = GUICreate("ControlID Decoder",300,115, -1, -1, -1, $WS_EX_TOPMOST) GUISetFont(12) GUISetOnEvent($GUI_EVENT_CLOSE, "Decoder_Events") GUISetOnEvent($GUI_EVENT_MINIMIZE, "Decoder_Events") GUISetOnEvent($GUI_EVENT_RESTORE, "Decoder_Events") Global $Window_Label = GUICtrlCreateLabel("Active Window:",5,5,290,24) Global $ControlID_Label = GUICtrlCreateLabel("ControlID:",5,32,290,24) Global $X_Coord_Label = GUICtrlCreateLabel("X:",5,59,290,24) Global $Y_Coord_Label = GUICtrlCreateLabel("Y:",5,86,290,24) GUISetState(@SW_SHOW) While 1 Sleep(100) Local $Cursor_Info_Array = GUIGetCursorInfo($hGUI) ; If Not @error Then Local $Active_Window_Title = WinGetTitle("[active]") GUICtrlSetData($Window_Label, "Active Window: " & $Active_Window_Title) GUICtrlSetData($ControlID_Label, "ControlID: " & $Cursor_Info_Array[4]) GUICtrlSetData($X_Coord_Label, "X: " & $Cursor_Info_Array[0]) GUICtrlSetData($Y_Coord_Label, "Y: " & $Cursor_Info_Array[1]) ; EndIf WEnd Func Decoder_Events() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE Case @GUI_CtrlId = $GUI_EVENT_RESTORE EndSelect EndFunc Does it solve your issue ? Link to comment Share on other sites More sharing options...
baconaise Posted January 20, 2023 Author Share Posted January 20, 2023 Hi pixelsearch, That prevents the program from crashing when I switch windows, but it does not provide me GUIGetCursorInfo for any new windows I click. Given that I was intending to use this program to identify ControlIDs of other windows, I can't say it solves my issue. Thank you for trying. Link to comment Share on other sites More sharing options...
ioa747 Posted January 20, 2023 Share Posted January 20, 2023 46 minutes ago, baconaise said: but it does not provide me GUIGetCursorInfo for any new windows I click. Hi @baconaise Just i saw in help https://www.autoitscript.com/autoit3/docs/functions/GUIGetCursorInfo.htm The mouse cursor position is successful only on an window created by a GUICreate(). When no winhandle it will be successful if the GUI Windows is active. that doesn't pass with GUIGetCursorInfo("[active]") I know that I know nothing Link to comment Share on other sites More sharing options...
pixelsearch Posted January 20, 2023 Share Posted January 20, 2023 Back to 2005, @jpm words (developer) : To have valid info, the GuiGetCursorInfo returns info just on active windows related with the GUI you create. Link to comment Share on other sites More sharing options...
Nine Posted January 20, 2023 Share Posted January 20, 2023 8 hours ago, baconaise said: but it does not provide me GUIGetCursorInfo for any new windows I click. You can use the solution I provided then : baconaise 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 Link to comment Share on other sites More sharing options...
pixelsearch Posted January 21, 2023 Share Posted January 21, 2023 (edited) @Nine do you think the following script could be used as a 1st step ? It's based on your idea of using _WinAPI_WindowFromPoint() to retrieve any handle found at cursor position. expandcollapse popup; 1st script ; ========== #include <GDIPlus.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars', 1) HotKeySet("{ESC}", "_Quit") ; <=================== Global $hGUI, $hGraphic, $hPen _Main() Func _Main() Local $aMPos, $aWPos, $hWnd = 0, $hWnd_Old = -1 ; Create a transparent GUI covering the desktop $hGUI = GUICreate("GDI+", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) GUISetBkColor(0xABCDEF) _WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF) ; Create a structure that defines any point to be checked. Local $tPoint = DllStructCreate($tagPOINT) _GDIPlus_Startup() $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) $hPen = _GDIPlus_PenCreate(0xFFFF0000, 4) ; alpha channel = 0xFF (opaque), red = 0xFF0000, width = 4 (pixels) GUISetState(@SW_SHOW, $hGUI) While 1 $aMPos = MouseGetPos() DllStructSetData($tPoint, "x", $aMPos[0]) DllStructSetData($tPoint, "y", $aMPos[1]) $hWnd = _WinAPI_WindowFromPoint($tPoint) If $hWnd <> $hWnd_Old Then ; _WinAPI_RedrawWindow($hGUI) ; works with AutoIt 3.3.14.5, not with 3.3.16.1 ; e.g. ; _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE) ; flags 0x01 + 0x04 (default) ; _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE + $RDW_UPDATENOW) ; works with both versions of AutoIt ; _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE + $RDW_ERASENOW) ; works with both versions of AutoIt _GDIPlus_GraphicsClear($hGraphic, 0xFFABCDEF) ; Nine's way (works with both versions of AutoIt) $aWPos = WinGetPos($hWnd) _GDIPlus_GraphicsDrawRect($hGraphic, $aWPos[0], $aWPos[1], $aWPos[2], $aWPos[3], $hPen) ; ToolTip("Ctrl ID = " & _WinAPI_GetDlgCtrlID($hWnd)) ; shouldn't be used for top-level windows $hWnd_Old = $hWnd EndIf Sleep(10) WEnd EndFunc ;==>_Main Func _Quit() ; Clean up resources _GDIPlus_PenDispose($hPen) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_ShutDown() GUIDelete($hGUI) Exit EndFunc ;==>_Quit Edited January 25, 2023 by pixelsearch Reworked the flags of _WinAPI_RedrawWindow so the script runs on AutoIt 3.3.14.5 and 3.3.16.1 . Added Nine's way too. Nine 1 Link to comment Share on other sites More sharing options...
Nine Posted January 21, 2023 Share Posted January 21, 2023 @pixelsearch Nice job. Only thing with my setup (Win7, non-aero), the rectangle is only flashing a fraction of a second. Replacing _WinAPI_RedrawWindow with _GDIPlus_GraphicsClear solves the issue. “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 Link to comment Share on other sites More sharing options...
pixelsearch Posted January 21, 2023 Share Posted January 21, 2023 Houston, we have a problem The script from my precedent post runs differently, depending on the version of AutoIt we use : 1) AutoIt version 3.3.14.5 (2018) => result ok : The red rectangle drawn by the script appears clearly, stable, solid, and it will stay like this until the mouse hovers another window, then another red rectangle will surround the new window. 2) AutoIt versions 3.3.15.1 beta (2020) until AutoIt version 3.3.16.1 stable (2022) : result not ok : The red rectangle appears briefly, then disappears immediately, even when the mouse doesn't move (Nine uses AutoIt version 3.3.16.1 and noticed this behavior in his precedent post) 2 hours ago, Nine said: Replacing _WinAPI_RedrawWindow with _GDIPlus_GraphicsClear solves the issue. Sorry but I didn't find the way to make this change as the screen goes immediately black (or white) depending on the color used in _GDIPlus_GraphicsClear() during the loop. Could you please indicate the new line(s) that worked for you ? Thanks @jpm in case you read this, if you still have the stable version of AutoIt 3.3.14.5 (2018), could you please confirm there's something wrong, then I'll open a Trac ticket pointing to this post ? For the record, I already compared a couple of functions in both AutoIt versions (_WinAPI_RedrawWindow etc...) but didn't notice anything special. Also, the help file which indicates the changes between versions (including beta versions) doesn't show anything special (though I checked it maybe too quickly) Link to comment Share on other sites More sharing options...
pixelsearch Posted January 21, 2023 Share Posted January 21, 2023 I just experimented the flags of _WinAPI_RedrawWindow() and found this : * Their value is 5 by default, e.g. $RDW_INVALIDATE (0x0001) + $RDW_ERASE (0x0004) . * As 0x0001 + 0x0004 works fine with AutoIt 3.3.14.5 then I started to add blindly another value when running the script with AutoIt 3.3.16.1, bingo ! * If you add $RDW_UPDATENOW (0x0100) or if you add $RDW_ERASENOW (0x0200) then it works fine with both versions of AutoIt @Nine could you please test it with your version of AutoIt 3.3.16.1 and share your results ? _WinAPI_RedrawWindow($hGUI, 0, 0, 0x0001 + 0x0004 + 0x0100) ; or _WinAPI_RedrawWindow($hGUI, 0, 0, 0x0001 + 0x0004 + 0x0200) Thanks Link to comment Share on other sites More sharing options...
ioa747 Posted January 21, 2023 Share Posted January 21, 2023 (edited) now work Ver: 3.3.16.1 Edited April 2, 2023 by ioa747 del image pixelsearch 1 I know that I know nothing Link to comment Share on other sites More sharing options...
pixelsearch Posted January 21, 2023 Share Posted January 21, 2023 Thanks @ioa747 for testing I just read an interesting sentence found in Msdn page, concerning the RedrawWindow function : The following flags control when repainting occurs. RedrawWindow will not repaint unless one of these flags is specified : RDW_ERASENOW [...] RDW_UPDATENOW [...] These are the same 2 flags that I tested "blindly", it would have been a good idea to read msdn first ! Now I'm gonna update my initial post to add RDW_UPDATENOW (0x0100) . Even if both flags work (RDW_UPDATENOW and RDW_ERASENOW), maybe RDW_UPDATENOW is a better choice as it processes WM_PAINT "before the function returns". On the contrary $RDW_ERASENOW processes WM_PAINT messages "at the ordinary time", we'll see... Link to comment Share on other sites More sharing options...
Nine Posted January 21, 2023 Share Posted January 21, 2023 (edited) 4 hours ago, pixelsearch said: Sorry but I didn't find the way to make this change The color you specify in _GDIPlus_GraphicsClear needs to be the same as the transparent color you use (in my case I decided to use 0000FF instead of ABCDEF -- so it must be FF0000FF in GraphicClear). ps. I kind of busy right now -- I'll test your modification later, if you don't mind Edited January 21, 2023 by Nine pixelsearch 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 Link to comment Share on other sites More sharing options...
pixelsearch Posted January 21, 2023 Share Posted January 21, 2023 @Nine you're right, it works too when I use this line in the loop... _GDIPlus_GraphicsClear($hGraphic, 0xFFABCDEF) ...instead of : _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE + $RDW_UPDATENOW) Can you imagine I started the script with _GDIPlus_GraphicsClear() but I couldn't make it because of the wrong color parameter I indicated, so I switched to _WinAPI_RedrawWindow I'm gonna add your solution with _GDIPlus_GraphicsClear in the script above. Link to comment Share on other sites More sharing options...
Nine Posted January 22, 2023 Share Posted January 22, 2023 yep -- your new redraw works well for me. Just curious, what is the faster graphicClear or RedrawWindow ? “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 Link to comment Share on other sites More sharing options...
pixelsearch Posted January 22, 2023 Share Posted January 22, 2023 @Nine I don't find any difference of speed between the 3 of them (GraphicsClear, RedrawWindow using UPDATENOW, RedrawWindow using ERASENOW) they do the job at the speed of sound without flickering. Anyway it's good to have several solutions in case something turns bad one day. What could turn bad ? No idea, but I got an eye on this paragraph of the RedrawWindow function : By default, the windows affected by RedrawWindow depend on whether the specified window has the WS_CLIPCHILDREN style. Child windows that are not the WS_CLIPCHILDREN style are unaffected; non-WS_CLIPCHILDREN windows are recursively validated or invalidated until a WS_CLIPCHILDREN window is encountered. The following flags control which windows are affected by the RedrawWindow function. Flag Description RDW_ALLCHILDREN Includes child windows, if any, in the repainting operation. RDW_NOCHILDREN Excludes child windows, if any, from the repainting operation So for now, let's use... _GDIPlus_GraphicsClear() and see where it goes. At least we won't have flags to manage. And if GraphicsClear isn't enough for special cases, then we'll add more flags to RedrawWindow Link to comment Share on other sites More sharing options...
pixelsearch Posted January 25, 2023 Share Posted January 25, 2023 (edited) @Nine could you please have a look at these 2 pics : There are 19 child windows in the parent window ("Propriétés de l'affichage") 1) With my 1st script found above in this thread, I can highlight only 7 child windows out of 19, when the mouse is hovered over the controls. The windows I can't highlight are : * All windows found inside any groupbox control * The disabled button "Appliquer" found at the bottom right corner of the pic : this is because, as read on msdn : The WindowFromPoint function does not retrieve a handle to a hidden or disabled window, even if the point is within the window. 2) My 2nd script below highlights correctly all the child windows (19) when they're hovered over : expandcollapse popup; 2nd script ; ========== #include <GDIPlus.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> HotKeySet("{ESC}", "_Quit") ; <=================== Local $hWnd_old = 0 ; Create a structure that defines any point to be checked. $tPoint = DllStructCreate($tagPOINT) ; Create a transparent GUI covering the desktop $hGUI = GUICreate("Window viewer", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) GUISetBkColor(0xABCDEF) _WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF) _GDIPlus_Startup() $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) $hPen = _GDIPlus_PenCreate(0xFFFF0000, 4) ; alpha channel = 0xFF (opaque), red = 0xFF0000, width = 4 (pixels) GUISetState(@SW_SHOW, $hGUI) While 1 Local $aMPos = MouseGetPos() ; screen coords DllStructSetData($tPoint, "x", $aMPos[0]) DllStructSetData($tPoint, "y", $aMPos[1]) ; $hParent = _WinAPI_GetParent(_WinAPI_WindowFromPoint($tPoint)) ; BAD (returns the handle of hidden ClassName RunDLL on some disabled controls) $hParent = _WinAPI_GetAncestor(_WinAPI_WindowFromPoint($tPoint), $GA_PARENT) ; ok $hWnd = 0 $aChild = _WinAPI_EnumChildWindows($hParent) If Not @error Then For $i = 1 To $aChild[0][0] $hParent = _WinAPI_GetParent($aChild[$i][0]) $tPoint = _WinAPI_GetMousePos(True, $hParent) ; mouse coords relative to parent client area ; $hWnd = _WinAPI_WindowFromPoint($tPoint) ; BAD (returns the group control when mouse hovered over a control inside it... ; ...also a disabled window handle isn't retrieved with this function) ; $hWnd = _WinAPI_ChildWindowFromPoint($hParent, $tPoint) ; BAD (returns the group control) ; $hWnd = _WinAPI_ChildWindowFromPointEx($hParent, $tPoint) ; BAD (returns the group control) $hWnd = _WinAPI_RealChildWindowFromPoint($hParent, $tPoint) ; ok (even on disabled controls) . Function not found in AutoIt If $hWnd = $aChild[$i][0] Then $tRect = _WinAPI_GetWindowRect($hWnd) ExitLoop EndIf Next EndIf If $hWnd <> $hWnd_old Then _GDIPlus_GraphicsClear($hGraphic, 0xFFABCDEF) If $hWnd Then _GDIPlus_GraphicsDrawRect($hGraphic, $tRect.Left, $tRect.Top, _ $tRect.Right - $tRect.Left, $tRect.Bottom - $tRect.Top, $hPen) EndIf $hWnd_old = $hWnd EndIf Sleep(10) WEnd Func _Quit() ; Clean up resources _GDIPlus_PenDispose($hPen) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_ShutDown() GUIDelete($hGUI) Exit EndFunc ;==>_Quit ; #FUNCTION# ==================================================================================================================== ; Author.........: pixelsearch ; Modified.......: ; =============================================================================================================================== Func _WinAPI_RealChildWindowFromPoint($hWnd, $tPOINT) Local $aRet = DllCall('user32.dll', 'hwnd', 'RealChildWindowFromPoint', 'hwnd', $hWnd, 'struct', $tPOINT) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc ;==>_WinAPI_RealChildWindowFromPoint But there's still an issue : * The 1st script (WindowFromPoint only) could highlight the whole parent window when the mouse hovered over : => the parent title bar : great ! => the bottom of the parent window (at the left of the OK button) : also great ! => the disabled "Appliquer" button : very bad. * The 2nd script (WindowFromPoint + RealChildWindowFromPoint [this last function not found in AutoIt]) does the following when the mouse hovers over : => the parent title bar : highlights... the desktop (red rectangle surrounds the desktop) : bad => the bottom of the parent window (at the left of the OK button) : highlights the desktop :bad => the disabled "Appliquer" button : correctly highlighted, great ! Do you think there's an easy way to combine both scripts in a 3rd (and last) script so all functionalities could work correctly ? I'll try again from my side and post here if I find a solution. Thanks for reading Edit: I'm trying to do a full test (when windows are found between the hovered window and the Desktop, when the mouse hovers over the title bar or a place in the window which is not a control, when the mouse hovers over a disabled control etc...) . I'm studying all the handles returned by the different functions in these different scenarios. If something looks correct, then I'll report here in a new post. Edited January 25, 2023 by pixelsearch Link to comment Share on other sites More sharing options...
Nine Posted January 25, 2023 Share Posted January 25, 2023 Nice job again @pixelsearch I came up with this. What do you think ? expandcollapse popup#include <Array.au3> #include <GDIPlus.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars', 1) HotKeySet("{ESC}", "_Quit") ; <=================== Global $hGraphic, $hPen _Main() Func _Main() Local $hGUI = GUICreate("GDI+", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) GUISetBkColor(0x0000FF) _WinAPI_SetLayeredWindowAttributes($hGUI, 0x0000FF) Local $tPoint = DllStructCreate($tagPOINT) _GDIPlus_Startup() $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) $hPen = _GDIPlus_PenCreate(0xFFFF0000, 5) ; alpha channel = 0xFF (opaque), red = 0xFF0000, width = 5 (pixels) GUISetState() Local $hWnd, $hRoot, $hWnd2, $hWnd_Old = -1, $aWPos While True $tPoint = _WinAPI_GetMousePos() $hWnd = _WinAPI_WindowFromPoint($tPoint) $hWnd2 = GetRealChild($hWnd) If $hWnd2 And $hWnd <> $hWnd2 Then $hWnd = $hWnd2 If $hWnd <> $hWnd_Old Then _GDIPlus_GraphicsClear($hGraphic, 0xFF0000FF) $aWPos = WinGetPos($hWnd) _GDIPlus_GraphicsDrawRect($hGraphic, $aWPos[0], $aWPos[1], $aWPos[2], $aWPos[3], $hPen) $hWnd_Old = $hWnd EndIf Sleep(100) WEnd EndFunc ;==>_Main Func _Quit() ; Clean up resources _GDIPlus_PenDispose($hPen) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_Shutdown() Exit EndFunc ;==>_Quit Func _WinAPI_RealChildWindowFromPoint($hWnd, $tPoint) Local $aRet = DllCall('user32.dll', 'hwnd', 'RealChildWindowFromPoint', 'hwnd', $hWnd, 'struct', $tPoint) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc ;==>_WinAPI_RealChildWindowFromPoint Func GetRealChild($hWnd) Local $tPoint, $hRoot = _WinAPI_GetAncestor($hWnd, $GA_ROOT) If $hWnd = $hRoot Then $tPoint = _WinAPI_GetMousePos(True, $hWnd) Return _WinAPI_ChildWindowFromPointEx($hWnd, $tPoint) EndIf Local $hParent = _WinAPI_GetAncestor($hWnd, $GA_PARENT) Local $aChild = _WinAPI_EnumChildWindows($hParent) If @error Then Return 0 Local $hFound For $i = 1 To $aChild[0][0] $hParent = _WinAPI_GetParent($aChild[$i][0]) $tPoint = _WinAPI_GetMousePos(True, $hParent) $hFound = _WinAPI_RealChildWindowFromPoint($hParent, $tPoint) If $hFound = $aChild[$i][0] Then Return $hFound Next Return 0 EndFunc ;==>GetRealChild ioa747, SkysLastChance 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 Link to comment Share on other sites More sharing options...
pixelsearch Posted January 25, 2023 Share Posted January 25, 2023 @Nine bravo you did it, it works great and covers all cases. I'm gonna study carefully your code to find out how you did that. Thanks again for your help ioa747 1 Link to comment Share on other sites More sharing options...
pixelsearch Posted January 28, 2023 Share Posted January 28, 2023 (edited) @Nine there's one additional thing that could be improved. You certainly noticed what happens when the mouse hovers over... the red rectangle drawn by the script itself. It will start to flicker until the mouse is moved from there. Why does it flicker ? Because the red rectangle got its parent handle = $hGUI , so this red rectangle is immediately cleared as soon as it's hovered upon, followed by the immediate apparition of a red rectangle surrounding the GUI (e.g. around the desktop in our case) and this little game will repeat itself several times per second. To avoid this, one additional line in the script seems enough. Instead of... $hWnd = _WinAPI_WindowFromPoint($tPoint) $hWnd2 = GetRealChild($hWnd) ...we can change it to : $hWnd = _WinAPI_WindowFromPoint($tPoint) If $hWnd = $hGUI Then ContinueLoop $hWnd2 = GetRealChild($hWnd) Now it's not flickering anymore. For the record, I was about to do it the complicated way, e.g. by checking the position of the cursor compared to the position of the red rectangle : There are some interesting points in the 5 pics above (zoomed) which were created with the following code : $hPen = _GDIPlus_PenCreate (0xFFFF0000, 1) ; then 2, 3, 4, 5 _GDIPlus_GraphicsDrawRect($hGraphic, 3, 3, 10, 10, $hPen) 1) The 4 white squares are here just as a visual reminder of the original rectangle position, when the pen got a 1 pixel width. 2) When the pen width is 2, then an outer red rectangle of 1 pixel is added to the original one. 3) When the pen width is 3, then an inner red rectangle of 1 pixel is added to the original one. 4) 4 pixels => same as 2 (outer) 5) 5 pixels => same as 3 (inner) etc... This explains why the biggest rectangle placed at 0, 0 and surrounding the desktop displays only 3 pixels width (when $hpen width = 5), that's because 2 pixels are here but not visible, they're beyond the desktop limits as shown in pic 5 above (if we consider for a moment that the 4 white squares correspond exactly to the 4 corners of the desktop). I also noticed that even when creating the rectangle with a width and a height = 10, then you can see that in fact the width and the height are not 10 but 11 (in pic 1) Maybe it has something to do with what we read on msdn, GetWindowRect function ? Remarks In conformance with conventions for the RECT structure, the bottom-right coordinates of the returned rectangle are exclusive. In other words, the pixel at (right, bottom) lies immediately outside the rectangle. Or even in PtInRect function : The PtInRect function determines whether the specified point lies within the specified rectangle. A point is within a rectangle if it lies on the left or top side or is within all four sides. A point on the right or bottom side is considered outside the rectangle. Maybe... Edited January 28, 2023 by pixelsearch 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