├── Examples ├── Example10_ExpandCollapsePattern.ahk ├── Example11_ScrollPatternScrollItemPattern.ahk ├── Example12_GridPatternGridItemPattern.ahk ├── Example13_TablePatternTableItemPattern.ahk ├── Example14_MultipleViewPattern.ahk ├── Example15_SelectionPatternSelectionItemPattern.ahk ├── Example16_WindowPatternTransformPattern.ahk ├── Example17_TextPatternTextRange.ahk ├── Example18_TextRangeTextChangedEvent.ahk ├── Example19_PropertyChangedEvent.ahk ├── Example1_Notepad.ahk ├── Example20_StructureChangedEvent.ahk ├── Example21_NotificationEvent.ahk ├── Example22_EventHandlerGroup.ahk ├── Example23_Caching.ahk ├── Example2_Notepad.ahk ├── Example3_Calculator.ahk ├── Example4_ChromeTest.ahk ├── Example5_ChromeGoogleTranslate.ahk ├── Example6_EdgeGoogle.ahk ├── Example7_FocusChangedEvent.ahk ├── Example8_SelectionEventHandler.ahk └── Example9_InvokePatternTogglePattern.ahk ├── LICENSE ├── Lib ├── UIA_Browser.ahk ├── UIA_Constants.ahk └── UIA_Interface.ahk ├── README.md ├── UIATreeInspector.ahk └── UIAViewer.ahk /Examples/Example10_ExpandCollapsePattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 4 | #Warn 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\ 13 | UIA := UIA_Interface() 14 | DriveGet, CDriveName, Label, C: 15 | CDriveName := CDriveName " (C:)" 16 | WinWaitActive, %CDriveName%,,1 17 | explorerEl := UIA.ElementFromHandle("A") 18 | CDriveEl := explorerEl.FindFirstByNameAndType(CDriveName, "TreeItem") 19 | if !CDriveEl { 20 | MsgBox, Drive C: element not found! Exiting app... 21 | ExitApp 22 | } 23 | 24 | ; expColPattern := CDriveEl.GetCurrentPatternAs("ExpandCollapse") ; Old method 25 | expColPattern := CDriveEl.ExpandCollapsePattern 26 | Sleep, 500 27 | MsgBox, % "ExpandCollapsePattern properties: " 28 | . "`nCurrentExpandCollapseState: " (state := expColPattern.ExpandCollapseState) " (" UIA_Enum.ExpandCollapseState(state) ")" 29 | 30 | MsgBox, Press OK to expand drive C: element 31 | expColPattern.Expand() 32 | Sleep, 500 33 | MsgBox, Press OK to collapse drive C: element 34 | expColPattern.Collapse() 35 | 36 | ExitApp 37 | -------------------------------------------------------------------------------- /Examples/Example11_ScrollPatternScrollItemPattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 4 | #Warn 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\ 13 | UIA := UIA_Interface() 14 | DriveGet, CDriveName, Label, C: 15 | CDriveName := CDriveName " (C:)" 16 | WinWaitActive, %CDriveName% 17 | explorerEl := UIA.ElementFromHandle("A") 18 | treeEl := explorerEl.FindFirstByType("Tree") 19 | 20 | MsgBox, % "For this example, make sure that the folder tree on the left side in File Explorer has some scrollable elements (make the window small enough)." 21 | scrollPattern := treeEl.ScrollPattern 22 | Sleep, 500 23 | MsgBox, % "ScrollPattern properties: " 24 | . "`nCurrentHorizontalScrollPercent: " scrollPattern.HorizontalScrollPercent ; If this returns an error about not existing, make sure you have the latest UIA_Interface.ahk 25 | . "`nCurrentVerticalScrollPercent: " scrollPattern.VerticalScrollPercent 26 | . "`nCurrentHorizontalViewSize: " scrollPattern.HorizontalViewSize 27 | . "`nCurrentHorizontallyScrollable: " scrollPattern.HorizontallyScrollable 28 | . "`nCurrentVerticallyScrollable: " scrollPattern.VerticallyScrollable 29 | Sleep, 50 30 | MsgBox, % "Press OK to set scroll percent to 50% vertically and 0% horizontally." 31 | scrollPattern.SetScrollPercent(,50) 32 | Sleep, 500 33 | MsgBox, % "Press OK to scroll a Page Up equivalent upwards vertically." 34 | scrollPattern.Scroll(, UIA.ScrollAmount_LargeDecrement) ; LargeDecrement is equivalent to pressing the PAGE UP key or clicking on a blank part of a scroll bar. SmallDecrement is equivalent to pressing an arrow key or clicking the arrow button on a scroll bar. 35 | 36 | Sleep, 500 37 | MsgBox, Press OK to scroll drive C: into view. 38 | CDriveEl := explorerEl.FindFirstByNameAndType(CDriveName, "TreeItem") 39 | if !CDriveEl { 40 | MsgBox, C: drive element not found! Exiting app... 41 | ExitApp 42 | } 43 | scrollItemPattern := CDriveEl.ScrollItemPattern 44 | scrollItemPattern.ScrollIntoView() 45 | 46 | ExitApp 47 | -------------------------------------------------------------------------------- /Examples/Example12_GridPatternGridItemPattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 4 | #Warn 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\ 13 | UIA := UIA_Interface() 14 | DriveGet, CDriveName, Label, C: 15 | CDriveName := CDriveName " (C:)" 16 | WinWaitActive, %CDriveName% 17 | explorerEl := UIA.ElementFromHandle("A") 18 | listEl := explorerEl.FindFirstByType("List") 19 | 20 | gridPattern := listEl.GridPattern 21 | Sleep, 500 22 | MsgBox, % "GridPattern properties: " 23 | . "`nCurrentRowCount: " gridPattern.RowCount 24 | . "`nCurrentColumnCount: " gridPattern.ColumnCount 25 | 26 | MsgBox, % "Getting grid item from row 4, column 1 (0-based indexing)" 27 | editEl := gridPattern.GetItem(3,0) 28 | MsgBox, % "Got this element: `n" editEl.Dump() 29 | 30 | gridItemPattern := editEl.GridItemPattern 31 | MsgBox, % "GridItemPattern properties: " 32 | . "`nCurrentRow: " gridItemPattern.Row 33 | . "`nCurrentColumn: " gridItemPattern.Column 34 | . "`nCurrentRowSpan: " gridItemPattern.RowSpan 35 | . "`nCurrentColumnSpan: " gridItemPattern.ColumnSpan 36 | ; gridItemPattern.CurrentContainingGrid should return listEl 37 | 38 | ExitApp 39 | -------------------------------------------------------------------------------- /Examples/Example13_TablePatternTableItemPattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 4 | #Warn 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\Windows 13 | UIA := UIA_Interface() 14 | WinWaitActive, Windows 15 | explorerEl := UIA.ElementFromHandle("A") 16 | listEl := explorerEl.FindFirstByType("List") 17 | 18 | tablePattern := listEl.TablePattern 19 | MsgBox, % "TablePattern properties: " 20 | . "`nCurrentRowOrColumnMajor: " tablePattern.CurrentRowOrColumnMajor 21 | 22 | 23 | rowHeaders := tablePattern.GetCurrentRowHeaders() 24 | rowHeadersDump := "" 25 | for _,header in rowHeaders 26 | rowHeadersDump .= header.Dump() "`n" 27 | MsgBox, % "TablePattern elements from GetCurrentRowHeaders:`n" rowHeadersDump ; Should be empty, there aren't any row headers 28 | columnHeaders := tablePattern.GetCurrentColumnHeaders() 29 | columnHeadersDump := "" 30 | for _,header in columnHeaders 31 | columnHeadersDump .= header.Dump() "`n" 32 | MsgBox, % "TablePattern elements from GetCurrentColumnHeaders:`n" columnHeadersDump 33 | 34 | editEl := listEl.GridPattern.GetItem(3,0) ; To test the TableItem pattern, we need to get an element supporting that using Grid pattern... 35 | tableItemPattern := editEl.TableItemPattern 36 | rowHeaderItems := tableItemPattern.GetCurrentRowHeaderItems() 37 | rowHeaderItemsDump := "" 38 | for _,headerItem in rowHeaderItems 39 | rowHeaderItemsDump .= headerItem.Dump() "`n" 40 | MsgBox, % "TableItemPattern elements from GetCurrentRowHeaderItems:`n" rowHeaderItemsDump ; Should be empty, there aren't any row headers 41 | columnHeaderItems := tableItemPattern.GetCurrentColumnHeaderItems() 42 | columnHeaderItemsDump := "" 43 | for _,headerItem in columnHeaderItems 44 | columnHeaderItemsDump .= headerItem.Dump() "`n" 45 | MsgBox, % "TableItemPattern elements from GetCurrentColumnHeaderItems:`n" columnHeaderItemsDump 46 | ExitApp 47 | -------------------------------------------------------------------------------- /Examples/Example14_MultipleViewPattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 4 | #Warn 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\ 13 | UIA := UIA_Interface() 14 | DriveGet, CDriveName, Label, C: 15 | CDriveName := CDriveName " (C:)" 16 | WinWaitActive, %CDriveName% 17 | explorerEl := UIA.ElementFromHandle("A") 18 | listEl := explorerEl.FindFirstByType("List") 19 | 20 | mvPattern := listEl.GetCurrentPatternAs("MultipleView") 21 | MsgBox, % "MultipleView properties: " 22 | . "`nCurrentCurrentView: " (currentView := mvPattern.CurrentCurrentView) 23 | 24 | supportedViews := mvPattern.GetCurrentSupportedViews() 25 | viewNames := "" 26 | for _, view in supportedViews { 27 | viewNames .= mvPattern.GetViewName(view) " (" view ")`n" 28 | } 29 | MsgBox, % "This MultipleView supported views:`n" viewNames 30 | MsgBox, % "Press OK to set MultipleView to view 4." 31 | mvPattern.SetCurrentView(4) 32 | 33 | Sleep, 500 34 | MsgBox, % "Press OK to reset back to view " currentView "." 35 | mvPattern.SetCurrentView(currentView) 36 | 37 | ExitApp 38 | -------------------------------------------------------------------------------- /Examples/Example15_SelectionPatternSelectionItemPattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 4 | #Warn 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\ 13 | UIA := UIA_Interface() 14 | DriveGet, CDriveName, Label, C: 15 | CDriveName := CDriveName " (C:)" 16 | WinWaitActive, %CDriveName% 17 | explorerEl := UIA.ElementFromHandle("A") 18 | listEl := explorerEl.FindFirstByType("List") 19 | 20 | selectionPattern := listEl.SelectionPattern ; Getting a pattern this way will get exactly that pattern. By default, GetCurrentPattern() will get the highest pattern available (for example SelectionPattern2 might also be available). 21 | MsgBox, % "SelectionPattern properties: " 22 | . "`nCurrentCanSelectMultiple: " selectionPattern.CurrentCanSelectMultiple 23 | . "`nCurrentIsSelectionRequired: " selectionPattern.CurrentIsSelectionRequired 24 | 25 | currentSelectionEls := selectionPattern.GetCurrentSelection() 26 | currentSelections := "" 27 | for index,selection in currentSelectionEls 28 | currentSelections .= index ": " selection.Dump() "`n" 29 | 30 | windowsListItem := explorerEl.FindFirstByNameAndType("Windows", "ListItem") 31 | selectionItemPattern := windowsListItem.GetCurrentPatternAs("SelectionItem") 32 | MsgBox, % "ListItemPattern properties for Windows folder list item:" 33 | . "`nCurrentIsSelected: " selectionItemPattern.CurrentIsSelected 34 | . "`nCurrentSelectionContainer: " selectionItemPattern.CurrentSelectionContainer.Dump() 35 | 36 | MsgBox, % "Press OK to select ""Windows"" folder list item." 37 | selectionItemPattern.Select() 38 | MsgBox, % "Press OK to add to selection ""Program Files"" folder list item." 39 | explorerEl.FindFirstByNameAndType("Program Files", "ListItem").SelectionItemPattern.AddToSelection() 40 | MsgBox, % "Press OK to remove selection from ""Windows"" folder list item." 41 | selectionItemPattern.RemoveFromSelection() 42 | 43 | ExitApp 44 | -------------------------------------------------------------------------------- /Examples/Example16_WindowPatternTransformPattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 4 | #Warn 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\ 13 | UIA := UIA_Interface() 14 | DriveGet, CDriveName, Label, C: 15 | CDriveName := CDriveName " (C:)" 16 | WinWaitActive, %CDriveName% 17 | explorerEl := UIA.ElementFromHandle("A") 18 | windowPattern := explorerEl.WindowPattern 19 | Sleep, 500 20 | MsgBox, % "WindowPattern properties: " 21 | . "`nCurrentCanMaximize: " windowPattern.CurrentCanMaximize 22 | . "`nCurrentCanMinimize: " windowPattern.CurrentCanMinimize 23 | . "`nCurrentIsModal: " windowPattern.CurrentIsModal 24 | . "`nCurrentIsTopmost: " windowPattern.CurrentIsTopmost 25 | . "`nCurrentWindowVisualState: " (visualState := windowPattern.CurrentWindowVisualState) " (" UIA_Enum.WindowVisualState(visualState) ")" 26 | . "`nCurrentWindowInteractionState: " (interactionState := windowPattern.CurrentWindowInteractionState) " (" UIA_Enum.WindowInteractionState(interactionState) ")" 27 | Sleep, 50 28 | MsgBox, Press OK to try minimizing 29 | windowPattern.SetWindowVisualState(UIA_Enum.WindowVisualState_Minimized) 30 | 31 | Sleep, 500 32 | MsgBox, Press OK to bring window back to normal 33 | windowPattern.SetWindowVisualState(UIA_Enum.WindowVisualState_Normal) 34 | 35 | transformPattern := explorerEl.TransformPattern ; Note: for some reason TransformPattern2 doesn't extend TransformPattern properties/methods. If we called GetCurrentPatternAs("Transform"), we would get TransformPattern2 and wouldn't be able to access these properties and methods. Thats why previously we could use GetCurrentPatternAs("Window") instead of GetCurrentPatternAs("WindowPattern"), but here we need GetCurrentPatternAs("TransformPattern") to get TransformPattern explicitly. 36 | Sleep, 500 37 | MsgBox, % "TransformPattern properties: " 38 | . "`nCurrentCanMove: " transformPattern.CurrentCanMove 39 | . "`nCurrentCanResize: " transformPattern.CurrentCanResize 40 | . "`nCurrentCanRotate: " transformPattern.CurrentCanRotate 41 | 42 | MsgBox, Press OK to move to coordinates x100 y200 43 | transformPattern.Move(100,200) 44 | 45 | Sleep, 500 46 | MsgBox, Press OK to resize to w600 h400 47 | transformPattern.Resize(600,400) 48 | 49 | Sleep, 500 50 | MsgBox, Press OK to close window 51 | windowPattern.Close() 52 | ExitApp 53 | -------------------------------------------------------------------------------- /Examples/Example17_TextPatternTextRange.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | 8 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 9 | #include ..\Lib\UIA_Interface.ahk 10 | 11 | lorem = 12 | ( 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 14 | ) 15 | 16 | Run notepad.exe 17 | ;WinActivate, ahk_exe notepad.exe 18 | UIA := UIA_Interface() 19 | WinWaitActive, ahk_exe notepad.exe 20 | Sleep, 40 21 | ;MsgBox, % UIA.TextPatternRangeEndpoint_Start " " UIA.TextPatternRangeEndpoint_End " " UIA.TextUnit_Character 22 | NotepadEl := UIA.ElementFromHandle("ahk_exe notepad.exe") 23 | editEl := NotepadEl.FindFirstBy("ControlType=Document OR ControlType=Edit") ; Get the Edit or Document element (differs between UIAutomation versions) 24 | if !editEl { 25 | ; Windows 11 has broken Notepad so that the Document element isn't findable; instead get it by the ClassNN 26 | ControlGet, hWnd, Hwnd,, RichEditD2DPT1 27 | editEl := UIA.ElementFromHandle(hWnd) 28 | } 29 | editEl.Value := lorem ; Set the text to our sample text 30 | textPattern := editEl.TextPattern ; Get the TextPattern 31 | 32 | MsgBox, % "TextPattern properties:" 33 | . "`nDocumentRange: returns the TextRange for all the text inside the element" 34 | . "`nSupportedTextSelection: " textPattern.SupportedTextSelection 35 | . "`n`nTextPattern methods:" 36 | . "`nRangeFromPoint(x,y): retrieves an empty TextRange nearest to the specified screen coordinates" 37 | . "`nRangeFromChild(child): retrieves a text range enclosing a child element such as an image, hyperlink, Microsoft Excel spreadsheet, or other embedded object." 38 | . "`nGetSelection(): returns the currently selected text" 39 | . "`nGetVisibleRanges(): retrieves an array of disjoint text ranges from a text-based control where each text range represents a contiguous span of visible text" 40 | 41 | wholeRange := textPattern.DocumentRange ; Get the TextRange for all the text inside the Edit element 42 | 43 | MsgBox, % "To select a certain phrase inside the text, use FindText() method to get the corresponding TextRange, then Select() to select it.`n`nPress OK to select the text ""dolor sit amet""" 44 | WinActivate, ahk_exe notepad.exe 45 | wholeRange.FindText("dolor sit amet").Select() 46 | Sleep, 1000 47 | 48 | ; For the next example we need to clone the TextRange, because some methods change the supplied TextRange directly (here we don't want to change our original wholeRange TextRange). An alternative would be to use wholeRange, and after moving the endpoints and selecting the new range, we could call ExpandToEnclosingUnit() to reset the endpoints and get the whole TextRange back 49 | textSpan := wholeRange.Clone() 50 | 51 | MsgBox, % "To select a span of text, we need to move the endpoints of the TextRange. This can be done with MoveEndpointByUnit.`n`nPress OK to select the text with startpoint of 28 characters from start`nand 390 characters from the end of the sample text" 52 | WinActivate, ahk_exe notepad.exe 53 | textSpan.MoveEndpointByUnit(UIA.TextPatternRangeEndpoint_Start, UIA.TextUnit_Character, 28) ; Move 28 characters from the start of the sample text 54 | textSpan.MoveEndpointByUnit(UIA.TextPatternRangeEndpoint_End, UIA.TextUnit_Character, -390) ; Move 390 characters backwards from the end of the sample text 55 | textSpan.Select() 56 | Sleep, 1000 57 | 58 | MsgBox, % "We can also get the location of texts. Press OK to test it" 59 | br := wholeRange.GetBoundingRectangles() 60 | for _, v in br { 61 | RangeTip(v.x, v.y, v.w, v.h) 62 | Sleep, 1000 63 | } 64 | RangeTip() 65 | 66 | ExitApp 67 | 68 | RangeTip(x:="", y:="", w:="", h:="", color:="Red", d:=2) ; from the FindText library, credit goes to feiyue 69 | { 70 | local 71 | static id:=0 72 | if (x="") 73 | { 74 | id:=0 75 | Loop 4 76 | Gui, Range_%A_Index%: Destroy 77 | return 78 | } 79 | if (!id) 80 | { 81 | Loop 4 82 | Gui, Range_%A_Index%: +Hwndid +AlwaysOnTop -Caption +ToolWindow 83 | -DPIScale +E0x08000000 84 | } 85 | x:=Floor(x), y:=Floor(y), w:=Floor(w), h:=Floor(h), d:=Floor(d) 86 | Loop 4 87 | { 88 | i:=A_Index 89 | , x1:=(i=2 ? x+w : x-d) 90 | , y1:=(i=3 ? y+h : y-d) 91 | , w1:=(i=1 or i=3 ? w+2*d : d) 92 | , h1:=(i=2 or i=4 ? h+2*d : d) 93 | Gui, Range_%i%: Color, %color% 94 | Gui, Range_%i%: Show, NA x%x1% y%y1% w%w1% h%h1% 95 | } 96 | } -------------------------------------------------------------------------------- /Examples/Example18_TextRangeTextChangedEvent.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | 8 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 9 | #include ..\Lib\UIA_Interface.ahk 10 | 11 | MsgBox, % "To test this file, create a new Word document (with the title ""Document1 - Word"") and write some sample text in it." 12 | 13 | UIA := UIA_Interface() ; Initialize UIA interface 14 | program := "Document1 - Word" 15 | WinActivate, %program% 16 | WinWaitActive, %program% 17 | wordEl := UIA.ElementFromHandle(program) 18 | bodyEl := wordEl.FindFirstBy("AutomationId=Body") ; First get the body element of Word 19 | textPattern := bodyEl.GetCurrentPatternAs("Text") ; Get TextPattern for the body element 20 | document := textPattern.DocumentRange ; Get the TextRange for the whole document 21 | 22 | MsgBox, % "Current text inside Word body element:`n" document.GetText() ; Display the text from the TextRange 23 | WinActivate, %program% 24 | 25 | MsgBox, % "We can get text from a specific attribute, such as text within a ""bullet list"".`nTo test this, create a bullet list (with filled bullets) in Word and press OK." 26 | MsgBox, % "Found the following text in bullet list:`n" document.FindAttribute(UIA_Enum.UIA_BulletStyleAttributeId, UIA_Enum.BulletStyle_FilledRoundBullet).GetText() 27 | 28 | Loop { 29 | InputBox, font, Find, % "Search text in Word by font. Type some example text in Word.`nThen write a font (such as ""Calibri"") and press OK`n`nNote that this is case-sensitive, and fonts start with a capital letter`n(""calibri"" is not the same as ""Calibri"")" 30 | if ErrorLevel 31 | break 32 | else if !font 33 | MsgBox, You need to type a font to search! 34 | else if (found := document.FindAttribute(UIA_Enum.UIA_FontNameAttributeId, font).GetText()) 35 | MsgBox, % "Found the following text:`n" found 36 | else 37 | MsgBox, No text with the font %font% found! 38 | } 39 | 40 | MsgBox, % "Press OK to create a new EventHandler for the TextChangedEvent.`nTo test this, type some new text inside Word, and a tooltip should pop up.`n`nTo exit the script, press F5." 41 | handler := UIA_CreateEventHandler("TextChangedEventHandler") ; Create a new event handler that points to the function TextChangedEventHandler, which must accept two arguments: element and eventId. 42 | UIA.AddAutomationEventHandler(UIA.Text_TextChangedEventId, wordEl,,, handler) ; Add a new automation handler for the TextChanged event. Note that we can only use wordEl here, not bodyEd, because the event is handled for the whole window. 43 | OnExit("ExitFunc") ; Set up an OnExit call to clean up the handler when exiting the script 44 | 45 | return 46 | 47 | TextChangedEventHandler(el, eventId) { 48 | local 49 | try { 50 | textPattern := el.GetCurrentPatternAs("Text") 51 | ToolTip, % "You changed text in Word:`n`n" textPattern.DocumentRange.GetText() 52 | SetTimer, RemoveToolTip, -2000 53 | } 54 | } 55 | 56 | ExitFunc() { 57 | global UIA, handler, bodyEl 58 | UIA.RemoveAutomationEventHandler(UIA.Text_ChangedEventId, bodyEl, handler) ; Remove the event handler. Alternatively use UIA.RemoveAllEventHandlers() to remove all handlers 59 | } 60 | 61 | RemoveToolTip: 62 | ToolTip 63 | return 64 | 65 | F5::ExitApp 66 | -------------------------------------------------------------------------------- /Examples/Example19_PropertyChangedEvent.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | 8 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 9 | #include ..\Lib\UIA_Interface.ahk 10 | 11 | UIA := UIA_Interface() 12 | Run, explore C:\ 13 | DriveGet, CDriveName, Label, C: 14 | CDriveName := CDriveName " (C:)" 15 | WinWaitActive, %CDriveName%,,1 16 | explorerEl := UIA.ElementFromHandle("A") 17 | MsgBox, % "Press OK to create a new EventHandler for the PropertyChanged event (property UIA_NamePropertyId).`nTo test this, click on any file/folder, and a tooltip should pop up.`n`nTo exit the script, press F5." 18 | handler := UIA_CreateEventHandler("PropertyChangedEventHandler", "PropertyChanged") 19 | UIA.AddPropertyChangedEventHandler(explorerEl,0x4,,handler, [UIA_Enum.UIA_NamePropertyId]) ; Multiple properties can be specified in the array 20 | OnExit("ExitFunc") ; Set up an OnExit call to clean up the handler when exiting the script 21 | return 22 | 23 | PropertyChangedEventHandler(sender, propertyId, newValue) { 24 | ToolTip, % "Sender: " sender.Dump() 25 | . "`nPropertyId: " propertyId 26 | . "`nNew value: " newValue 27 | SetTimer, RemoveToolTip, -3000 28 | } 29 | 30 | ExitFunc() { 31 | UIA_Interface().RemoveAllEventHandlers() 32 | } 33 | 34 | RemoveToolTip: 35 | ToolTip 36 | return 37 | 38 | F5::ExitApp 39 | -------------------------------------------------------------------------------- /Examples/Example1_Notepad.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | 8 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 9 | #include ..\Lib\UIA_Interface.ahk 10 | 11 | Run, notepad.exe 12 | UIA := UIA_Interface() ; Initialize UIA interface 13 | WinWaitActive, ahk_exe notepad.exe 14 | Sleep 40 15 | npEl := UIA.ElementFromHandle("ahk_exe notepad.exe") ; Get the element for the Notepad window 16 | documentEl := npEl.FindFirst("Type=Document or Type=Edit") ; Find the first Document/Edit control (in Notepad there is only one). In older Windows builds it's Edit, in newer it's Document. 17 | if !documentEl { 18 | ; Windows 11 has broken Notepad so that the Document element isn't findable; instead get it by the ClassNN 19 | ControlGet, hWnd, Hwnd,, RichEditD2DPT1 20 | documentEl := UIA.ElementFromHandle(hWnd) 21 | } 22 | documentEl.Highlight() ; Highlight the found element 23 | documentEl.Value := "Lorem ipsum" ; Set the value for the document control. 24 | 25 | ; This could also be done in one line: 26 | ;UIA.ElementFromHandle("ahk_exe notepad.exe").FindFirst("Type=Document or Type=Edit").Highlight().Value := "Lorem ipsum" 27 | 28 | ; Equivalent ways of setting the value: 29 | ; documentEl.CurrentValue := "Lorem ipsum" 30 | ; documentEl.SetValue("Lorem ipsum") 31 | ExitApp 32 | -------------------------------------------------------------------------------- /Examples/Example20_StructureChangedEvent.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | 8 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 9 | #include ..\Lib\UIA_Interface.ahk 10 | 11 | UIA := UIA_Interface() 12 | Run, explore C:\ 13 | DriveGet, CDriveName, Label, C: 14 | CDriveName := CDriveName " (C:)" 15 | WinWaitActive, %CDriveName%,,1 16 | explorerEl := UIA.ElementFromHandle() 17 | MsgBox, % "Press OK to create a new EventHandler for the StructureChanged event.`nTo test this, interact with the Explorer window, and a tooltip should pop up.`n`nTo exit the script, press F5." 18 | handler := UIA_CreateEventHandler("StructureChangedEventHandler", "StructureChanged") 19 | UIA.AddStructureChangedEventHandler(explorerEl,,, handler) 20 | OnExit("ExitFunc") ; Set up an OnExit call to clean up the handler when exiting the script 21 | return 22 | 23 | StructureChangedEventHandler(sender, changeType, runtimeId) { 24 | try ToolTip, % "Sender: " sender.Dump() 25 | . "`nChange type: " changeType 26 | . "`nRuntime Id: " PrintArray(runtimeId) 27 | SetTimer, RemoveToolTip, -3000 28 | } 29 | 30 | PrintArray(arr) { 31 | ret := "" 32 | for k, v in arr 33 | ret .= "Key: " k " Value: " (IsFunc(v)? v.name:IsObject(v)?PrintArray(v):v) "`n" 34 | return ret 35 | } 36 | 37 | ExitFunc() { 38 | UIA_Interface().RemoveAllEventHandlers() 39 | } 40 | 41 | RemoveToolTip: 42 | ToolTip 43 | return 44 | 45 | F5::ExitApp 46 | -------------------------------------------------------------------------------- /Examples/Example21_NotificationEvent.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | 8 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 9 | #include ..\Lib\UIA_Interface.ahk 10 | 11 | Run, calc.exe 12 | UIA := UIA_Interface() ; Initialize UIA interface 13 | winTitle := "Calculator" 14 | WinWaitActive, %winTitle% 15 | cEl := UIA.ElementFromHandle(winTitle) 16 | MsgBox, % "Press OK to create a new EventHandler for the Notification event.`nTo test this, interact with the Calculator window, and a tooltip should pop up.`n`nTo exit the script, press F5." 17 | handler := UIA_CreateEventHandler("NotificationEventHandler", "Notification") 18 | UIA.AddNotificationEventHandler(cEl,,, handler) 19 | OnExit("ExitFunc") ; Set up an OnExit call to clean up the handler when exiting the script 20 | return 21 | 22 | NotificationEventHandler(sender, notificationKind, notificationProcessing, displayString, activityId) { 23 | ToolTip, % "Sender: " sender.Dump() 24 | . "`nNotification kind: " notificationKind " (" UIA_Enum.NotificationKind(notificationKind) ")" 25 | . "`nNotification processing: " notificationProcessing " (" UIA_Enum.NotificationProcessing(notificationProcessing) ")" 26 | . "`nDisplay string: " displayString 27 | . "`nActivity Id: " activityId 28 | SetTimer, RemoveToolTip, -3000 29 | } 30 | 31 | PrintArray(arr) { 32 | ret := "" 33 | for k, v in arr 34 | ret .= "Key: " k " Value: " (IsFunc(v)? v.name:IsObject(v)?PrintArray(v):v) "`n" 35 | return ret 36 | } 37 | 38 | ExitFunc() { 39 | UIA_Interface().RemoveAllEventHandlers() 40 | } 41 | 42 | RemoveToolTip: 43 | ToolTip 44 | return 45 | 46 | F5::ExitApp 47 | -------------------------------------------------------------------------------- /Examples/Example22_EventHandlerGroup.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | 7 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 8 | #include ..\Lib\UIA_Interface.ahk 9 | 10 | Run, calc.exe 11 | UIA := UIA_Interface() ; Initialize UIA interface 12 | winTitle := "Calculator" 13 | WinWaitActive, %winTitle% 14 | cEl := UIA.ElementFromHandle(winTitle) 15 | 16 | ehGroup := UIA.CreateEventHandlerGroup() 17 | h1 := UIA_CreateEventHandler("AutomationEventHandler") 18 | h2 := UIA_CreateEventHandler("NotificationEventHandler", "Notification") 19 | ehGroup.AddAutomationEventHandler(UIA_Enum.UIA_AutomationFocusChangedEventId,,, h1) 20 | ehGroup.AddNotificationEventHandler(,,h2) 21 | UIA.AddEventHandlerGroup(cEl, ehGroup) 22 | 23 | OnExit("ExitFunc") ; Set up an OnExit call to clean up the handler when exiting the script 24 | return 25 | 26 | AutomationEventHandler(sender, eventId) { 27 | ToolTip, % "Sender: " sender.Dump() 28 | . "`nEvent Id: " eventId 29 | Sleep, 500 30 | SetTimer, RemoveToolTip, -3000 31 | } 32 | 33 | NotificationEventHandler(sender, notificationKind, notificationProcessing, displayString, activityId) { 34 | ToolTip, % "Sender: " sender.Dump() 35 | . "`nNotification kind: " notificationKind " (" UIA_Enum.NotificationKind(notificationKind) ")" 36 | . "`nNotification processing: " notificationProcessing " (" UIA_Enum.NotificationProcessing(notificationProcessing) ")" 37 | . "`nDisplay string: " displayString 38 | . "`nActivity Id: " activityId 39 | Sleep, 500 40 | SetTimer, RemoveToolTip, -3000 41 | } 42 | 43 | PrintArray(arr) { 44 | ret := "" 45 | for k, v in arr 46 | ret .= "Key: " k " Value: " (IsFunc(v)? v.name:IsObject(v)?PrintArray(v):v) "`n" 47 | return ret 48 | } 49 | 50 | ExitFunc() { 51 | UIA_Interface().RemoveAllEventHandlers() 52 | } 53 | 54 | RemoveToolTip: 55 | ToolTip 56 | return 57 | 58 | F5::ExitApp 59 | -------------------------------------------------------------------------------- /Examples/Example23_Caching.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | 7 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 8 | #include ..\Lib\UIA_Interface.ahk 9 | 10 | UIA := UIA_Interface() 11 | cacheRequest := UIA.CreateCacheRequest() 12 | cacheRequest.TreeScope := 5 ; Set TreeScope to include the starting element and all descendants as well 13 | cacheRequest.AddProperty("ControlType") ; Add all the necessary properties that DumpAll uses: ControlType, LocalizedControlType, AutomationId, Name, Value, ClassName, AcceleratorKey 14 | cacheRequest.AddProperty("LocalizedControlType") 15 | cacheRequest.AddProperty("AutomationId") 16 | cacheRequest.AddProperty("Name") 17 | cacheRequest.AddProperty("Value") 18 | cacheRequest.AddProperty("ClassName") 19 | cacheRequest.AddProperty("AcceleratorKey") 20 | 21 | cacheRequest.AddPattern("Window") ; To use cached patterns, first add the pattern 22 | cacheRequest.AddProperty("WindowCanMaximize") ; Also need to add any pattern properties we wish to use 23 | 24 | Run, notepad.exe 25 | WinWaitActive, ahk_exe notepad.exe 26 | 27 | npEl:= UIA.ElementFromHandleBuildCache("ahk_exe notepad.exe", cacheRequest) ; Get element and also build the cache 28 | MsgBox, % npEl.CachedDumpAll() 29 | MsgBox, % npEl.CachedWindowPattern.CachedCanMaximize 30 | 31 | ExitApp -------------------------------------------------------------------------------- /Examples/Example2_Notepad.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | 8 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 9 | #include ..\Lib\UIA_Interface.ahk 10 | 11 | Run, notepad.exe 12 | UIA := UIA_Interface() ; Initialize UIA interface 13 | WinWaitActive, ahk_exe notepad.exe 14 | npEl := UIA.ElementFromHandle("ahk_exe notepad.exe") ; Get the element for the Notepad window 15 | MsgBox, % npEl.DumpAll() ; Display all the sub-elements for the Notepad window. Press OK to continue 16 | documentEl := npEl.FindFirst("Type=Document or Type=Edit") ; Find the first Document/Edit control (in Notepad there is only one). In older Windows builds it's Edit, in newer it's Document. 17 | if !documentEl { 18 | ; Windows 11 has broken Notepad so that the Document element isn't findable; instead get it by the ClassNN 19 | ControlGet, hWnd, Hwnd,, RichEditD2DPT1 20 | documentEl := UIA.ElementFromHandle(hWnd) 21 | } 22 | documentEl.Value := "Lorem ipsum" ; Set the value of the document control, same as documentEl.SetValue("Lorem ipsum") 23 | MsgBox, Press OK to test saving. ; Wait for the user to press OK 24 | fileEl := npEl.FindFirstByNameAndType("File", "MenuItem") ; Find the "File" menu item 25 | fileEl.Highlight() 26 | fileEl.Click() 27 | saveEl := npEl.WaitElementExistByName("Save",,2) ; Wait for the "Save" menu item to exist 28 | saveEl.Highlight() 29 | saveEl.Click() ; And now click Save 30 | ExitApp 31 | 32 | -------------------------------------------------------------------------------- /Examples/Example3_Calculator.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetBatchLines, -1 6 | 7 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 8 | #include ..\Lib\UIA_Interface.ahk 9 | 10 | Run, calc.exe 11 | UIA := UIA_Interface() ; Initialize UIA interface 12 | winTitle := "Calculator" 13 | WinWaitActive, %winTitle% 14 | cEl := UIA.ElementFromHandle(winTitle) ; Get the element for the Calculator window 15 | ; All the calculator buttons are of "Button" ControlType, and if the system language is English then the Name of the elements are the English words for the buttons (eg button 5 is named "Five", = sign is named "Equals") 16 | cEl.WaitElementExist("Name=Six").Click() ; Wait for the "Six" button by name and click it 17 | cEl.FindFirst("Name=Five AND ControlType=Button").Click() ; Specify both name "Five" and control type "Button" 18 | cEl.FindFirstByName("Plus").Click() ; An alternative method to FindFirstBy("Name=Plus") 19 | cEl.FindFirstByNameAndType("Four", UIA.ButtonControlTypeId).Click() ; The type can be specified as "Button", UIA.ButtonControlTypeId, UIA_Enum.UIA_ButtonControlTypeId, or 50000 (which is the value of UIA.ButtonControlTypeId) 20 | cEl.FindFirstByNameAndType("Equals", "Button").Click() 21 | ExitApp 22 | -------------------------------------------------------------------------------- /Examples/Example4_ChromeTest.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 8 | #include ..\Lib\UIA_Interface.ahk 9 | ;#include ; Uncomment if you have moved UIA_Browser.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Browser.ahk 11 | 12 | browserExe := "chrome.exe" 13 | Run, %browserExe% -incognito --force-renderer-accessibility ; Run in Incognito mode to avoid any extensions interfering. Force accessibility in case its disabled by default. 14 | WinWaitActive, ahk_exe %browserExe% 15 | cUIA := new UIA_Browser("ahk_exe " browserExe) ; Initialize UIA_Browser, which also initializes UIA_Interface 16 | Clipboard= ; Clear clipboard 17 | Clipboard := cUIA.GetCurrentDocumentElement().DumpAll() ; Get the current document element (this excludes the URL bar, navigation buttons etc) and dump all the information about it in the clipboard. Use Ctrl+V to paste it somewhere, such as in Notepad. 18 | ClipWait, 1 19 | if Clipboard 20 | MsgBox, Page information successfully dumped. Use Ctrl+V to paste the info somewhere, such as in Notepad. 21 | else 22 | MsgBox, Something went wrong and nothing was dumped in the clipboard! 23 | ExitApp 24 | -------------------------------------------------------------------------------- /Examples/Example5_ChromeGoogleTranslate.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 8 | #include ..\Lib\UIA_Interface.ahk 9 | ;#include ; Uncomment if you have moved UIA_Browser.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Browser.ahk 11 | 12 | browserExe := "chrome.exe" 13 | Run, %browserExe% -incognito --force-renderer-accessibility ; Run in Incognito mode to avoid any extensions interfering. Force accessibility in case its disabled by default. 14 | WinWaitActive, ahk_exe %browserExe% 15 | cUIA := new UIA_Browser("ahk_exe " browserExe) ; Initialize UIA_Browser, which also initializes UIA_Interface 16 | cUIA.Navigate("https://www.google.com/preferences#languages") ; Set the URL and navigate to it. WaitPageLoad is not necessary with Navigate. 17 | 18 | EnglishEl := cUIA.WaitElementExistByName("English") ; Find the English language radiobutton 19 | EnglishEl.Click() ; Select English 20 | TW := cUIA.CreateTreeWalker(cUIA.CreateCondition("ControlType", "Button")) ; To find the "Save" button, we need to use a TreeWalker to get the next button element from the radiobutton, since "Save" differs between languages 21 | TW.GetNextSiblingElement(EnglishEl).Click(2000) ; Find the "Save" button, click it, and Sleep for 2000ms 22 | cUIA.CloseAlert() ; Sometimes a dialog pops up that confirms the save, in that case press "OK" 23 | cUIA.WaitPageLoad("Google") ; Wait for Google main page to load, default timeout of 10 seconds 24 | 25 | cUIA.Navigate("https://translate.google.com/") ; Navigate to Google Translate 26 | cUIA.FindFirstByName("More source languages").Click() ; Click source languages selection 27 | cUIA.WaitElementExistByName("Spanish").Click(500) ; Select Spanish, Sleep for 500ms 28 | cUIA.FindFirstByName("More target languages").Click(500) ; Open target languages selection, Sleep for 500ms 29 | allEnglishEls := cUIA.FindAllByName("English") ; Find all elements with name "English" 30 | allEnglishEls[allEnglishEls.MaxIndex()].Click() ; Select the last element with the name English (because English might also be an option in source languages, in which case it would be found first) 31 | 32 | cUIA.WaitElementExistByName("Source text").SetValue("Este es un texto de muestra") ; Set some text to translate 33 | ExitApp 34 | -------------------------------------------------------------------------------- /Examples/Example6_EdgeGoogle.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #NoEnv 3 | #Warn 4 | #SingleInstance force 5 | SetTitleMatchMode, 2 6 | SetBatchLines, -1 7 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 8 | #include ..\Lib\UIA_Interface.ahk 9 | ;#include ; Uncomment if you have moved UIA_Browser.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Browser.ahk 11 | 12 | browserExe := "msedge.exe" 13 | Run, %browserExe% -inprivate --force-renderer-accessibility ; Run in Incognito mode to avoid any extensions interfering. Force accessibility in case its disabled by default. 14 | WinWaitActive, ahk_exe %browserExe% 15 | cUIA := new UIA_Browser("ahk_exe " browserExe) ; Initialize UIA_Browser, which also initializes UIA_Interface 16 | cUIA.WaitPageLoad("New inprivate tab", 5000) ; Wait the New Tab (case insensitive) page to load with a timeout of 5 seconds 17 | cUIA.Navigate("google.com") ; Set the URL to google and navigate 18 | 19 | if (langBut := cUIA.WaitElementExist("ClassName=neDYw tHlp8d AND ControlType=Button OR ControlType=MenuItem",,,,2000)) { ; First lets make sure the selected language is correct. The expression is evaluated left to right: finds an element where ClassName is "neDYw tHlp8d" and ControlType is button OR an element with a MenuItem controltype. 20 | expandCollapsePattern := langBut.ExpandCollapsePattern ; Since this isn't a normal button, we need to get the ExpandCollapse pattern for it and then call the correct method. 21 | if (expandCollapsePattern.CurrentExpandCollapseState == cUIA.ExpandCollapseState_Collapsed) ; Check that it is collapsed 22 | expandCollapsePattern.Expand() ; Expand the menu 23 | cUIA.WaitElementExist("Name=English AND ControlType=MenuItem").Click() ; Select the English language 24 | 25 | cUIA.WaitElementExist("Name=Accept all OR Name=I agree AND ControlType=Button").Click() ; If the "I agree" or "Accept all" button exists, then click it to get rid of the consent form 26 | } 27 | searchBox := cUIA.WaitElementExist("Name=Searc AND ControlType=ComboBox",,2) ; Looking for a partial name match "Searc" using matchMode=2. FindFirstByNameAndType is not used here, because if the "I agree" button was clicked then this element might not exist right away, so lets first wait for it to exist. 28 | searchBox.Value := "autohotkey forums" ; Set the search box text to "autohotkey forums" 29 | cUIA.FindFirstByName("Google Search").Click() ; Click the search button to search 30 | cUIA.WaitPageLoad() 31 | 32 | ; Now that the Google search results have loaded, lets scroll the page to the end. 33 | docEl := cUIA.GetCurrentDocumentElement() ; Get the document element 34 | sbPat := docEl.ScrollPattern ; Get the Scroll pattern to access scrolling methods and properties 35 | hPer := sbPat.HorizontalScrollPercent ; Horizontal scroll percent doesn't actually interest us, but the SetScrollPercent method requires both horizontal and vertical scroll percents... 36 | ToolTip, % "Current scroll percent: " sbPat.VerticalScrollPercent 37 | for k, v in [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] { ; Lets scroll down in steps of 10% 38 | sbPat.SetScrollPercent(hPer, v) 39 | Sleep, 500 40 | ToolTip, % "Current scroll percent: " sbPat.VerticalScrollPercent 41 | } 42 | Sleep, 3000 43 | ToolTip 44 | ExitApp 45 | -------------------------------------------------------------------------------- /Examples/Example7_FocusChangedEvent.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #Warn 4 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | ;#include ; Uncomment if you have moved UIA_Browser.ahk to your main Lib folder 12 | #include ..\Lib\UIA_Browser.ahk 13 | 14 | EventHandler(el) { 15 | global cUIA 16 | try { 17 | ToolTip, % "Caught event!`nElement name: " el.CurrentName 18 | if cUIA.CompareElements(cUIA.URLEditElement, el) ; Check if the focused element is the same as Chrome's address bar element (comparison using == won't work) 19 | el.Value := "" ; If the Address bar was focused, clear it 20 | } 21 | } 22 | 23 | ExitFunc() { 24 | global cUIA, h 25 | UIA.RemoveFocusChangedEventHandler(h) ; Remove the event handler. Alternatively use cUIA.RemoveAllEventHandlers() to remove all handlers 26 | } 27 | 28 | browserExe := "chrome.exe" 29 | Run, %browserExe% -incognito 30 | WinWaitActive, ahk_exe %browserExe% 31 | cUIA := new UIA_Browser("ahk_exe " browserExe) 32 | 33 | h := UIA_CreateEventHandler("EventHandler", "FocusChanged") ; Create a new FocusChanged event handler that calls the function EventHandler (required arguments: element) 34 | cUIA.AddFocusChangedEventHandler(h) ; Add a new FocusChangedEventHandler 35 | OnExit("ExitFunc") ; Set up an OnExit call to clean up the handler when exiting the script 36 | return 37 | 38 | F5::ExitApp 39 | -------------------------------------------------------------------------------- /Examples/Example8_SelectionEventHandler.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #Warn 4 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | TextSelectionChangedEventHandler(el, eventId) { 13 | textPattern := el.TextPattern 14 | selectionArray := textPattern.GetSelection() ; Gets the currently selected text in Notepad as an array of TextRanges (some elements support selecting multiple pieces of text at the same time, thats why an array is returned) 15 | selectedRange := selectionArray[1] ; Our range of interest is the first selection (TextRange) 16 | wholeRange := textPattern.DocumentRange ; For comparison, get the whole range (TextRange) of the document 17 | selectionStart := selectedRange.CompareEndpoints(UIA_Enum.TextPatternRangeEndpoint_Start, wholeRange, UIA_Enum.TextPatternRangeEndpoint_Start) ; Compare the start point of the selection to the start point of the whole document 18 | selectionEnd := selectedRange.CompareEndpoints(UIA_Enum.TextPatternRangeEndpoint_End, wholeRange, UIA_Enum.TextPatternRangeEndpoint_Start) ; Compare the end point of the selection to the start point of the whole document 19 | 20 | ToolTip, % "Selected text: " selectedRange.GetText() "`nSelection start location: " selectionStart "`nSelection end location: " selectionEnd ; Display the selected text and locations of selection 21 | } 22 | 23 | ExitFunc() { 24 | global UIA, handler, NotepadEl 25 | try UIA.RemoveAutomationEventHandler(UIA.Text_TextSelectionChangedEventId, NotepadEl, handler) ; Remove the event handler. Alternatively use UIA.RemoveAllEventHandlers() to remove all handlers. If the Notepad window doesn't exist any more, this throws an error. 26 | } 27 | 28 | lorem = 29 | ( 30 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 31 | ) ; Some sample text to play around with 32 | Run, notepad.exe 33 | WinWaitActive, ahk_exe notepad.exe 34 | UIA := UIA_Interface() 35 | 36 | NotepadEl := UIA.ElementFromHandle("ahk_exe notepad.exe") 37 | DocumentControl := NotepadEl.FindFirst("Type=Document or Type=Edit") 38 | DocumentControl.Value := lorem ; Set the value to our sample text 39 | 40 | handler := UIA_CreateEventHandler("TextSelectionChangedEventHandler") ; Create a new event handler that points to the function TextSelectionChangedEventHandler, which must accept two arguments: element and eventId. 41 | UIA.AddAutomationEventHandler(UIA.Text_TextSelectionChangedEventId, NotepadEl,,, handler) ; Add a new automation handler for the TextSelectionChanged event 42 | OnExit("ExitFunc") ; Set up an OnExit call to clean up the handler when exiting the script 43 | return 44 | 45 | F5::ExitApp 46 | -------------------------------------------------------------------------------- /Examples/Example9_InvokePatternTogglePattern.ahk: -------------------------------------------------------------------------------- 1 | #Requires AutoHotkey v1.1.33+ 2 | #SingleInstance, force 3 | #Warn 4 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 5 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 6 | SetTitleMatchMode, 2 7 | SetBatchLines, -1 8 | 9 | ;#include ; Uncomment if you have moved UIA_Interface.ahk to your main Lib folder 10 | #include ..\Lib\UIA_Interface.ahk 11 | 12 | Run, explore C:\ 13 | UIA := UIA_Interface() 14 | WinWaitActive, (C:) 15 | explorerEl := UIA.ElementFromHandle("A") 16 | fileEl := explorerEl.FindFirstByNameAndType("File tab", "Button") 17 | invokePattern := fileEl.InvokePattern 18 | MsgBox, % "Invoke pattern doesn't have any properties. Press OK to call Invoke on the ""File"" button..." 19 | invokePattern.Invoke() 20 | 21 | Sleep, 1000 22 | MsgBox, Press OK to navigate to the View tab to test TogglePattern... ; Not part of this demonstration 23 | explorerEl.FindFirstByNameAndType("View", "TabItem").SelectionItemPattern.Select() ; Not part of this demonstration 24 | 25 | hiddenItemsCB := explorerEl.FindFirstByNameAndType("Hidden items", "CheckBox") 26 | togglePattern := hiddenItemsCB.TogglePattern 27 | Sleep, 500 28 | MsgBox, % "TogglePattern properties for ""Hidden items"" checkbox: " 29 | . "`nCurrentToggleState: " togglePattern.CurrentToggleState 30 | 31 | MsgBox, % "Press OK to toggle" 32 | togglePattern.Toggle() 33 | Sleep, 500 34 | MsgBox, % "Press OK to toggle again" 35 | togglePattern.Toggle() 36 | 37 | ; togglePattern.ToggleState := 1 ; CurrentToggleState can also be used to set the state 38 | 39 | ExitApp 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Descolada 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Lib/UIA_Browser.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | Introduction: 3 | UIA_Browser implements some methods to help automate browsers with UIAutomation framework. 4 | 5 | Initiate new instance of UIA_Browser with 6 | cUIA := new UIA_Browser(wTitle="A", customNames="", maxVersion="") 7 | wTitle: the title of the browser 8 | customNames is currently unused, but may be used to implement language-specific elements 9 | maxVersion: specifies the highest UIA version that will be used (default is up to version 7). 10 | Example: cUIA := new UIA_Browser("ahk_exe chrome.exe") 11 | 12 | Instances for specific browsers may be initiated with UIA_Chrome, UIA_Edge, UIA_Mozilla (arguments are the same as for UIA_Browser). 13 | These are usually auto-detected by UIA_Browser, so do not have to be used. 14 | 15 | Available properties for UIA_Browser: 16 | UIA_Browser can return both UIA_Interface and the browser window elements properties and methods, depending on where the property exists. 17 | Example: cUIA.CurrentProcessId will return the ProcessId for the browser window element by calling cUIA.BrowserElement.CurrentProcessId. 18 | UIA 19 | The UIA_Interface object itself, which can be more readily accessed by just calling a UIA_Interface method/property from UIA_Browser (eg cUIA.CreateNotCondition() will actually call cUIA.UIA.CreateNotCondition()) 20 | BrowserId 21 | ahk_id of the browser window 22 | BrowserType 23 | "Chrome", "Edge", "Mozilla" or "Unknown" 24 | BrowserElement 25 | The browser window element, which can also be accessed by just calling an element method from UIA_Browser (cUIA.FindFirst would call FindFirst method on the BrowserElement, is equal to cUIA.BrowserElement.FindFirst) 26 | MainPaneElement 27 | Element for the upper part of the browser containing the URL bar, tabs, extensions etc 28 | URLEditElement 29 | Element for the address bar 30 | TWT 31 | A UIA TreeWalker that is created with TrueCondition 32 | All UIA enumerations/constants are also available in the UIA_Browser object. 33 | cUIA.UIA_ControlTypePropertyId => returns UIA_ControlTypePropertyId from UIA_Enum, returning value 30003 34 | cUIA.ButtonControlTypeId => "UIA_" can be omitted. Returns UIA_ButtonControlTypeId from UIA_Enum class, returning value 50000 35 | 36 | UIA_Browser methods: 37 | UIA_Browser can return both UIA_Interface and the browser window elements properties and methods, depending on where the method exists. 38 | Example: cUIA.CreateTreeWalker(condition) accesses the CreateTreeWalker method from UIA_Interface class; cUIA.FindFirst(condition) calls FindFirst on the browser window element (because FindFirst doesn't exist inside UIA_Interface). 39 | GetCurrentMainPaneElement() 40 | Refreshes UIA_Browser.MainPaneElement and also returns it 41 | GetCurrentDocumentElement() 42 | Returns the current document/content element of the browser. For Mozilla, the tab name which content to get can be specified. 43 | GetAllText() 44 | Gets all text from the browser element (CurrentName properties for all child elements) 45 | GetAllLinks() 46 | Gets all link elements from the browser (returns an array of elements) 47 | WaitTitleChange(targetTitle="", timeOut=-1) 48 | Waits the browser title to change to targetTitle (by default just waits for the title to change), timeOut is in milliseconds (default is indefinite waiting) 49 | WaitPageLoad(targetTitle="", timeOut=-1, sleepAfter=500, titleMatchMode=3, titleCaseSensitive=True) 50 | Waits the browser page to load to targetTitle, default timeOut is indefinite waiting, sleepAfter additionally sleeps for 200ms after the page has loaded. 51 | Back() 52 | Presses the Back button 53 | Forward() 54 | Presses the Forward button 55 | Reload() 56 | Presses the Reload button 57 | Home() 58 | Presses the Home button if it exists. 59 | GetCurrentURL(fromAddressBar=False) 60 | Gets the current URL. fromAddressBar=True gets it straight from the URL bar element, which is not a very good method, because the text might be changed by the user and doesn't start with "http(s)://". Default of fromAddressBar=False will cause the real URL to be fetched, but the browser must be visible for it to work (if is not visible, it will be automatically activated). 61 | SetURL(newUrl, navigateToNewUrl = False) 62 | Sets the URL bar to newUrl, optionally also navigates to it if navigateToNewUrl=True 63 | Navigate(url, targetTitle="", waitLoadTimeOut=-1, sleepAfter=500) 64 | Navigates to URL and waits page to load 65 | NewTab() 66 | Presses the New tab button. 67 | GetTab(searchPhrase="", matchMode=3, caseSensitive=True) 68 | Returns a tab element with text of searchPhrase, or if empty then the currently selected tab. matchMode follows SetTitleMatchMode scheme: 1=tab name must must start with tabName; 2=can contain anywhere; 3=exact match; RegEx 69 | GetTabs(searchPhrase="", matchMode=3, caseSensitive=True) 70 | Returns all tab elements with text of searchPhrase, or if empty then all tabs. matchMode follows SetTitleMatchMode scheme: 1=tab name must must start with tabName; 2=can contain anywhere; 3=exact match; RegEx 71 | GetAllTabNames() 72 | Gets all the titles of tabs 73 | SelectTab(tabName, matchMode=3, caseSensitive=True) 74 | Selects a tab with the text of tabName. matchMode follows SetTitleMatchMode scheme: 1=tab name must must start with tabName; 2=can contain anywhere; 3=exact match; RegEx 75 | CloseTab(tabElementOrName="", matchMode=3, caseSensitive=True) 76 | Close tab by either providing the tab element or the name of the tab. If tabElementOrName is left empty, the current tab will be closed. 77 | IsBrowserVisible() 78 | Returns True if any of the 4 corners of the browser are visible. 79 | Send(text) 80 | Uses ControlSend to send text to the browser. 81 | GetAlertText() 82 | Gets the text from an alert box 83 | CloseAlert() 84 | Closes an alert box 85 | JSExecute(js) 86 | Executes Javascript code using the address bar 87 | JSReturnThroughClipboard(js) 88 | Executes Javascript code using the address bar and returns the return value of the code using the clipboard (resetting it back afterwards) 89 | JSReturnThroughTitle(js, timeOut=500) 90 | Executes Javascript code using the address bar and returns the return value of the code using the browsers title (resetting it back afterwards). This might be unreliable, so the clipboard method is recommended instead. 91 | JSSetTitle(newTitle) 92 | Uses Javascript through the address bar to change the title of the browser 93 | JSGetElementPos(selector, useRenderWidgetPos=False) 94 | Uses Javascript's querySelector to get a Javascript element and then its position. useRenderWidgetPos=True uses position of the Chrome_RenderWidgetHostHWND1 control to locate the position element relative to the window, otherwise it uses UIA_Browsers CurrentDocumentElement position. 95 | JSClickElement(selector) 96 | Uses Javascript's querySelector to get and click a Javascript element 97 | ControlClickJSElement(selector, WhichButton="", ClickCount="", Options="", useRenderWidgetPos=False) 98 | Uses Javascript's querySelector to get a Javascript element and then ControlClicks that position. useRenderWidgetPos=True uses position of the Chrome_RenderWidgetHostHWND1 control to locate the position element relative to the window, otherwise it uses UIA_Browsers CurrentDocumentElement position. 99 | ClickJSElement(selector, WhichButton="", ClickCount=1, DownOrUp="", Relative="", useRenderWidgetPos=False) 100 | Uses Javascript's querySelector to get a Javascript element and then Clicks that position. useRenderWidgetPos=True uses position of the Chrome_RenderWidgetHostHWND1 control to locate the position element relative to the window, otherwise it uses UIA_Browsers CurrentDocumentElement position. 101 | */ 102 | 103 | 104 | /* 105 | If implementing new browser classes, then necessary methods/properties for main browser functions are: 106 | 107 | this.GetCurrentMainPaneElement() -- fetches MainPaneElement, NavigationBarElement, TabBarElement, URLEditElement 108 | // this might be necessary to implement for speed reasons, and is automatically called by InitiateUIA method 109 | this.GetCurrentDocumentElement() -- fetches Document element for the current page // might be necessary to implement 110 | this.GetCurrentReloadButton() 111 | 112 | this.MainPaneElement -- element that doesn't contain page content: this element includes URL bar, navigation buttons, setting buttons etc 113 | this.NavigationBarElement -- smallest element (usually a Toolbar element) that contains the URL bar and navigation buttons 114 | this.TabBarElement -- contains only tabs 115 | this.URLEditElement -- the URL bar element 116 | this.ReloadButton 117 | */ 118 | 119 | class UIA_Chrome extends UIA_Browser { 120 | __New(wTitle:="A", customNames:="", maxVersion:="") { 121 | this.BrowserType := "Chrome" 122 | this.InitiateUIA(wTitle, customNames, maxVersion) 123 | } 124 | ; Refreshes UIA_Browser.MainPaneElement and returns it 125 | GetCurrentMainPaneElement() { 126 | this.BrowserElement.WaitElementExist("ControlType=Document") 127 | Loop, 2 128 | { 129 | try this.URLEditElement := this.BrowserElement.FindFirstWithOptions(4, this.EditControlCondition, 2) 130 | try { 131 | if !this.URLEditElement 132 | this.URLEditElement := this.UIA.CreateTreeWalker(this.EditControlCondition).GetLastChildElement(this.BrowserElement) 133 | this.NavigationBarElement := this.UIA.CreateTreeWalker(this.ToolbarControlCondition).GetParentElement(this.URLEditElement) 134 | this.MainPaneElement := this.TWT.GetParentElement(this.NavigationBarElement) 135 | if !this.NavigationBarElement 136 | this.NavigationBarElement := this.BrowserElement 137 | if !this.MainPaneElement 138 | this.MainPaneElement := this.BrowserElement 139 | if !(this.TabBarElement := this.CreateTreeWalker(this.TabControlCondition).GetPreviousSiblingElement(this.NavigationBarElement)) 140 | this.TabBarElement := this.MainPaneElement 141 | Loop 2 { 142 | try { 143 | this.ReloadButton := this.UIA.TreeWalkerTrue.GetNextSiblingElement(this.UIA.TreeWalkerTrue.GetNextSiblingElement(this.ButtonTreeWalker.GetFirstChildElement(this.NavigationBarElement))) 144 | this.ReloadButtonDescription := this.ReloadButton.GetCurrentPatternAs("LegacyIAccessible").CurrentDescription 145 | this.ReloadButtonName := this.ReloadButton.CurrentName 146 | } 147 | if (this.ReloadButtonDescription || this.ReloadButtonName) 148 | break 149 | Sleep 200 150 | } 151 | return this.MainPaneElement 152 | } catch { 153 | WinActivate, % "ahk_id " this.BrowserId 154 | WinWaitActive, % "ahk_id " this.BrowserId,,1 155 | } 156 | } 157 | ; If all goes well, this part is not reached 158 | } 159 | } 160 | 161 | class UIA_Edge extends UIA_Browser { 162 | __New(wTitle:="A", customNames:="", maxVersion:="") { 163 | this.BrowserType := "Edge" 164 | this.InitiateUIA(wTitle, customNames, maxVersion) 165 | } 166 | 167 | ; Refreshes UIA_Browser.MainPaneElement and returns it 168 | GetCurrentMainPaneElement() { 169 | local 170 | this.BrowserElement.WaitElementExist("ControlType=Document") 171 | Loop, 2 172 | { 173 | try { 174 | if !(this.URLEditElement := this.BrowserElement.FindFirst(this.EditControlCondition)) { 175 | this.ToolbarElements := this.BrowserElement.FindAll(this.ToolbarControlCondition), topCoord := 10000000 176 | for k, v in this.ToolbarElements { 177 | if ((bT := v.CurrentBoundingRectangle.t) && (bt < topCoord)) 178 | topCoord := bT, this.NavigationBarElement := v 179 | } 180 | this.URLEditElement := this.NavigationBarElement.FindFirst(this.EditControlCondition) 181 | if this.URLEditElement.GetChildren().MaxIndex() 182 | this.URLEditElement := (el := this.URLEditElement.FindFirst(this.EditControlCondition)) ? el : this.URLEditElement 183 | } Else { 184 | this.NavigationBarElement := this.UIA.CreateTreeWalker(this.ToolbarControlCondition).GetParentElement(this.URLEditElement) 185 | } 186 | this.MainPaneElement := this.TWT.GetParentElement(this.NavigationBarElement) 187 | if !this.NavigationBarElement 188 | this.NavigationBarElement := this.BrowserElement 189 | if !this.MainPaneElement 190 | this.MainPaneElement := this.BrowserElement 191 | if !(this.TabBarElement := this.CreateTreeWalker(this.TabControlCondition).GetPreviousSiblingElement(this.NavigationBarElement)) 192 | this.TabBarElement := this.MainPaneElement 193 | Loop 2 { 194 | try { 195 | this.ReloadButton := this.ButtonTreeWalker.GetNextSiblingElement(this.ButtonTreeWalker.GetNextSiblingElement(this.ButtonTreeWalker.GetFirstChildElement(this.NavigationBarElement))) 196 | this.ReloadButtonFullDescription := this.ReloadButton.CurrentFullDescription 197 | this.ReloadButtonName := this.ReloadButton.CurrentName 198 | } 199 | if (this.ReloadButtonFullDescription || this.ReloadButtonName) 200 | break 201 | Sleep 200 202 | } 203 | return this.MainPaneElement 204 | } catch { 205 | WinActivate, % "ahk_id " this.BrowserId 206 | WinWaitActive, % "ahk_id " this.BrowserId,,1 207 | } 208 | } 209 | ; If all goes well, this part is not reached 210 | } 211 | } 212 | 213 | class UIA_Mozilla extends UIA_Browser { 214 | __New(wTitle:="A", customNames:="", maxVersion:="", javascriptFromBookmark:=False) { 215 | this.BrowserType := "Mozilla" 216 | this.JavascriptFromBookmark := javascriptFromBookmark 217 | this.InitiateUIA(wTitle, customNames, maxVersion) 218 | } 219 | ; Refreshes UIA_Browser.MainPaneElement and returns it 220 | GetCurrentMainPaneElement() { 221 | this.BrowserElement.WaitElementExist("AutomationId=panel",2,2) 222 | Loop, 2 223 | { 224 | try { 225 | this.TabBarElement := this.ToolbarTreeWalker.GetNextSiblingElement(this.ToolbarTreeWalker.GetFirstChildElement(this.BrowserElement)) 226 | this.NavigationBarElement := this.ToolbarTreeWalker.GetNextSiblingElement(this.TabBarElement) 227 | this.URLEditElement := this.NavigationBarElement.FindFirst(this.EditControlCondition) 228 | this.MainPaneElement := this.TWT.GetParentElement(this.NavigationBarElement) 229 | if !this.NavigationBarElement 230 | this.NavigationBarElement := this.BrowserElement 231 | if !this.MainPaneElement 232 | this.MainPaneElement := this.BrowserElement 233 | Loop 2 { 234 | try { 235 | this.ReloadButton := this.UIA.TreeWalkerTrue.GetNextSiblingElement(this.UIA.TreeWalkerTrue.GetNextSiblingElement(this.UIA.TreeWalkerTrue.GetFirstChildElement(this.NavigationBarElement))) 236 | this.ReloadButtonFullDescription := this.ReloadButton.CurrentFullDescription 237 | this.ReloadButtonName := this.ReloadButton.CurrentName 238 | } 239 | if (this.ReloadButtonFullDescription || this.ReloadButtonName) 240 | break 241 | Sleep 200 242 | } 243 | return this.MainPaneElement 244 | } catch { 245 | WinActivate, % "ahk_id " this.BrowserId 246 | WinWaitActive, % "ahk_id " this.BrowserId,,1 247 | } 248 | } 249 | ; If all goes well, this part is not reached 250 | } 251 | 252 | ; Returns the current document/content element of the browser 253 | GetCurrentDocumentElement() { 254 | local 255 | this.DocumentPanelElement := this.BrowserElement.FindFirstBy("ControlType=Custom AND IsOffscreen=0",2) 256 | return this.TWT.GetFirstChildElement(this.TWT.GetFirstChildElement(this.DocumentPanelElement)) 257 | } 258 | 259 | ; Presses the New tab button. 260 | NewTab() { 261 | this.TabBarElement.FindFirst(this.ButtonControlCondition,4).Click() 262 | } 263 | 264 | ; Sets the URL bar to newUrl, optionally also navigates to it if navigateToNewUrl=True 265 | SetURL(newUrl, navigateToNewUrl := False) { 266 | this.URLEditElement.SetFocus() 267 | valuePattern := this.URLEditElement.GetCurrentPatternAs("Value") 268 | valuePattern.SetValue(newUrl " ") 269 | if (navigateToNewUrl&&InStr(this.URLEditElement.CurrentValue, newUrl)) { 270 | ControlFocus, ahk_parent, % "ahk_id" this.BrowserId 271 | ControlSend, ahk_parent, {LCtrl up}{LAlt up}{LShift up}{RCtrl up}{RAlt up}{RShift up}{Enter}, % "ahk_id" this.BrowserId 272 | } 273 | } 274 | 275 | JSExecute(js) { 276 | local 277 | if (this.JavascriptFromBookmark) { 278 | this.SetURL("javascript " js, True) 279 | return 280 | } 281 | ControlFocus, ahk_parent, % "ahk_id" this.BrowserId 282 | ControlSend, ahk_parent, {LCtrl up}{LAlt up}{LShift up}{RCtrl up}{RAlt up}{RShift up}, % "ahk_id" this.BrowserId 283 | ControlSend, ahk_parent, {ctrl down}{shift down}k{ctrl up}{shift up}, % "ahk_id" this.BrowserId 284 | this.GetCurrentDocumentElement() 285 | this.DocumentPanelElement.WaitElementExistByNameAndType("Switch to multi-line editor mode (Ctrl + B)", "Button") 286 | ClipSave := ClipboardAll 287 | Clipboard := js 288 | WinActivate, % "ahk_id" this.BrowserId 289 | WinWaitActive, % "ahk_id" this.BrowserId 290 | Send, {ctrl down}v{ctrl up}{enter down}{enter up} 291 | sleep 40 292 | Send, {ctrl down}{shift down}i{ctrl up}{shift up} 293 | Clipboard := ClipSave 294 | Clipsave= 295 | } 296 | 297 | ; Gets text from an alert-box 298 | GetAlertText(closeAlert:=True, timeOut:=3000) { 299 | local 300 | this.GetCurrentDocumentElement() 301 | startTime := A_TickCount 302 | alertEl := this.TWT.GetNextSiblingElement(this.TWT.GetFirstChildElement(this.DocumentPanelElement)) 303 | while (!(IsObject(dialogEl := alertEl.FindFirst("AutomationId=commonDialogWindow")) && IsObject(OKBut := dialogEl.FindFirst(this.ButtonControlCondition))) && ((A_tickCount - startTime) < timeOut)) 304 | Sleep, 100 305 | try text := dialogEl.FindFirst(this.TextControlCondition).CurrentName 306 | if closeAlert 307 | try OKBut.Click() 308 | return text 309 | } 310 | 311 | CloseAlert() { 312 | this.GetCurrentDocumentElement() 313 | try this.TWT.GetNextSiblingElement(this.TWT.GetFirstChildElement(this.DocumentPanelElement)).FindFirst("AutomationId=commonDialogWindow").FindFirst(this.ButtonControlCondition).Click() 314 | } 315 | 316 | ; Close tab by either providing the tab element or the name of the tab. If tabElementOrName is left empty, the current tab will be closed. 317 | CloseTab(tabElementOrName:="", matchMode:=3, caseSensitive:=True) { 318 | if (tabElementOrName != "") { 319 | if IsObject(tabElementOrName) { 320 | if (tabElementOrName.CurrentControlType == this.UIA.TabItemControlTypeId) 321 | tabElementOrName.Click() 322 | } else { 323 | try this.TabBarElement.FindFirstByNameAndType(tabElementOrName, "TabItem",, matchMode, caseSensitive).Click() 324 | } 325 | } 326 | ControlSend, ahk_parent, {LCtrl up}{LAlt up}{LShift up}{RCtrl up}{RAlt up}{RShift up}, % "ahk_id " this.BrowserId 327 | ControlSend, ahk_parent, {Ctrl down}w{Ctrl up}, % "ahk_id " this.BrowserId 328 | } 329 | } 330 | 331 | class UIA_Browser { 332 | InitiateUIA(wTitle:="A", customNames:="", maxVersion:="") { 333 | this.BrowserId := WinExist(wTitle) 334 | if !this.BrowserId 335 | throw Exception("UIA_Browser: failed to find the browser!", -1) 336 | this.UIA := UIA_Interface(maxVersion) 337 | this.TWT := this.UIA.TreeWalkerTrue 338 | this.CustomNames := (customNames == "") ? {} : customNames 339 | this.TextControlCondition := this.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.TextControlTypeId) 340 | this.ButtonControlCondition := this.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.ButtonControlTypeId) 341 | this.EditControlCondition := this.UIA.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.EditControlTypeId) 342 | this.ToolbarControlCondition := this.UIA.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.ToolBarControlTypeId) 343 | this.TabControlCondition := this.UIA.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.TabControlTypeId) 344 | this.ToolbarTreeWalker := this.UIA.CreateTreeWalker(this.ToolbarControlCondition) 345 | this.ButtonTreeWalker := this.UIA.CreateTreeWalker(this.ButtonControlCondition) 346 | this.BrowserElement := this.UIA.ElementFromHandle(this.BrowserId) 347 | this.GetCurrentMainPaneElement() 348 | } 349 | ; Initiates UIA and hooks to the browser window specified with wTitle. customNames can be an object that defines custom CurrentName values for locale-specific elements (such as the name of the URL bar): {URLEditName:"My URL Edit name", TabBarName:"Tab bar name", HomeButtonName:"Home button name", StopButtonName:"Stop button", NewTabButtonName:"New tab button name"}. maxVersion specifies the highest UIA version that will be used (default is up to version 7). 350 | __New(wTitle:="A", customNames:="", maxVersion:="") { 351 | local bt 352 | this.BrowserId := WinExist(wTitle) 353 | if !this.BrowserId 354 | throw Exception("UIA_Browser: failed to find the browser!", -1) 355 | WinGet, wExe, ProcessName, % "ahk_id" this.BrowserId 356 | WinGetClass, wClass, % "ahk_id" this.BrowserId 357 | this.BrowserType := (wExe == "chrome.exe") ? "Chrome" : (wExe == "msedge.exe") ? "Edge" : InStr(wClass, "Mozilla") ? "Mozilla" : "Unknown" 358 | bt := this.BrowserType 359 | if (bt != "Unknown") { 360 | this.base := UIA_%bt% 361 | this.__New(wTitle, customNames, maxVersion) 362 | } else 363 | this.InitiateUIA(wTitle, customNames, maxVersion) 364 | } 365 | 366 | __Get(member) { 367 | local 368 | global UIA_Enum 369 | if member not in base 370 | { 371 | if RegexMatch(member, "PatternId|EventId|PropertyId|AttributeId|ControlTypeId|AnnotationType|StyleId|LandmarkTypeId|HeadingLevel|ChangeId|MetadataId", match) 372 | return IsFunc("UIA_Enum.UIA_" match) ? UIA_Enum["UIA_" match](member) : UIA_Enum[match](member) 373 | else if (SubStr(member,1,1) != "_") { 374 | try return this.UIA[member] 375 | try return this.BrowserElement[member] 376 | } 377 | } 378 | } 379 | 380 | __Set(member, value) { 381 | if (member != "base") { 382 | if ObjRawGet(this, "UIA") 383 | try return this.UIA[member] := value 384 | if ObjRawGet(this, "BrowserElement") 385 | try return this.BrowserElement[member] := value 386 | } 387 | } 388 | 389 | __Call(member, params*) { 390 | local 391 | if !ObjHasKey(this.base, member) && !ObjHasKey(this.base.base, member) { 392 | try 393 | return this.UIA[member].Call(this.UIA, params*) 394 | catch e { 395 | if !InStr(e.Message, "Property not supported by the") 396 | throw Exception(e.Message, -1, e.What) 397 | } 398 | try 399 | return this.BrowserElement[member].Call(this.BrowserElement, params*) 400 | catch e { 401 | if !InStr(e.Message, "Property not supported by the") 402 | throw Exception(e.Message, -1, e.What) 403 | } 404 | throw Exception("Method call not supported by " this.__Class " nor UIA_Interface or UIA_Element class or an error was encountered.",-1,member) 405 | } 406 | } 407 | 408 | ; Refreshes UIA_Browser.MainPaneElement and returns it 409 | GetCurrentMainPaneElement() { 410 | this.BrowserElement.WaitElementExist("ControlType=Document") 411 | ; Finding the correct Toolbar ends up to be quite tricky. 412 | ; In Chrome the toolbar element is located in the tree after the content element, 413 | ; so if the content contains a toolbar then that will be returned. 414 | ; Two workarounds I can think of: either look for the Toolbar by name ("Address and search bar" 415 | ; both in Chrome and edge), or by location (it must be the topmost toolbar). I opted for a 416 | ; combination of two, so if finding by name fails, all toolbar elements are evaluated. 417 | Loop, 2 418 | { 419 | try this.URLEditElement := (this.BrowserType = "Chrome") ? this.BrowserElement.FindFirstWithOptions(4, this.EditControlCondition, 2) : this.BrowserElement.FindFirst(this.EditControlCondition) 420 | try { 421 | if (this.BrowserType = "Chrome") && !this.URLEditElement 422 | this.URLEditElement := this.UIA.CreateTreeWalker(this.EditControlCondition).GetLastChildElement(this.BrowserElement) 423 | this.NavigationBarElement := this.UIA.CreateTreeWalker(this.ToolbarControlCondition).GetParentElement(this.URLEditElement) 424 | this.MainPaneElement := this.TWT.GetParentElement(this.NavigationBarElement) 425 | if !this.NavigationBarElement 426 | this.NavigationBarElement := this.BrowserElement 427 | if !this.MainPaneElement 428 | this.MainPaneElement := this.BrowserElement 429 | ;if !(this.TabBarElement := this.BrowserElement.FindFirstByNameAndType(this.CustomNames.TabBarName ? this.CustomNames.TabBarName : "Tab bar", "Tab")) 430 | if !(this.TabBarElement := this.CreateTreeWalker(this.TabControlCondition).GetPreviousSiblingElement(this.NavigationBarElement)) 431 | this.TabBarElement := this.MainPaneElement 432 | Loop 2 { 433 | try { 434 | this.GetCurrentReloadButton() 435 | this.ReloadButtonFullDescription := this.ReloadButton.FullDescription 436 | this.ReloadButtonDescription := this.ReloadButton.GetCurrentPatternAs("LegacyIAccessible").CurrentDescription 437 | this.ReloadButtonName := this.ReloadButton.CurrentName 438 | } 439 | if (this.ReloadButtonFullDescription || this.ReloadButtonName || this.ReloadButtonDescription) 440 | break 441 | Sleep 200 442 | } 443 | return this.MainPaneElement 444 | } catch { 445 | WinActivate, % "ahk_id " this.BrowserId 446 | WinWaitActive, % "ahk_id " this.BrowserId,,1 447 | } 448 | } 449 | ; If all goes well, this part is not reached 450 | } 451 | 452 | ; Returns the current document/content element of the browser 453 | GetCurrentDocumentElement() { 454 | if !this.DocumentControlType 455 | this.DocumentControlType := this.UIA.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.DocumentControlTypeId) 456 | if (this.BrowserType = "Mozilla") 457 | return (this.CurrentDocumentElement := this.BrowserElement.FindFirstByNameAndType(this.GetTab().CurrentName, "Document")) 458 | return (this.CurrentDocumentElement := this.BrowserElement.FindFirst(this.DocumentControlType)) 459 | } 460 | 461 | GetCurrentReloadButton() { 462 | try CurrentName := this.ReloadButton.CurrentName 463 | try { 464 | if this.ReloadButton && CurrentName 465 | return this.ReloadButton 466 | } 467 | this.ReloadButton := this.ButtonTreeWalker.GetNextSiblingElement(this.ButtonTreeWalker.GetNextSiblingElement(this.ButtonTreeWalker.GetFirstChildElement(this.NavigationBarElement))) 468 | return this.ReloadButton 469 | } 470 | 471 | ; Uses Javascript to set the title of the browser. 472 | JSSetTitle(newTitle) { 473 | this.JSExecute("document.title=""" newTitle """; void(0);") 474 | } 475 | 476 | JSExecute(js) { 477 | this.SetURL("javascript:" js, True) 478 | } 479 | 480 | JSAlert(js, closeAlert:=True, timeOut:=3000) { 481 | this.JSExecute("alert(" js ");") 482 | return this.GetAlertText(closeAlert, timeOut) 483 | } 484 | 485 | ; Executes Javascript code through the address bar and returns the return value through the clipboard. 486 | JSReturnThroughClipboard(js) { 487 | local 488 | saveClip := ClipboardAll 489 | Clipboard= 490 | this.JSExecute("copyToClipboard(" js ");function copyToClipboard(text) {const elem = document.createElement('textarea');elem.value = text;document.body.appendChild(elem);elem.select();document.execCommand('copy');document.body.removeChild(elem);}") 491 | ClipWait,2 492 | returnText := Clipboard 493 | Clipboard := saveClip 494 | saveClip= 495 | return returnText 496 | } 497 | 498 | ; Executes Javascript code through the address bar and returns the return value through the browser windows title. 499 | JSReturnThroughTitle(js, timeOut:=500) { 500 | local 501 | WinGetTitle, origTitle, % "ahk_id " this.BrowserId 502 | this.JSExecute("origTitle=document.title;document.title=(" js ");void(0);setTimeout(function() {document.title=origTitle;void(0);}, " timeOut ")") 503 | startTime := A_TickCount 504 | Loop { 505 | WinGetTitle, newTitle, % "ahk_id " this.BrowserId 506 | Sleep, 40 507 | } Until ((origTitle != newTitle) || (A_TickCount - startTime > timeOut)) 508 | return (origTitle == newTitle) ? "" : RegexReplace(newTitle, "(?: - Personal)? - [^-]+$") 509 | } 510 | 511 | ; Uses Javascript's querySelector to get a Javascript element and then its position. useRenderWidgetPos=True uses position of the Chrome_RenderWidgetHostHWND1 control to locate the position element relative to the window, otherwise it uses UIA_Browsers CurrentDocumentElement position. 512 | JSGetElementPos(selector, useRenderWidgetPos:=False) { ; based on code by AHK Forums user william_ahk 513 | local 514 | js = 515 | (LTrim 516 | (() => { 517 | let bounds = document.querySelector("%selector%").getBoundingClientRect().toJSON(); 518 | let zoom = window.devicePixelRatio.toFixed(2); 519 | for (const key in bounds) { 520 | bounds[key] = bounds[key] * zoom; 521 | } 522 | return JSON.stringify(bounds); 523 | })() 524 | ) 525 | bounds_str := this.JSReturnThroughClipboard(js) 526 | RegexMatch(bounds_str, """x"":(\d+).?\d*?,""y"":(\d+).?\d*?,""width"":(\d+).?\d*?,""height"":(\d+).?\d*?", size) 527 | if useRenderWidgetPos { 528 | ControlGetPos, win_x, win_y, win_w, win_h, Chrome_RenderWidgetHostHWND1, % "ahk_id " this.BrowserId 529 | return {x:size1+win_x,y:size2+win_y,w:size3,h:size4} 530 | } else { 531 | br := this.GetCurrentDocumentElement().GetCurrentPos("window") 532 | return {x:size1+br.x,y:size2+br.y,w:size3,h:size4} 533 | } 534 | } 535 | 536 | ; Uses Javascript's querySelector to get and click a Javascript element. Compared with ClickJSElement method, this method has the advantage of skipping the need to wait for a return value from the clipboard, but it might be more unreliable (some elements might not support Javascript's "click()" properly). 537 | JSClickElement(selector) { 538 | this.JSExecute("document.querySelector(""" selector """).click();") 539 | } 540 | 541 | ; Uses Javascript's querySelector to get a Javascript element and then ControlClicks that position. useRenderWidgetPos=True uses position of the Chrome_RenderWidgetHostHWND1 control to locate the position element relative to the window, otherwise it uses UIA_Browsers CurrentDocumentElement position. 542 | ControlClickJSElement(selector, WhichButton:="", ClickCount:="", Options:="", useRenderWidgetPos:=False) { 543 | local 544 | bounds := this.JSGetElementPos(selector, useRenderWidgetPos) 545 | ControlClick % "X" (bounds.x + bounds.w // 2) " Y" (bounds.y + bounds.h // 2), % "ahk_id " this.browserId,, % WhichButton, % ClickCount, % Options 546 | } 547 | 548 | ; Uses Javascript's querySelector to get a Javascript element and then Clicks that position. useRenderWidgetPos=True uses position of the Chrome_RenderWidgetHostHWND1 control to locate the position element relative to the window, otherwise it uses UIA_Browsers CurrentDocumentElement position. 549 | ClickJSElement(selector, WhichButton:="", ClickCount:=1, DownOrUp:="", Relative:="", useRenderWidgetPos:=False) { 550 | local 551 | bounds := this.JSGetElementPos(selector, useRenderWidgetPos) 552 | Click % (bounds.x + bounds.w / 2) " " (bounds.y + bounds.h / 2)" " WhichButton (ClickCount ? " " ClickCount : "") (DownOrUp ? " " DownOrUp : "") (Relative ? " " Relative : "") 553 | } 554 | 555 | ; Gets text from an alert-box created with for example javascript:alert('message') 556 | GetAlertText(closeAlert:=True, timeOut:=3000) { 557 | local 558 | if !this.DialogTreeWalker 559 | this.DialogTreeWalker := this.UIA.CreateTreeWalker(this.CreateOrCondition(this.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.CustomControlTypeId), this.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.WindowControlTypeId))) 560 | startTime := A_TickCount 561 | while (!(IsObject(dialogEl := this.DialogTreeWalker.GetLastChildElement(this.BrowserElement)) && IsObject(OKBut := dialogEl.FindFirst(this.ButtonControlCondition))) && ((A_tickCount - startTime) < timeOut)) 562 | Sleep, 100 563 | try 564 | text := this.BrowserType = "Edge" ? dialogEl.FindFirstWithOptions(4, this.TextControlCondition, 2).CurrentName : dialogEl.FindFirst(this.TextControlCondition).CurrentName 565 | if closeAlert { 566 | Sleep, 500 567 | try OKBut.Click() 568 | } 569 | return text 570 | } 571 | 572 | CloseAlert() { 573 | local 574 | if !this.DialogTreeWalker 575 | this.DialogTreeWalker := this.UIA.CreateTreeWalker(this.CreateOrCondition(this.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.CustomControlTypeId), this.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.WindowControlTypeId))) 576 | try { 577 | dialogEl := this.DialogTreeWalker.GetLastChildElement(this.BrowserElement) 578 | OKBut := dialogEl.FindFirst(this.ButtonControlCondition) 579 | OKBut.Click() 580 | } 581 | } 582 | 583 | ; Gets all text from the browser element (CurrentName properties for all Text elements) 584 | GetAllText() { 585 | local 586 | if !this.IsBrowserVisible() 587 | WinActivate, % "ahk_id" this.BrowserId 588 | 589 | TextArray := this.BrowserElement.FindAll(this.TextControlCondition) 590 | Text := "" 591 | for k, v in TextArray 592 | Text .= v.CurrentName "`n" 593 | return Text 594 | } 595 | ; Gets all link elements from the browser 596 | GetAllLinks() { 597 | local 598 | if !this.IsBrowserVisible() 599 | WinActivate, % "ahk_id" this.BrowserId 600 | LinkCondition := this.UIA.CreatePropertyCondition(this.UIA.ControlTypePropertyId, this.UIA.HyperlinkControlTypeId) 601 | return this.BrowserElement.FindAll(LinkCondition) 602 | } 603 | 604 | __CompareTitles(compareTitle, winTitle, matchMode:="", caseSensitive:=True) { 605 | local 606 | if !matchMode 607 | matchMode := A_TitleMatchMode 608 | if (matchMode == 1) { 609 | if (caseSensitive ? (SubStr(winTitle, 1, StrLen(compareTitle)) == compareTitle) : (SubStr(winTitle, 1, StrLen(compareTitle)) = compareTitle)) 610 | return 1 611 | } else if (matchMode == 2) { 612 | if InStr(winTitle, compareTitle, caseSensitive) 613 | return 1 614 | } else if (matchMode == 3) { 615 | if (caseSensitive ? (compareTitle == winTitle) : (compareTitle = winTitle)) 616 | return 1 617 | } else if (matchMode = "RegEx") { 618 | if RegexMatch(winTitle, compareTitle) 619 | return 1 620 | } 621 | return 0 622 | } 623 | 624 | ; Waits the browser title to change to targetTitle (by default just waits for the title to change), timeOut is in milliseconds (default is indefinite waiting) 625 | WaitTitleChange(targetTitle:="", timeOut:=-1) { 626 | local 627 | WinGetTitle, origTitle, % "ahk_id" this.BrowserId 628 | startTime := A_TickCount, newTitle := origTitle 629 | while ((((A_TickCount - startTime) < timeOut) || (timeOut = -1)) && (targetTitle ? !this.__CompareTitles(targetTitle, newTitle) : (origTitle == newTitle))) { 630 | Sleep, 200 631 | WinGetActiveTitle, newTitle 632 | } 633 | } 634 | 635 | ; Waits the browser page to load to targetTitle, default timeOut is indefinite waiting, sleepAfter additionally sleeps for 200ms after the page has loaded. 636 | WaitPageLoad(targetTitle:="", timeOut:=-1, sleepAfter:=500, titleMatchMode:="", titleCaseSensitive:=False) { 637 | local 638 | legacyPattern := "", ReloadButtonName := "", ReloadButtonDescription := "", ReloadButtonFullDescription := "" 639 | Sleep, 200 ; Give some time for the Reload button to change after navigating 640 | if this.ReloadButtonDescription 641 | try legacyPattern := this.ReloadButton.GetCurrentPatternAs("LegacyIAccessible") 642 | startTime := A_TickCount 643 | while ((A_TickCount - startTime) < timeOut) || (timeOut = -1) { 644 | if this.BrowserType = "Mozilla" 645 | this.GetCurrentReloadButton() 646 | try ReloadButtonName := this.ReloadButton.CurrentName 647 | try ReloadButtonDescription := legacyPattern.CurrentDescription 648 | try ReloadButtonFullDescription := this.ReloadButton.CurrentFullDescription 649 | if ((this.ReloadButtonName ? InStr(ReloadButtonName, this.ReloadButtonName) : 1) 650 | && (this.ReloadButtonDescription ? InStr(ReloadButtonDescription, this.ReloadButtonDescription) : 1) 651 | && (this.ReloadButtonFullDescription ? InStr(ReloadButtonFullDescription, this.ReloadButtonFullDescription) : 1)) { 652 | if targetTitle { 653 | WinGetTitle, wTitle, % "ahk_id" this.BrowserId 654 | if this.__CompareTitles(targetTitle, wTitle, titleMatchMode, titleCaseSensitive) 655 | break 656 | } else 657 | break 658 | } 659 | Sleep, 40 660 | } 661 | if ((A_TickCount - startTime) < timeOut) || (timeOut = -1) 662 | Sleep, %sleepAfter% 663 | } 664 | 665 | ; Presses the Back button 666 | Back() { 667 | this.ButtonTreeWalker.GetFirstChildElement(this.NavigationBarElement).Click() 668 | } 669 | 670 | ; Presses the Forward button 671 | Forward() { 672 | this.ButtonTreeWalker.GetNextSiblingElement(this.ButtonTreeWalker.GetFirstChildElement(this.NavigationBarElement)).Click() 673 | } 674 | 675 | ; Presses the Reload button 676 | Reload() { 677 | this.GetCurrentReloadButton().Click() 678 | } 679 | 680 | ; Presses the Home button if it exists. 681 | Home() { 682 | local 683 | if (this.ReloadButton && (homeBut := this.ButtonTreeWalker.GetNextSiblingElement(this.ReloadButton))) 684 | return homeBut.Click() 685 | ;NameCondition := this.UIA.CreatePropertyCondition(this.UIA.NamePropertyId, this.CustomNames.HomeButtonName ? this.CustomNames.HomeButtonName : butName) 686 | ;this.NavigationBarElement.FindFirst(this.UIA.CreateAndCondition(NameCondition, this.ButtonControlCondition)).Click() 687 | } 688 | 689 | ; Gets the current URL. fromAddressBar=True gets it straight from the URL bar element, which is not a very good method, because the text might be changed by the user and doesn't start with "http(s)://". Default of fromAddressBar=False will cause the real URL to be fetched, but the browser must be visible for it to work (if is not visible, it will be automatically activated). 690 | GetCurrentURL(fromAddressBar:=False) { 691 | local 692 | if fromAddressBar { 693 | URL := this.URLEditElement.CurrentValue 694 | return URL ? (RegexMatch(URL, "^https?:\/\/") ? URL : "https://" URL) : "" 695 | } else { 696 | ; This can be used in Chrome and Edge, but works only if the window is active 697 | if (!this.IsBrowserVisible() && (this.BrowserType != "Mozilla")) 698 | WinActivate, % "ahk_id" this.BrowserId 699 | return this.GetCurrentDocumentElement().CurrentValue 700 | } 701 | } 702 | 703 | ; Sets the URL bar to newUrl, optionally also navigates to it if navigateToNewUrl=True 704 | SetURL(newUrl, navigateToNewUrl := False) { 705 | local 706 | this.URLEditElement.SetFocus() 707 | valuePattern := this.URLEditElement.GetCurrentPatternAs("Value") 708 | valuePattern.SetValue(newUrl " ") 709 | if !InStr(this.URLEditElement.CurrentValue, newUrl) { 710 | legacyPattern := this.URLEditElement.GetCurrentPatternAs("LegacyIAccessible") 711 | legacyPattern.SetValue(newUrl " ") 712 | legacyPattern.Select() 713 | } 714 | if (navigateToNewUrl&&InStr(this.URLEditElement.CurrentValue, newUrl)) { 715 | if (this.BrowserType = "Mozilla") 716 | ControlFocus, ahk_parent, % "ahk_id" this.BrowserId 717 | ControlSend, ahk_parent, {LCtrl up}{LAlt up}{LShift up}{RCtrl up}{RAlt up}{RShift up}{Enter}, % "ahk_id" this.BrowserId ; Or would it be better to use BlockInput instead of releasing modifier keys? 718 | } 719 | } 720 | 721 | ; Navigates to URL and waits page to load 722 | Navigate(url, targetTitle:="", waitLoadTimeOut:=-1, sleepAfter:=500) { 723 | this.SetURL(url, True) 724 | this.WaitPageLoad(targetTitle,waitLoadTimeOut,sleepAfter) 725 | } 726 | 727 | ; Presses the New tab button. The button name might differ if the browser language is not set to English and can be specified with butName 728 | NewTab() { 729 | local 730 | try el := this.TabBarElement.FindFirstWithOptions(4,this.ButtonControlCondition,2) 731 | if el 732 | el.Click() 733 | else { 734 | this.UIA.CreateTreeWalker(this.ButtonControlCondition).GetLastChildElement(this.TabBarElement).Click() 735 | } 736 | ;newTabBut := this.TabBarElement.FindFirstByNameAndType(this.CustomNames.NewTabButtonName ? this.CustomNames.NewTabButtonName : butName, UIA_Enum.UIA_ButtonControlTypeId,,matchMode,caseSensitive) 737 | ;newTabBut.Click() 738 | } 739 | 740 | GetAllTabs() { 741 | return this.TabBarElement.FindAll(this.UIA.CreatePropertyCondition(this.UIA.ControlTypePropertyId, UIA_Enum.UIA_ControlTypeId("TabItem"))) 742 | } 743 | ; Gets all tab elements matching searchPhrase, matchMode and caseSensitive 744 | ; If searchPhrase is omitted then all tabs will be returned 745 | GetTabs(searchPhrase:="", matchMode:=3, caseSensitive:=True) { 746 | return (searchPhrase == "") ? this.TabBarElement.FindAll(this.UIA.CreatePropertyCondition(this.UIA.ControlTypePropertyId, UIA_Enum.UIA_ControlTypeId("TabItem"))) : this.TabBarElement.FindAllByNameAndType(searchPhrase, "TabItem",, matchMode, caseSensitive) 747 | } 748 | 749 | ; Gets all the titles of tabs 750 | GetAllTabNames() { 751 | local 752 | names := [] 753 | for k, v in this.GetTabs() { 754 | names.Push(v.CurrentName) 755 | } 756 | return names 757 | } 758 | 759 | ; Returns a tab element with text of searchPhrase, or if empty then the currently selected tab. matchMode follows SetTitleMatchMode scheme: 1=tab name must must start with tabName; 2=can contain anywhere; 3=exact match; RegEx 760 | GetTab(searchPhrase:="", matchMode:=3, caseSensitive:=True) { 761 | return (searchPhrase == "") ? this.TabBarElement.FindFirstBy("ControlType=TabItem AND SelectionItemIsSelected=1") : this.TabBarElement.FindFirstByNameAndType(searchPhrase, "TabItem",, matchMode, caseSensitive) 762 | } 763 | 764 | ; Selects a tab with the text of tabName. matchMode follows SetTitleMatchMode scheme: 1=tab name must must start with tabName; 2=can contain anywhere; 3=exact match; RegEx 765 | SelectTab(tabName, matchMode:=3, caseSensitive:=True) { 766 | local 767 | (selectedTab := this.TabBarElement.FindFirstByNameAndType(tabName, "TabItem",, matchMode, caseSensitive)).Click() 768 | return selectedTab 769 | } 770 | 771 | ; Close tab by either providing the tab element or the name of the tab. If tabElementOrName is left empty, the current tab will be closed. 772 | CloseTab(tabElementOrName:="", matchMode:=3, caseSensitive:=True) { 773 | if IsObject(tabElementOrName) { 774 | if (tabElementOrName.CurrentControlType == this.UIA.TabItemControlTypeId) 775 | try this.TWT.GetLastChildElement(tabElementOrName).Click() 776 | } else { 777 | if (tabElementOrName == "") { 778 | try this.TWT.GetLastChildElement(this.GetTab()).Click() 779 | } else 780 | try this.TWT.GetLastChildElement(this.TabBarElement.FindFirstByNameAndType(tabElementOrName, "TabItem",, matchMode, caseSensitive)).Click() 781 | } 782 | } 783 | 784 | ; Returns True if any of window 4 corners are visible 785 | IsBrowserVisible() { 786 | local 787 | WinGetPos, X, Y, W, H, % "ahk_id" this.BrowserId 788 | if ((this.BrowserId == this.WindowFromPoint(X, Y)) || (this.BrowserId == this.WindowFromPoint(X, Y+H-1)) || (this.BrowserId == this.WindowFromPoint(X+W-1, Y)) || (this.BrowserId == this.WindowFromPoint(X+W-1, Y+H-1))) 789 | return True 790 | return False 791 | } 792 | 793 | Send(text) { 794 | if (this.BrowserType = "Mozilla") 795 | ControlFocus, ahk_parent, % "ahk_id" this.BrowserId 796 | ControlSend, ahk_parent, {LCtrl up}{LAlt up}{LShift up}{RCtrl up}{RAlt up}{RShift up}{Enter}, % "ahk_id" this.BrowserId 797 | ControlSend, ahk_parent, % text, % "ahk_id" this.BrowserId 798 | } 799 | 800 | WindowFromPoint(X, Y) { ; by SKAN and Linear Spoon 801 | return DllCall( "GetAncestor", "UInt" 802 | , DllCall( "WindowFromPoint", "UInt64", X | (Y << 32)) 803 | , "UInt", 2 ) ; GA_ROOT 804 | } 805 | 806 | PrintArray(arr) { 807 | local 808 | global UIA_Browser 809 | ret := "" 810 | for k, v in arr 811 | ret .= "Key: " k " Value: " (IsFunc(v)? v.name:IsObject(v)?UIA_Browser.PrintArray(v):v) "`n" 812 | return ret 813 | } 814 | } -------------------------------------------------------------------------------- /Lib/UIA_Constants.ahk: -------------------------------------------------------------------------------- 1 | ; UIA Constants, credit to LarsJ from https://www.autoitscript.com/forum/topic/201683-ui-automation-udfs/ 2 | ; Variant types for Property Ids: https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-automation-element-propids 3 | 4 | global sCLSID_UIAutomationClient := "{944DE083-8FB8-45CF-BCB7-C477ACB2F897}" 5 | 6 | ;CoClasses 7 | , sCLSID_CUIAutomation := "{FF48DBA4-60EF-4201-AA87-54103EEF594E}" 8 | ;module UIA_PatternIds 9 | global UIA_InvokePatternId := 10000 10 | , UIA_SelectionPatternId := 10001 11 | , UIA_ValuePatternId := 10002 12 | , UIA_RangeValuePatternId := 10003 13 | , UIA_ScrollPatternId := 10004 14 | , UIA_ExpandCollapsePatternId := 10005 15 | , UIA_GridPatternId := 10006 16 | , UIA_GridItemPatternId := 10007 17 | , UIA_MultipleViewPatternId := 10008 18 | , UIA_WindowPatternId := 10009 19 | , UIA_SelectionItemPatternId := 10010 20 | , UIA_DockPatternId := 10011 21 | , UIA_TablePatternId := 10012 22 | , UIA_TableItemPatternId := 10013 23 | , UIA_TextPatternId := 10014 24 | , UIA_TogglePatternId := 10015 25 | , UIA_TransformPatternId := 10016 26 | , UIA_ScrollItemPatternId := 10017 27 | , UIA_LegacyIAccessiblePatternId := 10018 28 | , UIA_ItemContainerPatternId := 10019 29 | , UIA_VirtualizedItemPatternId := 10020 30 | , UIA_SynchronizedInputPatternId := 10021 31 | , UIA_ObjectModelPatternId := 10022 32 | , UIA_AnnotationPatternId := 10023 33 | , UIA_TextPattern2Id := 10024 34 | , UIA_StylesPatternId := 10025 35 | , UIA_SpreadsheetPatternId := 10026 36 | , UIA_SpreadsheetItemPatternId := 10027 37 | , UIA_TransformPattern2Id := 10028 38 | , UIA_TextChildPatternId := 10029 39 | , UIA_DragPatternId := 10030 40 | , UIA_DropTargetPatternId := 10031 41 | , UIA_TextEditPatternId := 10032 42 | , UIA_CustomNavigationPatternId := 10033 43 | , UIA_SelectionPattern2Id := 10034 44 | 45 | ;module UIA_EventIds 46 | global UIA_ToolTipOpenedEventId := 20000 47 | , UIA_ToolTipClosedEventId := 20001 48 | , UIA_StructureChangedEventId := 20002 49 | , UIA_MenuOpenedEventId := 20003 50 | , UIA_AutomationPropertyChangedEventId := 20004 51 | , UIA_AutomationFocusChangedEventId := 20005 52 | , UIA_AsyncContentLoadedEventId := 20006 53 | , UIA_MenuClosedEventId := 20007 54 | , UIA_LayoutInvalidatedEventId := 20008 55 | , UIA_Invoke_InvokedEventId := 20009 56 | , UIA_SelectionItem_ElementAddedToSelectionEventId := 20010 57 | , UIA_SelectionItem_ElementRemovedFromSelectionEventId := 20011 58 | , UIA_SelectionItem_ElementSelectedEventId := 20012 59 | , UIA_Selection_InvalidatedEventId := 20013 60 | , UIA_Text_TextSelectionChangedEventId := 20014 61 | , UIA_Text_TextChangedEventId := 20015 62 | , UIA_Window_WindowOpenedEventId := 20016 63 | , UIA_Window_WindowClosedEventId := 20017 64 | , UIA_MenuModeStartEventId := 20018 65 | , UIA_MenuModeEndEventId := 20019 66 | , UIA_InputReachedTargetEventId := 20020 67 | , UIA_InputReachedOtherElementEventId := 20021 68 | , UIA_InputDiscardedEventId := 20022 69 | , UIA_SystemAlertEventId := 20023 70 | , UIA_LiveRegionChangedEventId := 20024 71 | , UIA_HostedFragmentRootsInvalidatedEventId := 20025 72 | , UIA_Drag_DragStartEventId := 20026 73 | , UIA_Drag_DragCancelEventId := 20027 74 | , UIA_Drag_DragCompleteEventId := 20028 75 | , UIA_DropTarget_DragEnterEventId := 20029 76 | , UIA_DropTarget_DragLeaveEventId := 20030 77 | , UIA_DropTarget_DroppedEventId := 20031 78 | , UIA_TextEdit_TextChangedEventId := 20032 79 | , UIA_TextEdit_ConversionTargetChangedEventId := 20033 80 | , UIA_ChangesEventId := 20034 81 | , UIA_NotificationEventId := 20035 82 | , UIA_ActiveTextPositionChangedEventId := 20036 83 | 84 | ;module UIA_PropertyIds 85 | global UIA_RuntimeIdPropertyId := 30000 86 | , UIA_BoundingRectanglePropertyId := 30001 87 | , UIA_ProcessIdPropertyId := 30002 88 | , UIA_ControlTypePropertyId := 30003 89 | , UIA_LocalizedControlTypePropertyId := 30004 90 | , UIA_NamePropertyId := 30005 91 | , UIA_AcceleratorKeyPropertyId := 30006 92 | , UIA_AccessKeyPropertyId := 30007 93 | , UIA_HasKeyboardFocusPropertyId := 30008 94 | , UIA_IsKeyboardFocusablePropertyId := 30009 95 | , UIA_IsEnabledPropertyId := 30010 96 | , UIA_AutomationIdPropertyId := 30011 97 | , UIA_ClassNamePropertyId := 30012 98 | , UIA_HelpTextPropertyId := 30013 99 | , UIA_ClickablePointPropertyId := 30014 100 | , UIA_CulturePropertyId := 30015 101 | , UIA_IsControlElementPropertyId := 30016 102 | , UIA_IsContentElementPropertyId := 30017 103 | , UIA_LabeledByPropertyId := 30018 104 | , UIA_IsPasswordPropertyId := 30019 105 | , UIA_NativeWindowHandlePropertyId := 30020 106 | , UIA_ItemTypePropertyId := 30021 107 | , UIA_IsOffscreenPropertyId := 30022 108 | , UIA_OrientationPropertyId := 30023 109 | , UIA_FrameworkIdPropertyId := 30024 110 | , UIA_IsRequiredForFormPropertyId := 30025 111 | , UIA_ItemStatusPropertyId := 30026 112 | , UIA_IsDockPatternAvailablePropertyId := 30027 113 | , UIA_IsExpandCollapsePatternAvailablePropertyId := 30028 114 | , UIA_IsGridItemPatternAvailablePropertyId := 30029 115 | , UIA_IsGridPatternAvailablePropertyId := 30030 116 | , UIA_IsInvokePatternAvailablePropertyId := 30031 117 | , UIA_IsMultipleViewPatternAvailablePropertyId := 30032 118 | , UIA_IsRangeValuePatternAvailablePropertyId := 30033 119 | , UIA_IsScrollPatternAvailablePropertyId := 30034 120 | , UIA_IsScrollItemPatternAvailablePropertyId := 30035 121 | , UIA_IsSelectionItemPatternAvailablePropertyId := 30036 122 | , UIA_IsSelectionPatternAvailablePropertyId := 30037 123 | , UIA_IsTablePatternAvailablePropertyId := 30038 124 | , UIA_IsTableItemPatternAvailablePropertyId := 30039 125 | , UIA_IsTextPatternAvailablePropertyId := 30040 126 | , UIA_IsTogglePatternAvailablePropertyId := 30041 127 | , UIA_IsTransformPatternAvailablePropertyId := 30042 128 | , UIA_IsValuePatternAvailablePropertyId := 30043 129 | , UIA_IsWindowPatternAvailablePropertyId := 30044 130 | , UIA_ValueValuePropertyId := 30045 131 | , UIA_ValueIsReadOnlyPropertyId := 30046 132 | , UIA_RangeValueValuePropertyId := 30047 133 | , UIA_RangeValueIsReadOnlyPropertyId := 30048 134 | , UIA_RangeValueMinimumPropertyId := 30049 135 | , UIA_RangeValueMaximumPropertyId := 30050 136 | , UIA_RangeValueLargeChangePropertyId := 30051 137 | , UIA_RangeValueSmallChangePropertyId := 30052 138 | , UIA_ScrollHorizontalScrollPercentPropertyId := 30053 139 | , UIA_ScrollHorizontalViewSizePropertyId := 30054 140 | , UIA_ScrollVerticalScrollPercentPropertyId := 30055 141 | , UIA_ScrollVerticalViewSizePropertyId := 30056 142 | , UIA_ScrollHorizontallyScrollablePropertyId := 30057 143 | , UIA_ScrollVerticallyScrollablePropertyId := 30058 144 | , UIA_SelectionSelectionPropertyId := 30059 145 | , UIA_SelectionCanSelectMultiplePropertyId := 30060 146 | , UIA_SelectionIsSelectionRequiredPropertyId := 30061 147 | , UIA_GridRowCountPropertyId := 30062 148 | , UIA_GridColumnCountPropertyId := 30063 149 | , UIA_GridItemRowPropertyId := 30064 150 | , UIA_GridItemColumnPropertyId := 30065 151 | , UIA_GridItemRowSpanPropertyId := 30066 152 | , UIA_GridItemColumnSpanPropertyId := 30067 153 | , UIA_GridItemContainingGridPropertyId := 30068 154 | , UIA_DockDockPositionPropertyId := 30069 155 | , UIA_ExpandCollapseExpandCollapseStatePropertyId := 30070 156 | , UIA_MultipleViewCurrentViewPropertyId := 30071 157 | , UIA_MultipleViewSupportedViewsPropertyId := 30072 158 | , UIA_WindowCanMaximizePropertyId := 30073 159 | , UIA_WindowCanMinimizePropertyId := 30074 160 | , UIA_WindowWindowVisualStatePropertyId := 30075 161 | , UIA_WindowWindowInteractionStatePropertyId := 30076 162 | , UIA_WindowIsModalPropertyId := 30077 163 | , UIA_WindowIsTopmostPropertyId := 30078 164 | , UIA_SelectionItemIsSelectedPropertyId := 30079 165 | , UIA_SelectionItemSelectionContainerPropertyId := 30080 166 | , UIA_TableRowHeadersPropertyId := 30081 167 | , UIA_TableColumnHeadersPropertyId := 30082 168 | , UIA_TableRowOrColumnMajorPropertyId := 30083 169 | , UIA_TableItemRowHeaderItemsPropertyId := 30084 170 | , UIA_TableItemColumnHeaderItemsPropertyId := 30085 171 | , UIA_ToggleToggleStatePropertyId := 30086 172 | , UIA_TransformCanMovePropertyId := 30087 173 | , UIA_TransformCanResizePropertyId := 30088 174 | , UIA_TransformCanRotatePropertyId := 30089 175 | , UIA_IsLegacyIAccessiblePatternAvailablePropertyId := 30090 176 | , UIA_LegacyIAccessibleChildIdPropertyId := 30091 177 | , UIA_LegacyIAccessibleNamePropertyId := 30092 178 | , UIA_LegacyIAccessibleValuePropertyId := 30093 179 | , UIA_LegacyIAccessibleDescriptionPropertyId := 30094 180 | , UIA_LegacyIAccessibleRolePropertyId := 30095 181 | , UIA_LegacyIAccessibleStatePropertyId := 30096 182 | , UIA_LegacyIAccessibleHelpPropertyId := 30097 183 | , UIA_LegacyIAccessibleKeyboardShortcutPropertyId := 30098 184 | , UIA_LegacyIAccessibleSelectionPropertyId := 30099 185 | , UIA_LegacyIAccessibleDefaultActionPropertyId := 30100 186 | , UIA_AriaRolePropertyId := 30101 187 | , UIA_AriaPropertiesPropertyId := 30102 188 | , UIA_IsDataValidForFormPropertyId := 30103 189 | , UIA_ControllerForPropertyId := 30104 190 | , UIA_DescribedByPropertyId := 30105 191 | , UIA_FlowsToPropertyId := 30106 192 | , UIA_ProviderDescriptionPropertyId := 30107 193 | , UIA_IsItemContainerPatternAvailablePropertyId := 30108 194 | , UIA_IsVirtualizedItemPatternAvailablePropertyId := 30109 195 | , UIA_IsSynchronizedInputPatternAvailablePropertyId := 30110 196 | , UIA_OptimizeForVisualContentPropertyId := 30111 197 | , UIA_IsObjectModelPatternAvailablePropertyId := 30112 198 | , UIA_AnnotationAnnotationTypeIdPropertyId := 30113 199 | , UIA_AnnotationAnnotationTypeNamePropertyId := 30114 200 | , UIA_AnnotationAuthorPropertyId := 30115 201 | , UIA_AnnotationDateTimePropertyId := 30116 202 | , UIA_AnnotationTargetPropertyId := 30117 203 | , UIA_IsAnnotationPatternAvailablePropertyId := 30118 204 | , UIA_IsTextPattern2AvailablePropertyId := 30119 205 | , UIA_StylesStyleIdPropertyId := 30120 206 | , UIA_StylesStyleNamePropertyId := 30121 207 | , UIA_StylesFillColorPropertyId := 30122 208 | , UIA_StylesFillPatternStylePropertyId := 30123 209 | , UIA_StylesShapePropertyId := 30124 210 | , UIA_StylesFillPatternColorPropertyId := 30125 211 | , UIA_StylesExtendedPropertiesPropertyId := 30126 212 | , UIA_IsStylesPatternAvailablePropertyId := 30127 213 | , UIA_IsSpreadsheetPatternAvailablePropertyId := 30128 214 | , UIA_SpreadsheetItemFormulaPropertyId := 30129 215 | , UIA_SpreadsheetItemAnnotationObjectsPropertyId := 30130 216 | , UIA_SpreadsheetItemAnnotationTypesPropertyId := 30131 217 | , UIA_IsSpreadsheetItemPatternAvailablePropertyId := 30132 218 | , UIA_Transform2CanZoomPropertyId := 30133 219 | , UIA_IsTransformPattern2AvailablePropertyId := 30134 220 | , UIA_LiveSettingPropertyId := 30135 221 | , UIA_IsTextChildPatternAvailablePropertyId := 30136 222 | , UIA_IsDragPatternAvailablePropertyId := 30137 223 | , UIA_DragIsGrabbedPropertyId := 30138 224 | , UIA_DragDropEffectPropertyId := 30139 225 | , UIA_DragDropEffectsPropertyId := 30140 226 | , UIA_IsDropTargetPatternAvailablePropertyId := 30141 227 | , UIA_DropTargetDropTargetEffectPropertyId := 30142 228 | , UIA_DropTargetDropTargetEffectsPropertyId := 30143 229 | , UIA_DragGrabbedItemsPropertyId := 30144 230 | , UIA_Transform2ZoomLevelPropertyId := 30145 231 | , UIA_Transform2ZoomMinimumPropertyId := 30146 232 | , UIA_Transform2ZoomMaximumPropertyId := 30147 233 | , UIA_FlowsFromPropertyId := 30148 234 | , UIA_IsTextEditPatternAvailablePropertyId := 30149 235 | , UIA_IsPeripheralPropertyId := 30150 236 | , UIA_IsCustomNavigationPatternAvailablePropertyId := 30151 237 | , UIA_PositionInSetPropertyId := 30152 238 | , UIA_SizeOfSetPropertyId := 30153 239 | , UIA_LevelPropertyId := 30154 240 | , UIA_AnnotationTypesPropertyId := 30155 241 | , UIA_AnnotationObjectsPropertyId := 30156 242 | , UIA_LandmarkTypePropertyId := 30157 243 | , UIA_LocalizedLandmarkTypePropertyId := 30158 244 | , UIA_FullDescriptionPropertyId := 30159 245 | , UIA_FillColorPropertyId := 30160 246 | , UIA_OutlineColorPropertyId := 30161 247 | , UIA_FillTypePropertyId := 30162 248 | , UIA_VisualEffectsPropertyId := 30163 249 | , UIA_OutlineThicknessPropertyId := 30164 250 | , UIA_CenterPointPropertyId := 30165 251 | , UIA_RotationPropertyId := 30166 252 | , UIA_SizePropertyId := 30167 253 | , UIA_IsSelectionPattern2AvailablePropertyId := 30168 254 | , UIA_Selection2FirstSelectedItemPropertyId := 30169 255 | , UIA_Selection2LastSelectedItemPropertyId := 30170 256 | , UIA_Selection2CurrentSelectedItemPropertyId := 30171 257 | , UIA_Selection2ItemCountPropertyId := 30172 258 | , UIA_HeadingLevelPropertyId := 30173 259 | , UIA_IsDialogPropertyId := 30174 260 | 261 | ;module UIA_TextAttributeIds 262 | global UIA_AnimationStyleAttributeId := 40000 263 | , UIA_BackgroundColorAttributeId := 40001 264 | , UIA_BulletStyleAttributeId := 40002 265 | , UIA_CapStyleAttributeId := 40003 266 | , UIA_CultureAttributeId := 40004 267 | , UIA_FontNameAttributeId := 40005 268 | , UIA_FontSizeAttributeId := 40006 269 | , UIA_FontWeightAttributeId := 40007 270 | , UIA_ForegroundColorAttributeId := 40008 271 | , UIA_HorizontalTextAlignmentAttributeId := 40009 272 | , UIA_IndentationFirstLineAttributeId := 40010 273 | , UIA_IndentationLeadingAttributeId := 40011 274 | , UIA_IndentationTrailingAttributeId := 40012 275 | , UIA_IsHiddenAttributeId := 40013 276 | , UIA_IsItalicAttributeId := 40014 277 | , UIA_IsReadOnlyAttributeId := 40015 278 | , UIA_IsSubscriptAttributeId := 40016 279 | , UIA_IsSuperscriptAttributeId := 40017 280 | , UIA_MarginBottomAttributeId := 40018 281 | , UIA_MarginLeadingAttributeId := 40019 282 | , UIA_MarginTopAttributeId := 40020 283 | , UIA_MarginTrailingAttributeId := 40021 284 | , UIA_OutlineStylesAttributeId := 40022 285 | , UIA_OverlineColorAttributeId := 40023 286 | , UIA_OverlineStyleAttributeId := 40024 287 | , UIA_StrikethroughColorAttributeId := 40025 288 | , UIA_StrikethroughStyleAttributeId := 40026 289 | , UIA_TabsAttributeId := 40027 290 | , UIA_TextFlowDirectionsAttributeId := 40028 291 | , UIA_UnderlineColorAttributeId := 40029 292 | , UIA_UnderlineStyleAttributeId := 40030 293 | , UIA_AnnotationTypesAttributeId := 40031 294 | , UIA_AnnotationObjectsAttributeId := 40032 295 | , UIA_StyleNameAttributeId := 40033 296 | , UIA_StyleIdAttributeId := 40034 297 | , UIA_LinkAttributeId := 40035 298 | , UIA_IsActiveAttributeId := 40036 299 | , UIA_SelectionActiveEndAttributeId := 40037 300 | , UIA_CaretPositionAttributeId := 40038 301 | , UIA_CaretBidiModeAttributeId := 40039 302 | , UIA_LineSpacingAttributeId := 40040 303 | , UIA_BeforeParagraphSpacingAttributeId := 40041 304 | , UIA_AfterParagraphSpacingAttributeId := 40042 305 | , UIA_SayAsInterpretAsAttributeId := 40043 306 | 307 | ;module UIA_ControlTypeIds 308 | global UIA_ButtonControlTypeId := 50000 309 | , UIA_CalendarControlTypeId := 50001 310 | , UIA_CheckBoxControlTypeId := 50002 311 | , UIA_ComboBoxControlTypeId := 50003 312 | , UIA_EditControlTypeId := 50004 313 | , UIA_HyperlinkControlTypeId := 50005 314 | , UIA_ImageControlTypeId := 50006 315 | , UIA_ListItemControlTypeId := 50007 316 | , UIA_ListControlTypeId := 50008 317 | , UIA_MenuControlTypeId := 50009 318 | , UIA_MenuBarControlTypeId := 50010 319 | , UIA_MenuItemControlTypeId := 50011 320 | , UIA_ProgressBarControlTypeId := 50012 321 | , UIA_RadioButtonControlTypeId := 50013 322 | , UIA_ScrollBarControlTypeId := 50014 323 | , UIA_SliderControlTypeId := 50015 324 | , UIA_SpinnerControlTypeId := 50016 325 | , UIA_StatusBarControlTypeId := 50017 326 | , UIA_TabControlTypeId := 50018 327 | , UIA_TabItemControlTypeId := 50019 328 | , UIA_TextControlTypeId := 50020 329 | , UIA_ToolBarControlTypeId := 50021 330 | , UIA_ToolTipControlTypeId := 50022 331 | , UIA_TreeControlTypeId := 50023 332 | , UIA_TreeItemControlTypeId := 50024 333 | , UIA_CustomControlTypeId := 50025 334 | , UIA_GroupControlTypeId := 50026 335 | , UIA_ThumbControlTypeId := 50027 336 | , UIA_DataGridControlTypeId := 50028 337 | , UIA_DataItemControlTypeId := 50029 338 | , UIA_DocumentControlTypeId := 50030 339 | , UIA_SplitButtonControlTypeId := 50031 340 | , UIA_WindowControlTypeId := 50032 341 | , UIA_PaneControlTypeId := 50033 342 | , UIA_HeaderControlTypeId := 50034 343 | , UIA_HeaderItemControlTypeId := 50035 344 | , UIA_TableControlTypeId := 50036 345 | , UIA_TitleBarControlTypeId := 50037 346 | , UIA_SeparatorControlTypeId := 50038 347 | , UIA_SemanticZoomControlTypeId := 50039 348 | , UIA_AppBarControlTypeId := 50040 349 | 350 | ; module AnnotationType 351 | , UIA_AnnotationType_Unknown := 60000 352 | , UIA_AnnotationType_SpellingError := 60001 353 | , UIA_AnnotationType_GrammarError := 60002 354 | , UIA_AnnotationType_Comment := 60003 355 | , UIA_AnnotationType_FormulaError := 60004 356 | , UIA_AnnotationType_TrackChanges := 60005 357 | , UIA_AnnotationType_Header := 60006 358 | , UIA_AnnotationType_Footer := 60007 359 | , UIA_AnnotationType_Highlighted := 60008 360 | , UIA_AnnotationType_Endnote := 60009 361 | , UIA_AnnotationType_Footnote := 60010 362 | , UIA_AnnotationType_InsertionChange := 60011 363 | , UIA_AnnotationType_DeletionChange := 60012 364 | , UIA_AnnotationType_MoveChange := 60013 365 | , UIA_AnnotationType_FormatChange := 60014 366 | , UIA_AnnotationType_UnsyncedChange := 60015 367 | , UIA_AnnotationType_EditingLockedChange := 60016 368 | , UIA_AnnotationType_ExternalChange := 60017 369 | , UIA_AnnotationType_ConflictingChange := 60018 370 | , UIA_AnnotationType_Author := 60019 371 | , UIA_AnnotationType_AdvancedProofingIssue := 60020 372 | , UIA_AnnotationType_DataValidationError := 60021 373 | , UIA_AnnotationType_CircularReferenceError := 60022 374 | , UIA_AnnotationType_Mathematics := 60023 375 | 376 | ;enum StyleId 377 | , UIA_StyleId_Custom := 70000 378 | , UIA_StyleId_Heading1 := 70001 379 | , UIA_StyleId_Heading2 := 70002 380 | , UIA_StyleId_Heading3 := 70003 381 | , UIA_StyleId_Heading4 := 70004 382 | , UIA_StyleId_Heading5 := 70005 383 | , UIA_StyleId_Heading6 := 70006 384 | , UIA_StyleId_Heading7 := 70007 385 | , UIA_StyleId_Heading8 := 70008 386 | , UIA_StyleId_Heading9 := 70009 387 | , UIA_StyleId_Title := 70010 388 | , UIA_StyleId_Subtitle := 70011 389 | , UIA_StyleId_Normal := 70012 390 | , UIA_StyleId_Emphasis := 70013 391 | , UIA_StyleId_Quote := 70014 392 | , UIA_StyleId_BulletedList := 70015 393 | , UIA_StyleId_NumberedList := 70016 394 | 395 | ;enum LandmarkTypeIds 396 | , UIA_CustomLandmarkTypeId := 80000 397 | , UIA_FormLandmarkTypeId := 80001 398 | , UIA_MainLandmarkTypeId := 80002 399 | , UIA_NavigationLandmarkTypeId := 80003 400 | , UIA_SearchLandmarkTypeId := 80004 401 | 402 | ;enum HeadingLevelIds 403 | , UIA_HeadingLevel_None := 80050 404 | , UIA_HeadingLevel1 := 80051 405 | , UIA_HeadingLevel2 := 80052 406 | , UIA_HeadingLevel3 := 80053 407 | , UIA_HeadingLevel4 := 80054 408 | , UIA_HeadingLevel5 := 80055 409 | , UIA_HeadingLevel6 := 80056 410 | , UIA_HeadingLevel7 := 80057 411 | , UIA_HeadingLevel8 := 80058 412 | , UIA_HeadingLevel9 := 80059 413 | 414 | ;enum ChangeIds 415 | , UIA_SummaryChangeId := 90000 416 | 417 | ;enum MetadataIds 418 | , UIA_SayAsInterpretAsMetadataId := 100000 419 | 420 | ;enum TreeScope 421 | global UIA_TreeScope_Element := 1 422 | , UIA_TreeScope_Children := 2 423 | , UIA_TreeScope_Descendants := 4 424 | , UIA_TreeScope_Parent := 8 425 | , UIA_TreeScope_Ancestors := 16 426 | , UIA_TreeScope_Subtree := 7 427 | 428 | ;enum AutomationElementMode 429 | , UIA_AutomationElementMode_None := 0 430 | , UIA_AutomationElementMode_Full := 1 431 | 432 | ;enum OrientationType 433 | , UIA_OrientationType_None := 0 434 | , UIA_OrientationType_Horizontal := 1 435 | , UIA_OrientationType_Vertical := 2 436 | 437 | ;enum PropertyConditionFlags 438 | , UIA_PropertyConditionFlags_None := 0 439 | , UIA_PropertyConditionFlags_IgnoreCase := 1 440 | 441 | ;enum StructureChangeType 442 | , UIA_StructureChangeType_ChildAdded := 0 443 | , UIA_StructureChangeType_ChildRemoved := 1 444 | , UIA_StructureChangeType_ChildrenInvalidated := 2 445 | , UIA_StructureChangeType_ChildrenBulkAdded := 3 446 | , UIA_StructureChangeType_ChildrenBulkRemoved := 4 447 | , UIA_StructureChangeType_ChildrenReordered := 5 448 | 449 | ;enum TextEditChangeType 450 | , UIA_TextEditChangeType_None := 0x0 451 | , UIA_TextEditChangeType_AutoCorrect := 0x1 452 | , UIA_TextEditChangeType_Composition := 0x2 453 | , UIA_TextEditChangeType_CompositionFinalized := 0x3 454 | , UIA_TextEditChangeType_AutoComplete := 0x4 455 | 456 | ;enum DockPosition 457 | , UIA_DockPosition_Top := 0 458 | , UIA_DockPosition_Left := 1 459 | , UIA_DockPosition_Bottom := 2 460 | , UIA_DockPosition_Right := 3 461 | , UIA_DockPosition_Fill := 4 462 | , UIA_DockPosition_None := 5 463 | 464 | ;enum ExpandCollapseState 465 | , UIA_ExpandCollapseState_Collapsed := 0 466 | , UIA_ExpandCollapseState_Expanded := 1 467 | , UIA_ExpandCollapseState_PartiallyExpanded := 2 468 | , UIA_ExpandCollapseState_LeafNode := 3 469 | 470 | ;enum ScrollAmount 471 | , UIA_ScrollAmount_LargeDecrement := 0 472 | , UIA_ScrollAmount_SmallDecrement := 1 473 | , UIA_ScrollAmount_NoAmount := 2 474 | , UIA_ScrollAmount_LargeIncrement := 3 475 | , UIA_ScrollAmount_SmallIncrement := 4 476 | 477 | ;enum SynchronizedInputType 478 | , UIA_SynchronizedInputType_KeyUp := 1 479 | , UIA_SynchronizedInputType_KeyDown := 2 480 | , UIA_SynchronizedInputType_LeftMouseUp := 4 481 | , UIA_SynchronizedInputType_LeftMouseDown := 8 482 | , UIA_SynchronizedInputType_RightMouseUp := 16 483 | , UIA_SynchronizedInputType_RightMouseDown := 32 484 | 485 | ;enum RowOrColumnMajor 486 | , UIA_RowOrColumnMajor_RowMajor := 0 487 | , UIA_RowOrColumnMajor_ColumnMajor := 1 488 | , UIA_RowOrColumnMajor_Indeterminate := 2 489 | 490 | ;enum ToggleState 491 | , UIA_ToggleState_Off := 0 492 | , UIA_ToggleState_On := 1 493 | , UIA_ToggleState_Indeterminate := 2 494 | 495 | ;enum WindowVisualState 496 | , UIA_WindowVisualState_Normal := 0 497 | , UIA_WindowVisualState_Maximized := 1 498 | , UIA_WindowVisualState_Minimized := 2 499 | 500 | ;enum WindowInteractionState 501 | , UIA_WindowInteractionState_Running := 0 502 | , UIA_WindowInteractionState_Closing := 1 503 | , UIA_WindowInteractionState_ReadyForUserInteraction := 2 504 | , UIA_WindowInteractionState_BlockedByModalWindow := 3 505 | , UIA_WindowInteractionState_NotResponding := 4 506 | 507 | ;enum TextPatternRangeEndpoint 508 | , UIA_TextPatternRangeEndpoint_Start := 0 509 | , UIA_TextPatternRangeEndpoint_End := 1 510 | 511 | ;enum TextUnit 512 | , UIA_TextUnit_Character := 0 513 | , UIA_TextUnit_Format := 1 514 | , UIA_TextUnit_Word := 2 515 | , UIA_TextUnit_Line := 3 516 | , UIA_TextUnit_Paragraph := 4 517 | , UIA_TextUnit_Page := 5 518 | , UIA_TextUnit_Document := 6 519 | 520 | ;enum SupportedTextSelection 521 | , UIA_SupportedTextSelection_None := 0 522 | , UIA_SupportedTextSelection_Single := 1 523 | , UIA_SupportedTextSelection_Multiple := 2 524 | 525 | ;enum NavigateDirection 526 | , UIA_NavigateDirection_Parent := 0x0 527 | , UIA_NavigateDirection_NextSibling := 0x1 528 | , UIA_NavigateDirection_PreviousSibling := 0x2 529 | , UIA_NavigateDirection_FirstChild := 0x3 530 | , UIA_NavigateDirection_LastChild := 0x4 531 | 532 | ;enum ZoomUnit 533 | , UIA_ZoomUnit_NoAmount := 0x0 534 | , UIA_ZoomUnit_LargeDecrement := 0x1 535 | , UIA_ZoomUnit_SmallDecrement := 0x2 536 | , UIA_ZoomUnit_LargeIncrement := 0x3 537 | , UIA_ZoomUnit_SmallIncrement := 0x4 538 | 539 | ;enum LiveSetting 540 | , UIA_LiveSetting_Off := 0x0 541 | , UIA_LiveSetting_Polite := 0x1 542 | , UIA_LiveSetting_Assertive := 0x2 543 | 544 | ;enum TreeTraversalOptions 545 | , UIA_TreeTraversalOptions_Default := 0x0 546 | , UIA_TreeTraversalOptions_PostOrder := 0x1 547 | , UIA_TreeTraversalOptions_LastToFirstOrder := 0x2 548 | 549 | ;enum ProviderOptions 550 | , UIA_ProviderOptions_ClientSideProvider := 1 551 | , UIA_ProviderOptions_ServerSideProvider := 2 552 | , UIA_ProviderOptions_NonClientAreaProvider := 4 553 | , UIA_ProviderOptions_OverrideProvider := 8 554 | , UIA_ProviderOptions_ProviderOwnsSetFocus := 16 555 | , UIA_ProviderOptions_UseComThreading := 32 556 | , UIA_ProviderOptions_RefuseNonClientSupport := 64 557 | , UIA_ProviderOptions_HasNativeIAccessible := 128 558 | , UIA_ProviderOptions_UseClientCoordinates := 256 559 | 560 | 561 | global sIID_IUIAutomationElement := "{D22108AA-8AC5-49A5-837B-37BBB3D7591E}" 562 | , dtagIUIAutomationElement := "SetFocus hresult();" 563 | . "GetRuntimeId hresult(ptr*);" 564 | . "FindFirst hresult(long;ptr;ptr*);" 565 | . "FindAll hresult(long;ptr;ptr*);" 566 | . "FindFirstBuildCache hresult(long;ptr;ptr;ptr*);" 567 | . "FindAllBuildCache hresult(long;ptr;ptr;ptr*);" 568 | . "BuildUpdatedCache hresult(ptr;ptr*);" 569 | . "GetCurrentPropertyValue hresult(int;variant*);" 570 | . "GetCurrentPropertyValueEx hresult(int;long;variant*);" 571 | . "GetCachedPropertyValue hresult(int;variant*);" 572 | . "GetCachedPropertyValueEx hresult(int;long;variant*);" 573 | . "GetCurrentPatternAs hresult(int;none;none*);" 574 | . "GetCachedPatternAs hresult(int;none;none*);" 575 | . "GetCurrentPattern hresult(int;ptr*);" 576 | . "GetCachedPattern hresult(int;ptr*);" 577 | . "GetCachedParent hresult(ptr*);" 578 | . "GetCachedChildren hresult(ptr*);" 579 | . "CurrentProcessId hresult(int*);" 580 | . "CurrentControlType hresult(int*);" 581 | . "CurrentLocalizedControlType hresult(bstr*);" 582 | . "CurrentName hresult(bstr*);" 583 | . "CurrentAcceleratorKey hresult(bstr*);" 584 | . "CurrentAccessKey hresult(bstr*);" 585 | . "CurrentHasKeyboardFocus hresult(long*);" 586 | . "CurrentIsKeyboardFocusable hresult(long*);" 587 | . "CurrentIsEnabled hresult(long*);" 588 | . "CurrentAutomationId hresult(bstr*);" 589 | . "CurrentClassName hresult(bstr*);" 590 | . "CurrentHelpText hresult(bstr*);" 591 | . "CurrentCulture hresult(int*);" 592 | . "CurrentIsControlElement hresult(long*);" 593 | . "CurrentIsContentElement hresult(long*);" 594 | . "CurrentIsPassword hresult(long*);" 595 | . "CurrentNativeWindowHandle hresult(hwnd*);" 596 | . "CurrentItemType hresult(bstr*);" 597 | . "CurrentIsOffscreen hresult(long*);" 598 | . "CurrentOrientation hresult(long*);" 599 | . "CurrentFrameworkId hresult(bstr*);" 600 | . "CurrentIsRequiredForForm hresult(long*);" 601 | . "CurrentItemStatus hresult(bstr*);" 602 | . "CurrentBoundingRectangle hresult(struct*);" 603 | . "CurrentLabeledBy hresult(ptr*);" 604 | . "CurrentAriaRole hresult(bstr*);" 605 | . "CurrentAriaProperties hresult(bstr*);" 606 | . "CurrentIsDataValidForForm hresult(long*);" 607 | . "CurrentControllerFor hresult(ptr*);" 608 | . "CurrentDescribedBy hresult(ptr*);" 609 | . "CurrentFlowsTo hresult(ptr*);" 610 | . "CurrentProviderDescription hresult(bstr*);" 611 | . "CachedProcessId hresult(int*);" 612 | . "CachedControlType hresult(int*);" 613 | . "CachedLocalizedControlType hresult(bstr*);" 614 | . "CachedName hresult(bstr*);" 615 | . "CachedAcceleratorKey hresult(bstr*);" 616 | . "CachedAccessKey hresult(bstr*);" 617 | . "CachedHasKeyboardFocus hresult(long*);" 618 | . "CachedIsKeyboardFocusable hresult(long*);" 619 | . "CachedIsEnabled hresult(long*);" 620 | . "CachedAutomationId hresult(bstr*);" 621 | . "CachedClassName hresult(bstr*);" 622 | . "CachedHelpText hresult(bstr*);" 623 | . "CachedCulture hresult(int*);" 624 | . "CachedIsControlElement hresult(long*);" 625 | . "CachedIsContentElement hresult(long*);" 626 | . "CachedIsPassword hresult(long*);" 627 | . "CachedNativeWindowHandle hresult(hwnd*);" 628 | . "CachedItemType hresult(bstr*);" 629 | . "CachedIsOffscreen hresult(long*);" 630 | . "CachedOrientation hresult(long*);" 631 | . "CachedFrameworkId hresult(bstr*);" 632 | . "CachedIsRequiredForForm hresult(long*);" 633 | . "CachedItemStatus hresult(bstr*);" 634 | . "CachedBoundingRectangle hresult(struct*);" 635 | . "CachedLabeledBy hresult(ptr*);" 636 | . "CachedAriaRole hresult(bstr*);" 637 | . "CachedAriaProperties hresult(bstr*);" 638 | . "CachedIsDataValidForForm hresult(long*);" 639 | . "CachedControllerFor hresult(ptr*);" 640 | . "CachedDescribedBy hresult(ptr*);" 641 | . "CachedFlowsTo hresult(ptr*);" 642 | . "CachedProviderDescription hresult(bstr*);" 643 | . "GetClickablePoint hresult(struct*;long*);" 644 | 645 | , sIID_IUIAutomationCondition := "{352FFBA8-0973-437C-A61F-F64CAFD81DF9}" 646 | , dtagIUIAutomationCondition := "" 647 | 648 | , sIID_IUIAutomationElementArray := "{14314595-B4BC-4055-95F2-58F2E42C9855}" 649 | , dtagIUIAutomationElementArray := "Length hresult(int*);" 650 | . "GetElement hresult(int;ptr*);" 651 | 652 | , sIID_IUIAutomationCacheRequest := "{B32A92B5-BC25-4078-9C08-D7EE95C48E03}" 653 | , dtagIUIAutomationCacheRequest := "AddProperty hresult(int);" 654 | . "AddPattern hresult(int);" 655 | . "Clone hresult(ptr*);" 656 | . "get_TreeScope hresult(long*);" 657 | . "put_TreeScope hresult(long);" 658 | . "get_TreeFilter hresult(ptr*);" 659 | . "put_TreeFilter hresult(ptr);" 660 | . "get_AutomationElementMode hresult(long*);" 661 | . "put_AutomationElementMode hresult(long);" 662 | 663 | , sIID_IUIAutomationBoolCondition := "{1B4E1F2E-75EB-4D0B-8952-5A69988E2307}" 664 | , dtagIUIAutomationBoolCondition := "BooleanValue hresult(long*);" 665 | 666 | , sIID_IUIAutomationPropertyCondition := "{99EBF2CB-5578-4267-9AD4-AFD6EA77E94B}" 667 | , dtagIUIAutomationPropertyCondition := "propertyId hresult(int*);" 668 | . "PropertyValue hresult(variant*);" 669 | . "PropertyConditionFlags hresult(long*);" 670 | 671 | , sIID_IUIAutomationAndCondition := "{A7D0AF36-B912-45FE-9855-091DDC174AEC}" 672 | , dtagIUIAutomationAndCondition := "ChildCount hresult(int*);" 673 | . "GetChildrenAsNativeArray hresult(ptr*;int*);" 674 | . "GetChildren hresult(ptr*);" 675 | 676 | , sIID_IUIAutomationOrCondition := "{8753F032-3DB1-47B5-A1FC-6E34A266C712}" 677 | , dtagIUIAutomationOrCondition := "ChildCount hresult(int*);" 678 | . "GetChildrenAsNativeArray hresult(ptr*;int*);" 679 | . "GetChildren hresult(ptr*);" 680 | 681 | , sIID_IUIAutomationNotCondition := "{F528B657-847B-498C-8896-D52B565407A1}" 682 | , dtagIUIAutomationNotCondition := "GetChild hresult(ptr*);" 683 | 684 | , sIID_IUIAutomationTreeWalker := "{4042C624-389C-4AFC-A630-9DF854A541FC}" 685 | , dtagIUIAutomationTreeWalker := "GetParentElement hresult(ptr;ptr*);" 686 | . "GetFirstChildElement hresult(ptr;ptr*);" 687 | . "GetLastChildElement hresult(ptr;ptr*);" 688 | . "GetNextSiblingElement hresult(ptr;ptr*);" 689 | . "GetPreviousSiblingElement hresult(ptr;ptr*);" 690 | . "NormalizeElement hresult(ptr;ptr*);" 691 | . "GetParentElementBuildCache hresult(ptr;ptr;ptr*);" 692 | . "GetFirstChildElementBuildCache hresult(ptr;ptr;ptr*);" 693 | . "GetLastChildElementBuildCache hresult(ptr;ptr;ptr*);" 694 | . "GetNextSiblingElementBuildCache hresult(ptr;ptr;ptr*);" 695 | . "GetPreviousSiblingElementBuildCache hresult(ptr;ptr;ptr*);" 696 | . "NormalizeElementBuildCache hresult(ptr;ptr;ptr*);" 697 | . "condition hresult(ptr*);" 698 | 699 | , sIID_IUIAutomationEventHandler := "{146C3C17-F12E-4E22-8C27-F894B9B79C69}" 700 | , dtagIUIAutomationEventHandler := "HandleAutomationEvent hresult(ptr;int);" 701 | 702 | , sIID_IUIAutomationPropertyChangedEventHandler := "{40CD37D4-C756-4B0C-8C6F-BDDFEEB13B50}" 703 | , dtagIUIAutomationPropertyChangedEventHandler := "HandlePropertyChangedEvent hresult(ptr;int;variant);" 704 | 705 | , sIID_IUIAutomationStructureChangedEventHandler := "{E81D1B4E-11C5-42F8-9754-E7036C79F054}" 706 | , dtagIUIAutomationStructureChangedEventHandler := "HandleStructureChangedEvent hresult(ptr;long;ptr);" 707 | 708 | , sIID_IUIAutomationFocusChangedEventHandler := "{C270F6B5-5C69-4290-9745-7A7F97169468}" 709 | , dtagIUIAutomationFocusChangedEventHandler := "HandleFocusChangedEvent hresult(ptr);" 710 | 711 | , sIID_IUIAutomationInvokePattern := "{FB377FBE-8EA6-46D5-9C73-6499642D3059}" 712 | , dtagIUIAutomationInvokePattern := "Invoke hresult();" 713 | 714 | , sIID_IUIAutomationDockPattern := "{FDE5EF97-1464-48F6-90BF-43D0948E86EC}" 715 | , dtagIUIAutomationDockPattern := "SetDockPosition hresult(long);" 716 | . "CurrentDockPosition hresult(long*);" 717 | . "CachedDockPosition hresult(long*);" 718 | 719 | , sIID_IUIAutomationExpandCollapsePattern := "{619BE086-1F4E-4EE4-BAFA-210128738730}" 720 | , dtagIUIAutomationExpandCollapsePattern := "Expand hresult();" 721 | . "Collapse hresult();" 722 | . "CurrentExpandCollapseState hresult(long*);" 723 | . "CachedExpandCollapseState hresult(long*);" 724 | 725 | , sIID_IUIAutomationGridPattern := "{414C3CDC-856B-4F5B-8538-3131C6302550}" 726 | , dtagIUIAutomationGridPattern := "GetItem hresult(int;int;ptr*);" 727 | . "CurrentRowCount hresult(int*);" 728 | . "CurrentColumnCount hresult(int*);" 729 | . "CachedRowCount hresult(int*);" 730 | . "CachedColumnCount hresult(int*);" 731 | 732 | , sIID_IUIAutomationGridItemPattern := "{78F8EF57-66C3-4E09-BD7C-E79B2004894D}" 733 | , dtagIUIAutomationGridItemPattern := "CurrentContainingGrid hresult(ptr*);" 734 | . "CurrentRow hresult(int*);" 735 | . "CurrentColumn hresult(int*);" 736 | . "CurrentRowSpan hresult(int*);" 737 | . "CurrentColumnSpan hresult(int*);" 738 | . "CachedContainingGrid hresult(ptr*);" 739 | . "CachedRow hresult(int*);" 740 | . "CachedColumn hresult(int*);" 741 | . "CachedRowSpan hresult(int*);" 742 | . "CachedColumnSpan hresult(int*);" 743 | 744 | , sIID_IUIAutomationMultipleViewPattern := "{8D253C91-1DC5-4BB5-B18F-ADE16FA495E8}" 745 | , dtagIUIAutomationMultipleViewPattern := "GetViewName hresult(int;bstr*);" 746 | . "SetCurrentView hresult(int);" 747 | . "CurrentCurrentView hresult(int*);" 748 | . "GetCurrentSupportedViews hresult(ptr*);" 749 | . "CachedCurrentView hresult(int*);" 750 | . "GetCachedSupportedViews hresult(ptr*);" 751 | 752 | , sIID_IUIAutomationRangeValuePattern := "{59213F4F-7346-49E5-B120-80555987A148}" 753 | , dtagIUIAutomationRangeValuePattern := "SetValue hresult(ushort);" 754 | . "CurrentValue hresult(ushort*);" 755 | . "CurrentIsReadOnly hresult(long*);" 756 | . "CurrentMaximum hresult(ushort*);" 757 | . "CurrentMinimum hresult(ushort*);" 758 | . "CurrentLargeChange hresult(ushort*);" 759 | . "CurrentSmallChange hresult(ushort*);" 760 | . "CachedValue hresult(ushort*);" 761 | . "CachedIsReadOnly hresult(long*);" 762 | . "CachedMaximum hresult(ushort*);" 763 | . "CachedMinimum hresult(ushort*);" 764 | . "CachedLargeChange hresult(ushort*);" 765 | . "CachedSmallChange hresult(ushort*);" 766 | 767 | , sIID_IUIAutomationScrollPattern := "{88F4D42A-E881-459D-A77C-73BBBB7E02DC}" 768 | , dtagIUIAutomationScrollPattern := "Scroll hresult(long;long);" 769 | . "SetScrollPercent hresult(ushort;ushort);" 770 | . "CurrentHorizontalScrollPercent hresult(ushort*);" 771 | . "CurrentVerticalScrollPercent hresult(ushort*);" 772 | . "CurrentHorizontalViewSize hresult(ushort*);" 773 | . "CurrentVerticalViewSize hresult(ushort*);" 774 | . "CurrentHorizontallyScrollable hresult(long*);" 775 | . "CurrentVerticallyScrollable hresult(long*);" 776 | . "CachedHorizontalScrollPercent hresult(ushort*);" 777 | . "CachedVerticalScrollPercent hresult(ushort*);" 778 | . "CachedHorizontalViewSize hresult(ushort*);" 779 | . "CachedVerticalViewSize hresult(ushort*);" 780 | . "CachedHorizontallyScrollable hresult(long*);" 781 | . "CachedVerticallyScrollable hresult(long*);" 782 | 783 | , sIID_IUIAutomationScrollItemPattern := "{B488300F-D015-4F19-9C29-BB595E3645EF}" 784 | , dtagIUIAutomationScrollItemPattern := "ScrollIntoView hresult();" 785 | 786 | , sIID_IUIAutomationSelectionPattern := "{5ED5202E-B2AC-47A6-B638-4B0BF140D78E}" 787 | , dtagIUIAutomationSelectionPattern := "GetCurrentSelection hresult(ptr*);" 788 | . "CurrentCanSelectMultiple hresult(long*);" 789 | . "CurrentIsSelectionRequired hresult(long*);" 790 | . "GetCachedSelection hresult(ptr*);" 791 | . "CachedCanSelectMultiple hresult(long*);" 792 | . "CachedIsSelectionRequired hresult(long*);" 793 | 794 | , sIID_IUIAutomationSelectionItemPattern := "{A8EFA66A-0FDA-421A-9194-38021F3578EA}" 795 | , dtagIUIAutomationSelectionItemPattern := "Select hresult();" 796 | . "AddToSelection hresult();" 797 | . "RemoveFromSelection hresult();" 798 | . "CurrentIsSelected hresult(long*);" 799 | . "CurrentSelectionContainer hresult(ptr*);" 800 | . "CachedIsSelected hresult(long*);" 801 | . "CachedSelectionContainer hresult(ptr*);" 802 | 803 | , sIID_IUIAutomationSynchronizedInputPattern := "{2233BE0B-AFB7-448B-9FDA-3B378AA5EAE1}" 804 | , dtagIUIAutomationSynchronizedInputPattern := "StartListening hresult(long);" 805 | . "Cancel hresult();" 806 | 807 | , sIID_IUIAutomationTablePattern := "{620E691C-EA96-4710-A850-754B24CE2417}" 808 | , dtagIUIAutomationTablePattern := "GetCurrentRowHeaders hresult(ptr*);" 809 | . "GetCurrentColumnHeaders hresult(ptr*);" 810 | . "CurrentRowOrColumnMajor hresult(long*);" 811 | . "GetCachedRowHeaders hresult(ptr*);" 812 | . "GetCachedColumnHeaders hresult(ptr*);" 813 | . "CachedRowOrColumnMajor hresult(long*);" 814 | 815 | , sIID_IUIAutomationTableItemPattern := "{0B964EB3-EF2E-4464-9C79-61D61737A27E}" 816 | , dtagIUIAutomationTableItemPattern := "GetCurrentRowHeaderItems hresult(ptr*);" 817 | . "GetCurrentColumnHeaderItems hresult(ptr*);" 818 | . "GetCachedRowHeaderItems hresult(ptr*);" 819 | . "GetCachedColumnHeaderItems hresult(ptr*);" 820 | 821 | , sIID_IUIAutomationTogglePattern := "{94CF8058-9B8D-4AB9-8BFD-4CD0A33C8C70}" 822 | , dtagIUIAutomationTogglePattern := "Toggle hresult();" 823 | . "CurrentToggleState hresult(long*);" 824 | . "CachedToggleState hresult(long*);" 825 | 826 | , sIID_IUIAutomationTransformPattern := "{A9B55844-A55D-4EF0-926D-569C16FF89BB}" 827 | , dtagIUIAutomationTransformPattern := "Move hresult(double;double);" ;~ fixed ushort to be double 828 | . "Resize hresult(double;double);" ;~ fixed ushort to be double 829 | . "Rotate hresult(ushort);" 830 | . "CurrentCanMove hresult(long*);" 831 | . "CurrentCanResize hresult(long*);" 832 | . "CurrentCanRotate hresult(long*);" 833 | . "CachedCanMove hresult(long*);" 834 | . "CachedCanResize hresult(long*);" 835 | . "CachedCanRotate hresult(long*);" 836 | 837 | , sIID_IUIAutomationValuePattern := "{A94CD8B1-0844-4CD6-9D2D-640537AB39E9}" 838 | , dtagIUIAutomationValuePattern := "SetValue hresult(bstr);" 839 | . "CurrentValue hresult(bstr*);" 840 | . "CurrentIsReadOnly hresult(long*);" 841 | . "CachedValue hresult(bstr*);" 842 | . "CachedIsReadOnly hresult(long*);" 843 | 844 | , sIID_IUIAutomationWindowPattern := "{0FAEF453-9208-43EF-BBB2-3B485177864F}" 845 | , dtagIUIAutomationWindowPattern := "Close hresult();" 846 | . "WaitForInputIdle hresult(int;long*);" 847 | . "SetWindowVisualState hresult(long);" 848 | . "CurrentCanMaximize hresult(long*);" 849 | . "CurrentCanMinimize hresult(long*);" 850 | . "CurrentIsModal hresult(long*);" 851 | . "CurrentIsTopmost hresult(long*);" 852 | . "CurrentWindowVisualState hresult(long*);" 853 | . "CurrentWindowInteractionState hresult(long*);" 854 | . "CachedCanMaximize hresult(long*);" 855 | . "CachedCanMinimize hresult(long*);" 856 | . "CachedIsModal hresult(long*);" 857 | . "CachedIsTopmost hresult(long*);" 858 | . "CachedWindowVisualState hresult(long*);" 859 | . "CachedWindowInteractionState hresult(long*);" 860 | 861 | , sIID_IUIAutomationTextRange := "{A543CC6A-F4AE-494B-8239-C814481187A8}" 862 | , dtagIUIAutomationTextRange := "Clone hresult(ptr*);" 863 | . "Compare hresult(ptr;long*);" 864 | . "CompareEndpoints hresult(long;ptr;long;int*);" 865 | . "ExpandToEnclosingUnit hresult(long);" 866 | . "FindAttribute hresult(int;variant;long;ptr*);" 867 | . "FindText hresult(bstr;long;long;ptr*);" 868 | . "GetAttributeValue hresult(int;variant*);" 869 | . "GetBoundingRectangles hresult(ptr*);" 870 | . "GetEnclosingElement hresult(ptr*);" 871 | . "GetText hresult(int;bstr*);" 872 | . "Move hresult(long;int;int*);" 873 | . "MoveEndpointByUnit hresult(long;long;int;int*);" 874 | . "MoveEndpointByRange hresult(long;ptr;long);" 875 | . "Select hresult();" 876 | . "AddToSelection hresult();" 877 | . "RemoveFromSelection hresult();" 878 | . "ScrollIntoView hresult(long);" 879 | . "GetChildren hresult(ptr*);" 880 | 881 | , sIID_IUIAutomationTextRangeArray := "{CE4AE76A-E717-4C98-81EA-47371D028EB6}" 882 | , dtagIUIAutomationTextRangeArray := "Length hresult(int*);" 883 | . "GetElement hresult(int;ptr*);" 884 | 885 | , sIID_IUIAutomationTextPattern := "{32EBA289-3583-42C9-9C59-3B6D9A1E9B6A}" 886 | , dtagIUIAutomationTextPattern := "RangeFromPoint hresult(struct;ptr*);" 887 | . "RangeFromChild hresult(ptr;ptr*);" 888 | . "GetSelection hresult(ptr*);" 889 | . "GetVisibleRanges hresult(ptr*);" 890 | . "DocumentRange hresult(ptr*);" 891 | . "SupportedTextSelection hresult(long*);" 892 | 893 | , sIID_IUIAutomationLegacyIAccessiblePattern := "{828055AD-355B-4435-86D5-3B51C14A9B1B}" 894 | , dtagIUIAutomationLegacyIAccessiblePattern := "Select hresult(long);" 895 | . "DoDefaultAction hresult();" 896 | . "SetValue hresult(wstr);" 897 | . "CurrentChildId hresult(int*);" 898 | . "CurrentName hresult(bstr*);" 899 | . "CurrentValue hresult(bstr*);" 900 | . "CurrentDescription hresult(bstr*);" 901 | . "CurrentRole hresult(uint*);" 902 | . "CurrentState hresult(uint*);" 903 | . "CurrentHelp hresult(bstr*);" 904 | . "CurrentKeyboardShortcut hresult(bstr*);" 905 | . "GetCurrentSelection hresult(ptr*);" 906 | . "CurrentDefaultAction hresult(bstr*);" 907 | . "CachedChildId hresult(int*);" 908 | . "CachedName hresult(bstr*);" 909 | . "CachedValue hresult(bstr*);" 910 | . "CachedDescription hresult(bstr*);" 911 | . "CachedRole hresult(uint*);" 912 | . "CachedState hresult(uint*);" 913 | . "CachedHelp hresult(bstr*);" 914 | . "CachedKeyboardShortcut hresult(bstr*);" 915 | . "GetCachedSelection hresult(ptr*);" 916 | . "CachedDefaultAction hresult(bstr*);" 917 | . "GetIAccessible hresult(idispatch*);" 918 | 919 | global sIID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}" 920 | , dtagIAccessible := "GetTypeInfoCount hresult(uint*);" ; IDispatch 921 | . "GetTypeInfo hresult(uint;int;ptr*);" 922 | . "GetIDsOfNames hresult(struct*;wstr;uint;int;int);" 923 | . "Invoke hresult(int;struct*;int;word;ptr*;ptr*;ptr*;uint*);" 924 | . "get_accParent hresult(ptr*);" ; IAccessible 925 | . "get_accChildCount hresult(long*);" 926 | . "get_accChild hresult(variant;idispatch*);" 927 | . "get_accName hresult(variant;bstr*);" 928 | . "get_accValue hresult(variant;bstr*);" 929 | . "get_accDescription hresult(variant;bstr*);" 930 | . "get_accRole hresult(variant;variant*);" 931 | . "get_accState hresult(variant;variant*);" 932 | . "get_accHelp hresult(variant;bstr*);" 933 | . "get_accHelpTopic hresult(bstr*;variant;long*);" 934 | . "get_accKeyboardShortcut hresult(variant;bstr*);" 935 | . "get_accFocus hresult(struct*);" 936 | . "get_accSelection hresult(variant*);" 937 | . "get_accDefaultAction hresult(variant;bstr*);" 938 | . "accSelect hresult(long;variant);" 939 | . "accLocation hresult(long*;long*;long*;long*;variant);" 940 | . "accNavigate hresult(long;variant;variant*);" 941 | . "accHitTest hresult(long;long;variant*);" 942 | . "accDoDefaultAction hresult(variant);" 943 | . "put_accName hresult(variant;bstr);" 944 | . "put_accValue hresult(variant;bstr);" 945 | 946 | , sIID_IUIAutomationItemContainerPattern := "{C690FDB2-27A8-423C-812D-429773C9084E}" 947 | , dtagIUIAutomationItemContainerPattern := "FindItemByProperty hresult(ptr;int;variant;ptr*);" 948 | 949 | , sIID_IUIAutomationVirtualizedItemPattern := "{6BA3D7A6-04CF-4F11-8793-A8D1CDE9969F}" 950 | , dtagIUIAutomationVirtualizedItemPattern := "Realize hresult();" 951 | 952 | , sIID_IUIAutomationProxyFactory := "{85B94ECD-849D-42B6-B94D-D6DB23FDF5A4}" 953 | , dtagIUIAutomationProxyFactory := "CreateProvider hresult(hwnd;long;long;ptr*);" 954 | . "ProxyFactoryId hresult(bstr*);" 955 | 956 | , sIID_IRawElementProviderSimple := "{D6DD68D1-86FD-4332-8666-9ABEDEA2D24C}" 957 | , dtagIRawElementProviderSimple := "ProviderOptions hresult(long*);" 958 | . "GetPatternProvider hresult(int;ptr*);" 959 | . "GetPropertyValue hresult(int;variant*);" 960 | . "HostRawElementProvider hresult(ptr*);" 961 | 962 | , sIID_IUIAutomationProxyFactoryEntry := "{D50E472E-B64B-490C-BCA1-D30696F9F289}" 963 | , dtagIUIAutomationProxyFactoryEntry := "ProxyFactory hresult(ptr*);" 964 | . "ClassName hresult(bstr*);" 965 | . "ImageName hresult(bstr*);" 966 | . "AllowSubstringMatch hresult(long*);" 967 | . "CanCheckBaseClass hresult(long*);" 968 | . "NeedsAdviseEvents hresult(long*);" 969 | . "ClassName hresult(wstr);" 970 | . "ImageName hresult(wstr);" 971 | . "AllowSubstringMatch hresult(long);" 972 | . "CanCheckBaseClass hresult(long);" 973 | . "NeedsAdviseEvents hresult(long);" 974 | . "SetWinEventsForAutomationEvent hresult(int;int;ptr);" 975 | . "GetWinEventsForAutomationEvent hresult(int;int;ptr*);" 976 | 977 | , sIID_IUIAutomationProxyFactoryMapping := "{09E31E18-872D-4873-93D1-1E541EC133FD}" 978 | , dtagIUIAutomationProxyFactoryMapping := "count hresult(uint*);" 979 | . "GetTable hresult(ptr*);" 980 | . "GetEntry hresult(uint;ptr*);" 981 | . "SetTable hresult(ptr);" 982 | . "InsertEntries hresult(uint;ptr);" 983 | . "InsertEntry hresult(uint;ptr);" 984 | . "RemoveEntry hresult(uint);" 985 | . "ClearTable hresult();" 986 | . "RestoreDefaultTable hresult();" 987 | 988 | , sIID_IUIAutomation := "{30CBE57D-D9D0-452A-AB13-7AC5AC4825EE}" 989 | , dtagIUIAutomation := "CompareElements hresult(ptr;ptr;long*);" 990 | . "CompareRuntimeIds hresult(ptr;ptr;long*);" 991 | . "GetRootElement hresult(ptr*);" 992 | . "ElementFromHandle hresult(hwnd;ptr*);" 993 | . "ElementFromPoint hresult(struct;ptr*);" 994 | . "GetFocusedElement hresult(ptr*);" 995 | . "GetRootElementBuildCache hresult(ptr;ptr*);" 996 | . "ElementFromHandleBuildCache hresult(hwnd;ptr;ptr*);" 997 | . "ElementFromPointBuildCache hresult(struct;ptr;ptr*);" 998 | . "GetFocusedElementBuildCache hresult(ptr;ptr*);" 999 | . "CreateTreeWalker hresult(ptr;ptr*);" 1000 | . "ControlViewWalker hresult(ptr*);" 1001 | . "ContentViewWalker hresult(ptr*);" 1002 | . "RawViewWalker hresult(ptr*);" 1003 | . "RawViewCondition hresult(ptr*);" 1004 | . "ControlViewCondition hresult(ptr*);" 1005 | . "ContentViewCondition hresult(ptr*);" 1006 | . "CreateCacheRequest hresult(ptr*);" 1007 | . "CreateTrueCondition hresult(ptr*);" 1008 | . "CreateFalseCondition hresult(ptr*);" 1009 | . "CreatePropertyCondition hresult(int;variant;ptr*);" 1010 | . "CreatePropertyConditionEx hresult(int;variant;long;ptr*);" 1011 | . "CreateAndCondition hresult(ptr;ptr;ptr*);" 1012 | . "CreateAndConditionFromArray hresult(ptr;ptr*);" 1013 | . "CreateAndConditionFromNativeArray hresult(ptr;int;ptr*);" 1014 | . "CreateOrCondition hresult(ptr;ptr;ptr*);" 1015 | . "CreateOrConditionFromArray hresult(ptr;ptr*);" 1016 | . "CreateOrConditionFromNativeArray hresult(ptr;int;ptr*);" 1017 | . "CreateNotCondition hresult(ptr;ptr*);" 1018 | . "AddAutomationEventHandler hresult(int;ptr;long;ptr;ptr);" 1019 | . "RemoveAutomationEventHandler hresult(int;ptr;ptr);" 1020 | . "AddPropertyChangedEventHandlerNativeArray hresult(ptr;long;ptr;ptr;struct*;int);" 1021 | . "AddPropertyChangedEventHandler hresult(ptr;long;ptr;ptr;ptr);" 1022 | . "RemovePropertyChangedEventHandler hresult(ptr;ptr);" 1023 | . "AddStructureChangedEventHandler hresult(ptr;long;ptr;ptr);" 1024 | . "RemoveStructureChangedEventHandler hresult(ptr;ptr);" 1025 | . "AddFocusChangedEventHandler hresult(ptr;ptr);" 1026 | . "RemoveFocusChangedEventHandler hresult(ptr);" 1027 | . "RemoveAllEventHandlers hresult();" 1028 | . "IntNativeArrayToSafeArray hresult(int;int;ptr*);" 1029 | . "IntSafeArrayToNativeArray hresult(ptr;int*;int*);" 1030 | . "RectToVariant hresult(struct;variant*);" 1031 | . "VariantToRect hresult(variant;struct*);" 1032 | . "SafeArrayToRectNativeArray hresult(ptr;struct*;int*);" 1033 | . "CreateProxyFactoryEntry hresult(ptr;ptr*);" 1034 | . "ProxyFactoryMapping hresult(ptr*);" 1035 | . "GetPropertyProgrammaticName hresult(int;bstr*);" 1036 | . "GetPatternProgrammaticName hresult(int;bstr*);" 1037 | . "PollForPotentialSupportedPatterns hresult(ptr;ptr*;ptr*);" 1038 | . "PollForPotentialSupportedProperties hresult(ptr;ptr*;ptr*);" 1039 | . "CheckNotSupported hresult(variant;long*);" 1040 | . "ReservedNotSupportedValue hresult(ptr*);" 1041 | . "ReservedMixedAttributeValue hresult(ptr*);" 1042 | . "ElementFromIAccessible hresult(idispatch;int;ptr*);" 1043 | . "ElementFromIAccessibleBuildCache hresult(iaccessible;int;ptr;ptr*);" 1044 | , UIA_MaxVersion_Interface := 7 1045 | , UIA_MaxVersion_Element := 7 1046 | , UIA_MaxVersion_TextRange := 3 1047 | 1048 | , VT_BSTR_Properties := [UIA_AcceleratorKeyPropertyId, UIA_AccessKeyPropertyId, UIA_AriaPropertiesPropertyId, UIA_AriaRolePropertyId, UIA_AutomationIdPropertyId, UIA_ClassNamePropertyId, UIA_FrameworkIdPropertyId, UIA_FullDescriptionPropertyId, UIA_HelpTextPropertyId, UIA_ItemStatusPropertyId, UIA_ItemTypePropertyId, UIA_LocalizedControlTypePropertyId, UIA_LocalizedLandmarkTypePropertyId, UIA_NamePropertyId, UIA_ProviderDescriptionPropertyId] 1049 | , VT_I4_Properties := [UIA_ControlTypePropertyId, UIA_CulturePropertyId, UIA_FillColorPropertyId, UIA_FillTypePropertyId, UIA_HeadingLevelPropertyId, UIA_LandmarkTypePropertyId, UIA_LevelPropertyId, UIA_LiveSettingPropertyId, UIA_NativeWindowHandlePropertyId, UIA_OrientationPropertyId, UIA_PositionInSetPropertyId, UIA_ProcessIdPropertyId, UIA_SizeOfSetPropertyId, UIA_VisualEffectsPropertyId] 1050 | 1051 | , VT_EMPTY:=0,VT_NULL:=1,VT_I2:=2,VT_I4:=3,VT_R8:=5,VT_CY:=6,VT_DATE:=7,VT_BSTR:=8,VT_DISPATCH:=9,VT_ERROR:=10,VT_BOOL:=11,VT_VARIANT:=12,VT_UNKNOWN:=13,VT_DECIMAL:=14,VT_I1:=16,VT_UI1=17,VT_UI2:=18,VT_UI4:=19,VT_I8:=20,VT_UI8:=21,VT_INT:=22,VT_UINT:=23,VT_RECORD:=36,VT_BYREF:=4096 1052 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UIAutomation 2 | 3 | UIAutomation related files for AutoHotkey. 4 | Main library files: 5 | 1) UIA_Interface.ahk, which is based on jethrow's project, and contains wrapper functions for the UIAutomation framework. In addition it has some helper functions for easier use of UIA. 6 | 2) UIA_Browser.ahk, which contains helper functions for Chrome (and Edge mostly too) automation (fetching URLs, switching tabs etc). 7 | 3) OPTIONAL: UIA_Constants.ahk, which contains most necessary constants to use UIA. It is mostly based on an Autoit3 project by LarsJ. Note that this file creates a lot of global variables, so make sure your script doesn't change any of these during runtime. The preferred option is to use constants/enumerations from the UIA_Interface.ahk UIA_Enum class (details are available in the AHK forum thread). 8 | 9 | Additionally UIAViewer.ahk is included to view UIA elements and browse the UIA tree. It can be ran as a standalone file without the UIA_Interface.ahk library. 10 | 11 | For more information and tutorials, [check out the Wiki](https://github.com/Descolada/UIAutomation/wiki). Some instructional videos are available on [Joe the Automator webpage](https://www.the-automator.com/automate-any-program-with-ui-automation/). 12 | 13 | If you have questions or issues, either post it in the [AutoHotkey forums' main thread](https://www.autohotkey.com/boards/viewtopic.php?f=6&t=104999) or create a [new issue](https://github.com/Descolada/UIAutomation/issues). 14 | 15 | If you wish to support me in this and other projects: 16 | [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/descolada) 17 | -------------------------------------------------------------------------------- /UIATreeInspector.ahk: -------------------------------------------------------------------------------- 1 | #SingleInstance Force 2 | #NoEnv 3 | SetWorkingDir %A_ScriptDir% 4 | SetBatchLines -1 5 | CoordMode, Mouse, Screen 6 | #include 7 | DetectHiddenWindows, Off 8 | 9 | global UIA := UIA_Interface(), IsCapturing := False, Stored := {}, Acc, EnableAccTree := False, MainGuiHwnd 10 | Stored.TreeView := {} 11 | Acc_Init() 12 | Acc_Error(1) 13 | 14 | _xoffsetfirst := 328 15 | _xoffset := 5 16 | _yoffset := 20 17 | _ysoffset := 2 18 | _minSplitterPosX := 100, _maxSplitterPosX := 500, _maxSplitter3PosX, _minSplitterPosY := 100, _maxSplitterPosY := 500, SplitterW = 5 19 | 20 | Gui Main: New, AlwaysOnTop Resize hwndMainGuiHwnd, UIA Tree Inspector 21 | Gui Main: Default 22 | 23 | Gui Add, ListView, x8 y15 h460 w305 vLVWindowList gLVWindowList AltSubmit, Title|Process|ID 24 | 25 | Gui Add, GroupBox, x328 y10 w302 h130 vGBWindowInfo, Window/Control Info 26 | Gui Add, Text, x338 y28 w30 vTextWinTitle, WinTitle: 27 | Gui Add, Edit, x385 yp-%_ysoffset% w235 vEditWinTitle, 28 | Gui Add, Text, x338 y56 vTextHwnd, Hwnd: 29 | Gui Add, Edit, x385 yp-%_ysoffset% w90 vEditWinHwnd, 30 | Gui Add, Text, x338 y86 vTextPosition, Position: 31 | Gui Add, Edit, x385 yp-%_ysoffset% w90 vEditWinPosition, 32 | Gui Add, Text, x338 y116 vTextSize, Size: 33 | Gui Add, Edit, x385 yp-%_ysoffset% w90 vEditWinSize, 34 | Gui Add, Text, x480 y56 vTextClassNN, ClassNN: 35 | Gui Add, Edit, x530 yp-%_ysoffset% w90 vEditWinClass, 36 | Gui Add, Text, x480 y86 vTextProcess, Process: 37 | Gui Add, Edit, x530 yp-%_ysoffset% w90 vEditWinProcess, 38 | Gui Add, Text, x480 y116 vTextProcessID, PID: 39 | Gui Add, Edit, x530 yp-%_ysoffset% w90 vEditWinProcessID, 40 | 41 | Gui Add, GroupBox, x%_xoffsetfirst% y150 w302 h240 vGBProperties, UIAutomation Element Properties 42 | Gui Add, ListView, xm+%_xoffsetfirst% yp+%_yoffset% h210 w285 vLVPropertyIds gLVPropertyIds AltSubmit, PropertyId|Value 43 | ClearLVPropertyIds() 44 | 45 | Gui Add, GroupBox, x%_xoffsetfirst% y395 w302 h150 vGBPatterns, UIAutomation Element Patterns 46 | Gui Add, TreeView, xm+%_xoffsetfirst% yp+%_yoffset% h100 w285 vTVPatterns gTVPatterns 47 | Gui Add, Button, xm+0 yp+75 w150 gButRefreshWindowList vButRefreshWindowList, Refresh window list 48 | Gui Add, CheckBox, xm+160 yp+0 w50 gCBVisible vCBVisible Checked, Visible 49 | Gui Add, CheckBox, xm+210 yp+0 w40 gCBTitle vCBTitle Checked, Title 50 | Gui Add, CheckBox, xm+250 yp+0 w60 vCBActivate Checked, Activate 51 | 52 | gosub ButRefreshWindowList 53 | Gui Add, TreeView, x640 y8 w300 h400 hwndhMainTreeView vMainTreeView gMainTreeView 54 | Gui, Font, Bold 55 | Gui, Add, StatusBar, gMainSB vMainSB 56 | SB_SetText("`tClick here to enable Acc path capturing (can't be used with UIA!)") 57 | Gui, Font 58 | SB_SetParts(380) 59 | SB_SetText("`tCurrent UIA Interface version: " UIA.__Version,2) 60 | 61 | Gui, Add, Text, x630 y0 w%SplitterW% h500 vSplitter1 gMoveSplitter1 62 | Gui, Add, Text, x%_xoffsetfirst% y390 w300 h%SplitterW% vSplitter2 gMoveSplitter2 63 | Gui, Add, Text, x320 y0 w%SplitterW% h500 vSplitter3 gMoveSplitter3 64 | ; Change the cursor when mouse is over splitter control 65 | OnMessage(WM_SETCURSOR := 0x20, "HandleMessage") 66 | OnMessage(WM_MOUSEMOVE := 0x200, "HandleMessage") 67 | 68 | Gui Show,, UIA Tree Inspector 69 | Return 70 | 71 | MainGuiEscape: 72 | MainGuiClose: 73 | IsCapturing := False 74 | ExitApp 75 | 76 | MainGuiSize(GuiHwnd, EventInfo, Width, Height){ 77 | global splitterW, _minSplitterPosX := 200, _maxSplitterPosX := (Width - SplitterW), _minSplitterPosY := 220, _maxSplitterPosY := (Height - SplitterW - 100), _maxSplitter3PosX 78 | 79 | GuiControl, -Redraw, MainTreeView 80 | GuiControlGet, Pos, Pos , MainTreeView 81 | GuiControl, Move, MainTreeView, % "w" Width -Posx-10 " h" Height -Posy-35 82 | GuiControl, Move, Splitter1, % "h" Height-60 83 | GuiControl, Move, Splitter3, % "h" Height-60 84 | GuiControl, +Redraw, MainTreeView 85 | GuiControl, -Redraw, TVPatterns 86 | GuiControlGet, Pos, Pos , TVPatterns 87 | _maxSplitter3PosX := PosX+PosW-100 88 | GuiControl, Move, TVPatterns, % " h" Height -Posy-35 89 | GuiControl, +Redraw, TVPatterns 90 | GuiControlGet, Pos, Pos , LVWindowList 91 | GuiControl, Move, LVWindowList, % " h" Height -Posy-60 92 | GuiControl, +Redraw, LVWindowList 93 | GuiControl, Move, ButRefreshWindowList, % "y" Height -50 94 | GuiControl, Move, CBVisible, % "y" Height -45 95 | GuiControl, Move, CBTitle, % "y" Height -45 96 | GuiControl, Move, CBActivate, % "y" Height -45 97 | GuiControlGet, Pos, Pos , GBPatterns 98 | GuiControl, Move, GBPatterns, % " h" Height -Posy-30 99 | GuiControl, +Redraw, MainSB 100 | SetTimer, RedrawMainWindow, -500 101 | } 102 | 103 | RedrawMainWindow: 104 | WinSet, Redraw,, ahk_id %MainGuiHwnd% 105 | return 106 | 107 | MainSB: 108 | GuiControlGet, SBText,, MainSB 109 | if (SBText == "`tClick here to enable Acc path capturing (can't be used with UIA!)") { 110 | EnableAccTree := True 111 | SB_SetText("",1) 112 | SB_SetText("`tClick on path to copy to Clipboard",2) 113 | } else if SBText { 114 | Clipboard := SubStr(SBText, 8) 115 | ToolTip, % "Copied """ SubStr(SBText, 8) """ to Clipboard!" 116 | SetTimer, RemoveToolTip, -2000 117 | } 118 | return 119 | 120 | CBVisible: 121 | gosub ButRefreshWindowList 122 | return 123 | CBTitle: 124 | gosub ButRefreshWindowList 125 | return 126 | 127 | LVWindowList: 128 | GuiControlGet, chk,, CBVisible 129 | DetectHiddenWindows, % chk ? "Off" : "On" 130 | 131 | Gui, ListView, LVWindowList 132 | LV_GetText(wId, A_EventInfo, 3) 133 | if (!wId || !WinExist("ahk_id " wId) || (A_GuiEvent != "Normal")) 134 | return 135 | GuiControlGet, activate,, CBActivate 136 | if activate 137 | WinActivate, ahk_id %wId% 138 | 139 | try { 140 | mEl := UIA.ElementFromHandle(wId, True) 141 | } catch e { 142 | UpdateElementFields() 143 | GuiControl, Main:, EditName, % "ERROR: " e.Message 144 | if InStr(e.Message, "0x80070005") 145 | GuiControl, Main:, EditValue, Try running UIA Tree Inspector with Admin privileges 146 | } 147 | Stored.Hwnd := wId 148 | 149 | WinGetTitle, wTitle, ahk_id %wId% 150 | WinGetPos, wX, wY, wW, wH, ahk_id %wId% 151 | WinGetClass, wClass, ahk_id %wId% 152 | WinGetText, wText, ahk_id %wId% 153 | WinGet, wProc, ProcessName, ahk_id %wId% 154 | WinGet, wProcID, PID, ahk_id %wId% 155 | 156 | GuiControl, Main:, EditWinTitle, %wTitle% 157 | GuiControl, Main:, EditWinHwnd, ahk_id %wId% 158 | GuiControl, Main:, EditWinPosition, X: %wX% Y: %wY% 159 | GuiControl, Main:, EditWinSize, W: %wW% H: %wH% 160 | GuiControl, Main:, EditWinClass, %wClass% 161 | GuiControl, Main:, EditWinProcess, %wProc% 162 | GuiControl, Main:, EditWinProcessID, %wProcID% 163 | 164 | try { 165 | UpdateElementFields(mEl) 166 | if EnableAccTree { 167 | oAcc := Acc_ObjectFromWindow(wId, 0), Acc_Location(oAcc,mEl.GetCurrentPatternAs("LegacyIAccessible").CurrentChildId,vAccLoc) 168 | SB_SetText(" Path: " GetAccPathTopDown(wId, vAccLoc), 1) 169 | } 170 | } 171 | try RedrawTreeView(mEl, False) 172 | return 173 | 174 | LVPropertyIds: 175 | if (A_GuiEvent == "RightClick") { 176 | Gui, ListView, LVPropertyIds 177 | LV_GetText(info, A_EventInfo, 2) 178 | if info { 179 | LV_GetText(prop, A_EventInfo, 1) 180 | if (prop == "ControlType") 181 | RegexMatch(info, "(?<=\().+(?=\))", info) 182 | Clipboard := info 183 | ToolTip, % "Copied """ info """ to Clipboard!" 184 | SetTimer, RemoveToolTip, -2000 185 | } 186 | } 187 | return 188 | 189 | TVPatterns: 190 | if (A_GuiEvent == "RightClick") { 191 | Gui, TreeView, TVPatterns 192 | TV_GetText(info, A_EventInfo) 193 | if info { 194 | Clipboard := info 195 | ToolTip, % "Copied """ info """ to Clipboard!" 196 | SetTimer, RemoveToolTip, -2000 197 | } 198 | } 199 | if (A_GuiEvent == "DoubleClick") { 200 | Gui, TreeView, TVPatterns 201 | TV_GetText(info, A_EventInfo) 202 | if (SubStr(info,-1) == "()") { 203 | info := SubStr(info,1, StrLen(info)-2) 204 | if (info == "DoDefaultAction") { 205 | WinActivate, % "ahk_id " Stored.Hwnd 206 | WinWaitActive, % "ahk_id " Stored.Hwnd,,1 207 | Stored.Element.GetCurrentPatternAs("LegacyIAccessible").DoDefaultAction() 208 | } else if (info == "Invoke") { 209 | Stored.Element.GetCurrentPatternAs("Invoke").Invoke() 210 | } else if (info == "Select") { 211 | Stored.Element.GetCurrentPatternAs("SelectionItem").Select() 212 | } else if (info == "SetValue") { 213 | Gui +LastFound +OwnDialogs +AlwaysOnTop 214 | InputBox, val, SetValue, Insert value to set 215 | Gui +LastFound +OwnDialogs -AlwaysOnTop 216 | if (val && !ErrorLevel) 217 | Stored.Element.GetCurrentPatternAs("Value").SetValue(val) 218 | } 219 | } 220 | } 221 | return 222 | 223 | ButRefreshWindowList: 224 | GuiControlGet, chk,, CBVisible 225 | DetectHiddenWindows, % chk ? "Off" : "On" 226 | 227 | GuiControlGet, NeedsTitle,, CBTitle 228 | Gui, ListView, LVWindowList 229 | LV_Delete() 230 | WinGet, wList, List 231 | Loop, %wList% 232 | { 233 | wId := wList%A_Index% 234 | WinGetTitle, wTitle, ahk_id %wId% 235 | if (NeedsTitle && (wTitle == "")) 236 | continue 237 | WinGet, wExe, ProcessName, ahk_id %wId% 238 | LV_Add("", wTitle, wExe, wId) 239 | } 240 | LV_ModifyCol(1, 140) 241 | LV_ModifyCol(2) 242 | return 243 | 244 | MainTreeView: 245 | if (A_GuiEvent == "S") { 246 | Stored.Element := Stored.Treeview[A_EventInfo] 247 | UpdateElementFields(Stored.Treeview[A_EventInfo]) 248 | if EnableAccTree { 249 | br := Stored.Treeview[A_EventInfo].CurrentBoundingRectangle 250 | SB_SetText(" Path: " GetAccPathTopDown(Stored.Hwnd, "x" br.l " y" br.t " w" (br.r-br.l) " h" (br.b-br.t)), 1) 251 | } 252 | } 253 | return 254 | 255 | MoveSplitter1: 256 | DragSplitter1("Splitter1") 257 | return 258 | MoveSplitter2: 259 | DragSplitter2("Splitter2") 260 | return 261 | MoveSplitter3: 262 | DragSplitter3("Splitter3") 263 | return 264 | 265 | RemoveToolTip: 266 | ToolTip 267 | return 268 | 269 | ; Handle splitters to adjust the size of controls 270 | GetMouseOffsets(ByRef offsetX, ByRef offsetY, _controlName) { 271 | CoordMode Mouse, Screen 272 | MouseGetPos initScrX, initScrY, hWnd 273 | CoordMode Mouse, Relative ; Restore default 274 | MouseGetPos initWinX, initWinY 275 | ; Compute client area relative coordinates of the mouse 276 | VarSetCapacity(point, 8), NumPut(initScrX, point, 0, "int"), NumPut(initScrY, point, 4, "int") 277 | DllCall("user32\ScreenToClient", "ptr", hWnd, "ptr", &point, "int") 278 | initCliX := NumGet(point,0,"Int"), initCliY := NumGet(point,4,"Int") 279 | ; Coordinates of the control, relative to the client area 280 | GuiControlGet controlPos, Pos, %_controlName% 281 | mouseX := controlPosX, mouseY := controlPosY 282 | ; Compute offset between click inside control and top-left corner of control 283 | offsetX := initCliX - controlPosX, offsetY := initCliY - controlPosY 284 | ; Add offset between window and client area 285 | offsetX += initWinX - initCliX, offsetY += initWinY - initCliY 286 | } 287 | 288 | DragSplitter1(_controlName) { ; Based on a script by user PhiLho (https://www.autohotkey.com/board/topic/8001-splitter-bar-window-control-with-ahk/) 289 | global _minSplitterPosX, _maxSplitterPosX 290 | if !GetKeyState("LButton") 291 | return 292 | GetMouseOffsets(offsetX, offsetY, _controlName) 293 | originalSizes := GetControlSizes(_controlName, "LVPropertyIds", "GBWindowInfo", "EditWinTitle", "GBProperties", "GBPatterns", "TVPatterns", "ButCapture", "EditWinHwnd", "EditWinPosition", "EditWinSize", "TextClassNN", "TextProcess", "TextProcessID", "EditWinClass", "EditWinProcess", "EditWinProcessID", "MainTreeView", "ButRefreshTreeview", "Splitter2") 294 | oldControlPos := originalSizes[_controlName] 295 | Loop { 296 | if !GetKeyState("LButton") 297 | Break 298 | MouseGetPos, mouseX, mouseY 299 | mouseX -= offsetX 300 | 301 | if (mouseX < _minSplitterPosX) { 302 | mouseX := _minSplitterPosX 303 | } 304 | if (mouseX > _maxSplitterPosX) { 305 | mouseX := _maxSplitterPosX 306 | } 307 | moveX := Floor((mouseX-oldControlPos.x)*(96/A_ScreenDPI)) 308 | OffsetControls(originalSizes,moveX,,,, _controlName) 309 | OffsetControls(originalSizes,,, moveX,, "LVPropertyIds", "GBWindowInfo", "EditWinTitle", "GBProperties", "GBPatterns", "TVPatterns", "ButCapture", "Splitter2") 310 | OffsetControls(originalSizes,,, moveX//2,, "EditWinHwnd", "EditWinPosition", "EditWinSize") 311 | OffsetControls(originalSizes,moveX//2,, moveX//2,,"EditWinClass", "EditWinProcess", "EditWinProcessID") 312 | OffsetControls(originalSizes,moveX//2,,,, "TextClassNN", "TextProcess", "TextProcessID") 313 | OffsetControls(originalSizes,moveX,, -moveX,, "MainTreeView", "ButRefreshTreeview") 314 | Sleep 100 315 | } 316 | WinSet, Redraw,, ahk_id %MainGuiHwnd% 317 | } 318 | DragSplitter2(_controlName) { 319 | global _minSplitterPosY, _maxSplitterPosY 320 | if !GetKeyState("LButton") 321 | return 322 | GetMouseOffsets(offsetX, offsetY, _controlName) 323 | 324 | originalSizes := GetControlSizes(_controlName, "LVPropertyIds", "GBWindowInfo", "EditWinTitle", "GBProperties", "GBPatterns", "TVPatterns", "ButCapture", "EditWinHwnd", "EditWinPosition", "EditWinSize", "TextClassNN", "TextProcess", "TextProcessID", "EditWinClass", "EditWinProcess", "EditWinProcessID", "MainTreeView", "ButRefreshTreeview") 325 | oldControlPos := originalSizes[_controlName] 326 | Loop { 327 | if !GetKeyState("LButton") 328 | Break 329 | MouseGetPos, mouseX, mouseY 330 | mouseY -= offsetY 331 | 332 | if (mouseY < _minSplitterPosY) { 333 | mouseY := _minSplitterPosY 334 | } 335 | if (mouseY > _maxSplitterPosY) { 336 | mouseY := _maxSplitterPosY 337 | } 338 | moveY := Floor((mouseY-oldControlPos.y)*(96/A_ScreenDPI)) 339 | OffsetControls(originalSizes,,moveY,,, _controlName) 340 | OffsetControls(originalSizes, ,, ,moveY, "LVPropertyIds", "GBProperties") 341 | OffsetControls(originalSizes,,moveY, ,-moveY, "GBPatterns", "TVPatterns") 342 | Sleep 100 343 | } 344 | WinSet, Redraw,, ahk_id %MainGuiHwnd% 345 | } 346 | DragSplitter3(_controlName) { ; Based on a script by user PhiLho (https://www.autohotkey.com/board/topic/8001-splitter-bar-window-control-with-ahk/) 347 | global _minSplitterPosX, _maxSplitter3PosX 348 | if !GetKeyState("LButton") 349 | return 350 | GetMouseOffsets(offsetX, offsetY, _controlName) 351 | originalSizes := GetControlSizes(_controlName, "LVWindowList", "LVPropertyIds", "GBWindowInfo", "EditWinTitle", "GBProperties", "GBPatterns", "TVPatterns", "TextWinTitle", "TextHwnd", "TextPosition", "TextSize", "EditWinHwnd", "EditWinPosition", "EditWinSize", "TextClassNN", "TextProcess", "TextProcessID", "EditWinClass", "EditWinProcess", "EditWinProcessID", "ButRefreshTreeview", "ButRefreshWindowList", "CBVisible", "CBTitle", "CBActivate", "MainTreeView", "Splitter3") 352 | oldControlPos := originalSizes[_controlName] 353 | Loop { 354 | if !GetKeyState("LButton") 355 | Break 356 | MouseGetPos, mouseX, mouseY 357 | mouseX -= offsetX 358 | 359 | if (mouseX < _minSplitterPosX) { 360 | mouseX := _minSplitterPosX 361 | } 362 | if (mouseX > _maxSplitter3PosX) { 363 | mouseX := _maxSplitter3PosX 364 | } 365 | moveX := Floor((mouseX-oldControlPos.x)*(96/A_ScreenDPI)) 366 | OffsetControls(originalSizes,moveX,,,, _controlName) 367 | OffsetControls(originalSizes,,, moveX,, "LVWindowList", "ButRefreshWindowList", "MainTreeView") 368 | OffsetControls(originalSizes,moveX,, -moveX,, "LVPropertyIds", "GBWindowInfo", "EditWinTitle", "GBProperties", "GBPatterns", "TVPatterns", "Splitter2") 369 | OffsetControls(originalSizes,moveX,, -moveX//2,, "EditWinHwnd", "EditWinPosition", "EditWinSize") 370 | OffsetControls(originalSizes,moveX//2,, -moveX//2,, "EditWinClass", "EditWinProcess", "EditWinProcessID") 371 | OffsetControls(originalSizes,moveX,,,, "CBVisible", "CBTitle", "CBActivate", "TextWinTitle", "TextHwnd", "TextPosition", "TextSize") 372 | OffsetControls(originalSizes,moveX//2,,,, "TextClassNN", "TextProcess", "TextProcessID") 373 | 374 | ;OffsetControls(originalSizes,moveX,, -moveX,, "MainTreeView", "ButRefreshTreeview") 375 | Sleep 100 376 | } 377 | WinSet, Redraw,, ahk_id %MainGuiHwnd% 378 | } 379 | 380 | GetControlSizes(ctrls*) { 381 | sizes := {} 382 | for _, ctrl in ctrls { 383 | GuiControlGet ctrlSize, Pos, %ctrl% 384 | sizes[ctrl] := {x:ctrlSizeX, y:ctrlSizeY, w:ctrlSizeW, h:ctrlSizeH} 385 | } 386 | return sizes 387 | } 388 | 389 | OffsetControls(sizes=0, offsetX=0, offsetY=0, offsetW=0, offsetH=0, ctrls*) { 390 | for _, ctrl in ctrls { 391 | ctrlSize := sizes[ctrl] 392 | GuiControl Move, %ctrl%, % "x" (ctrlSize.x+offsetX) " y" (ctrlSize.y+offsetY) " w" (ctrlSize.w+offsetW) " h" (ctrlSize.h+offsetH) 393 | } 394 | } 395 | 396 | HandleMessage(p_w, p_l, p_m, p_hw) 397 | { 398 | global WM_SETCURSOR, WM_MOUSEMOVE 399 | static hover, IDC_SIZEWE, h_old_cursor 400 | 401 | if (p_m = WM_SETCURSOR) { 402 | if hover 403 | return, true 404 | } 405 | else if (p_m = WM_MOUSEMOVE) { 406 | ; cursor hovers splitter control 407 | if InStr(A_GuiControl, "Splitter") { 408 | if hover = 409 | { 410 | IDC_SIZEWE := DllCall("LoadCursor", "uint", 0, "uint", A_GuiControl == "Splitter2" ? 32645 : 32644) ; IDC_SIZEWE = 32644 411 | hover = true 412 | } 413 | h_old_cursor := DllCall("SetCursor", "uint", IDC_SIZEWE) 414 | } else if hover { 415 | DllCall("SetCursor", "uint", h_old_cursor) 416 | hover= 417 | } 418 | } 419 | } 420 | 421 | ClearLVPropertyIds() { 422 | Gui, ListView, LVPropertyIds 423 | LV_Delete() 424 | LV_Add("", "ControlType", "") 425 | LV_Add("", "LocalizedControlType", "") 426 | LV_Add("", "Name", "") 427 | LV_Add("", "Value", "") 428 | LV_Add("", "AutomationId", "") 429 | LV_Add("", "BoundingRectangle", "") 430 | LV_Add("", "ClassName", "") 431 | LV_Add("", "HelpText", "") 432 | LV_Add("", "AccessKey", "") 433 | LV_Add("", "AcceleratorKey", "") 434 | LV_Add("", "HasKeyboardFocus", "") 435 | LV_Add("", "IsKeyboardFocusable", "") 436 | LV_Add("", "ItemType", "") 437 | LV_Add("", "ProcessId", "") 438 | LV_Add("", "IsEnabled", "") 439 | LV_Add("", "IsPassword", "") 440 | LV_Add("", "IsOffscreen", "") 441 | LV_Add("", "FrameworkId", "") 442 | LV_Add("", "IsRequiredForForm", "") 443 | LV_Add("", "ItemStatus", "") 444 | LV_Add("", "LabeledBy", "") 445 | LV_ModifyCol(1) 446 | } 447 | 448 | UpdateElementFields(mEl="") { 449 | if !IsObject(mEl) { 450 | ClearLVPropertyIds() 451 | return 452 | } 453 | try { 454 | mElPos := mEl.CurrentBoundingRectangle 455 | RangeTip(mElPos.l, mElPos.t, mElPos.r-mElPos.l, mElPos.b-mElPos.t, "Blue", 4) 456 | } 457 | Gui, ListView, LVPropertyIds 458 | LV_Delete() 459 | Gui, TreeView, TVPatterns 460 | TV_Delete() 461 | try { 462 | for k, v in UIA.PollForPotentialSupportedPatterns(mEl) { 463 | parent := TV_Add(RegexReplace(k, "Pattern$")) 464 | if IsObject(UIA_%k%) { 465 | pos := 1, m := "", pattern := mEl.GetCurrentPatternAs(k) 466 | for key, value in UIA_%k% { 467 | if (InStr(key, "Current") && !IsObject(val := pattern[key])) { 468 | TV_Add(SubStr(key,8) ": " val, parent) 469 | } 470 | } 471 | } 472 | if InStr(k, "Invoke") 473 | TV_Add("Invoke()", parent) 474 | if InStr(k, "LegacyIAccessible") 475 | TV_Add("DoDefaultAction()", parent) 476 | if InStr(k, "SelectionItem") 477 | TV_Add("Select()", parent) 478 | if InStr(k, "Value") 479 | TV_Add("SetValue()", parent) 480 | } 481 | } 482 | Gui, ListView, LVPropertyIds 483 | try LV_Add("", "ControlType", (ctrlType := mEl.CurrentControlType) " (" UIA_Enum.UIA_ControlTypeId(ctrlType) ")") 484 | try LV_Add("", "LocalizedControlType", mEl.CurrentLocalizedControlType) 485 | try LV_Add("", "Name", mEl.CurrentName) 486 | try LV_Add("", "Value", mEl.GetCurrentPropertyValue(UIA_ValueValuePropertyId := 30045)) 487 | try LV_Add("", "AutomationId", mEl.CurrentAutomationId) 488 | try LV_Add("", "BoundingRectangle", "l: " mElPos.l " t: " mElPos.t " r: " mElPos.r " b: " mElPos.b) 489 | try LV_Add("", "ClassName", mEl.CurrentClassName) 490 | try LV_Add("", "HelpText", mEl.CurrentHelpText) 491 | try LV_Add("", "AccessKey", mEl.CurrentAccessKey) 492 | try LV_Add("", "AcceleratorKey", mEl.CurrentAcceleratorKey) 493 | try LV_Add("", "HasKeyboardFocus", mEl.CurrentHasKeyboardFocus) 494 | try LV_Add("", "IsKeyboardFocusable", mEl.CurrentIsKeyboardFocusable) 495 | try LV_Add("", "ItemType", mEl.CurrentItemType) 496 | try LV_Add("", "ProcessId", mEl.CurrentProcessId) 497 | try LV_Add("", "IsEnabled", mEl.CurrentIsEnabled) 498 | try LV_Add("", "IsPassword", mEl.CurrentIsPassword) 499 | try LV_Add("", "IsOffscreen", mEl.CurrentIsOffscreen) 500 | try LV_Add("", "FrameworkId", mEl.CurrentFrameworkId) 501 | try LV_Add("", "IsRequiredForForm", mEl.CurrentIsRequiredForForm) 502 | try LV_Add("", "ItemStatus", mEl.CurrentItemStatus) 503 | try LV_ModifyCol(1) 504 | return 505 | } 506 | 507 | RedrawTreeView(el, noAncestors=True) { 508 | global MainTreeView, hMainTreeView 509 | Gui, TreeView, MainTreeView 510 | TV_Delete() 511 | TV_Add("Constructing TreeView...") 512 | Sleep, 40 513 | GuiControl, Main: -Redraw, MainTreeView 514 | TV_Delete() 515 | Stored.TreeView := {} 516 | if noAncestors { 517 | ConstructTreeView(el) 518 | } else { 519 | ; Get all ancestors 520 | ancestors := [], parent := el 521 | while IsObject(parent) { 522 | try { 523 | ancestors.Push(parent := UIA.TreeWalkerTrue.GetParentElement(parent)) 524 | } catch { 525 | break 526 | } 527 | } 528 | 529 | ; Loop backwards through ancestors to create the TreeView 530 | maxInd := ancestors.MaxIndex(), parent := "" 531 | while (--maxInd) { 532 | if !IsObject(ancestors[maxInd]) 533 | return 534 | try { 535 | elDesc := ancestors[maxInd].CurrentLocalizedControlType " """ ancestors[maxInd].CurrentName """" 536 | if (elDesc == " """"") 537 | break 538 | Stored.TreeView[parent := TV_Add(elDesc, parent)] := ancestors[maxInd] 539 | } 540 | } 541 | ; Add child elements to TreeView also 542 | ConstructTreeView(el, parent) 543 | } 544 | for k,v in Stored.TreeView 545 | TV_Modify(k, "Expand") 546 | 547 | SendMessage, 0x115, 6, 0,, ahk_id %hMainTreeView% ; scroll to top 548 | GuiControl, Main: +Redraw, MainTreeView 549 | } 550 | 551 | ConstructTreeView(el, parent="") { 552 | if !IsObject(el) 553 | return 554 | try { 555 | elDesc := el.CurrentLocalizedControlType " """ el.CurrentName """" 556 | ;if (elDesc == " """"") 557 | ; return 558 | Stored.TreeView[TWEl := TV_Add(elDesc, parent)] := el 559 | if !(children := el.FindAll(UIA.TrueCondition, 0x2)) 560 | return 561 | for k, v in children 562 | ConstructTreeView(v, TWEl) 563 | } 564 | } 565 | 566 | ; Acc functions 567 | 568 | GetAccPathTopDown(hwnd, vAccPos, updateTree=False) { 569 | static accTree 570 | if !IsObject(accTree) 571 | accTree := {} 572 | if (!IsObject(accTree[hwnd]) || updateTree) 573 | accTree[hwnd] := BuildAccTreeRecursive(Acc_ObjectFromWindow(hwnd, 0), {}) 574 | for k, v in accTree[hwnd] { 575 | if (v == vAccPos) 576 | return k 577 | } 578 | } 579 | 580 | BuildAccTreeRecursive(oAcc, tree, path="") { 581 | if !IsObject(oAcc) 582 | return tree 583 | try 584 | oAcc.accChildCount 585 | catch 586 | return tree 587 | For i, oChild in Acc_Children(oAcc) { 588 | if IsObject(oChild) 589 | Acc_Location(oChild,,vChildPos) 590 | else 591 | Acc_Location(oAcc,oChild,vChildPos) 592 | tree[path (path?(IsObject(oChild)?".":" c"):"") i] := vChildPos 593 | tree := BuildAccTreeRecursive(oChild, tree, path (path?".":"") i) 594 | } 595 | return tree 596 | } 597 | Acc_Init() 598 | { 599 | Static h 600 | If Not h 601 | h:=DllCall("LoadLibrary","Str","oleacc","Ptr") 602 | } 603 | Acc_ObjectFromEvent(ByRef _idChild_, hWnd, idObject, idChild) 604 | { 605 | Acc_Init() 606 | If DllCall("oleacc\AccessibleObjectFromEvent", "Ptr", hWnd, "UInt", idObject, "UInt", idChild, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0 607 | Return ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt") 608 | } 609 | 610 | Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "") 611 | { 612 | Acc_Init() 613 | If DllCall("oleacc\AccessibleObjectFromPoint", "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0 614 | Return ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt") 615 | } 616 | 617 | Acc_ObjectFromWindow(hWnd, idObject = -4) 618 | { 619 | Acc_Init() 620 | If DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0 621 | Return ComObjEnwrap(9,pacc,1) 622 | } 623 | 624 | Acc_WindowFromObject(pacc) 625 | { 626 | If DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0 627 | Return hWnd 628 | } 629 | Acc_Error(p="") { 630 | static setting:=0 631 | return p=""?setting:setting:=p 632 | } 633 | Acc_Children(Acc) { 634 | if ComObjType(Acc,"Name") != "IAccessible" 635 | ErrorLevel := "Invalid IAccessible Object" 636 | else { 637 | Acc_Init(), cChildren:=Acc.accChildCount, Children:=[] 638 | if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 { 639 | Loop %cChildren% 640 | i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Push(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child): 641 | return Children.MaxIndex()?Children: 642 | } else 643 | ErrorLevel := "AccessibleChildren DllCall Failed" 644 | } 645 | if Acc_Error() 646 | throw Exception(ErrorLevel,-1) 647 | } 648 | Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code 649 | try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId) 650 | catch 651 | return 652 | Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int") 653 | return {x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")} 654 | } 655 | Acc_Parent(Acc) 656 | { 657 | try parent:=Acc.accParent 658 | return parent?Acc_Query(parent): 659 | } 660 | Acc_Child(Acc, ChildId=0) 661 | { 662 | try child:=Acc.accChild(ChildId) 663 | return child?Acc_Query(child): 664 | } 665 | Acc_Query(Acc) 666 | { 667 | try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1) 668 | } 669 | 670 | RangeTip(x:="", y:="", w:="", h:="", color:="Red", d:=2) ; from the FindText library, credit goes to feiyue 671 | { 672 | static id:=0 673 | if (x="") 674 | { 675 | id:=0 676 | Loop 4 677 | Gui, Range_%A_Index%: Destroy 678 | return 679 | } 680 | if (!id) 681 | { 682 | Loop 4 683 | Gui, Range_%A_Index%: +Hwndid +AlwaysOnTop -Caption +ToolWindow 684 | -DPIScale +E0x08000000 685 | } 686 | x:=Floor(x), y:=Floor(y), w:=Floor(w), h:=Floor(h), d:=Floor(d) 687 | Loop 4 688 | { 689 | i:=A_Index 690 | , x1:=(i=2 ? x+w : x-d) 691 | , y1:=(i=3 ? y+h : y-d) 692 | , w1:=(i=1 or i=3 ? w+2*d : d) 693 | , h1:=(i=2 or i=4 ? h+2*d : d) 694 | Gui, Range_%i%: Color, %color% 695 | Gui, Range_%i%: Show, NA x%x1% y%y1% w%w1% h%h1% 696 | } 697 | } --------------------------------------------------------------------------------