Jump to content

Recommended Posts

Posted

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
Posted

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

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Posted (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 by NassauSky
Posted

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.

Posted (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 by markyrocks
Posted (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:

#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.

MSAA:

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 by NassauSky
Posted

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...

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...