Leaderboard
Popular Content
Showing content with the highest reputation on 01/04/2024 in all areas
-
This is based on this topic. With this UDF, you can define all the HotKeySet you want on any of the keyboards. The keys registered as HotKeySet are not sent to the active window. I also created a "Event-driven" mode for lengthy procedure. There is still the immediate action mode for short procedure. Note that in Event-driven mode, you will need to create an close loop to intercept the HotKey events. Events are asynchronous. In Event-driven mode only one procedure can be running at a given time. But immediate action procedure can interrupt a Event-driven procedure. All procedures are declared as actual function (without quotes). It is important that lengthy procedure should be declared as Event-driven, otherwise the system may become unstable. Version 2024-01-04 * Added support to {LEFT} and {RIGHT} keys * Added more information about keyboards in list * Added new parameter to _MKHKS_Initialize to exclude a specific keyboard from the list. To do so, you simply provide partial part (as a string) of the device name. Version 2024-01-03 * Added support to Send command, Hotkey must be set for the first keyboard. Version 2022-12-22 * Added support to register the same Hotkey on multiple keyboards (same or different functions) * Added possibility to unregister a Hotkey for a particular keyboard * Added validation on registering the same Hotkey twice It may happen that the list would provide more keyboards than they are actually connected. To exclude one particular keyboard, you could run the following example and test the hotkeys (0, 1, 2, ...) on each keyboard to see which ones are responding. Then you can provide partial string of the device to be excluded with the _MKHKS_Initialize function. #include "MKHKS-UDF.au3" Example() Func Example() HotKeySet("{END}", _Exit) Local $iNumKB = _MKHKS_Initialize() For $i = 0 To $iNumKB - 1 _MKHKS_Register_HotKey(String($i), _Test, $i, False) ; set hotkey to keyboard number (0, 1, 2,...) Next While Sleep(50) WEnd EndFunc ;==>Example Func _Exit() Exit EndFunc ;==>_Exit Func _Test() ConsoleWrite("Test succeeded - " & @HotKeyPressed & " was Key Pressed" & @CRLF) EndFunc ;==>_Test As usual if you have any suggestion, I would be very interested to hear them. MKHKS-UDF.zip1 point
-
Multiple Keyboards - HotKeySet - UDF
argumentum reacted to Nine for a topic
New version available. Solved previous issue and added support to exclude one particular keyboard.1 point -
There is also other issue. using: https://github.com/Danp2/au3WebDriver open wd_helper.au3 find any __WD_Error( try to jump into __WD_Error() In console you will see: It should jump to the coresponding line in wd_core.au3 file https://github.com/Danp2/au3WebDriver/blob/860eeb4e6a451465aeba7664686fe3adcbb803d8/wd_core.au3#L1656 For this reason I would like to add something like this: #SciTE4AutoIt3_AutoItAutocomplete_Internal=__WD_* to all of this files: https://github.com/Danp2/au3WebDriver/blob/master/wd_cdp.au3 https://github.com/Danp2/au3WebDriver/blob/master/wd_capabilities.au3 https://github.com/Danp2/au3WebDriver/blob/master/wd_helper.au31 point
-
I can see that this would be handy. @donnyh13 is talking about: https://github.com/mlipok/Au3LibreOffice/blob/main/LibreOfficeCalc_Internal.au3 I would like to add something like this: or even better something like: to all files below: btw. I had a similar situation a few days ago, luckily in my case it was enough to change the name of the function, because it was actually not "Internal"1 point
-
@ioa747 Thanks for reporting. I got same problem as you. As of now, it seems there is a special treatment by Windows for those 2 keys. I will need to investigate further although I still do not understand why Windows would do such a thing.1 point
-
Automating Notepad This example is a response to a request by mLipok for a simple Notepad automation. Task: Create a simple script to fill up "Edit1" with HelloWorld, click "Save As...", enter filename and finally save it to disc. This involves automating Notepad or more generally an Edit control, it involves automating a menu and a Save As dialog. Note that "Edit1" (from AutoIt Window Info tool) is not a valid control identification in UI Automation code. Do not open Notepad in advance. This will be done in the code. Start the code by opening Notepad and create the UI Automation object through IUIAutomation interface. I almost always create the Desktop element. Note how you first get a pointer to the element (GetRootElement method of $oUIAutomation object), and then creates the object that represents the element through IUIAutomationElement interface. UI Automation elements are nearly always created this way through a pointer. #include "..\..\Includes\CUIAutomation2.au3" Example() Func Example() ; Open Notepad Run( "Notepad" ) Sleep( 1000 ) ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtagIUIAutomation ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement( $pDesktop ) $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oDesktop ) Then Return ConsoleWrite( "$oDesktop ERR" & @CRLF ) ConsoleWrite( "$oDesktop OK" & @CRLF ) EndFunc Open Examples\Notepad\Notepad.au3 (empty) in SciTE. Add the code, run the code with F5 and leave Notepad open. Check that SciTE output is OK. Next step is to get the Notepad window as an UI Automation element. Open UIASpy (included in zip-file, keep UIASpy open throughout the entire example), place mouse cursor over Notepad title bar and press F2: (You can delete other windows in UIASpy by right-clicking treeview top windows (level one items).) $UIA_ClassNamePropertyId = "Notepad" is used to create a property condition to identify Notepad. Note that you can copy this line in UIASpy listview: Select the line in the listview, click "Right pane" item in main menu, click "Copy all or selected items to clipboard", paste the line into your code editor. Add this code to the existing code: ; --- Notepad window --- ConsoleWrite( "--- Notepad window ---" & @CRLF ) Local $pCondition ; Note that $UIA_ClassNamePropertyId maybe ia a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "Notepad", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pNotepad, $oNotepad $oDesktop.FindFirst( $TreeScope_Descendants, $pCondition, $pNotepad ) $oNotepad = ObjCreateInterface( $pNotepad, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oNotepad ) Then Return ConsoleWrite( "$oNotepad ERR" & @CRLF ) ConsoleWrite( "$oNotepad OK" & @CRLF ) EndFunc Note again how we first get a pointer to Notepad (FindFirst method of $oDesktop object, $oDesktop because the Desktop is the parent element of Notepad) and then creates the object. Also note that $oDesktop and $oNotepad are created in exactly the same way. Close the previous Notepad, run the code and leave Notepad open. Check that SciTE output is OK. Now, the actual automation starts: Fill up "Edit1" with HelloWorld. An automation task is almost always done in two or three steps: 1. Create condition to find element 2. Find the UI Automation element 3. Extract info or perform action Each of these steps can usually be done in 1 - 3 lines of UI Automation code. All three steps can usually be done in less that 10 lines of UI Automation code (common AutoIt debug/info code not included). To get the Notepad window above we only used two steps. The first automation task is to perform an action to fill out the Edit control with "HelloWorld". Place mouse cursor in the Edit control and press F1: (If there are two or more Notepad windows in UIASpy, you can delete the old windows (red) by right-clicking the treeview.) This time we can use $UIA_AutomationIdPropertyId = "15" to create a property condition to identify the Edit control. Add this code: ; --- Fill Edit element --- ConsoleWrite( "--- Fill Edit element ---" & @CRLF ) ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "15", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pEdit, $oEdit $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pEdit ) $oEdit = ObjCreateInterface( $pEdit, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oEdit ) Then Return ConsoleWrite( "$oEdit ERR" & @CRLF ) ConsoleWrite( "$oEdit OK" & @CRLF ) EndFunc $oNotepad.FindFirst means that the search for the Edit control starts in the Notepad window. $oEdit reprecents the Edit control. Close the previous Notepad, run the code and leave Notepad open. Check that SciTE output is OK. The Edit control must be filled with "HelloWorld". This is an action that has to be performed on the Edit control. The following actions are available: (Scroll down UIASpy listview to see Control Patterns (actions).) The interesting action or pattern here is the ValuePattern. The action is created and performed this way: Local $pValue, $oValue $oEdit.GetCurrentPattern( $UIA_ValuePatternId, $pValue ) $oValue = ObjCreateInterface( $pValue, $sIID_IUIAutomationValuePattern, $dtagIUIAutomationValuePattern ) If Not IsObj( $oValue ) Then Return ConsoleWrite( "$oValue ERR" & @CRLF ) ConsoleWrite( "$oValue OK" & @CRLF ) $oValue.SetValue( "HelloWorld" ) EndFunc $oEdit.GetCurrentPattern means that a pattern is created that performs actions on the Edit control. GetCurrentPattern method returns a pointer where from the ValuePattern object ($oValue) can be created. $UIA_ValuePatternId and the ValuePattern interface is defined in CUIAutomation2.au3. The $oValue object represents the ValuePattern interface for the Edit control. $oValue.SetValue( "HelloWorld" ) sets the text in the Edit control. An action or pattern is almost always created and performed this way. Add the code, close the previous Notepad, run the code and leave Notepad open. Open File menu. Place mouse cursor over the File menu and press F1: (Scroll down UIASpy listview to see Control Patterns (actions) in bottom of image.) ; --- Open File menu --- ConsoleWrite( "--- Open File menu ---" & @CRLF ) Local $pCondition1 $oUIAutomation.CreatePropertyCondition( $UIA_ControlTypePropertyId, $UIA_MenuItemControlTypeId, $pCondition1 ) If Not $pCondition1 Then Return ConsoleWrite( "$pCondition1 ERR" & @CRLF ) ConsoleWrite( "$pCondition1 OK" & @CRLF ) Local $pCondition2 ; $UIA_NamePropertyId is LOCALIZED and maybe CASE SENSITIVE $oUIAutomation.CreatePropertyCondition( $UIA_NamePropertyId, "File", $pCondition2 ) ; File <<<<<<<<<<<<<<<<<<<< If Not $pCondition2 Then Return ConsoleWrite( "$pCondition2 ERR" & @CRLF ) ConsoleWrite( "$pCondition2 OK" & @CRLF ) ; And condition $oUIAutomation.CreateAndCondition( $pCondition1, $pCondition2, $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pFile, $oFile $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pFile ) $oFile = ObjCreateInterface( $pFile, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oFile ) Then Return ConsoleWrite( "$oFile ERR" & @CRLF ) ConsoleWrite( "$oFile OK" & @CRLF ) Local $pInvoke, $oInvoke $oFile.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() Sleep( 100 ) EndFunc The Invoke action or pattern is used to click and open the File menu. Note the similarity between the code for InvokePattern and ValuePattern above. When a menu, dialog box or child window is opened it need some time to open. You must add a Sleep statement. Add the code, change "File" to the corresponding word in your own language (copy the word from the listview), close the previous Notepad (don't save), run the code and leave Notepad open. Click "Save As..." menu. If the File menu that was opened above is closed, then open it manually with a mouse click. Place mouse cursor over the "Save As..." menu and press F1: ; --- Click "Save As..." menu --- ConsoleWrite( "--- Click ""Save As..."" menu ---" & @CRLF ) ; Reuse $pCondition1 above ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "4", $pCondition2 ) If Not $pCondition2 Then Return ConsoleWrite( "$pCondition2 ERR" & @CRLF ) ConsoleWrite( "$pCondition2 OK" & @CRLF ) ; And condition $oUIAutomation.CreateAndCondition( $pCondition1, $pCondition2, $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pSaveAs, $oSaveAs $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pSaveAs ) $oSaveAs = ObjCreateInterface( $pSaveAs, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oSaveAs ) Then Return ConsoleWrite( "$oSaveAs ERR" & @CRLF ) ConsoleWrite( "$oSaveAs OK" & @CRLF ) $oSaveAs.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() Sleep( 1000 ) EndFunc Note how similar the "Open File menu" code and the "Click Save As... menu" code is. Note also the long Sleep because it's a "Save As" dialog with a large number of elements. Add the code, close the previous Notepad (don't save), run the code and leave Notepad and Save As open. Save As window. Place mouse cursor over Save As title bar and press F2: ; --- Save As window --- ConsoleWrite( "--- Save As window ---" & @CRLF ) ; Note that $UIA_ClassNamePropertyId maybe ia a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "#32770", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pSaveAsWin, $oSaveAsWin $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pSaveAsWin ) $oSaveAsWin = ObjCreateInterface( $pSaveAsWin, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oSaveAsWin ) Then Return ConsoleWrite( "$oSaveAsWin ERR" & @CRLF ) ConsoleWrite( "$oSaveAsWin OK" & @CRLF ) EndFunc The rest of the automation tasks is about the Save As window. Therefore we want to use the Save As window as the starting point. Not Notepad. Add the code, close the previous Save As and Notepad (don't save), run the code and leave Notepad and Save As open. Set File name. Place mouse cursor over File name Edit control and press F1: ; --- Set File name --- ConsoleWrite( "--- Set File name ---" & @CRLF ) ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "1001", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) $oSaveAsWin.FindFirst( $TreeScope_Descendants, $pCondition, $pEdit ) $oEdit = ObjCreateInterface( $pEdit, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oEdit ) Then Return ConsoleWrite( "$oEdit ERR" & @CRLF ) ConsoleWrite( "$oEdit OK" & @CRLF ) $oEdit.GetCurrentPattern( $UIA_ValuePatternId, $pValue ) $oValue = ObjCreateInterface( $pValue, $sIID_IUIAutomationValuePattern, $dtagIUIAutomationValuePattern ) If Not IsObj( $oValue ) Then Return ConsoleWrite( "$oValue ERR" & @CRLF ) ConsoleWrite( "$oValue OK" & @CRLF ) $oValue.SetValue( "HelloWorld.txt" ) EndFunc $oSaveAsWin.FindFirst searches in the Save As window. $oEdit is now the File name Edit control in the Save As window. The file name is set to "HelloWorld.txt". Add the code, close the previous Save As and Notepad (don't save), run the code and leave Notepad and Save As open. Click Save button. Place mouse cursor over Save button and press F1: ; --- Click Save button --- ConsoleWrite( "--- Click Save button ---" & @CRLF ) $oUIAutomation.CreatePropertyCondition( $UIA_ControlTypePropertyId, $UIA_ButtonControlTypeId, $pCondition1 ) If Not $pCondition1 Then Return ConsoleWrite( "$pCondition1 ERR" & @CRLF ) ConsoleWrite( "$pCondition1 OK" & @CRLF ) ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "1", $pCondition2 ) If Not $pCondition2 Then Return ConsoleWrite( "$pCondition2 ERR" & @CRLF ) ConsoleWrite( "$pCondition2 OK" & @CRLF ) ; And condition $oUIAutomation.CreateAndCondition( $pCondition1, $pCondition2, $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pSave, $oSave $oSaveAsWin.FindFirst( $TreeScope_Descendants, $pCondition, $pSave ) $oSave = ObjCreateInterface( $pSave, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oSave ) Then Return ConsoleWrite( "$oSave ERR" & @CRLF ) ConsoleWrite( "$oSave OK" & @CRLF ) $oSave.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() EndFunc Add the code, close the previous Save As and Notepad (don't save) and run the code. All code (Examples\Notepad\NotepadAll.au3): #include "..\..\Includes\CUIAutomation2.au3" Example() Func Example() ; Open Notepad Run( "Notepad" ) Sleep( 1000 ) ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtagIUIAutomation ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement( $pDesktop ) $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oDesktop ) Then Return ConsoleWrite( "$oDesktop ERR" & @CRLF ) ConsoleWrite( "$oDesktop OK" & @CRLF ) ; --- Notepad window --- ConsoleWrite( "--- Notepad window ---" & @CRLF ) Local $pCondition ; Note that $UIA_ClassNamePropertyId maybe ia a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "Notepad", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pNotepad, $oNotepad $oDesktop.FindFirst( $TreeScope_Descendants, $pCondition, $pNotepad ) $oNotepad = ObjCreateInterface( $pNotepad, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oNotepad ) Then Return ConsoleWrite( "$oNotepad ERR" & @CRLF ) ConsoleWrite( "$oNotepad OK" & @CRLF ) ; --- Fill Edit element --- ConsoleWrite( "--- Fill Edit element ---" & @CRLF ) ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "15", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pEdit, $oEdit $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pEdit ) $oEdit = ObjCreateInterface( $pEdit, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oEdit ) Then Return ConsoleWrite( "$oEdit ERR" & @CRLF ) ConsoleWrite( "$oEdit OK" & @CRLF ) Local $pValue, $oValue $oEdit.GetCurrentPattern( $UIA_ValuePatternId, $pValue ) $oValue = ObjCreateInterface( $pValue, $sIID_IUIAutomationValuePattern, $dtagIUIAutomationValuePattern ) If Not IsObj( $oValue ) Then Return ConsoleWrite( "$oValue ERR" & @CRLF ) ConsoleWrite( "$oValue OK" & @CRLF ) $oValue.SetValue( "HelloWorld" ) ; --- Open File menu --- ConsoleWrite( "--- Open File menu ---" & @CRLF ) Local $pCondition1 $oUIAutomation.CreatePropertyCondition( $UIA_ControlTypePropertyId, $UIA_MenuItemControlTypeId, $pCondition1 ) If Not $pCondition1 Then Return ConsoleWrite( "$pCondition1 ERR" & @CRLF ) ConsoleWrite( "$pCondition1 OK" & @CRLF ) Local $pCondition2 ; $UIA_NamePropertyId is LOCALIZED and maybe CASE SENSITIVE $oUIAutomation.CreatePropertyCondition( $UIA_NamePropertyId, "File", $pCondition2 ) ; File <<<<<<<<<<<<<<<<<<<< If Not $pCondition2 Then Return ConsoleWrite( "$pCondition2 ERR" & @CRLF ) ConsoleWrite( "$pCondition2 OK" & @CRLF ) ; And condition $oUIAutomation.CreateAndCondition( $pCondition1, $pCondition2, $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pFile, $oFile $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pFile ) $oFile = ObjCreateInterface( $pFile, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oFile ) Then Return ConsoleWrite( "$oFile ERR" & @CRLF ) ConsoleWrite( "$oFile OK" & @CRLF ) Local $pInvoke, $oInvoke $oFile.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() Sleep( 100 ) ; --- Click "Save As..." menu --- ConsoleWrite( "--- Click ""Save As..."" menu ---" & @CRLF ) ; Reuse $pCondition1 above ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "4", $pCondition2 ) If Not $pCondition2 Then Return ConsoleWrite( "$pCondition2 ERR" & @CRLF ) ConsoleWrite( "$pCondition2 OK" & @CRLF ) ; And condition $oUIAutomation.CreateAndCondition( $pCondition1, $pCondition2, $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pSaveAs, $oSaveAs $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pSaveAs ) $oSaveAs = ObjCreateInterface( $pSaveAs, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oSaveAs ) Then Return ConsoleWrite( "$oSaveAs ERR" & @CRLF ) ConsoleWrite( "$oSaveAs OK" & @CRLF ) $oSaveAs.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() Sleep( 1000 ) ; --- Save As window --- ConsoleWrite( "--- Save As window ---" & @CRLF ) ; Note that $UIA_ClassNamePropertyId maybe ia a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "#32770", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pSaveAsWin, $oSaveAsWin $oNotepad.FindFirst( $TreeScope_Descendants, $pCondition, $pSaveAsWin ) $oSaveAsWin = ObjCreateInterface( $pSaveAsWin, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oSaveAsWin ) Then Return ConsoleWrite( "$oSaveAsWin ERR" & @CRLF ) ConsoleWrite( "$oSaveAsWin OK" & @CRLF ) ; --- Set File name --- ConsoleWrite( "--- Set File name ---" & @CRLF ) ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "1001", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) $oSaveAsWin.FindFirst( $TreeScope_Descendants, $pCondition, $pEdit ) $oEdit = ObjCreateInterface( $pEdit, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oEdit ) Then Return ConsoleWrite( "$oEdit ERR" & @CRLF ) ConsoleWrite( "$oEdit OK" & @CRLF ) $oEdit.GetCurrentPattern( $UIA_ValuePatternId, $pValue ) $oValue = ObjCreateInterface( $pValue, $sIID_IUIAutomationValuePattern, $dtagIUIAutomationValuePattern ) If Not IsObj( $oValue ) Then Return ConsoleWrite( "$oValue ERR" & @CRLF ) ConsoleWrite( "$oValue OK" & @CRLF ) $oValue.SetValue( "HelloWorld.txt" ) ; --- Click Save button --- ConsoleWrite( "--- Click Save button ---" & @CRLF ) $oUIAutomation.CreatePropertyCondition( $UIA_ControlTypePropertyId, $UIA_ButtonControlTypeId, $pCondition1 ) If Not $pCondition1 Then Return ConsoleWrite( "$pCondition1 ERR" & @CRLF ) ConsoleWrite( "$pCondition1 OK" & @CRLF ) ; Note that $UIA_AutomationIdPropertyId is a STRING and maybe a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition( $UIA_AutomationIdPropertyId, "1", $pCondition2 ) If Not $pCondition2 Then Return ConsoleWrite( "$pCondition2 ERR" & @CRLF ) ConsoleWrite( "$pCondition2 OK" & @CRLF ) ; And condition $oUIAutomation.CreateAndCondition( $pCondition1, $pCondition2, $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pSave, $oSave $oSaveAsWin.FindFirst( $TreeScope_Descendants, $pCondition, $pSave ) $oSave = ObjCreateInterface( $pSave, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) If Not IsObj( $oSave ) Then Return ConsoleWrite( "$oSave ERR" & @CRLF ) ConsoleWrite( "$oSave OK" & @CRLF ) $oSave.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() EndFunc SciTE output: $oUIAutomation OK $oDesktop OK --- Notepad window --- $pCondition OK $oNotepad OK --- Fill Edit element --- $pCondition OK $oEdit OK $oValue OK --- Open File menu --- $pCondition1 OK $pCondition2 OK $pCondition OK $oFile OK $oInvoke OK --- Click "Save As..." menu --- $pCondition2 OK $pCondition OK $oSaveAs OK $oInvoke OK --- Save As window --- $pCondition OK $oSaveAsWin OK --- Set File name --- $pCondition OK $oEdit OK $oValue OK --- Click Save button --- $pCondition1 OK $pCondition2 OK $pCondition OK $oSave OK $oInvoke OK Maybe somebody can show how to implement such a Notepad automation with the functions in UIAWrappers.au3 and with classic code. Summary The two most important objects in UI Automation code are the $oUIAutomation and $oUIElement objects created from IUIAutomation and IUIAutomationElement interfaces. An UI Automation element object that represents a window or control is always created with the IUIAutomationElement interface through a pointer to the element object: $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) $oNotepad = ObjCreateInterface( $pNotepad, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) $oEdit = ObjCreateInterface( $pEdit, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) An UI Automation task is almost always done in two or three steps: 1. Create condition to find element 2. Find the UI Automation element 3. Extract info or perform action Each of these steps can usually be done in 1 - 3 lines of UI Automation code. All three steps can usually be done in less that 10 lines of UI Automation code (common AutoIt debug/info code not included). UI Automation actions (patterns) are performed through pattern interfaces, objects and methods. The code is nearly always implemented this way: Fill an Edit control: Local $pValue, $oValue $oEdit.GetCurrentPattern( $UIA_ValuePatternId, $pValue ) $oValue = ObjCreateInterface( $pValue, $sIID_IUIAutomationValuePattern, $dtagIUIAutomationValuePattern ) If Not IsObj( $oValue ) Then Return ConsoleWrite( "$oValue ERR" & @CRLF ) ConsoleWrite( "$oValue OK" & @CRLF ) $oValue.SetValue( "HelloWorld" ) $oEdit is an Edit control. The $oValue object represents the ValuePattern interface for the Edit control. $oValue.SetValue() sets the text in the Edit control. Click a menu item: Local $pInvoke, $oInvoke $oFile.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() Sleep( 100 ) $oFile is a File menu. The $oInvoke object represents the InvokePattern interface for the File menu. $oInvoke.Invoke() clicks the File menu. Sleep( 100 ) gives the File menu time to open. Click a button control: $oSave.GetCurrentPattern( $UIA_InvokePatternId, $pInvoke ) $oInvoke = ObjCreateInterface( $pInvoke, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern ) If Not IsObj( $oInvoke ) Then Return ConsoleWrite( "$oInvoke ERR" & @CRLF ) ConsoleWrite( "$oInvoke OK" & @CRLF ) $oInvoke.Invoke() $oSave is a Save button. The $oInvoke object represents the InvokePattern interface for the Save button. $oInvoke.Invoke() clicks the Save button. When writing UI Automation code, it's easiest to write the code in small steps and test the code after each step. Error management based on checking objects with IsObj() and ConsoleWrite() is required and sufficient. It's very rare necessary to use an actual object (COM) error handler. Too small Sleep times after a menu, dialog or window is opened is a common error.1 point