NassauSky Posted April 12, 2020 Posted April 12, 2020 Hi all, 2 questions. I haven't worked with Windows Hooks in many years and have a simple question and deeper question. 1) There is an example of _WinAPI_SetWinEventHook at https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_SetWinEventHook.htm. I really don't see it doing anything but starting up Notepad on Window 10 (64). I see that with a certain even it might start up calc.exe.. What's the trick and what does it supposed to do. 2) I have a new project I'm working on that involves adding capturing when an external application changes focus from an edit box to a list view. SimpleSpy shows the class remains the same but on focus change I can distinguish each object from UIA_LocalizedControlType:= <edit> as opposed to UIA_LocalizedControlType:= <list>. I've tried so many things as far as traversing down the UI tree with UIASpy but that doesn't work so far. In the UI Automation method, the branch is hidden below 2 nodes named Pane with very little detail.. Using Microsoft Inspect.exe it detects the focus change between both objects. How might I capture the change or which object is selected if inspect. catches it. Thanks for any clues.
Moderators Melba23 Posted April 12, 2020 Moderators Posted April 12, 2020 Moved to the appropriate forum, as the AutoIt Example Scripts forum very clearly states: Quote Share your cool AutoIt scripts, UDFs and applications with others. Do not post general support questions here, instead use the AutoIt Help and Support forums. Moderation Team Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
junkew Posted April 12, 2020 Posted April 12, 2020 1. https://docs.microsoft.com/en-us/windows/win32/winmsg/about-hooks 2. There are many event examples on uia. If you catch them with that just print the parental tree to get an indication how to find it with a walker. FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
NassauSky Posted April 12, 2020 Author Posted April 12, 2020 (edited) My apologies @Melba and all. The creating a new post defaulted to the wrong thread. Thanks @junkew, I've been working with different techniques this week including your treewalker examples but there is only so far I can walk into the tree without deadlocking because of two subnodes with very little details. I'm not giving up yet 🙂 Any chance someone can answer my first question? What is the example of _WinAPI_SetWinEventHooksupposed on this site supposed to do? The example doesn't have a description or comments. Looking through it a few time, it looks like it's supposed to create a submenu called Calculator but I don't see it. Thanks Edited April 12, 2020 by NassauSky
Nine Posted April 12, 2020 Posted April 12, 2020 Ok lets start with the example, there is a "bug" in there that relates to OS language. In order to make it work, remove the line : If (_GUICtrlMenu_IsMenu($g_hMenu)) And (StringInStr(_GUICtrlMenu_GetItemText($g_hMenu, 0), 'Status Bar')) And (StringInStr(_WinAPI_GetWindowFileName($hWnd), 'notepad.exe')) Then and simply replace it with : If _GUICtrlMenu_IsMenu($g_hMenu) Then Now right click on Notepad and you should see the Calculator line at the end. As for your general question, please read MSDN API. It says : "Sets an event hook function for a range of events." To see the event list, go here. There is a very wide range of events that you can hook to (it could be a single PID like in the example) or all processes if you don't specify the PID. “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) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
markyrocks Posted April 12, 2020 Posted April 12, 2020 (edited) The dll callback register asigns the _eventproc() a pseudo function pointer that gets called when the hooked event happens. This is actually pretty cool bc I was actually wondering if function pointers were a thing in autoit. I'm assuming it opens notepad or whatever and waits for something to get clicked on and once the event happens, based on what the event is does something different in the function. Edited April 12, 2020 by markyrocks Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning"
NassauSky Posted April 12, 2020 Author Posted April 12, 2020 Thanks @Nine & @markyrocks, OK I got the example to work but still not seeing how it knows to add the Calculator to the "View" menu after Status Bar. On a side note I'm going to start playing with EVENT_OBJECT_FOCUS 0x8005 now.
NassauSky Posted April 12, 2020 Author Posted April 12, 2020 (edited) Ok thanks I figured out one part of the Windows Hook. Specifically the focus changing between the Editbox & the List I realized I might need something like the following to trace EVENT_OBJECT_FOCUS 0x8005 now. This works to just show me the events but doesn't show me the NAME or VALUE property of the focused event: expandcollapse popup#include <WindowsConstants.au3> #include <WinAPI.au3> #include <Process.au3> #include <Misc.au3> Global $hDLL, $hWinEventProc, $hHook HotKeySet("{ESC}", "_HotKey") ; Exit $hDLL = DllOpen("User32.dll") $hWinEventProc = DllCallbackRegister("_WinEventProc", "none", "hwnd;int;hwnd;long;long;int;int") if not @error then OnAutoItExitRegister("OnAutoItExit") Else MsgBox(16+262144,"Error","_SetWinEventHook did not succeed.") Exit endif $hHook = _SetWinEventHook($EVENT_OBJECT_FOCUS, $EVENT_OBJECT_FOCUS, $hDLL) ;Trace focus event only while 1 sleep(10) WEnd Func _WinEventProc($hHook, $iEvent, $hWnd, $idObject, $idChild, $iEventThread, $iEventTime) Local $PID = WinGetProcess($hWnd), $sEventProcName = _ProcessGetName($PID) ConsoleWrite("PID: " & $PID & @tab & "WinTitle: " & WinGetTitle($hWnd) & @tab & "EventTime: " & $iEventTime & @tab & @tab & "Event: " & $iEvent & @crlf) EndFunc ;==>_WinEventProc Func _SetWinEventHook($iEventMin, $iEventMax, $hDLLUser32) Local $aRet Local Const $WINEVENT_OUTOFCONTEXT = 0x0 Local Const $WINEVENT_SKIPOWNPROCESS = 0x2 If Not $hDLLUser32 Or $hDLLUser32 = -1 Then $hDLLUser32 = "User32.dll" $aRet = DllCall($hDLLUser32, "hwnd", "SetWinEventHook", _ "uint", $iEventMin, _ "uint", $iEventMax, _ "hwnd", 0, _ "ptr", DllCallbackGetPtr($hWinEventProc), _ "int", 0, _ "int", 0, _ "uint", BitOR($WINEVENT_OUTOFCONTEXT, $WINEVENT_SKIPOWNPROCESS)) If @error Then Return SetError(@error, 0, 0) Return $aRet[0] EndFunc ;==>_SetWinEventHook Func _HotKey() Switch @HotKeyPressed Case "{ESC}" Exit EndSwitch EndFunc ;==>_HotKey Func OnAutoItExit() If $hWinEventProc Then Beep(3000, 5) DllCallbackFree($hWinEventProc) EndIf If $hHook Then DllCall("User32.dll", "int", "UnhookWinEvent", "hwnd", $hHook) If $hDLL Then DllClose($hDLL) EndFunc ;==>OnAutoItExit This is what I've captured in Microsoft Inspect so I would figure Windows Messages are sending the Name & Value property somewhere that I'm not sure how it does it. expandcollapse popupMSAA: Howfound: Focus [o:Qc18341D98,c:0x0] hwnd=0x0008089A 32bit class="ChatWinClass" style=0x56000000 ex=0x10 ChildId: 0 Interfaces: Impl: Remote native IAccessible Name: "ChatMsg" Value: "Type message here" Role: editable text (0x2A) State: focused (0x4) Location: :1599,t:800,w:287,h:52 Selection: Error: calling getter for this property: hr=0x80004001 - Not implemented Description: Error: hr=0x80004001 - Not implemented Kbshortcut: Error: hr=0x80004001 - Not implemented Def/Action: Double-click Help: Error: hr=0x80004001 - Not implemented HelpTopic: "" ChildCount: 0 Window: 0x8089A FirstChild: Error: hr=0x80004001 - Not implemented LastChild: Error: hr=0x80004001 - Not implemented Next: Error: hr=0x80004001 - Not implemented Previous: Error: hr=0x80004001 - Not implemented Left: Error: hr=0x80004001 - Not implemented Up: Error: hr=0x80004001 - Not implemented Right: Error: hr=0x80004001 - Not implemented Down: Error: hr=0x80004001 - Not implemented Other Props: Object has no additional properties Children: Container has no children Ancestors: none: pane: normal none: pane: normal none: pane: normal "Chat Group": window: normal "Chat Group": window: focused,focusablefocusable "ChatContainer": window: normal "ChatContainer": window: focusable "ChtRightPanel": window: normal "ChtRightPanel": window: focusable "ChatX": client : focusable "ChatX": window: sizable,moveable,focusable "Desktop 1 ": client: focusable "Desktop 1 ": window: focusable No Parent Edited April 12, 2020 by NassauSky
Nine Posted April 12, 2020 Posted April 12, 2020 The way you wrote your script, you are capturing all OBJECT_FOCUS events. But you must know that if all objects have a handle and are ran under a process, not all objects have a window title. For example, a button has a handle, but it doesn't have a title. So you may need to get ancestors of the objects you are getting until you find a win title... “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) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
junkew Posted April 12, 2020 Posted April 12, 2020 Take a look also to the uia eventhandlers examples that @larsj has written. Uia eventhandling will in general be more stable then building it from scratch by using windows handlers directly. FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
NassauSky Posted April 12, 2020 Author Posted April 12, 2020 Thanks @junkew OK you gave me a route to take. I'll do some researching now adding the "event handling" keywords
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