前言:最近我一直在做一个涉及浏览器(特别是Chrome)自动化的项目,限制是不允许使用外部程序(例如Rufaydium)。这让我找到了 UIAutomation 框架,我发现该框架已经存在一些 AHK 库。 AHK1 最受欢迎的似乎是 jethro 的 UIA_Interface ( https://github.com/jethro/UIA_Interface/blob/master/UIA_Interface.ahk),不幸的是目前似乎已被放弃。尽管如此,在克服了一些最初的障碍(例如它不能在 32 位模式下工作)之后,我让它工作起来,并一点一点地添加了一些额外的方法和辅助函数。也许其他人也有兴趣使用或改进它。请不要太讨厌代码,因为我对 dll 调用、变体等非常不熟悉...

该库可在此处使用:https ://github.com/Decolada/UIAutomation

教学中了解有关 UIAutomation 的更多信息来自 Joe the Automator 的视频

它由两个(三个?)主文件组成:
1) UIA_Interface.ahk,它基于 jethro 的项目,包含 UIAutomation 框架的包装函数。此外,它还具有一些帮助函数,可以更轻松地使用 UIA。
2) UIA_Browser.ahk,其中包含 Chrome(也大多是 Edge)自动化的辅助函数(获取 URL、切换选项卡等)。
3) 可选UIA_Constants.ahk,其中包含使用 UIA 的常量。所有常量也可在 UIA_Interface.ahk 中使用,但 UIA_Constants.ahk 中常量的格式可能对某些人来说更受欢迎。请注意,此文件创建了许多全局变量,因此请确保您的脚本在运行时不会更改任何这些变量。图片来源:UIA_Constants 文件主要基于 LarsJ 的 Autoit3 项目。

UIAutomation 的简短介绍:
https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-overview
UIAutomation 是一个 Microsoft 辅助功能框架,允许与用户可访问的元素(单击按钮、发送文本等)进行交互一种程序化的方式。它是Acc/MSAA 框架的后继者。

UIAutomation 框架将整个桌面以及所有窗口和控件保存在 AutomationElement 对象树中。根元素是桌面本身,它的子元素是所有窗口(记事本、Chrome 等),然后窗口又具有子元素(工具栏、主要内容、按钮等)等等。

要与窗口和控件交互,通常我们需要首先获取该窗口/控件的 AutomationElement。这可以使用 UIA_Interface.ahk UIA_Interface 类中的函数来完成,例如使用 ElementFromHandle 从 ahk_id 句柄获取窗口元素,或使用 ElementFromPoint 从点获取窗口元素。我们还可以使用 GetRootElement 获取根元素(桌面)。
找到元素后,查找子元素的一种方法是使用 FindFirst 或 FindAll 函数,它们采用特定条件(例如控件类型需要为“edit”,或者名称必须为“something”)并且返回第一个匹配元素 (FindFirst) 或所有匹配元素 (FindAll)。可以使用 Create...Condition 方法(CreatePropertyCondition、CreateTrueCondition 等)并结合使用 CreateAndCondition、CreateOrCondition 创建条件。最常用的条件方法之一是 CreatePropertyCondition,它采用属性 id(可以在 PropertyIds 下的 UIA_Enum 类下找到,或在 UIA_PropertyIds 下的 UIA_Constants.ahk 文件中找到)和所需的属性值。例如,要创建仅查找按钮元素的条件,首先在UIA_Enum类中查找相应的PropertyId(“按钮”是一个控件类型,因此它将是UIA_ControlTypePropertyId),然后在UIA_ControlTypeIds下查找按钮的值(UIA_ButtonControlTypeId)。
或者,可以使用 TreeWalker 类来遍历树。这可以对任何元素(例如在 ElementFromHandle 或 FindFirst 方法之后)完成,并使用 TreeWalker 类方法(例如 GetFirstChildElement 或 GetNextSiblingElement)。也可以使用条件创建 TreeWalkers,以仅返回按类型、名称等过滤的某些元素。

找到元素后,可以通过属性访问一些基本信息,例如 CurrentName(返回元素的名称)、CurrentControlType(返回类型)这些可以在 UIA_Element 类的 UIA_Interface.ahk 中找到(属性以 [] 结尾)。
可以使用控制模式与元素进行交互。模式包含与元素交互的实际方法,例如 InvokePattern 来调用(单击)按钮,或 ScrollPattern 来滚动控件,ValuePattern 来获取或设置值(例如编辑框)。可以通过调用 GetCurrentPatternAs 方法,然后使用模式中可用的方法来获取模式(例如,在调用 GetCurrentPatternAs("Invoke") 获取 UIA_InvokePattern 对象后,这将是 object.Invoke())。

 

UIA_Interface.ahk

/*
  Introduction & credits
  This library implements Microsoft's UI Automation framework. More information is here: https://docs.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32
  Credit for this file mostly goes to jethrow: https://github.com/jethrow/UIA_Interface/blob/master/UIA_Interface.ahk
  I have added a lot of modifications to it, including custom methods for elements (eg element.Click()), UIA_Enum class etc
*/

/* 
  Usage
  UIA needs to be initialized with UIA_Interface() function, which returns a UIA_Interface object:
  UIA := UIA_Interface()
  After calling this function, all UIA_Interface class properties and methods can be accessed through it. 
  In addition some extra variables are initialized: 
    CurrentVersion contains the version number of IUIAutomation interface
    TrueCondition contains a UIA_TrueCondition
    TreeWalkerTrue contains an UIA_TreeWalker that was created with UIA_TrueCondition
  Note that a new UIA_Interface object can't be created with the "new" keyword. 
  
  UIAutomation constants and enumerations are available from the UIA_Enum class (see a more thorough description at the class header).
  Microsoft documentation for constants and enumerations:
    UI Automation Constants: https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-entry-constants
    UI Automation Enumerations: https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-entry-enumerations
  
  For more information, see the AHK Forums post on UIAutomation: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=104999
*/


/* 	
  Questions:
  - if method returns a SafeArray, should we return a Wrapped SafeArray, Raw SafeArray, or AHK Array. Currently we return wrapped AHK arrays for SafeArrays. Although SafeArrays are more convenient to loop over, this causes more confusion in users who are not familiar with SafeArrays (questions such as why are they 0-indexed not 1-indexed, why doesnt for k, v in SafeArray work properly etc). 
  - on UIA Interface conversion methods, how should the data be returned? wrapped/extracted or raw? should raw data be a ByRef param?
  - do variants need cleared? what about SysAllocString BSTRs? As per Microsoft documentation (https://docs.microsoft.com/en-us/cpp/atl-mfc-shared/allocating-and-releasing-memory-for-a-bstr?view=msvc-170), when we pass a BSTR into IUIAutomation, then IUIAutomation should take care of freeing it. But when we receive a UIA_Variant and use UIA_VariantData, then we should clear the BSTR.
  - ObjRelease: if IUIA returns an interface then it automatically increases the ref count for the object it inherits from, and when released decreases it. So do all returned objects (UIA_Element, UIA_Pattern, UIA_TextRange) need to be released? Currently we release these objects as well, but jethrow's version didn't. 
  - do RECT structs need destroyed?
  - if returning wrapped data & raw is ByRef, will the wrapped data being released destroy the raw data?
  - returning variant data other than vt=3|8|9|13|0x2000
  - Cached Members?
  - UIA Element existance - dependent on window being visible (non minimized), and also sometimes Elements are lazily generated (eg Microsoft Teams, when a meeting is started then the toolbar buttons (eg Mute, react) aren't visible to UIA, but hovering over them with the cursor or calling ElementFromPoint causes Teams to generate and make them visible to UIA.
  - better way of supporting differing versions of IUIAutomation (version 2, 3, 4)
  - Get methods vs property getter: currently we use properties when the item stores data, fetching the data is "cheap" and when it doesn't have side-effects, and in computationally expensive cases use Get...(). 
  - should ElementFromHandle etc methods have activateChromiumAccessibility set to True or False? Currently is True, because Chromium apps are very common, and checking whether its on should be relatively fast.
*/

; Base class for all UIA objects (UIA_Interface, UIA_Element etc), that is also used to get constants and enumerations from UIA_Enum.
class UIA_Base {
  __New(p:="", flag:=0, version:="") {
    ObjRawSet(this,"__Type","IUIAutomation" SubStr(this.__Class,5))
    ,ObjRawSet(this,"__Value",p)
    ,ObjRawSet(this,"__Flag",flag)
    ,ObjRawSet(this,"__Version",version)
  }
  __Get(members*) {
    local
    global UIA_Enum
    member := members[1]
    if member not in base,__UIA,TreeWalkerTrue,TrueCondition ; These should act as normal
    {
      if (!InStr(member, "Current")) {
        baseKey := this
        While (ObjGetBase(baseKey)) {
          if baseKey.HasKey("Current" member)
            return this["Current" member]
          baseKey := ObjGetBase(baseKey)
        }
      }
      if ObjHasKey(UIA_Enum, member) {
        return UIA_Enum[member]
      } else if RegexMatch(member, "i)PatternId|EventId|PropertyId|AttributeId|ControlTypeId|AnnotationType|StyleId|LandmarkTypeId|HeadingLevel|ChangeId|MetadataId", match) {
        return UIA_Enum["UIA_" match](member)
      } else if InStr(this.__Class, "UIA_Element") {
        if (prop := UIA_Enum.UIA_PropertyId(member))
          return this.GetCurrentPropertyValue(prop)
        else if (RegExMatch(member, "i)=|\.|^[+-]?\d+$") || (RegexMatch(member, "^([A-Za-z]+)\d*$", match) && UIA_Enum.UIA_ControlTypeId(match1))) {
          for _, member in members
            this := InStr(member, "=") ? this.FindFirstBy(member, 2) : this.FindByPath(member)
          return this
        } else if ((SubStr(member, 1, 6) = "Cached") && (prop := UIA_Enum.UIA_PropertyId(SubStr(member, 7))))
          return this.GetCachedPropertyValue(prop)
        else if (member ~= "i)Pattern\d?") { 
          if UIA_Enum.UIA_PatternId(member)
            return this.GetCurrentPatternAs(member)
          else if ((SubStr(member, 1, 6) = "Cached") && UIA_Enum.UIA_PatternId(pattern := SubStr(member, 7)))
            return this.GetCachedPatternAs(pattern)
        }
      }
      throw Exception("Property not supported by the " this.__Class " Class.",-1,member)
    }
  }
  __Set(member, value) {
    if (member != "base") {
      if !InStr(member, "Current")
        try return this["Current" member] := value
      throw Exception("Assigning values not supported by the " this.__Class " Class.",-1,member)
    }
  }
  __Call(member, params*) {
    local
    global UIA_Base, UIA_Enum
    if member not in base,HasKey 
    {
      if RegexMatch(member, "i)^(?:UIA_)?(PatternId|EventId|PropertyId|AttributeId|ControlTypeId|AnnotationType|StyleId|LandmarkTypeId|HeadingLevel|ChangeId|MetadataId)$", match) {
        return UIA_Enum["UIA_" match1](params*)
      } else if !ObjHasKey(UIA_Base,member)&&!ObjHasKey(this,member)&&!(member = "_NewEnum") {
        throw Exception("Method Call not supported by the " this.__Class " Class.",-1,member)
      }
    }
  }
  __Delete() {
    this.__Flag ? ((this.__Flag == 2) ? DllCall("GlobalFree", "Ptr", this.__Value) : ObjRelease(this.__Value)):
  }
  __Vt(n) {
    return NumGet(NumGet(this.__Value+0,"ptr")+n*A_PtrSize,"ptr")
  }
}	

/* 
  Exposes methods that enable to discover, access, and filter UI Automation elements. UI Automation exposes every element of the UI Automation as an object represented by the IUIAutomation interface. The members of this interface are not specific to a particular element.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomation
*/
class UIA_Interface extends UIA_Base {
  static __IID := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}"

  ; ---------- UIA_Interface properties ----------

  ControlViewWalker[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "ptr*",out:=""))?new UIA_TreeWalker(out):
    }
  }
  ContentViewWalker[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?new UIA_TreeWalker(out):
    }
  }
  RawViewWalker[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "ptr*",out:=""))?new UIA_TreeWalker(out):
    }
  }
  RawViewCondition[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(17), "ptr",this.__Value, "ptr*",out:=""))?new UIA_Condition(out):
    }
  }
  ControlViewCondition[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(18), "ptr",this.__Value, "ptr*",out:=""))?new UIA_Condition(out):
    }
  }
  ContentViewCondition[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(19), "ptr",this.__Value, "ptr*",out:=""))?new UIA_Condition(out):
    }
  }
  ProxyFactoryMapping[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(48), "ptr",this.__Value, "ptr*",out:=""))?new UIA_ProxyFactoryMapping(out):
    }
  }
  ReservedNotSupportedValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(54), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  ReservedMixedAttributeValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(55), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_Interface methods ----------
    
  ; Compares two UI Automation elements to determine whether they represent the same underlying UI element.
  CompareElements(e1,e2) { 
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr",e1.__Value, "ptr",e2.__Value, "int*",out:=""))? out:
  }
  ; Compares two integer arrays containing run-time identifiers (IDs) to determine whether their content is the same and they belong to the same UI element. r1 and r2 need to be RuntimeId arrays (returned by GetRuntimeId()), where array.base.__Value contains the corresponding safearray.
  CompareRuntimeIds(r1,r2) { 
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr",ComObjValue(r1.__Value), "ptr",ComObjValue(r2.__Value), "int*",out:=""))? out:
  }
  ; Retrieves the UI Automation element that represents the desktop.
  GetRootElement() { 
    local
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves a UI Automation element for the specified window. Additionally activateChromiumAccessibility flag can be set to True to send the WM_GETOBJECT message to Chromium-based apps to activate accessibility if it isn't activated.
  ElementFromHandle(hwnd:="A", ByRef activateChromiumAccessibility:=True) { 
    local
    if hwnd is not integer
      hwnd := WinExist(hwnd)
    if !hwnd
      return
    if (activateChromiumAccessibility != 0)
      activateChromiumAccessibility := this.ActivateChromiumAccessibility(hwnd)
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr",hwnd, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves the UI Automation element at the specified point on the desktop. Additionally activateChromiumAccessibility flag can be set to True to send the WM_GETOBJECT message to Chromium-based apps to activate accessibility if it isn't activated. If Chromium needs to be activated, then activateChromiumAccessibility is set to that windows element.
  ElementFromPoint(x:="", y:="", ByRef activateChromiumAccessibility:=True) { 
    local
    if (x==""||y=="") {
      VarSetCapacity(pt, 8, 0), NumPut(8, pt, "Int"), DllCall("user32.dll\GetCursorPos","UInt",&pt), x :=  NumGet(pt,0,"Int"), y := NumGet(pt,4,"Int")
    }
    if ((activateChromiumAccessibility!=0) && (hwnd := DllCall("GetAncestor", "UInt", DllCall("user32.dll\WindowFromPoint", "int64",  y << 32 | x), "UInt", GA_ROOT := 2))) { ; hwnd from point by SKAN
      activateChromiumAccessibility := this.ActivateChromiumAccessibility(hwnd)
    }
    return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "UInt64",x==""||y==""?pt:x&0xFFFFFFFF|(y&0xFFFFFFFF)<<32, "ptr*",out:=""))? UIA_Element(out):
  }	
  ; Retrieves the UI Automation element that has the input focus. If activateChromiumAccessibility is set to True, and Chromium needs to be activated, then activateChromiumAccessibility is set to that windows element.
  GetFocusedElement(ByRef activateChromiumAccessibility:=True) { 
    local
    if (activateChromiumAccessibility!=0)
      activateChromiumAccessibility := this.ActivateChromiumAccessibility()
    return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves the UI Automation element that represents the desktop, prefetches the requested properties and control patterns, and stores the prefetched items in the cache.
  GetRootElementBuildCache(cacheRequest) { ; UNTESTED. 
    local
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr", cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves a UI Automation element for the specified window, prefetches the requested properties and control patterns, and stores the prefetched items in the cache.
  ElementFromHandleBuildCache(hwnd:="A", cacheRequest:=0, ByRef activateChromiumAccessibility:=True) { 
    local
    if hwnd is not integer
      hwnd := WinExist(hwnd)
    if !hwnd
      return
    if (activateChromiumAccessibility != 0)
      activateChromiumAccessibility := this.ActivateChromiumAccessibility(hwnd, cacheRequest)
    return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr",hwnd, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves the UI Automation element at the specified point on the desktop, prefetches the requested properties and control patterns, and stores the prefetched items in the cache.
  ElementFromPointBuildCache(x:="", y="", cacheRequest:=0, ByRef activateChromiumAccessibility:=True) {
    local 
    if (x==""||y=="")
      VarSetCapacity(pt, 8, 0), NumPut(8, pt, "Int"), DllCall("user32.dll\GetCursorPos","UInt",&pt), x :=  NumGet(pt,0,"Int"), y := NumGet(pt,4,"Int")
    if (activateChromiumAccessibility!=0)
      activateChromiumAccessibility := this.ActivateChromiumAccessibility(hwnd, cacheRequest)
    return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "UInt64",x==""||y==""?pt:x&0xFFFFFFFF|(y&0xFFFFFFFF)<<32, "ptr", cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }	
  ; Retrieves the UI Automation element that has the input focus, prefetches the requested properties and control patterns, and stores the prefetched items in the cache. 
  GetFocusedElementBuildCache(cacheRequest, ByRef activateChromiumAccessibility:=True) { ; UNTESTED. 
    local
    if (activateChromiumAccessibility!=0)
      activateChromiumAccessibility := this.ActivateChromiumAccessibility(,cacheRequest)
    return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr", cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves a UIA_TreeWalker object that can be used to traverse the Microsoft UI Automation tree.
  CreateTreeWalker(condition) {
    local out
    return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "ptr",(IsObject(condition)?condition:this.CreateCondition(condition)).__Value, "ptr*",out:=""))? new UIA_TreeWalker(out):
  }
  CreateCacheRequest() { 
    local out
    return UIA_Hr(DllCall(this.__Vt(20), "ptr",this.__Value, "ptr*",out:=""))? new UIA_CacheRequest(out):
  }
  ; Creates a condition that is always true.
  CreateTrueCondition() { 
    local out
    return UIA_Hr(DllCall(this.__Vt(21), "ptr",this.__Value, "ptr*",out:=""))? new UIA_BoolCondition(out):
  }
  ; Creates a condition that is always false.
  CreateFalseCondition() { 
    local out
    return UIA_Hr(DllCall(this.__Vt(22), "ptr",this.__Value, "ptr*",out:=""))? new UIA_BoolCondition(out):
  }
  ; Creates a condition that selects elements that have a property with the specified value. 
  ; If type is specified then a new variant is created with the specified variant type, otherwise the type is fetched from UIA_PropertyVariantType enums (so usually this can be left unchanged).
  CreatePropertyCondition(propertyId, value, type:=0xC) { 
    local
    global UIA_Enum, UIA_PropertyCondition
    if propertyId is not integer
      propertyId := UIA_Enum.UIA_PropertyId(propertyId)
    if ((maybeVar := UIA_Enum.UIA_PropertyVariantType(propertyId)) && (type = 0xC))
      type := maybeVar
    var := UIA_ComVar(type, value)
    return UIA_Hr((A_PtrSize == 4) ? DllCall(this.__Vt(23), "ptr",this.__Value, "int",propertyId, "int64", NumGet(var.ptr+0, 0, "int64"), "int64", NumGet(var.ptr+0, 8, "int64"), "ptr*",out:="") : DllCall(this.__Vt(23), "ptr",this.__Value, "int",propertyId, "ptr",var.ptr, "ptr*",out:=""))? new UIA_PropertyCondition(out, 1):
  }
  ; Creates a condition that selects elements that have a property with the specified value (value), using optional flags. If type is specified then a new variant is created with the specified variant type, otherwise the type is fetched from UIA_PropertyVariantType enums (so usually this can be left unchanged). flags can be one of PropertyConditionFlags, default is PropertyConditionFlags_IgnoreCase = 0x1.
  CreatePropertyConditionEx(propertyId, value, type:=0xC, flags:=0x1) { 
    local
    global UIA_Enum, UIA_PropertyCondition
    if propertyId is not integer
      propertyId := UIA_Enum.UIA_PropertyId(propertyId)
    if ((maybeVar := UIA_Enum.UIA_PropertyVariantType(propertyId)) && (type = 0xC))
      type := maybeVar
    var := UIA_ComVar(type, value)
    if (type != 8)
      flags := 0
    return UIA_Hr((A_PtrSize == 4) ? DllCall(this.__Vt(24), "ptr",this.__Value, "int",propertyId, "int64", NumGet(var.ptr+0, 0, "int64"), "int64", NumGet(var.ptr+0, 8, "int64"), "uint",flags, "ptr*",out:="") : DllCall(this.__Vt(24), "ptr",this.__Value, "int",propertyId, "ptr", var.ptr, "uint",flags, "ptr*",out:=""))? new UIA_PropertyCondition(out, 1):
  }
  ; Creates a condition that selects elements that match both of two conditions.
  CreateAndCondition(c1,c2) { 
    local out
    return UIA_Hr(DllCall(this.__Vt(25), "ptr",this.__Value, "ptr",c1.__Value, "ptr",c2.__Value, "ptr*",out:=""))? new UIA_AndCondition(out, 1):
  }
  ; Creates a condition that selects elements based on multiple conditions, all of which must be true.
  CreateAndConditionFromArray(array) { 
    local
    global UIA_AndCondition
  ;->in: AHK Array or Wrapped SafeArray
    if ComObjValue(array)&0x2000
      SafeArray:=array
    else {
      SafeArray:=ComObj(0x2003,DllCall("oleaut32\SafeArrayCreateVector", "uint",13, "uint",0, "uint",array.MaxIndex()),1)
      for i,c in array
        SafeArray[A_Index-1]:=c.__Value, ObjAddRef(c.__Value) ; AddRef - SafeArrayDestroy will release UIA_Conditions - they also release themselves
    }
    return UIA_Hr(DllCall(this.__Vt(26), "ptr",this.__Value, "ptr",ComObjValue(SafeArray), "ptr*",out:=""))? new UIA_AndCondition(out, 1):
  }
  ; Creates a condition that selects elements from a native array, based on multiple conditions that must all be true
  CreateAndConditionFromNativeArray(conditions, conditionCount) { ; UNTESTED. 
    /*	[in]           IUIAutomationCondition **conditions,
      [in]           int conditionCount,
      [out, retval]  IUIAutomationCondition **newCondition
    */
    local out
    return UIA_Hr(DllCall(this.__Vt(27), "ptr",this.__Value, "ptr", conditions, "int", conditionCount, "ptr*",out:=""))? new UIA_AndCondition(out, 1):
  }
  ; Creates a combination of two conditions where a match exists if either of the conditions is true.
  CreateOrCondition(c1,c2) { 
    local out
    return UIA_Hr(DllCall(this.__Vt(28), "ptr",this.__Value, "ptr",c1.__Value, "ptr",c2.__Value, "ptr*",out:=""))? new UIA_OrCondition(out, 1):
  }
  ; Creates a combination of two or more conditions where a match exists if any of the conditions is true.
  CreateOrConditionFromArray(array) { 
    local SafeArray, i, c, out
  ;->in: AHK Array or Wrapped SafeArray
    if ComObjValue(array)&0x2000
      SafeArray:=array
    else {
      SafeArray:=ComObj(0x2003,DllCall("oleaut32\SafeArrayCreateVector", "uint",13, "uint",0, "uint",array.MaxIndex()),1)
      for i,c in array
        SafeArray[A_Index-1]:=c.__Value, ObjAddRef(c.__Value) ; AddRef - SafeArrayDestroy will release UIA_Conditions - they also release themselves
    }
    return UIA_Hr(DllCall(this.__Vt(29), "ptr",this.__Value, "ptr",ComObjValue(SafeArray), "ptr*",out:=""))? new UIA_OrCondition(out, 1):
  }
  CreateOrConditionFromNativeArray(p*) { ; Not Implemented
    local out
    return UIA_Hr(DllCall(this.__Vt(30), "ptr",this.__Value, "ptr",conditions, "int", conditionCount, "ptr*",out:=""))? new UIA_OrCondition(out, 1):
  /*	[in]           IUIAutomationCondition **conditions,
    [in]           int conditionCount,
    [out, retval]  IUIAutomationCondition **newCondition
  */
  }
  ; Creates a condition that is the negative of a specified condition.
  CreateNotCondition(c) { 
    local out
    return UIA_Hr(DllCall(this.__Vt(31), "ptr",this.__Value, "ptr",c.__Value, "ptr*",out:=""))? new UIA_NotCondition(out, 1):
  }
  ; Registers a method that handles Microsoft UI Automation events. eventId must be an EventId enum. scope must be a TreeScope enum. cacheRequest can be specified is caching is used. handler is an event handler object, which can be created with UIA_CreateEventHandler function.
  AddAutomationEventHandler(eventId, element, scope=0x4, cacheRequest=0, handler="") { 
    return UIA_Hr(DllCall(this.__Vt(32), "ptr",this.__Value, "int", eventId, "ptr", element.__Value, "uint", scope, "ptr",cacheRequest.__Value,"ptr",handler.__Value))
  }
  ; Removes the specified UI Automation event handler.
  RemoveAutomationEventHandler(eventId, element, handler) { 
    return UIA_Hr(DllCall(this.__Vt(33), "ptr",this.__Value, "int", eventId, "ptr", element.__Value, "ptr",handler.__Value))
  }

  ;~ AddPropertyChangedEventHandlerNativeArray 	34
  
  ; Registers a method that handles an array of property-changed events
  AddPropertyChangedEventHandler(element,scope:=0x1,cacheRequest:=0,handler:="",propertyArray:="") {
    local
    if !IsObject(propertyArray)
      propertyArray := [propertyArray] 
    SafeArray:=ComObjArray(0x3,propertyArray.MaxIndex())
    for i,propertyId in propertyArray
      SafeArray[i-1]:=propertyId
    return UIA_Hr(DllCall(this.__Vt(35), "ptr",this.__Value, "ptr",element.__Value, "int",scope, "ptr",cacheRequest.__Value,"ptr",handler.__Value,"ptr",ComObjValue(SafeArray)))
  }
  RemovePropertyChangedEventHandler(element, handler) {
    return UIA_Hr(DllCall(this.__Vt(36), "ptr",this.__Value, "ptr",element.__Value, "ptr", handler.__Value))
  }

  AddStructureChangedEventHandler(element, scope:=0x4, cacheRequest:=0, handler:=0) { 
    return UIA_Hr(DllCall(this.__Vt(37), "ptr",this.__Value, "ptr",element.__Value, "int", scope, "ptr", cacheRequest.__Value, "ptr",handler.__Value))
  }
  RemoveStructureChangedEventHandler(element, handler) { ; UNTESTED
    return UIA_Hr(DllCall(this.__Vt(38), "ptr",this.__Value, "ptr", element.__Value, "ptr",handler.__Value))
  }
  ; Registers a method that handles ChangedEvent events. handler is required, cacheRequest can be left to 0
  AddFocusChangedEventHandler(handler, cacheRequest:=0) { 
    return UIA_Hr(DllCall(this.__Vt(39), "ptr",this.__Value, "ptr",cacheRequest.__Value, "ptr",handler.__Value))
  }
  RemoveFocusChangedEventHandler(handler) {
    return UIA_Hr(DllCall(this.__Vt(40), "ptr",this.__Value, "ptr",handler.__Value))
  }
  RemoveAllEventHandlers() {
    return UIA_Hr(DllCall(this.__Vt(41), "ptr",this.__Value))
  }

  IntNativeArrayToSafeArray(ByRef nArr, n:="") { 
    local out
    return UIA_Hr(DllCall(this.__Vt(42), "ptr",this.__Value, "ptr",&nArr, "int",n?n:VarSetCapacity(nArr)/4, "ptr*",out:=""))? ComObj(0x2003,out,1):
  }
  IntSafeArrayToNativeArray(sArr, Byref nArr, Byref arrayCount) { ; NOT WORKING
    local
    VarSetCapacity(nArr,(sArr.MaxIndex()+1)*A_PtrSize)
    return UIA_Hr(DllCall(this.__Vt(43), "ptr",this.__Value, "ptr",ComObjValue(sArr), "ptr*",nArr:="", "int*",arrayCount:=""))? nArr:
  }

  RectToVariant(ByRef rect, ByRef out="") {	; in:{left,top,right,bottom} ; out:(left,top,width,height)
    ; in:	RECT Struct
    ; out:	AHK Wrapped SafeArray & ByRef Variant
    return UIA_Hr(DllCall(this.__Vt(44), "ptr",this.__Value, "ptr",&rect, "ptr",UIA_Variant(out)))? UIA_VariantData(out):UIA_VariantClear(out)
  }
  VariantToRect(ByRef var, ByRef rect="") { ; NOT WORKING
    ; in:	VT_VARIANT (SafeArray)
    ; out:	AHK Wrapped RECT Struct & ByRef Struct
    VarSetCapacity(rect,16)
    return UIA_Hr(DllCall(this.__Vt(45), "ptr",this.__Value, "ptr",var, "ptr*",rect:=""))? UIA_RectToObject(rect):
  }

  ;~ SafeArrayToRectNativeArray 	46
  ;~ CreateProxyFactoryEntry 	47
  
  ; Retrieves the registered programmatic name of a property. Intended for debugging and diagnostic purposes only. The string is not localized.
  GetPropertyProgrammaticName(Id) { 
    local
    return UIA_Hr(DllCall(this.__Vt(49), "ptr",this.__Value, "int",Id, "ptr*",out:=""))? UIA_GetBSTRValue(out):
  }
  ; Retrieves the registered programmatic name of a control pattern. Intended for debugging and diagnostic purposes only. The string is not localized.
  GetPatternProgrammaticName(Id) { 
    local
    return UIA_Hr(DllCall(this.__Vt(50), "ptr",this.__Value, "int",Id, "ptr*",out:=""))? UIA_GetBSTRValue(out):
  }
  ; Returns an object where keys are the names and values are the Ids
  PollForPotentialSupportedPatterns(e, Byref Ids:="", Byref Names:="") { 
    return UIA_Hr(DllCall(this.__Vt(51), "ptr",this.__Value, "ptr",e.__Value, "ptr*",Ids:="", "ptr*",Names:=""))? UIA_SafeArraysToObject(Names:=ComObj(0x2008,Names,1),Ids:=ComObj(0x2003,Ids,1)): ; These SafeArrays are wrapped by ComObj, so they will automatically be released
  }
  PollForPotentialSupportedProperties(e, Byref Ids:="", Byref Names:="") {
    return UIA_Hr(DllCall(this.__Vt(52), "ptr",this.__Value, "ptr",e.__Value, "ptr*",Ids:="", "ptr*",Names:=""))? UIA_SafeArraysToObject(Names:=ComObj(0x2008,Names,1),Ids:=ComObj(0x2003,Ids,1)):
  }
  CheckNotSupported(value) { ; Useless in this Framework???
    /*	Checks a provided VARIANT to see if it contains the Not Supported identifier.
      After retrieving a property for a UI Automation element, call this method to determine whether the element supports the 
      retrieved property. CheckNotSupported is typically called after calling a property retrieving method such as GetCurrentPropertyValue.
    */
    local
    return UIA_Hr(DllCall(this.__Vt(53), "ptr",this.__Value, "ptr",value, "int*",out:=""))? out:
  }
  
  ;~ ReservedNotSupportedValue 	54
  ;~ ReservedMixedAttributeValue 	55
  
  /*
    This only works if the program implements IAccessible (Acc/MSAA) natively (option 1 in the following explanation). 

    There are two types of Acc objects:
    1) Where the program implements Acc natively. In this case, Acc will be the actual IAccessible object for the implementation.
    2) The program doesn't implement Acc, but Acc instead creates a proxy object which sends messages to the window and maps Win32 controls to a specific IAccessible method. This would be for most Win32 programs, where for example accName would actually do something similar to ControlGetText and return that value. If ElementFromIAccessible is used with this kind of proxy object, E_INVALIDARG - "One or more arguments are not valid" error is returned.
  */
  ElementFromIAccessible(IAcc, childId:=0) {
    /* The method returns E_INVALIDARG - "One or more arguments are not valid" - if the underlying implementation of the
    Microsoft UI Automation element is not a native Microsoft Active Accessibility server; that is, if a client attempts to retrieve
    the IAccessible interface for an element originally supported by a proxy object from Oleacc.dll, or by the UIA-to-MSAA Bridge.
    */
    local
    return UIA_Hr(DllCall(this.__Vt(56), "ptr",this.__Value, "ptr",IsObject(IAcc) ? ComObjValue(IAcc) : IAcc, "int",childId, "ptr*",out:=""))? UIA_Element(out):
  }
  ElementFromIAccessibleBuildCache(IAcc, childId:=0, cacheRequest:=0) {
    local
    return UIA_Hr(DllCall(this.__Vt(57), "ptr",this.__Value, "ptr",IsObject(IAcc) ? ComObjValue(IAcc) : IAcc, "int",childId, "ptr", cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }

  ; ------- ONLY CUSTOM FUNCTIONS FROM HERE ON ----------------

  /*
    CreateCondition can create a condition from an expression, or a PropertyId and property value pair.

    1) If creating a single condition from a PropertyId and value pair:
        propertyOrExpr: Property can be the PropertyId, or (partial) name (eg 30000 == "ControlType" == "ControlTypePropertyId").  
        valueOrFlags: the value corresponding to the PropertyId
        flags: 0=no flags; 1=ignore case (case insensitive matching); 2=match substring; 3=ignore case and match substring
      Example: CreateCondition("Name", "Username", 1) would create a condition with NameProperty and value of "Username", with case sensitivity turned off.
      
    2) If creating a condition from an expression, propertyOrExpr takes the expression and valueOrFlags the default flags, and flags argument is ignored.

      Similarly to FindFirstBy, the expression takes a value in the form of "PropertyId=propertyValue" to create a property condition for PropertyId with the value propertyValue. PropertyId can be most properties from UIA_Enum.UIA_PropertyId method (for example Name, ControlType, AutomationId etc). 
      If propertyValue contains any parentheses, then the value needs to be surrounded by single quotes. Escape ' with \, escape \ with \.
        "Name=Username:" would create a property condition with UIA_Enum.UIA_NamePropertyId and the value "Username:"
        "Name='MyTest\''" creates a NameProperty condition for value "MyTest'"
      
      Criteria can be combined with AND, OR, &&, || (not case sensitive):
        "Name=Username: AND ControlType=Button" would create a condition with the name property of "Username:" and control type of button.
      Parentheses are supported.
      
      Negation can be specified with NOT or !:
        "NOT ControlType=Edit" would create a condition that selects everything but ControlType Edit

      Different flags can be specified for each condition by specifying "FLAGS=n" after the condition value.
        "Name=Username: FLAGS=1" would create a case-insensitive condition only for that condition. By default the flags argument is used.
      
      Flags: 0=no flags; 1=ignore case (case insensitive); 2=match substring; 3=ignore case and match substring
  */
  CreateCondition(propertyOrExpr, valueOrFlags:="", flags:=0) {
    local
    global UIA_Enum
    if InStr(propertyOrExpr, "=") { ; Expression
      match := "", match3 := "", match5 := "", currentCondition := "", fullCondition := "", operator := "", valueOrFlags := ((!valueOrFlags) ? 0 : valueOrFlags), counter := 1, conditions := [], currentExpr := "(" propertyOrExpr ")"
      ; First create all single conditions (not applying AND, OR, NOT)
      while RegexMatch(currentExpr, "i) *(NOT|!)? *(\w+?(?<!UIA_CONDITION)) *=(?: *(\d+|'.*?(?<=[^\\]|[^\\]\\\\)')|([^()]*?)) *(?: FLAGS=(\d))? *?( AND | OR |&&|\|\||[()]|$) *", match) {
        /*
          matchRegex:
            group1 : NOT
            group2 : propertyId
            group3 : propertyValue
            group4 : propertyValueOld
            group5 : "FLAGS" value
            group6 : next and/or operator
          
          Escape ' with \ : 'Test\'' -> Test'
          Escape \ with \ : 'Test\\\'' -> Test\'
        */
        if !match
          break
        match3 := (match3 == "") ? match4 : match3
        currentFlags := (match5 == "") ? valueOrFlags : match5
        if ((SubStr(match3,1,1) == "'") && (SubStr(match3,0,1) == "'"))
          match3 := StrReplace(RegexReplace(SubStr(match3,2,StrLen(match3)-2), "(?<=[^\\]|[^\\]\\\\)\\'", "'"), "\\", "\")
        conditions[counter] := this.CreateCondition(match2, match3, currentFlags)
        if (match1 == "NOT")
          match1 := "!"
        currentExpr := StrReplace(currentExpr, match, " " match1 "UIA_CONDITION=" counter (match6 ? ((match6 == ")") ? ") " : match6) : ""))
        counter++
      }
      currentExpr := StrReplace(StrReplace(StrReplace(currentExpr, " OR ", "||"), " AND ", "&&"), "NOT", "!")
      ; Create NNF: Move NOT conditions to inside parenthesis, remove double NOTs
      While RegexMatch(currentExpr, "! *(\((?:[^)(]+|(?1))*+\))", match) {
        match1 := SubStr(match1, 2, StrLen(match1)-2)
        currentExpr := StrReplace(currentExpr, match, "(" RegexReplace(match1, "([^)(]+?|\((?:[^)(]+|(?1))*+\)) *(\|\||&&|\)|$) *", "!$1$2$3") ")")
        currentExpr := StrReplace(currentExpr, "!!", "")
      }
      ; Create all NOT conditions
      pos:=1, match:=""
      While (pos := RegexMatch(currentExpr, "! *UIA_CONDITION=(\d+)", match, pos+StrLen(match))) {
        conditions[match1] := this.CreateNotCondition(conditions[match1])
        currentExpr := StrReplace(currentExpr, match, "UIA_CONDITION=" match1)
        pos -= 1
      }
      ; Create AND/OR conditions
      currentExpr := StrReplace(currentExpr, " ", ""), parenthesisMatch:=""
      While RegexMatch(currentExpr, "\(([^()]+)\)", parenthesisMatch) { ; Match parenthesis that doesn't have parentheses inside
        pos := 1, match:="", match1:="", fullCondition:="", operator:=""
        while (pos := RegexMatch(parenthesisMatch1, "UIA_CONDITION=(\d+)(&&|\|\||$)", match, pos+StrLen(match))) {
          fullCondition := (operator == "&&") ? this.CreateAndCondition(fullCondition, conditions[match1]) : (operator == "||") ? this.CreateOrCondition(fullCondition, conditions[match1]) : conditions[match1]
          operator := match2
        }
        conditions[counter] := fullCondition
        currentExpr := StrReplace(currentExpr, parenthesisMatch, "UIA_CONDITION=" counter)
        counter++
      }
      return conditions[counter-1]
    } else {
      if RegexMatch(propertyOrExpr, "^\d+$")
        propCond := propertyOrExpr
      else {
        if (propertyOrExpr = "Type")
          propertyOrExpr := "ControlType"
        RegexMatch(propertyOrExpr, "i)(?:UIA_)?\K.+?(?=(Id)?PropertyId|$)", propertyOrExpr), propCond := UIA_Enum.UIA_PropertyId(propertyOrExpr), propertyOrExpr := StrReplace(StrReplace(propertyOrExpr, "AnnotationAnnotation", "Annotation"), "StylesStyle", "Style")
      }	
      if valueOrFlags is not integer
      {
        valueOrFlags := IsFunc("UIA_Enum.UIA_" propertyOrExpr "Id") ? UIA_Enum["UIA_" propertyOrExpr "Id"](valueOrFlags) : IsFunc("UIA_Enum.UIA_" propertyOrExpr) ? UIA_Enum["UIA_" propertyOrExpr](valueOrFlags) : valueOrFlags
      }
      if propCond
        return this.CreatePropertyConditionEx(propCond, valueOrFlags,, flags)
    }
  }

  ; Gets ElementFromPoint and filters out the smallest subelement that is under the specified point. If windowEl (window under the point) is provided, then a deep search is performed for the smallest element (this might be very slow in large trees).
  SmallestElementFromPoint(x:="", y:="", ByRef activateChromiumAccessibility:=True, windowEl:="") { 
    local
    if (x==""||y=="") {
      VarSetCapacity(pt, 8, 0), NumPut(8, pt, "Int"), DllCall("user32.dll\GetCursorPos","UInt",&pt), x :=  NumGet(pt,0,"Int"), y := NumGet(pt,4,"Int")
    }
    if IsObject(windowEl) {
      element := this.ElementFromPoint(x, y, activateChromiumAccessibility)
      bound := element.CurrentBoundingRectangle, elementSize := (bound.r-bound.l)*(bound.b-bound.t), prevElementSize := 0, stack := [windowEl, element], x := x==""?0:x, y := y==""?0:y
      Loop 
      {
        bound := stack[1].CurrentBoundingRectangle
        if ((x >= bound.l) && (x <= bound.r) && (y >= bound.t) && (y <= bound.b)) { ; If parent is not in bounds, then children arent either
          if ((newSize := (bound.r-bound.l)*(bound.b-bound.t)) < elementSize)
            element := stack[1], elementSize := newSize
          for _, childEl in stack[1].GetChildren() {
            bound := childEl.CurrentBoundingRectangle
            if ((x >= bound.l) && (x <= bound.r) && (y >= bound.t) && (y <= bound.b)) { ; Select only children that are under the mouse
              stack.Push(childEl)
              if ((newSize := (bound.r-bound.l)*(bound.b-bound.t)) < elementSize)
                elementSize := newSize, element := childEl
            }
          }
        }
        stack.RemoveAt(1)
      } Until !stack.MaxIndex()
      return element
    } else {
      element := this.ElementFromPoint(x, y, activateChromiumAccessibility)
      bound := element.CurrentBoundingRectangle, elementSize := (bound.r-bound.l)*(bound.b-bound.t), prevElementSize := 0
      for k, v in element.FindAll(this.__UIA.TrueCondition) {
        bound := v.CurrentBoundingRectangle
        if ((x >= bound.l) && (x <= bound.r) && (y >= bound.t) && (y <= bound.b) && ((newSize := (bound.r-bound.l)*(bound.b-bound.t)) < elementSize))
          element := v, elementSize := newSize
      }
      return element
    }
  }
  ; This can be used when a Chromium apps content isn't accessible by normal methods (ElementFromHandle, GetRootElement etc). fromFocused=True uses the focused element as a reference point, fromFocused=False uses ElementFromPoint
  GetChromiumContentElement(winTitle:="A", ByRef fromFocused:=True) {
    local
    WinActivate, %winTitle%
    WinWaitActive, %winTitle%,,1
    WinGetPos, X, Y, W, H, %winTitle%
    if fromFocused
      fromFocused := this.GetFocusedElement()
    else
      fromFocused := this.ElementFromPoint(x+w//2, y+h//2) ; Use ElementFromPoint on the center of the window (the actual coordinate doesn't really matter, it just needs to be inside the window)
    chromiumTW := this.CreateTreeWalker(this.CreateCondition("ControlType","Document")) ; Create a TreeWalker to find the Document element (the content)
    try focusedEl := chromiumTW.NormalizeElement(fromFocused) ; Get the first parent that is a Window element
    return focusedEl
  }
  ; Tries to get the Chromium content from Chrome_RenderWidgetHostHWND1 control
  ElementFromChromium(winTitle:="A", activateChromiumAccessibility:=True, timeOut:=500) {
    local
    try ControlGet, cHwnd, Hwnd,, Chrome_RenderWidgetHostHWND1, %winTitle%
    if !cHwnd
      return
    cEl := this.ElementFromHandle(cHwnd,False)
    if (activateChromiumAccessibility != 0) {
      SendMessage, WM_GETOBJECT := 0x003D, 0, 1, , ahk_id %cHwnd%
      if cEl {
        cEl.CurrentName ; it doesn't work without calling CurrentName (at least in Skype)
        if (cEl.CurrentControlType == 50030) {
          startTime := A_TickCount
          while (!cEl.CurrentValue && (A_TickCount-startTime < timeOut))
            Sleep, 20
        }
      }
    }
    return cEl
  }
  ; In some setups Chromium-based renderers don't react to UIA calls by enabling accessibility, so we need to send the WM_GETOBJECT message to the renderer control to enable accessibility. Thanks to users malcev and rommmcek for this tip. Explanation why this works: https://www.chromium.org/developers/design-documents/accessibility/#TOC-How-Chrome-detects-the-presence-of-Assistive-Technology 
  ActivateChromiumAccessibility(hwnd:="A", cacheRequest:=0, timeOut:=500) {
    static activatedHwnds := {}
    if hwnd is not integer
      hwnd := WinExist(hwnd)
    if activatedHwnds[hwnd] 
      return
    activatedHwnds[hwnd] := 1 ; Shouldn't store the element here, otherwise it can't be released until the program exits
    return this.ElementFromChromium("ahk_id " hwnd,, timeOut)
  }
}

class UIA_Interface2 extends UIA_Interface {
  static __IID := "{34723aff-0c9d-49d0-9896-7ab52df8cd8a}"
  
  ; ---------- UIA_Interface2 properties ----------

  ; Specifies whether calls to UI Automation control pattern methods automatically set focus to the target element. Default is True. 
  AutoSetFocus[] 
  {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(58), "ptr",this.__Value, "ptr*", out:=""))?out:
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(59), "ptr",this.__Value, "int", value))
    }
  }
  ; Specifies the length of time that UI Automation will wait for a provider to respond to a client request for an automation element. Default is 20000ms (20 seconds), minimum seems to be 50ms.
  ConnectionTimeout[] 
  {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(60), "ptr",this.__Value, "ptr*", out:=""))?out:
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(61), "ptr",this.__Value, "int", value)) ; Minimum seems to be 50 (ms?)
    }
  }
  ; Specifies the length of time that UI Automation will wait for a provider to respond to a client request for information about an automation element. Default is 2000ms (2 seconds), minimum seems to be 50ms.
  TransactionTimeout[] 
  {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(62), "ptr",this.__Value, "ptr*", out:=""))?out:
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(63), "ptr",this.__Value, "int", value))
    }
  }
}

class UIA_Interface3 extends UIA_Interface2 { ; UNTESTED
  static __IID := "{73d768da-9b51-4b89-936e-c209290973e7}"

  AddTextEditTextChangedEventHandler(element, scope, textEditChangeType, cacheRequest:=0, handler:="") {
    return UIA_Hr(DllCall(this.__Vt(64), "ptr",this.__Value, "ptr", element.__Value, "int", scope, "int", textEditChangeType, "ptr", cacheRequest.__Value, "ptr", handler.__Value))
  }
  RemoveTextEditTextChangedEventHandler(element, handler) {
    return UIA_Hr(DllCall(this.__Vt(65), "ptr",this.__Value, "ptr", element.__Value, "ptr", handler.__Value))
  }
}

class UIA_Interface4 extends UIA_Interface3 { ; UNTESTED
  static __IID := "{1189c02a-05f8-4319-8e21-e817e3db2860}"

  AddChangesEventHandler(element, scope, changeTypes, changesCount, cacheRequest:=0, handler:="") { ; NOT WORKING. changeTypes should be an array?
    return UIA_Hr(DllCall(this.__Vt(66), "ptr",this.__Value, "ptr", element.__Value, "int", scope, "int", changeTypes, "int", changesCount, "ptr", cacheRequest.__Value, "ptr", handler.__Value))
  }
  RemoveChangesEventHandler(element, handler) {
    return UIA_Hr(DllCall(this.__Vt(67), "ptr",this.__Value, "ptr", element.__Value, "ptr", handler.__Value))
  }
}
class UIA_Interface5 extends UIA_Interface4 { ; UNTESTED
  static __IID := "{25f700c8-d816-4057-a9dc-3cbdee77e256}"

  AddNotificationEventHandler(element, scope:=0x4, cacheRequest:=0, handler:=0) {
    return UIA_Hr(DllCall(this.__Vt(68), "ptr",this.__Value, "ptr", element.__Value, "uint", scope, "ptr", cacheRequest.__Value, "ptr", handler.__Value))
  }
  RemoveNotificationEventHandler(element, handler) {
    return UIA_Hr(DllCall(this.__Vt(69), "ptr",this.__Value, "ptr", element.__Value, "ptr", handler.__Value))
  }
}
class UIA_Interface6 extends UIA_Interface5 { ; UNTESTED
  static __IID := "{aae072da-29e3-413d-87a7-192dbf81ed10}"

  ; ---------- UIA_Interface6 properties ----------

  ; Indicates whether an accessible technology client adjusts provider request timeouts when the provider is non-responsive.
  ConnectionRecoveryBehavior[] 
  {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(73), "ptr",this.__Value, "ptr*", out:=""))?out:
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(74), "ptr",this.__Value, "int", value)) 
    }
  }
  ; Gets or sets whether an accessible technology client receives all events, or a subset where duplicate events are detected and filtered.
  CoalesceEvents[] 
  {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(75), "ptr",this.__Value, "ptr*", out:=""))?out:
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(76), "ptr",this.__Value, "int", value))
    }
  }

  ; ---------- UIA_Interface6 methods ----------

  ; Registers one or more event listeners in a single method call.
  CreateEventHandlerGroup() {
    local out
    return UIA_Hr(DllCall(this.__Vt(70), "ptr",this.__Value, "ptr*", out:="")) ? new UIA_AutomationEventHandlerGroup(out):
  }
  ; Registers a collection of event handler methods specified with the UIA_Interface6 CreateEventHandlerGroup.
  AddEventHandlerGroup(element, handlerGroup) {
    return UIA_Hr(DllCall(this.__Vt(71), "ptr",this.__Value, "ptr", element.__Value, "ptr", handlerGroup.__Value)) 
  }
  RemoveEventHandlerGroup(element, handlerGroup) {
    return UIA_Hr(DllCall(this.__Vt(72), "ptr",this.__Value, "ptr", element.__Value, "ptr", handlerGroup.__Value)) 
  }
  ; Registers a method that handles when the active text position changes.
  AddActiveTextPositionChangedEventHandler(element,scope:=0x4,cacheRequest:=0,handler:="") {
    return UIA_Hr(DllCall(this.__Vt(77), "ptr",this.__Value, "ptr", element.__Value, "int", scope, "ptr", cacheRequest.__Value, "ptr", handler.__Value)) 
  }
  RemoveActiveTextPositionChangedEventHandler(element,handler) {
    return UIA_Hr(DllCall(this.__Vt(78), "ptr",this.__Value, "ptr", element.__Value, "ptr", handler.__Value)) 
  }
}
class UIA_Interface7 extends UIA_Interface6 {
  static __IID := "{29de312e-83c6-4309-8808-e8dfcb46c3c2}"
}

/*
  Exposes methods and properties for a UI Automation element, which represents a UI item.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationelement
*/
class UIA_Element extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee671425(v=vs.85).aspx
  static __IID := "{d22108aa-8ac5-49a5-837b-37bbb3d7591e}"
  
  ; ---------- UIA_Element properties ----------
  CurrentProcessId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(20), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentControlType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(21), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentLocalizedControlType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(22), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(23), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentAcceleratorKey[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(24), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentAccessKey[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(25), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentHasKeyboardFocus[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(26), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsKeyboardFocusable[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(27), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsEnabled[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(28), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentAutomationId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(29), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentClassName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(30), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentHelpText[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(31), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentCulture[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(32), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsControlElement[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(33), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsContentElement[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(34), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsPassword[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(35), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentNativeWindowHandle[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(36), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentItemType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(37), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentIsOffscreen[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(38), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentOrientation[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(39), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentFrameworkId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(40), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentIsRequiredForForm[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(41), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentItemStatus[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(42), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentBoundingRectangle[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(43), "ptr",this.__Value, "ptr",&(rect,VarSetCapacity(rect,16))))?UIA_RectToObject(rect):
    }
  }
  CurrentLabeledBy[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(44), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CurrentAriaRole[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(45), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentAriaProperties[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(46), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentIsDataValidForForm[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(47), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentControllerFor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(48), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CurrentDescribedBy[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(49), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CurrentFlowsTo[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(50), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CurrentProviderDescription[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(51), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedProcessId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(52), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedControlType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(53), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedLocalizedControlType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(54), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(55), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedAcceleratorKey[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(56), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedAccessKey[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(57), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedHasKeyboardFocus[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(58), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsKeyboardFocusable[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(59), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsEnabled[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(60), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedAutomationId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(61), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedClassName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(62), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedHelpText[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(63), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedCulture[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(64), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsControlElement[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(65), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsContentElement[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(66), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsPassword[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(67), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedNativeWindowHandle[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(68), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedItemType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(69), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedIsOffscreen[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(70), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedOrientation[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(71), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedFrameworkId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(72), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedIsRequiredForForm[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(73), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedItemStatus[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(74), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedBoundingRectangle[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(75), "ptr",this.__Value, "ptr",&(rect,VarSetCapacity(rect,16))))?UIA_RectToObject(rect):
    }
  }
  CachedLabeledBy[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(76), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CachedAriaRole[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(77), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedAriaProperties[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(78), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedIsDataValidForForm[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(79), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedControllerFor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(80), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CachedDescribedBy[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(81), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CachedFlowsTo[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(82), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CachedProviderDescription[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(83), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  ; ---------- Custom UIA_Element properties ----------

  ; Gets or sets the current value of the element. Getter is a wrapper for GetCurrentPropertyValue("Value"), setter a wrapper for SetValue
  CurrentValue[] { 
    get {
      return this.GetCurrentPropertyValue("Value")
    }
    set {
      return this.SetValue(value)
    }
  }
  CachedValue[] { 
    get {
      return this.GetCachedPropertyValue("Value")
    }
  }
  CurrentExists[] {
    get {
      try {
        if ((this.CurrentName this.CurrentValue (this.CurrentBoundingRectangle.t ? 1 : "")) == "")
          return 0
      } 
      return 1
    }
  }

  ; ---------- UIA_Element methods ----------

  SetFocus() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
  ; Retrieves the unique identifier assigned to the UI element. The identifier is only guaranteed to be unique to the UI of the desktop on which it was generated. Identifiers can be reused over time.
  GetRuntimeId() { 
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",sa:=""))? UIA_SafeArrayToAHKArray(ComObj(0x2003,sa,1)):
  }
  ; Retrieves the first child or descendant element that matches the specified condition. scope must be one of TreeScope enums (default is TreeScope_Descendants := 0x4). If cacheRequest is specified, then FindFirstBuildCache is used instead.
  FindFirst(c:="", scope:=0x4, cacheRequest:="") { 
    local
    if !cacheRequest	
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "uint",scope, "ptr", (c:=(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c)))).__Value, "ptr*",out:=""))? UIA_Element(out):
    return this.FindFirstBuildCache(c, scope, cacheRequest)
  }
  ; Returns all UI Automation elements that satisfy the specified condition. scope must be one of TreeScope enums (default is TreeScope_Descendants := 0x4). If cacheRequest is specified, then FindAllBuildCache is used instead.
  FindAll(c:="", scope:=0x4, cacheRequest:="") { 
    local
    if !cacheRequest
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "uint",scope, "ptr", (c:=(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c)))).__Value, "ptr*",out:=""))? UIA_ElementArray(out):
    return this.FindAllBuildCache(c, scope, cacheRequest)
  }
  ; Retrieves the first child or descendant element that matches the specified condition, prefetches the requested properties and control patterns, and stores the prefetched items in the cache
  FindFirstBuildCache(c:="", scope:=0x4, cacheRequest:="") { ; UNTESTED. 
    local
    return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "uint",scope, "ptr",(c:=(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c)))).__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Returns all UI Automation elements that satisfy the specified condition, prefetches the requested properties and control patterns, and stores the prefetched items in the cache.
  FindAllBuildCache(c:="", scope:=0x4, cacheRequest:="") { ; UNTESTED. 
    local
    return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "uint",scope, "ptr",(c:=(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c)))).__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_ElementArray(out):
  }
  ; Retrieves a new UI Automation element with an updated cache.
  BuildUpdatedCache(cacheRequest) { ; UNTESTED. 
    local
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr", cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves the current value of a property for this element. "out" will be set to the raw variant (generally not used).
  GetCurrentPropertyValue(propertyId, ByRef out:="") { 
    if propertyId is not integer
      propertyId := UIA_Enum.UIA_PropertyId(propertyId)
    return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "uint", propertyId, "ptr",UIA_Variant(out)))? UIA_VariantData(out):UIA_VariantClear(out)
    
  }
  ; Retrieves a property value for this element, optionally ignoring any default value. Passing FALSE in the ignoreDefaultValue parameter is equivalent to calling GetCurrentPropertyValue
  GetCurrentPropertyValueEx(propertyId, ignoreDefaultValue:=1, ByRef out:="") { 
    if propertyId is not integer
      propertyId := UIA_Enum.UIA_PropertyId(propertyId)
    return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "uint",propertyId, "uint",ignoreDefaultValue, "ptr",UIA_Variant(out)))? UIA_VariantData(out):UIA_VariantClear(out)
  }
  ; Retrieves a property value from the cache for this element.
  GetCachedPropertyValue(propertyId, ByRef out:="") { ; UNTESTED. 
    if propertyId is not integer
      propertyId := UIA_Enum.UIA_PropertyId(propertyId)
    return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "uint",propertyId, "ptr",UIA_Variant(out)))? UIA_VariantData(out):UIA_VariantClear(out)
  }
  ; Retrieves a property value from the cache for this element, optionally ignoring any default value. Passing FALSE in the ignoreDefaultValue parameter is equivalent to calling GetCachedPropertyValue
  GetCachedPropertyValueEx(propertyId, ignoreDefaultValue:=1, ByRef out:="") { 
    if propertyId is not integer
      propertyId := UIA_Enum.UIA_PropertyId(propertyId)
    return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "uint",propertyId, "uint",ignoreDefaultValue, "ptr",UIA_Variant(out)))? UIA_VariantData(out):UIA_VariantClear(out)
  }
  ; Retrieves a UIA_Pattern object of the specified control pattern on this element. If a full pattern name is specified then that exact version will be used (eg "TextPattern" will return a UIA_TextPattern object), otherwise the highest version will be used (eg "Text" might return UIA_TextPattern2 if it is available). usedPattern will be set to the actual string used to look for the pattern (used mostly for debugging purposes)
  GetCurrentPatternAs(pattern, ByRef usedPattern:="") { 
    local riid, out
    if (usedPattern := InStr(pattern, "Pattern") ? pattern : UIA_Pattern(pattern, this))
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "int",UIA_%usedPattern%.__PatternId, "ptr",UIA_GUID(riid,UIA_%usedPattern%.__iid), "ptr*",out:="")) ? new UIA_%usedPattern%(out,1):
    throw Exception("Pattern not implemented.",-1, "UIA_" pattern "Pattern")
  }
  ; Retrieves a UIA_Pattern object of the specified control pattern on this element from the cache of this element. 
  GetCachedPatternAs(pattern, ByRef usedPattern:="") { 
    local riid, out
    if (usedPattern := InStr(pattern, "Pattern") ? pattern : UIA_Pattern(pattern, this))
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "int",UIA_%usedPattern%.__PatternId, "ptr",UIA_GUID(riid,UIA_%usedPattern%.__iid), "ptr*",out:="")) ? new UIA_%usedPattern%(out,1):
    throw Exception("Pattern not implemented.",-1, "UIA_" pattern "Pattern")
  }
  GetCurrentPattern(pattern, ByRef usedPattern:="") {
    local out
    ; I don't know the difference between this and GetCurrentPatternAs
    if (usedPattern := InStr(pattern, "Pattern") ? pattern : UIA_Pattern(pattern, this))
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "int",UIA_%usedPattern%.__PatternId, "ptr*",out:="")) ? new UIA_%usedPattern%(out,1):
    else throw Exception("Pattern not implemented.",-1, "UIA_" pattern "Pattern")
  }
  GetCachedPattern(pattern, ByRef usedPattern:="") {
    local out
    ; I don't know the difference between this and GetCachedPatternAs
    if (usedPattern := InStr(pattern, "Pattern") ? pattern : UIA_Pattern(pattern, this))
      return UIA_Hr(DllCall(this.__Vt(17), "ptr",this.__Value, "int", UIA_%usedPattern%.__PatternId, "ptr*",out:="")) ? new UIA_%usedPattern%(out,1):
    else throw Exception("Pattern not implemented.",-1, "UIA_" pattern "Pattern")
  }
  ; Retrieves from the cache the parent of this UI Automation element
  GetCachedParent() { 
    local
    return UIA_Hr(DllCall(this.__Vt(18), "ptr",this.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  ; Retrieves the cached child elements of this UI Automation element
  GetCachedChildren() { ; UNTESTED. 
    local
    return UIA_Hr(DllCall(this.__Vt(19), "ptr",this.__Value, "ptr*",out:=""))? UIA_ElementArray(out):
  }
  ; Retrieves the physical screen coordinates of a point on the element that can be clicked
  GetClickablePoint() { 
    local
    return UIA_Hr(DllCall(this.__Vt(84), "ptr",this.__Value, "ptr", &(point,VarSetCapacity(point,8)), "ptr*",out:=""))&&out? {x:NumGet(point,0,"int"), y:NumGet(point,4,"int")}:
  }
  
  ; ---------- Custom UIA_Element methods ----------

  ; Wait until the element doesn't exist, with a default timeOut of 10000ms (10 seconds). Returns 1 if the element doesn't exist, otherwise 0.
  WaitNotExist(timeOut:=10000) { 
    local
    startTime := A_TickCount
    while ((exists := this.CurrentExists) && ((timeOut < 1) ? 1 : (A_tickCount - startTime < timeOut)))
      Sleep, 100
    return !exists
  }
  ; Wrapper for GetClickablePoint(), where additionally the coordinates are converted to relative coordinates. relativeTo can be window, screen or client, default is A_CoordModeMouse
  GetClickablePointRelativeTo(relativeTo:="") { 
    local
    res := this.GetClickablePoint()
    relativeTo := (relativeTo == "") ? A_CoordModeMouse : relativeTo
    StringLower, relativeTo, relativeTo
    if (relativeTo == "screen")
      return res
    else {
      hwnd := this.GetParentHwnd()
      if ((relativeTo == "window") || (relativeTo == "relative")) {
        VarSetCapacity(RECT, 16)
        DllCall("user32\GetWindowRect", "Ptr", hwnd, "Ptr", &RECT)
        return {x:(res.x-NumGet(&RECT, 0, "Int")), y:(res.y-NumGet(&RECT, 4, "Int"))}
      } else if (relativeTo == "client") {
        VarSetCapacity(pt,8,0), NumPut(res.x,&pt,0,"int"), NumPut(res.y,&pt,4,"int")
        DllCall("ScreenToClient", "Ptr",hwnd, "Ptr",&pt)
        return {x:NumGet(pt,"int"), y:NumGet(pt,4,"int")}
      }
    }
  }
  ; Get all available patterns for the element. Use of this should be avoided, since it calls GetCurrentPatternAs for every possible pattern. A better option is PollForPotentialSupportedPatterns.
  GetSupportedPatterns() {
    local result := [], patterns := "Invoke,Selection,Value,RangeValue,Scroll,ExpandCollapse,Grid,GridItem,MultipleView,Window,SelectionItem,Dock,Table,TableItem,Text,Toggle,Transform,ScrollItem,ItemContainer,VirtualizedItem,SyncronizedInput,LegacyIAccessible"

    Loop, Parse, patterns, `,
    {
      try {
        if this.GetCurrentPropertyValue(UIA_Enum.UIA_PropertyId("Is" A_LoopField "PatternAvailable")) {
          result.Push(A_LoopField)
        }
      }
    }
    return result
  }
  ; Get the parent window hwnd from the element
  GetParentHwnd() {
    local TW, hwndNotZeroCond, hwndRoot, hwnd
    hwndNotZeroCond := this.__UIA.CreateNotCondition(this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_PropertyId("NativeWindowHandle"), 0)) ; create a condition to find NativeWindowHandlePropertyId of not 0
    TW := this.__UIA.CreateTreeWalker(hwndNotZeroCond)
    try {
      hwnd := TW.NormalizeElement(this).GetCurrentPropertyValue(UIA_Enum.UIA_PropertyId("NativeWindowHandle"))
      return hwndRoot := DllCall("user32\GetAncestor", Ptr,hwnd, UInt,2, Ptr)
    } catch {
      return 0
    }
  }
  ; Set element value using Value pattern, or as a fall-back using LegacyIAccessible pattern. If a pattern is specified then that is used instead. Alternatively CurrentValue property can be used to set the value.
  SetValue(val, pattern:="") { 
    if !pattern {
      try {
        this.GetCurrentPatternAs("Value").SetValue(val)
      } catch {
        this.GetCurrentPatternAs("LegacyIAccessible").SetValue(val)
      }
    } else {
      this.GetCurrentPatternAs(pattern).SetValue(val)
    }
  }
  ; Click using one of the available click-like methods (InvokePattern Invoke(), TogglePattern Toggle(), ExpandCollapsePattern Expand() or Collapse() (depending on the state of the element), SelectionItemPattern Select(), or LegacyIAccessible DoDefaultAction()), in which case ClickCount is ignored. If WhichButton is specified (for example "left", "right") then the native mouse Click function will be used to click the center of the element.
  ; If WhichButton is a number, then Sleep will be called with that number. Eg Click(200) will sleep 200ms after clicking
  ; If ClickCountAndSleepTime is a number >=10, then Sleep will be called with that number. To click 10+ times and sleep after, specify "ClickCount SleepTime". Ex: Click("left", 200) will sleep 200ms after clicking. Ex: Click("left", "20 200") will left-click 20 times and then sleep 200ms.
  ; If Relative is "Rel" or "Relative" then X and Y coordinates are treated as offsets from the current mouse position. Otherwise it expects offset values for both X and Y (eg "-5 10" would offset X by -5 and Y by +10).
  Click(WhichButtonOrSleepTime:="", ClickCountAndSleepTime:=1, DownOrUp:="", Relative:="") {	
    local
    global UIA_Enum
    if ((WhichButtonOrSleepTime == "") or RegexMatch(WhichButtonOrSleepTime, "^\d+$")) {
      SleepTime := WhichButtonOrSleepTime ? WhichButtonOrSleepTime : -1
      if (this.GetCurrentPropertyValue(UIA_Enum.UIA_IsInvokePatternAvailablePropertyId)) {
        this.GetCurrentPatternAs("Invoke").Invoke()
        Sleep, %SleepTime%
        return 1
      }
      if (this.GetCurrentPropertyValue(UIA_Enum.UIA_IsTogglePatternAvailablePropertyId)) {
        togglePattern := this.GetCurrentPatternAs("Toggle"), toggleState := togglePattern.CurrentToggleState
        togglePattern.Toggle()
        if (togglePattern.CurrentToggleState != toggleState) {
          Sleep, %SleepTime%
          return 1
        }
      }
      if (this.GetCurrentPropertyValue(UIA_Enum.UIA_IsExpandCollapsePatternAvailablePropertyId)) {
        if ((expandState := (pattern := this.GetCurrentPatternAs("ExpandCollapse")).CurrentExpandCollapseState) == 0)
          pattern.Expand()
        Else
          pattern.Collapse()
        if (pattern.CurrentExpandCollapseState != expandState) {
          Sleep, %SleepTime%
          return 1
        }
      } 
      if (this.GetCurrentPropertyValue(UIA_Enum.UIA_IsSelectionItemPatternAvailablePropertyId)) {
        selectionPattern := this.GetCurrentPatternAs("SelectionItem"), selectionState := selectionPattern.CurrentIsSelected
        selectionPattern.Select()
        if (selectionPattern.CurrentIsSelected != selectionState) {
          Sleep, %sleepTime%
          return 1
        }
      }
      if (this.GetCurrentPropertyValue(UIA_Enum.UIA_IsLegacyIAccessiblePatternAvailablePropertyId)) {
        this.GetCurrentPatternAs("LegacyIAccessible").DoDefaultAction()
        Sleep, %sleepTime%
        return 1
      }
      return 0
    } else {
      rel := [0,0]
      if (Relative && !InStr(Relative, "rel"))
        rel := StrSplit(Relative, " "), Relative := ""
      ClickCount := 1, SleepTime := -1
      if (ClickCountAndSleepTime := StrSplit(ClickCountAndSleepTime, " "))[2] {
        ClickCount := ClickCountAndSleepTime[1], SleepTime := ClickCountAndSleepTime[2]
      } else if ClickCountAndSleepTime[1] {
        if (ClickCountAndSleepTime[1] > 9) {
          SleepTime := ClickCountAndSleepTime[1]
        } else {
          ClickCount := ClickCountAndSleepTime[1]
        }
      }
      try pos := this.GetClickablePointRelativeTo()
      if !(pos.x || pos.y) {
        pos := this.GetCurrentPos() ; or should only GetClickablePoint be used instead?
        Click, % (pos.x+pos.w//2+rel[1]) " " (pos.y+pos.h//2+rel[2]) " " WhichButtonOrSleepTime (ClickCount ? " " ClickCount : "") (DownOrUp ? " " DownOrUp : "") (Relative ? " " Relative : "")
      } else {
        Click, % (pos.x+rel[1]) " " (pos.y+rel[2]) " " WhichButtonOrSleepTime (ClickCount ? " " ClickCount : "") (DownOrUp ? " " DownOrUp : "") (Relative ? " " Relative : "")
      }
      Sleep, %SleepTime%
    }
  }
  ; ControlClicks the element after getting relative coordinates with GetClickablePointRelativeTo("window"). Specifying WinTitle makes the function faster, since it bypasses getting the Hwnd from the element. 
  ; If WinTitle or WinText is a number, then Sleep will be called with that number of milliseconds. Ex: ControlClick(200) will sleep 200ms after clicking. Same for ControlClick("ahk_id 12345", 200)
  ControlClick(WinTitleOrSleepTime:="", WinTextOrSleepTime:="", WhichButton:="", ClickCount:="", Options:="", ExcludeTitle:="", ExcludeText:="") { 
    local
    try this.SetFocus()
    if (WinTitleOrSleepTime == "")
      WinTitleOrSleepTime := "ahk_id " this.GetParentHwnd()
    try pos := this.GetClickablePointRelativeTo("window")
    if !(pos.x || pos.y) {
      pos := this.GetCurrentPos("window") ; or should GetClickablePoint be used instead?
      ControlClick, % "X" pos.x+pos.w//2 " Y" pos.y+pos.h//2, % WinTitleOrSleepTime, % WinTextOrSleepTime, % WhichButton, % ClickCount, % Options, % ExcludeTitle, % ExcludeText
    } else {
      ControlClick, % "X" pos.x " Y" pos.y, % WinTitleOrSleepTime, % WinTextOrSleepTime, % WhichButton, % ClickCount, % Options, % ExcludeTitle, % ExcludeText
    }
    if WinTitleOrSleepTime is integer
      Sleep, %WinTitleOrSleepTime%
    else if WinTextOrSleepTime is integer
      Sleep, %WinTextOrSleepTime%
  }
  ; Returns an object containing the x, y coordinates and width and height: {x:x coordinate, y:y coordinate, w:width, h:height}. relativeTo can be client, window or screen, default is A_CoordModeMouse.
  GetCurrentPos(relativeTo:="") { 
    local
    relativeTo := (relativeTo == "") ? A_CoordModeMouse : relativeTo
    StringLower, relativeTo, relativeTo
    br := this.CurrentBoundingRectangle
    if (relativeTo == "screen")
      return {x:br.l, y:br.t, w:(br.r-br.l), h:(br.b-br.t)}
    else {
      hwnd := this.GetParentHwnd()
      if ((relativeTo == "window") || (relativeTo == "relative")) {
        VarSetCapacity(RECT, 16)
        DllCall("user32\GetWindowRect", "Ptr", hwnd, "Ptr", &RECT)
        return {x:(br.l-NumGet(&RECT, 0, "Int")), y:(br.t-NumGet(&RECT, 4, "Int")), w:(br.r-br.l), h:(br.b-br.t)}
      } else if (relativeTo == "client") {
        VarSetCapacity(pt,8,0), NumPut(br.l,&pt,0,"int"), NumPut(br.t,&pt,4,"int")
        DllCall("ScreenToClient", "Ptr",hwnd, "Ptr",&pt)
        return {x:NumGet(pt,"int"), y:NumGet(pt,4,"int"), w:(br.r-br.l), h:(br.b-br.t)}
      }
    }			
  }
  ; By default get only direct children (UIA_TreeScope_Children := 0x2)
  GetChildren(scope:=0x2, c:="") { 
    return this.FindAll(c=="" ? this.TrueCondition : c, scope)
  }
  ; Get all child elements using TreeViewer
  TWGetChildren() { 
    local
    arr := []
    if !IsObject(nextChild := this.TreeWalkerTrue.GetFirstChildElement(this))
      return 0
    arr.Push(nextChild)
    while IsObject(nextChild := this.TreeWalkerTrue.GetNextSiblingElement(nextChild))
      arr.Push(nextChild)
    return arr
  }
  DumpRecursive(maxDepth:=20, layer:="", useTreeWalker := False, cached := False) { ; This function might hang if the element has thousands of empty custom elements (e.g. complex webpage)
    local
    StrReplace(layer, ".",, dotcount)
    if (dotcount >= maxDepth)
      return ""
    if !(children := (cached ? this.GetCachedChildren() : (useTreeWalker ? this.TWGetChildren() : this.GetChildren())))
      return ""
    returnStr := ""
    for k, v in children {
      returnStr .= layer . (layer == "" ? "" : ".") . k " " (cached ? v.CachedDump() : v.Dump()) . "`n" . v.DumpRecursive(maxDepth, layer (layer == "" ? "" : ".") k, useTreeWalker, cached)
    }
    return returnStr
  }
  ; Returns info about the element: ControlType, Name, Value, LocalizedControlType, AutomationId, AcceleratorKey. 
  Dump() { 
    local
    global UIA_Enum
    return "Type: " (ctrlType := this.CurrentControlType) " (" UIA_Enum.UIA_ControlTypeId(ctrlType) ")" ((name := this.CurrentName) == "" ? "" : " Name: """ name """") ((val := this.CurrentValue) == "" ? "" : " Value: """ val """") ((lct := this.CurrentLocalizedControlType) == "" ? "" : " LocalizedControlType: """ lct """") ((aid := this.CurrentAutomationId) == "" ? "" : " AutomationId: """ aid """") ((cm := this.CurrentClassName) == "" ? "" : " ClassName: """ cm """") ((ak := this.CurrentAcceleratorKey) == "" ? "" : " AcceleratorKey: """ ak """")
  }
  CachedDump() { 
    local
    global UIA_Enum
    return "Type: " (ctrlType := this.CachedControlType) " (" UIA_Enum.UIA_ControlTypeId(ctrlType) ")" ((name := this.CachedName) == "" ? "" : " Name: """ name """") ((val := this.CachedValue) == "" ? "" : " Value: """ val """") ((lct := this.CachedLocalizedControlType) == "" ? "" : " LocalizedControlType: """ lct """") ((aid := this.CachedAutomationId) == "" ? "" : " AutomationId: """ aid """") ((cm := this.CachedClassName) == "" ? "" : " ClassName: """ cm """") ((ak := this.CachedAcceleratorKey) == "" ? "" : " AcceleratorKey: """ ak """")
  }
  ; Returns info (ControlType, Name etc) for all descendants of the element. maxDepth is the allowed depth of recursion, by default 20 layers. DO NOT call this on the root element!
  DumpAll(maxDepth:=20) { 
    return (this.Dump() .  "`n" . this.DumpRecursive(maxDepth))
  }
  ; Requires caching for properties ControlType, LocalizedControlType, Name, Value, AutomationId, AcceleratorKey
  CachedDumpAll(maxDepth:=20) { 
    return (this.CachedDump() .  "`n" . this.DumpRecursive(maxDepth,,,True))
  }
  /*
    FindFirst using search criteria. 
    expr: 
      Takes a value in the form of "PropertyId=matchvalue" to match a specific property with the value matchValue. PropertyId can be most properties from UIA_Enum.UIA_PropertyId method (for example Name, ControlType, AutomationId etc). 
      
      Example1: "Name=Username:" would use FindFirst with UIA_Enum.UIA_NamePropertyId matching the name "Username:"
      Example2: "ControlType=Button would FindFirst using UIA_Enum.UIA_ControlTypePropertyId and matching for UIA_Enum.UIA_ButtonControlTypeId. Alternatively "ControlType=50000" can be used (direct value for UIA_ButtonControlTypeId which is 50000)
      
      Criteria can be combined with AND, OR, &&, ||:
      Example3: "Name=Username: AND ControlType=Button" would FindFirst an element with the name property of "Username:" and control type of button.

      Flags can be modified for each individual condition by specifying FLAGS=n after the condition (and before and/or operator). 0=no flags; 1=ignore case (case insensitive matching); 2=match substring; 3=ignore case and match substring

      If matchMode==3 or matching substrings is supported (Windows 10 17763 and above) and matchMode==2, then parentheses are supported. 
      Otherwise parenthesis are not supported, and criteria are evaluated left to right, so "a AND b OR c" would be evaluated as "(a and b) or c".
      
      Negation can be specified with NOT:
      Example4: "NOT ControlType=Edit" would return the first element that is not an edit element
    
    scope:
      Scope by default is UIA_TreeScope_Descendants. 
      
    matchMode:
      If using Name PropertyId as a criteria, this follows the SetTitleMatchMode scheme: 
        1=name must must start with the specified name
        2=can contain anywhere
        3=exact match
        RegEx=using regular expression. In this case the Name can't be empty.
    
    caseSensitive:
      If matching for a string, this will specify case-sensitivity.

  */
  FindFirstBy(expr, scope:=0x4, matchMode:=3, caseSensitive:=True, cacheRequest:="") { 
    local
    global UIA_Enum
    static MatchSubstringSupported := !InStr(A_OSVersion, "WIN") && (StrSplit(A_OSVersion, ".")[3] >= 17763)
    if ((matchMode == 3) || (matchMode==2 && MatchSubstringSupported)) {
      return this.FindFirst(this.__UIA.CreateCondition(expr, ((matchMode==2)?2:0)|!caseSensitive), scope, cacheRequest)
    }
    pos := 1, match := "", createCondition := "", operator := "", bufName := []
    while (pos := RegexMatch(expr, "i) *(NOT|!)? *(\w+?) *=(?: *(\d+|'.*?(?<=[^\\]|[^\\]\\\\)')|(.*?))(?: FLAGS=(\d))?( AND | OR | && | \|\| |$)", match, pos+StrLen(match))) {
      if !match
        break
      if ((StrLen(match3) > 1) && (SubStr(match3,1,1) == "'") && (SubStr(match3,0,1) == "'"))
        match3 := StrReplace(RegexReplace(SubStr(match3,2,StrLen(match3)-2), "(?<=[^\\]|[^\\]\\\\)\\'", "'"), "\\", "\") ; Remove single quotes and escape characters
      else if match4
        match3 := match4
      if ((isNamedProperty := RegexMatch(match2, "i)Name|AutomationId|Value|ClassName|FrameworkId")) && !bufName[1] && ((matchMode != 2) || ((matchMode == 2) && !MatchSubstringSupported)) && (matchMode != 3)) { ; Check if we have a condition that needs FindAll to be searched, and save it. Apply only for the first one encountered.
        bufName[1] := (match1 ? "NOT " : "") match2, bufName[2] := match3, bufName[3] := match5
        Continue
      }
      newCondition := this.__UIA.CreateCondition(match2, match3, match5 ? match5 : ((((matchMode==2) && isNamedProperty)?2:0)|!caseSensitive))
      if match1
        newCondition := this.__UIA.CreateNotCondition(newCondition)
      fullCondition := (operator == " AND " || operator == " && ") ? this.__UIA.CreateAndCondition(fullCondition, newCondition) : (operator == " OR " || operator == " || ") ? this.__UIA.CreateOrCondition(fullCondition, newCondition) : newCondition
      operator := match6 ; Save the operator to be used in the next loop
    }
    if (bufName[1]) { ; If a special case was encountered requiring FindAll
      notProp := InStr(bufName[1], "NOT "), property := StrReplace(StrReplace(bufName[1], "NOT "), "Current"), value := bufName[2], caseSensitive := bufName[3] ? !(bufName[3]&1) : caseSensitive 
      if (property = "value")
        property := "ValueValue"
      if (MatchSubstringSupported && (matchMode==1)) { ; Check if we can speed up the search by limiting to substrings when matchMode==1
        propertyCondition := this.__UIA.CreatePropertyConditionEx(UIA_Enum["UIA_" property "PropertyId"], value,, 2|!caseSensitive)
        if notProp
          propertyCondition := this.__UIA.CreateNotCondition(propertyCondition)
      } else 
        propertyCondition := this.__UIA.CreateNotCondition(this.__UIA.CreatePropertyCondition(UIA_Enum["UIA_" property "PropertyId"], ""))
      fullCondition := IsObject(fullCondition) ? this.__UIA.CreateAndCondition(propertyCondition, fullCondition) : propertyCondition
      for _, element in this.FindAll(fullCondition, scope, cacheRequest) {
        curValue := element["Current" property]
        if notProp {
          if (((matchMode == 1) && !InStr(SubStr(curValue, 1, StrLen(value)), value, caseSensitive)) || ((matchMode == 2) && !InStr(curValue, value, caseSensitive)) || (InStr(matchMode, "RegEx") && !RegExMatch(curValue, value)))
            return element
        } else {
          if (((matchMode == 1) && InStr(SubStr(curValue, 1, StrLen(value)), value, caseSensitive)) || ((matchMode == 2) && InStr(curValue, value, caseSensitive)) || (InStr(matchMode, "RegEx") && RegExMatch(curValue, value)))
            return element
        }
      }
    } else {
      return this.FindFirst(fullCondition, scope, cacheRequest)
    }
  }
  ; FindFirst using UIA_NamePropertyId. "scope" is search scope, which can be any of UIA_Enum TreeScope values. "MatchMode" has same convention as window TitleMatchMode: 1=needs to start with the specified name, 2=can contain anywhere, 3=exact match, RegEx=regex match. 
  FindFirstByName(name, scope:=0x4, matchMode:=3, caseSensitive:=True, cacheRequest:="") {
    local
    global UIA_Enum
    static MatchSubstringSupported := !InStr(A_OSVersion, "WIN") && (StrSplit(A_OSVersion, ".")[3] >= 17763)
    if (matchMode == 3 || (MatchSubstringSupported && (matchMode == 2))) {
      nameCondition := this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, ((matchMode==3)?0:2)|!caseSensitive)
      return this.FindFirst(nameCondition, scope, cacheRequest)
    }
    nameCondition := ((matchMode==1)&&MatchSubstringSupported)?this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, 2|!caseSensitive):this.__UIA.CreateNotCondition(this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_NamePropertyId, ""))
    for k, v in this.FindAll(nameCondition, scope, cacheRequest) {
      curName := v.CurrentName
      if (((matchMode == 1) && InStr(SubStr(curName, 1, StrLen(name)), name, caseSensitive))|| ((matchMode == 2) && InStr(curName, name, caseSensitive)) || ((matchMode = "RegEx") && RegExMatch(curName, name)))
        return v		
    }
  }
  ; FindFirst using UIA_ControlTypeId. controlType can be the ControlTypeId numeric value, or in string form (eg "Button")
  FindFirstByType(controlType, scope:=0x4, cacheRequest:="") {
    local
    global UIA_Enum
    if controlType is not integer
      controlType := UIA_Enum.UIA_ControlTypeId(controlType)
    if !controlType
      throw Exception("Invalid control type specified", -1)
    controlCondition := this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_ControlTypePropertyId, controlType)
    return this.FindFirst(controlCondition, scope, cacheRequest)
  }
  ; FindFirst using UIA_NamePropertyId and UIA_ControlTypeId. controlType can be the ControlTypeId numeric value, or in string form (eg "Button"). scope is search scope, which can be any of UIA_Enum TreeScope values. matchMode has same convention as window TitleMatchMode: 1=needs to start with the specified name, 2=can contain anywhere, 3=exact match, RegEx=regex match
  FindFirstByNameAndType(name, controlType, scope:=0x4, matchMode:=3, caseSensitive:=True, cacheRequest:="") { 
    local
    global UIA_Enum
    static MatchSubstringSupported := !InStr(A_OSVersion, "WIN") && (StrSplit(A_OSVersion, ".")[3] >= 17763)
    if controlType is not integer
      controlType := UIA_Enum.UIA_ControlTypeId(controlType)
    if !controlType
      throw Exception("Invalid control type specified", -1)
    controlCondition := this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_ControlTypePropertyId, controlType, 3)
    if (matchMode == 3 || (MatchSubstringSupported && (matchMode == 2))) {
      nameCondition := this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, ((matchMode==3)?0:2)|!caseSensitive)
      AndCondition := this.__UIA.CreateAndCondition(nameCondition, controlCondition)
      return this.FindFirst(AndCondition, scope, cacheRequest)
    }
    nameCondition := ((matchMode==1) && MatchSubstringSupported)?this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, 2|(!caseSensitive)):this.__UIA.CreateNotCondition(this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_NamePropertyId, ""))
    AndCondition := this.__UIA.CreateAndCondition(nameCondition, controlCondition)
    for k, v in this.FindAll(AndCondition, scope, cacheRequest) {
      curName := v.CurrentName
      if (((matchMode == 1) && InStr(SubStr(curName, 1, StrLen(name)), name, caseSensitive)) || ((matchMode == 2) && InStr(curName, name, caseSensitive)) || ((matchMode = "RegEx") && RegExMatch(curName, name)))
        return v		
    }
  }
  ; FindAll using an expression containing the desired conditions. For more information about expr, see FindFirstBy explanation
  FindAllBy(expr, scope:=0x4, matchMode:=3, caseSensitive:=True, cacheRequest:="") {
    local
    global UIA_Enum
    static MatchSubstringSupported := !InStr(A_OSVersion, "WIN") && (StrSplit(A_OSVersion, ".")[3] >= 17763)
    if ((matchMode == 3) || (matchMode==2 && MatchSubstringSupported)) 
      return this.FindAll(this.__UIA.CreateCondition(expr, ((matchMode==2)?2:0)|!caseSensitive), scope, cacheRequest)
    pos := 1, match := "", createCondition := "", operator := "", bufName := []
    while (pos := RegexMatch(expr, "i) *(NOT|!)? *(\w+?) *=(?: *(\d+|'.*?(?<=[^\\]|[^\\]\\\\)')|(.*?))(?: FLAGS=(\d))?( AND | OR | && | \|\| |$)", match, pos+StrLen(match))) {
      if !match
        break
      if ((StrLen(match3) > 1) && (SubStr(match3,1,1) == "'") && (SubStr(match3,0,1) == "'"))
        match3 := StrReplace(RegexReplace(SubStr(match3,2,StrLen(match3)-2), "(?<=[^\\]|[^\\]\\\\)\\'", "'"), "\\", "\") ; Remove single quotes and escape characters
      else if match4
        match3 := match4
      if ((isNamedProperty := RegexMatch(match2, "i)Name|AutomationId|Value|ClassName|FrameworkId")) && !bufName[1] && ((matchMode != 2) || ((matchMode == 2) && !MatchSubstringSupported)) && (matchMode != 3)) { ; Check if we have a condition that needs FindAll to be searched, and save it. Apply only for the first one encountered.
        bufName[1] := (match1 ? "NOT " : "") match2, bufName[2] := match3, bufName[3] := match5
        Continue
      }
      newCondition := this.__UIA.CreateCondition(match2, match3, match5 ? match5 : ((((matchMode==2) && isNamedProperty)?2:0)|!caseSensitive))
      if match1
        newCondition := this.__UIA.CreateNotCondition(newCondition)
      fullCondition := (operator == " AND " || operator == " && ") ? this.__UIA.CreateAndCondition(fullCondition, newCondition) : (operator == " OR " || operator == " || ") ? this.__UIA.CreateOrCondition(fullCondition, newCondition) : newCondition
      operator := match6 ; Save the operator to be used in the next loop
    }
    if (bufName[1]) { ; If a special case was encountered requiring FindAll
      notProp := InStr(bufName[1], "NOT "), property := StrReplace(StrReplace(bufName[1], "NOT "), "Current"), value := bufName[2], returnArr := [], caseSensitive := bufName[3] ? !(bufName[3]&1) : caseSensitive
      if (property = "value")
        property := "ValueValue"
      if (MatchSubstringSupported && (matchMode==1)) { ; Check if we can speed up the search by limiting to substrings when matchMode==1
        propertyCondition := this.__UIA.CreatePropertyConditionEx(UIA_Enum["UIA_" property "PropertyId"], value,, 2|!caseSensitive)
        if notProp
          propertyCondition := this.__UIA.CreateNotCondition(propertyCondition)
      } else 
        propertyCondition := this.__UIA.CreateNotCondition(this.__UIA.CreatePropertyCondition(UIA_Enum["UIA_" property "PropertyId"], ""))
      fullCondition := IsObject(fullCondition) ? this.__UIA.CreateAndCondition(propertyCondition, fullCondition) : propertyCondition
      for _, element in this.FindAll(fullCondition, scope, cacheRequest) {
        curValue := element["Current" property]
        if notProp {
          if (((matchMode == 1) && !InStr(SubStr(curValue, 1, StrLen(value)), value, caseSensitive)) || ((matchMode == 2) && !InStr(curValue, value, caseSensitive)) || (InStr(matchMode, "RegEx") && !RegExMatch(curValue, value)))
            returnArr.Push(element)
        } else {
          if (((matchMode == 1) && InStr(SubStr(curValue, 1, StrLen(value)), value, caseSensitive)) || ((matchMode == 2) && InStr(curValue, value, caseSensitive)) || (InStr(matchMode, "RegEx") && RegExMatch(curValue, value)))
            returnArr.Push(element)
        }
      }
      return returnArr[1] ? returnArr : ""
    } else {
      return this.FindAll(fullCondition, scope, cacheRequest)
    }
  }
  ; FindAll using UIA_NamePropertyId. scope is search scope, which can be any of UIA_Enum TreeScope values. matchMode has same convention as window TitleMatchMode: 1=needs to start with the specified name, 2=can contain anywhere, 3=exact match, RegEx=regex match
  FindAllByName(name, scope:=0x4, matchMode:=3, caseSensitive:=True, cacheRequest:="") { 
    local
    global UIA_Enum
    static MatchSubstringSupported := !InStr(A_OSVersion, "WIN") && (StrSplit(A_OSVersion, ".")[3] >= 17763)
    if (matchMode == 3 || ((matchMode == 2) && MatchSubstringSupported)) {
      nameCondition := this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, ((matchMode==3)?0:2)|!caseSensitive)
      return this.FindAll(nameCondition, scope, cacheRequest)
    }
    nameCondition := ((matchMode==1) && MatchSubstringSupported)?this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, 2|!caseSensitive):this.__UIA.CreateNotCondition(this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_NamePropertyId, ""))
    retList := []
    for k, v in this.FindAll(nameCondition, scope, cacheRequest) {
      curName := v.CurrentName
      if (((matchMode == 1) && InStr(SubStr(curName, 1, StrLen(name)), name, caseSensitive)) || ((matchMode == 2) && InStr(curName, name, caseSensitive)) || ((matchMode = "RegEx") && RegExMatch(curName, name)))
        retList.Push(v)		
    }
    return retList
  }
  ; FindAll using UIA_ControlTypeId. controlType can be the ControlTypeId numeric value, or in string form (eg "Button"). scope is search scope, which can be any of UIA_Enum TreeScope values.
  FindAllByType(controlType, scope:=0x4, cacheRequest:="") {
    local
    global UIA_Enum
    if controlType is not integer
      controlType := UIA_Enum.UIA_ControlTypeId(controlType)
    if !controlType
      throw Exception("Invalid control type specified", -1)
    controlCondition := this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_ControlTypePropertyId, controlType)
    return this.FindAll(controlCondition, scope, cacheRequest)
  }
  ; FindAll using UIA_NamePropertyId and UIA_ControlTypeId. controlType can be the ControlTypeId numeric value, or in string form (eg "Button"). scope is search scope, which can be any of UIA_Enum TreeScope values. matchMode has same convention as window TitleMatchMode: 1=needs to start with the specified name, 2=can contain anywhere, 3=exact match, RegEx=regex match
  FindAllByNameAndType(name, controlType, scope:=0x4, matchMode:=3, caseSensitive:=True, cacheRequest:="") { 
    local
    global UIA_Enum
    static MatchSubstringSupported := !InStr(A_OSVersion, "WIN") && (StrSplit(A_OSVersion, ".")[3] >= 17763)
    if controlType is not integer
      controlType := UIA_Enum.UIA_ControlTypeId(controlType)
    if !controlType
      throw Exception("Invalid control type specified", -1)
    controlCondition := this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_ControlTypePropertyId, controlType)
    if (matchMode == 3 || (MatchSubstringSupported && (matchMode == 2))) {
      nameCondition := this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, ((matchMode==3)?0:2)|!caseSensitive)
      AndCondition := this.__UIA.CreateAndCondition(nameCondition, controlCondition)
      return this.FindAll(AndCondition, scope, cacheRequest)
    }
    nameCondition := ((matchMode==1) && MatchSubstringSupported)?this.__UIA.CreatePropertyConditionEx(UIA_Enum.UIA_NamePropertyId, name,, 2|!caseSensitive):this.__UIA.CreateNotCondition(this.__UIA.CreatePropertyCondition(UIA_Enum.UIA_NamePropertyId, ""))
    AndCondition := this.__UIA.CreateAndCondition(nameCondition, controlCondition)
    returnArr := []
    for k, v in this.FindAll(AndCondition, scope, cacheRequest) {
      curName := v.CurrentName
      if (((matchMode == 1) && InStr(SubStr(curName, 1, StrLen(name)), name, caseSensitive)) || ((matchMode == 2) && InStr(curName, name, caseSensitive)) || ((matchMode = "RegEx") && RegExMatch(curName, name)))
        returnArr.Push(v)	
    }
    return returnArr
  }
  /*
    FindByPath gets an element by a relative "path" from a starting element. 
    1) To get the nth child of the starting element, set searchPath to "n". To get a deeper node, separate the numbers with a ".": "2.1" will get the second childs first child. This kind of path can easily be got from the UIA_Element.DumpAll() method, which returns a path in the same style (this is like the Acc path but for UIA, they are not compatible!).
    2) To get the nth parent of the starting element, use "Pn": "P2" will get the parent of the parent.
    3) To get sibling elements, put a "+" or "-" in front of "n": +2 will get the next sibling from the next sibling (calling GetNextSiblingElement twice). Using this after "Pn" doesn't require a "." separator ("P2.-1" == "P2-1").

    These conditions can also be combined:
    searchPath="P1-1.1.1.2" -> gets the parent element, then the previous sibling element of the parent, and then "1.1.2" gets the second child of the first childs first child. 

    c or condition argument can be used to only filter elements specified by the condition: 
    UIA_Element.FindByPath("+2", "Type=Button") will only consider "Button" controls and gets the second sibling button.
  */
  FindByPath(searchPath:="", c:="") {
    local
    el := this, ErrorLevel := 0, PathTW := (c=="" ? this.TreeWalkerTrue : this.__UIA.CreateTreeWalker(c))
    searchPath := StrReplace(StrReplace(searchPath, " "), ",", ".")
    Loop, Parse, searchPath, .
    {
      if RegexMatch(A_LoopField, "^\d+$") {
        children := el.GetChildren(0x2,c)
        if !IsObject(el := children[A_LoopField])
          return ErrorLevel := "Step " A_index " was out of bounds"
      } else if RegexMatch(A_LoopField, "i)^(?!p\d*[+-]?\d*$)([A-Za-z]+)([+-]?\d*)$", m) {
        el := (m2 && m2 != 1) ? (els := el.FindAllByType(m1, 2))[m2 > 1 ? m2 : els.MaxIndex()+m2+1] : el.FindFirstByType(m1, 2)
      } else {
        if RegexMatch(A_LoopField, "i)p(\d+)?", m) {
          if !m1
            m1 := 1
          Loop, %m1% {
            if !(el := PathTW.GetParentElement(el))
              return ErrorLevel := "Step " A_index " with P" m1 " was out of bounds (GetParentElement failed)"
          }
        }
        if RegexMatch(A_LoopField, "([+-])(\d+)?", m) {
          if !m2
            m2 := 1
          if (m1 == "+") {
            Loop, %m2% {
              if !(el := PathTW.GetNextSiblingElement(el))
                return ErrorLevel := "Step " A_index " with """ m1 m2 """ was out of bounds (GetNextSiblingElement failed)"
            }
          } else if (m1 == "-") {
            Loop, %m2% {
              if !(el := PathTW.GetPreviousSiblingElement(el))
                return ErrorLevel := "Step " A_index " with """ m1 m2 """ was out of bounds (GetPreviousSiblingElement failed)"
            }
          }
        }
      }
    }
    return el
  }
  ; Calls UIA_Element.FindByPath until the element is found and then returns it. By default waits indefinitely, timeOut can be specified in milliseconds. 
  WaitElementExistByPath(searchPath, c:="", timeOut:=-1) { 
    local
    startTime := A_TickCount
    while (!IsObject(el := this.FindByPath(searchPath, c)) && ((timeOut < 1) ? 1 : (A_tickCount - startTime < timeOut)))
      Sleep, 40
    return el
  }
  ; Calls UIA_Element.FindFirstBy until the element is found and then returns it. By default waits indefinitely, timeOut can be specified in milliseconds. For explanations of the other arguments, see FindFirstBy
  WaitElementExist(expr, scope:=0x4, matchMode:=3, caseSensitive:=True, timeOut:=-1, cacheRequest:="") { 
    local
    startTime := A_TickCount
    while (!IsObject(el := this.FindFirstBy(expr, scope, matchMode, caseSensitive, cacheRequest)) && ((timeOut < 1) ? 1 : (A_tickCount - startTime < timeOut)))
      Sleep, 40
    return el
  }
  ; Tries to FindFirstBy the element and if it is found then waits until the element doesn't exist (using WaitNotExist()), with a timeOut of 10000ms (10 seconds). For explanations of the other arguments, see FindFirstBy
  WaitElementNotExist(expr, scope:=0x4, matchMode:=3, caseSensitive:=True, timeOut:=-1) { 
    local
    return !IsObject(el := this.FindFirstBy(expr, scope, matchMode, caseSensitive)) || el.WaitNotExist(timeOut)
  }
  ; Calls UIA_Element.FindFirstByName until the element is found and then returns it. By default waits indefinitely, timeOut can be specified in milliseconds.
  WaitElementExistByName(name, scope:=0x4, matchMode:=3, caseSensitive:=True, timeOut:=-1, cacheRequest:="") {
    local
    startTime := A_TickCount
    while (!IsObject(el := this.FindFirstByName(name, scope, matchMode, caseSensitive, cacheRequest)) && ((timeOut < 1) ? 1 : (A_tickCount - startTime < timeOut)))
      Sleep, 40
    return el
  }
  ; Calls UIA_Element.FindFirstByType until the element is found and then returns it. By default waits indefinitely, timeOut can be specified in milliseconds.
  WaitElementExistByType(controlType, scope:=0x4, timeOut:=-1, cacheRequest:="") { 
    local
    startTime := A_TickCount
    while (!IsObject(el := this.FindFirstByType(controlType, scope, cacheRequest)) && ((timeOut < 1) ? 1 : (A_tickCount - startTime < timeOut)))
      Sleep, 100
    return el
  }
  ; Calls UIA_Element.FindFirstByNameAndType until the element is found and then returns it. By default waits indefinitely, timeOut can be specified in milliseconds.
  WaitElementExistByNameAndType(name, controlType, scope:=0x4, matchMode:=3, caseSensitive:=True, timeOut:=-1, cacheRequest:="") {
    local
    startTime := A_TickCount
    while (!IsObject(el := (this.FindFirstByNameAndType(name, controlType, scope, matchMode, caseSensitive, cacheRequest))) && ((timeOut < 1) ? 1 : (A_tickCount - startTime < timeOut))) {
      Sleep, 100
    }
    return el
  }

  Highlight(displayTime:=2000, color:="Red", d:=4) { ; Based on FindText().RangeTip from the FindText library, credit goes to feiyue
    local
    br := this.CurrentBoundingRectangle, x := br.l, y := br.t, w := br.r-br.l, h := br.b-br.t, d:=Floor(d)
    Loop 4 {
      Gui, Range_%A_Index%: +Hwndid +AlwaysOnTop -Caption +ToolWindow -DPIScale +E0x08000000
      i:=A_Index
      , x1:=(i=2 ? x+w : x-d)
      , y1:=(i=3 ? y+h : y-d)
      , w1:=(i=1 or i=3 ? w+2*d : d)
      , h1:=(i=2 or i=4 ? h+2*d : d)
      Gui, Range_%i%: Color, %color%
      Gui, Range_%i%: Show, NA x%x1% y%y1% w%w1% h%h1%
    }
    Sleep, %displayTime%
    Loop 4
      Gui, Range_%A_Index%: Destroy
    return this
  }
}

class UIA_Element2 extends UIA_Element {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee671425(v=vs.85).aspx
  static __IID := "{6749C683-F70D-4487-A698-5F79D55290D6}"

  ; ---------- UIA_Element2 properties ----------

  CurrentOptimizeForVisualContent[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(85), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedOptimizeForVisualContent[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(86), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentLiveSetting[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(87), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedLiveSetting[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(88), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentFlowsFrom[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(89), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CachedFlowsFrom[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(90), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
}
class UIA_Element3 extends UIA_Element2 {
  static __IID := "{8471DF34-AEE0-4A01-A7DE-7DB9AF12C296}"

  ; ---------- UIA_Element3 properties ----------

  CurrentIsPeripheral[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(92), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsPeripheral[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(93), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA methods ----------

  ShowContextMenu() {
    return UIA_Hr(DllCall(this.__Vt(91), "ptr",this.__Value))
  }
}
class UIA_Element4 extends UIA_Element3 {
  static __IID := "{3B6E233C-52FB-4063-A4C9-77C075C2A06B}"

  ; ---------- UIA_Element4 properties ----------

  CurrentPositionInSet[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(94), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentSizeOfSet[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(95), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentLevel[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(96), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentAnnotationTypes[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(97), "ptr",this.__Value, "ptr",UIA_Variant(out:="")))&&out?UIA_VariantData(out):UIA_VariantClear(out)
    }
  }
  CurrentAnnotationObjects[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(98), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }
  CachedPositionInSet[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(99), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedSizeOfSet[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(100), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedLevel[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(101), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedAnnotationTypes[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(102), "ptr",this.__Value, "ptr",UIA_Variant(out:="")))&&out?UIA_VariantData(out):UIA_VariantClear(out)
    }
  }
  CachedAnnotationObjects[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(103), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
    }
  }

}
class UIA_Element5 extends UIA_Element4 {
  static __IID := "{98141C1D-0D0E-4175-BBE2-6BFF455842A7}"

  ; ---------- UIA_Element5 properties ----------

  CurrentLandmarkType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(104), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentLocalizedLandmarkType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(105), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedLandmarkType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(106), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedLocalizedLandmarkType[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(107), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
}
class UIA_Element6 extends UIA_Element5 {
  static __IID := "{4780D450-8BCA-4977-AFA5-A4A517F555E3}"

  ; ---------- UIA_Element6 properties ----------

  CurrentFullDescription[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(108), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedFullDescription[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(109), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
}
class UIA_Element7 extends UIA_Element6 {
  static __IID := "{204E8572-CFC3-4C11-B0C8-7DA7420750B7}"
  
  ; Finds the first matching element in the specified order. traversalOptions must be one of TreeTraversalOptions enums. [optional] root is pointer to the element with which to begin the search.
  FindFirstWithOptions(scope:=0x4, c:="", traversalOptions:=0, root:=0) { 
    local
    return UIA_Hr(DllCall(this.__Vt(110), "ptr",this.__Value, "uint", scope, "ptr",(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c))).__Value, "uint", traversalOptions, "ptr", root ? root.__Value : this.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  FindAllWithOptions(scope:=0x4, c:="", traversalOptions:=0, root:=0) {
    local
    return UIA_Hr(DllCall(this.__Vt(111), "ptr",this.__Value, "uint",scope, "ptr",(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c))).__Value, "int", traversalOptions, "ptr", root ? root.__Value : this.__Value, "ptr*",out:=""))? UIA_ElementArray(out):
  }
  FindFirstWithOptionsBuildCache(scope:=0x4, c:="", cacheRequest:=0, traversalOptions:=0, root:=0) {
    local
    return UIA_Hr(DllCall(this.__Vt(112), "ptr",this.__Value, "uint",scope, "ptr",(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c))).__Value, "ptr", cacheRequest.__Value, "int", traversalOptions, "ptr", root ? root.__Value : this.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  FindAllWithOptionsBuildCache(scope:=0x4, c:="", cacheRequest:=0, traversalOptions:=0, root:=0) {
    local
    return UIA_Hr(DllCall(this.__Vt(113), "ptr",this.__Value, "uint",scope, "ptr",(c=""?this.TrueCondition:(IsObject(c)?c:this.__UIA.CreateCondition(c))).__Value, "ptr", cacheRequest.__Value, "int", traversalOptions, "ptr", root ? root.__Value : this.__Value, "ptr*",out:=""))? UIA_ElementArray(out):
  }
  GetCurrentMetadataValue(targetId, metadataId) {
    local
    return UIA_Hr(DllCall(this.__Vt(114), "ptr",this.__Value, "int",targetId, "int", metadataId, "ptr*", UIA_Variant(out:="")))? UIA_VariantData(out):UIA_VariantClear(out)
  }
}

class UIA_ElementArray extends UIA_Base {
  static __IID := "{14314595-b4bc-4055-95f2-58f2e42c9855}"

  ; ---------- UIA_ElementArray properties ----------

  Length[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_ElementArray methods ----------
  
  GetElement(i) {
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "int",i, "ptr*",out:=""))? UIA_Element(out):
  }
}
/*
  Exposes properties and methods that UI Automation client applications use to view and navigate the UI Automation elements on the desktop.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtreewalker
*/
class UIA_TreeWalker extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee671470(v=vs.85).aspx
  static __IID := "{4042c624-389c-4afc-a630-9df854a541fc}"

  ; ---------- UIA_TreeWalker properties ----------

  Condition[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?new UIA_Condition(out):
    }
  }

  ; ---------- UIA_TreeWalker methods ----------

  GetParentElement(e) {
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr",e.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetFirstChildElement(e) {
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr",e.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetLastChildElement(e) {
    local
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr",e.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetNextSiblingElement(e) {
    local
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr",e.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetPreviousSiblingElement(e) {
    local
    return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr",e.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  NormalizeElement(e) {
    local
    return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr",e.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetParentElementBuildCache(e, cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr",e.__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetFirstChildElementBuildCache(e, cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr",e.__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetLastChildElementBuildCache(e, cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr",e.__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetNextSiblingElementBuildCache(e, cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr",e.__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  GetPreviousSiblingElementBuildCache(e, cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "ptr",e.__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
  NormalizeElementBuildCache(e, cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "ptr",e.__Value, "ptr",cacheRequest.__Value, "ptr*",out:=""))? UIA_Element(out):
  }
}

/*
  This is the primary interface for conditions used in filtering when searching for elements in the UI Automation tree. This interface has no members.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationcondition
*/
class UIA_Condition extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee671420(v=vs.85).aspx
  static __IID := "{352ffba8-0973-437c-a61f-f64cafd81df9}"
}

/*
  Represents a condition based on a property value that is used to find UI Automation elements.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationpropertycondition
*/
class UIA_PropertyCondition extends UIA_Condition {
  static __IID := "{99ebf2cb-5578-4267-9ad4-afd6ea77e94b}"

  ; ---------- UIA_PropertyCondition properties ----------

  PropertyId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  PropertyValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr",UIA_Variant(out:="")))&&out?UIA_VariantData(out):UIA_VariantClear(out)
    }
  }
  PropertyConditionFlags[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
}

/*
  Exposes properties and methods that Microsoft UI Automation client applications can use to retrieve information about an AND-based property condition.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationandcondition
*/
class UIA_AndCondition extends UIA_Condition {
  static __IID := "{a7d0af36-b912-45fe-9855-091ddc174aec}"

  ; ---------- UIA_AndCondition properties ----------

  ChildCount[] {
    get {
      local out
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ;~ GetChildrenAsNativeArray	4	IUIAutomationCondition ***childArray
  GetChildren() { ; Returns a native AHK array containing all the conditions (already subtyped to AndCondition, OrCondition etc)
    local
    global UIA_AndCondition, UIA_OrCondition, UIA_BoolCondition, UIA_NotCondition, UIA_PropertyCondition
    ret := UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:="")), arr := []
    if (out && (safeArray := ComObj(0x2003,out,1))) {
      for k in safeArray {
        obj := ComObject(9, k, 1), ObjAddRef(k)
        for _, n in ["Property", "Bool", "And", "Or", "Not"] {
          if ComObjQuery(obj, UIA_%n%Condition.__IID) {
            arr.Push(new UIA_%n%Condition(k))
            break
          }
        }
        ObjRelease(k)
      }
      return arr
    }
    return
  }
}

/*
  Represents a condition made up of multiple conditions, at least one of which must be true.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationorcondition
*/
class UIA_OrCondition extends UIA_Condition {
  static __IID := "{8753f032-3db1-47b5-a1fc-6e34a266c712}"

  ; ---------- UIA_OrCondition properties ----------

  ChildCount[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_OrCondition methods ----------

  ;~ GetChildrenAsNativeArray	4	IUIAutomationCondition ***childArray
  GetChildren() {
    local
    global UIA_AndCondition, UIA_OrCondition, UIA_BoolCondition, UIA_NotCondition, UIA_PropertyCondition
    ret := UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:="")), arr := []
    if (out && (safeArray := ComObject(0x2003,out,1))) {
      for k in safeArray {
        obj := ComObject(9, k, 1) ; ObjAddRef and ObjRelease probably aren't needed here, since ref count won't fall to 0
        for _, n in ["Property", "Bool", "And", "Or", "Not"] {
          if ComObjQuery(obj, UIA_%n%Condition.__IID) {
            arr.Push(new UIA_%n%Condition(k,1))
            break
          }
        }
      }
      return arr
    }
    return
  }
}

/*
  Represents a condition that can be either TRUE=1 (selects all elements) or FALSE=0(selects no elements).
  Microsoft documentation: 
*/
class UIA_BoolCondition extends UIA_Condition {
  static __IID := "{1B4E1F2E-75EB-4D0B-8952-5A69988E2307}"

  ; ---------- UIA_BoolCondition properties ----------

  BooleanValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
}

/*
  Represents a condition that is the negative of another condition.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationnotcondition
*/
class UIA_NotCondition extends UIA_Condition {
  static __IID := "{f528b657-847b-498c-8896-d52b565407a1}"

  GetChild() { ; Type of the received condition can be determined with out.__Class
    local
    global UIA_AndCondition, UIA_OrCondition, UIA_BoolCondition, UIA_NotCondition, UIA_PropertyCondition
    ret := UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:="")), obj := ComObject(9, out, 1)
    for k, v in ["Bool", "Property", "And", "Or", "Not"] {
      if ComObjQuery(obj, UIA_%v%Condition.__IID)
        return ret?new UIA_%v%Condition(out):
    }
    return UIA_Hr(0x80004005)
  }
}

class UIA_IUnknown extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ms680509(v=vs.85).aspx
  static __IID := "{00000000-0000-0000-C000-000000000046}"
}

/*
  Exposes properties and methods of a cache request. Client applications use this interface to specify the properties and control patterns to be cached when a Microsoft UI Automation element is obtained.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationcacherequest
*/
class UIA_CacheRequest extends UIA_Base {
  static __IID := "{b32a92b5-bc25-4078-9c08-d7ee95c48e03}"

  ; ---------- UIA_CacheRequest properties ----------

  TreeScope[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
    set {
      UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr", value))
    }
  }
  TreeFilter[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
    set {
      UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr",value.__Value))
    }
  }
  AutomationElementMode[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
    set {
      UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr",value))
    }
  }

  ; ---------- UIA_CacheRequest methods ----------

  Clone() {
    local out
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:="")) ? new UIA_CacheRequest(out):
  }	
  AddProperty(property) {
    if property is not integer
      property := UIA_Enum.UIA_PropertyId(property)
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr",property))
  }
  AddPattern(pattern) {
    if pattern is not integer
      pattern := UIA_Enum.UIA_PatternId(pattern)
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value,"ptr",pattern))
  }
}

/*
  Exposes a method to handle Microsoft UI Automation events
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationeventhandler
*/
class _UIA_EventHandler extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696044(v=vs.85).aspx
  static __IID := "{146c3c17-f12e-4e22-8c27-f894b9b79c69}"

  HandleAutomationEvent(sender, eventId) {
    local param1, funcName
    param1 := this, this := Object(A_EventInfo), funcName := this.__Version
    %funcName%(UIA_Element(sender), eventId)
    return 0
  }
}
/*
  Exposes a method to handle events that are raised when the keyboard focus moves to another UI Automation element.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationfocuschangedeventhandler
*/
class _UIA_FocusChangedEventHandler extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696051(v=vs.85).aspx
  static __IID := "{c270f6b5-5c69-4290-9745-7a7f97169468}"

  HandleFocusChangedEvent(sender) {
    local param1, funcName
    param1 := this, this := Object(A_EventInfo), funcName := this.__Version
    %funcName%(UIA_Element(sender))
    return 0
  }
}
/*
  Exposes a method to handle Microsoft UI Automation events that occur when a property is changed.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationpropertychangedeventhandler
*/
class _UIA_PropertyChangedEventHandler extends UIA_Base { ; UNTESTED
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696119(v=vs.85).aspx
  static __IID := "{40cd37d4-c756-4b0c-8c6f-bddfeeb13b50}"

  HandlePropertyChangedEvent(sender, propertyId, newValue) {
    local param1, funcName
    param1 := this, this := Object(A_EventInfo), funcName := this.__Version
    %funcName%(UIA_Element(sender), propertyId, UIA_VariantData(newValue,0))
    return 0
  }
}
/*
  Exposes a method to handle events that occur when the Microsoft UI Automation tree structure is changed.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationstructurechangedeventhandler
*/
class _UIA_StructureChangedEventHandler extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696197(v=vs.85).aspx
  static __IID := "{e81d1b4e-11c5-42f8-9754-e7036c79f054}"

  HandleStructureChangedEvent(sender, changeType, runtimeId) {
    local param1, funcName
    param1 := this, this := Object(A_EventInfo), funcName := this.__Version
    %funcName%(UIA_Element(sender), changeType, UIA_SafeArrayToAHKArray(ComObj(0x2003,runtimeId))) ; ComObj(0x2003,runtimeId,1) crashes the script. Should the SAFEARRAY be released manually?
    return 0
  }
}
/*
  Exposes a method to handle events that occur when Microsoft UI Automation reports a text-changed event from text edit controls
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtextedittextchangedeventhandler
*/
class _UIA_TextEditTextChangedEventHandler extends UIA_Base { ; UNTESTED
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/dn302202(v=vs.85).aspx
  static __IID := "{92FAA680-E704-4156-931A-E32D5BB38F3F}"

  HandleTextEditTextChangedEvent(sender, changeType, eventStrings) {
    local param1, funcName
    param1 := this, this := Object(A_EventInfo), funcName := this.__Version
    %funcName%(UIA_Element(sender), changeType, UIA_SafeArrayToAHKArray(ComObj(0x2008,eventStrings)))
    return 0
  }
}
/*
  Exposes a method to handle one or more Microsoft UI Automation change events
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationchangeseventhandler
*/
class _UIA_ChangesEventHandler extends UIA_Base { ; UNTESTED
  static __IID := "{58EDCA55-2C3E-4980-B1B9-56C17F27A2A0}"

  HandleChangesEvent(sender, uiaChanges, changesCount) {
    local param1, funcName, changes
    param1 := this, this := Object(A_EventInfo), funcName := this.__Version, changes := {}
    changes.uiaId := NumGet(uiaChanges,, 0), changes.payload := UIA_VariantData(uiaChanges,, 8), changes.extraInfo := UIA_VariantData(uiaChanges,,16+2*A_PtrSize)
    
    %funcName%(UIA_Element(sender), changes, changesCount)
    return 0
  }
}
/*
  Exposes a method to handle Microsoft UI Automation notification events
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationnotificationeventhandler
*/
class _UIA_NotificationEventHandler extends UIA_Base {
  static __IID := "{C7CB2637-E6C2-4D0C-85DE-4948C02175C7}"

  HandleNotificationEvent(sender, notificationKind, notificationProcessing, displayString, activityId) {
    local param1, funcName
    param1 := this, this := Object(A_EventInfo), funcName := this.__Version
    %funcName%(UIA_Element(sender), notificationKind, notificationProcessing, StrGet(displayString), StrGet(activityId))
    DllCall("oleaut32\SysFreeString", "ptr", displayString), DllCall("oleaut32\SysFreeString", "ptr", activityId)
    return 0
  }
}

class UIA_AutomationEventHandlerGroup extends UIA_Base {
  static __IID := "{C9EE12F2-C13B-4408-997C-639914377F4E}"

  AddActiveTextPositionChangedEventHandler(scope:=0x4, cacheRequest:=0, handler:="") {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "int", scope, "int", cacheRequest.__Value, "ptr", handler.__Value))
  }
  AddAutomationEventHandler(eventId, scope:=0x4, cacheRequest:=0, handler:="") {
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "uint", eventId, "uint", scope, "ptr",cacheRequest.__Value,"ptr", handler.__Value))
  }
  AddChangesEventHandler(scope, changeTypes, changesCount, cacheRequest:=0, handler:="") {
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "int", scope, "int", changeTypes, "int", changesCount, "ptr", cacheRequest.__Value, "ptr", handler.__Value))
  }
  AddNotificationEventHandler(scope:=0x4, cacheRequest:=0, handler:="") {
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "int", scope, "int", cacheRequest.__Value, "ptr", handler.__Value))
  }
  AddPropertyChangedEventHandler(scope:=0x1,cacheRequest:=0,handler:="",propertyArray:="") {
    local
    SafeArray:=ComObjArray(0x3,propertyArray.MaxIndex())
    for i,propertyId in propertyArray
      SafeArray[i-1]:=propertyId
    return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "int",scope, "ptr",cacheRequest.__Value,"ptr",handler.__Value,"ptr",ComObjValue(SafeArray)))
  }
  AddStructureChangedEventHandler(scope:=0x4, cacheRequest:=0, handler:="") { ; UNTESTED. 
    return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "int", scope, "ptr",cacheRequest.__Value, "ptr", handler.__Value))
  }
  AddTextEditTextChangedEventHandler(scope, textEditChangeType, cacheRequest:=0, handler:="") {
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "int", scope, "int", textEditChangeType, "ptr", cacheRequest.__Value, "ptr", handler.__Value))
  }
}

/*
  Provides access to a control that enables child elements to be arranged horizontally and vertically, relative to each other.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationdockpattern
*/
class UIA_DockPattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee671421
  static	__IID := "{fde5ef97-1464-48f6-90bf-43d0948e86ec}"
    ,	__PatternID := 10011

  ; ---------- UIA_DockPattern properties ----------

  CurrentDockPosition[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedDockPosition[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_DockPattern methods ----------

  SetDockPosition(Pos) {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "uint",pos))
  }
  /*	DockPosition_Top	= 0,
    DockPosition_Left	= 1,
    DockPosition_Bottom	= 2,
    DockPosition_Right	= 3,
    DockPosition_Fill	= 4,
    DockPosition_None	= 5
  */
}

/*
  Provides access to a control that can visually expand to display content, and collapse to hide content.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationexpandcollapsepattern
*/
class UIA_ExpandCollapsePattern extends UIA_Base {
  static	__IID := "{619be086-1f4e-4ee4-bafa-210128738730}"
    ,	__PatternID := 10005

  ; ---------- UIA_ExpandCollapsePattern properties ----------

  CachedExpandCollapseState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentExpandCollapseState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_ExpandCollapsePattern methods ----------
  
  Expand() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
  Collapse() {
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value))
  }	
  /*	ExpandCollapseState_Collapsed	= 0,
    ExpandCollapseState_Expanded	= 1,
    ExpandCollapseState_PartiallyExpanded	= 2,
    ExpandCollapseState_LeafNode	= 3
  */
}

/*
  Provides access to a child control in a grid-style container that supports the IUIAutomationGridPattern interface.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationgriditempattern
*/
class UIA_GridItemPattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696053
  static	__IID := "{78f8ef57-66c3-4e09-bd7c-e79b2004894d}"
    ,	__PatternID := 10007

  ; ---------- UIA_GridItemPattern properties ----------

  CurrentContainingGrid[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CurrentRow[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentColumn[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentRowSpan[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentColumnSpan[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedContainingGrid[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CachedRow[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedColumn[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedRowSpan[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedColumnSpan[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
}

/*
  Provides access to a control that acts as a container for a collection of child controls that are organized in a two-dimensional logical coordinate system that can be traversed by row and column. The children of this element support the GridItemPattern interface.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationgridpattern
*/
class UIA_GridPattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696064
  static	__IID := "{414c3cdc-856b-4f5b-8538-3131c6302550}"
    ,	__PatternID := 10006

  ; ---------- UIA_GridPattern properties ----------

  CurrentRowCount[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentColumnCount[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedRowCount[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedColumnCount[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_GridPattern methods ----------

  GetItem(row,column) { ; Hr!=0 if no result, or blank output?
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "uint",row, "uint",column, "ptr*",out:=""))? UIA_Element(out):
  }
}

/*
  Exposes a method that enables a client application to invoke the action of a control (typically a button). A control should support this interface if it initiates or performs a single, unambiguous action and does not maintain state when activated.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationinvokepattern
*/
class UIA_InvokePattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696070
  static	__IID := "{fb377fbe-8ea6-46d5-9c73-6499642d3059}"
    ,	__PatternID := 10000
  
  Invoke() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
}

/*
  Exposes a method that retrieves an item from a container, such as a virtual list. This interface is not limited to use by virtualized containers. Any container that can implement efficient name lookup can support this control pattern, enabling clients to look up names more quickly than by using methods such as FindFirst, which must traverse the Microsoft UI Automation tree.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationitemcontainerpattern
*/
class UIA_ItemContainerPattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696072
  static	__IID := "{c690fdb2-27a8-423c-812d-429773c9084e}"
    ,	__PatternID := 10019

  FindItemByProperty(startAfter, propertyId, ByRef value, type:=8) {	; Hr!=0 if no result, or blank output?
    local
    var := UIA_ComVar(type,value)
    return UIA_Hr((A_PtrSize == 4) ? DllCall(this.__Vt(3), "ptr",this.__Value, "ptr",startAfter.__Value, "int",propertyId, "int64",NumGet(var.ptr+0, 0, "int64"),"int64",NumGet(var.ptr+0, 8, "int64"), "ptr*",out:="") : DllCall(this.__Vt(3), "ptr",this.__Value, "ptr",startAfter.__Value, "int",propertyId, "ptr",var.ptr+0, "ptr*",out:=""))? UIA_Element(out):
  }
}

/*
  Exposes methods and properties that enable Microsoft UI Automation clients to retrieve UI information from Microsoft Active Accessibility (MSAA) servers.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationlegacyiaccessiblepattern
*/
class UIA_LegacyIAccessiblePattern extends UIA_Base {
  static	__IID := "{828055ad-355b-4435-86d5-3b51c14a9b1b}"
    ,	__PatternID := 10018

  ; ---------- UIA_LegacyIAccessiblePattern properties ----------

  CurrentChildId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr",&value))
    }
  }
  CurrentDescription[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentRole[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentHelp[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentKeyboardShortcut[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentDefaultAction[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedChildId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(17), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(18), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedDescription[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(19), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedRole[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(20), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(21), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedHelp[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(22), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedKeyboardShortcut[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(23), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedDefaultAction[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(25), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }

  ; ---------- UIA_LegacyIAccessiblePattern methods ----------

  Select(flags:=3) {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "int",flags))
  }
  DoDefaultAction() {
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value))
  }
  SetValue(value) {
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr",&value))
  }
  GetCurrentSelection() { ; UNTESTED
    local
    return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "ptr*",out:=""))? UIA_ElementArray(out):
  }
  ;~ GetCachedSelection	24	IUIAutomationElementArray
  GetIAccessible() {
  /*	This method returns NULL if the underlying implementation of the UI Automation element is not a native 
  Microsoft Active Accessibility server; that is, if a client attempts to retrieve the IAccessible interface 
  for an element originally supported by a proxy object from OLEACC.dll, or by the UIA-to-MSAA Bridge.
  */
    local
    return UIA_Hr(DllCall(this.__Vt(26), "ptr",this.__Value, "ptr*",pacc:=""))&&pacc? ComObj(9,pacc,1):
  }
}

/*
  Provides access to a control that can switch between multiple representations of the same information or set of child controls.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationmultipleviewpattern
*/
class UIA_MultipleViewPattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696099
  static	__IID := "{8d253c91-1dc5-4bb5-b18f-ade16fa495e8}"
    ,	__PatternID := 10008

  ; ---------- UIA_MultipleViewPattern properties ----------

  CurrentCurrentView[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCurrentView[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_MultipleViewPattern methods ----------

  GetViewName(view) { ; need to release BSTR?
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "int",view, "ptr*",out:=""))? StrGet(out) (DllCall("oleaut32\SysFreeString", "ptr", out)?"":""):
  }
  SetCurrentView(view) {
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "int",view))
  }
  GetCurrentSupportedViews() {
    local
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))? UIA_SafeArrayToAHKArray(ComObj(0x2003,out,1)):
  }
  GetCachedSupportedViews() {
    local
    return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))? UIA_SafeArrayToAHKArray(ComObj(0x2003,out,1)):
  }
}

/*
  Provides access to a control that presents a range of values.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationrangevaluepattern
*/
class UIA_RangeValuePattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696147
  static	__IID := "{59213f4f-7346-49e5-b120-80555987a148}"
    ,	__PatternID := 10003

  ; ---------- UIA_RangeValuePattern properties ----------

  CurrentValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "Double*",out:=""))?out:
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "double",value))
    }
  }
  CurrentIsReadOnly[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentMaximum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "Double*",out:=""))?out:
    }
  }
  CurrentMinimum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentLargeChange[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentSmallChange[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedIsReadOnly[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedMaximum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedMinimum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedLargeChange[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedSmallChange[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }

  ; ---------- UIA_RangeValuePattern methods ----------

  SetValue(val) {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "double",val))
  }
}

/*
  Exposes a method that enables an item in a scrollable view to be placed in a visible portion of the view.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationscrollitempattern
*/
class UIA_ScrollItemPattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696165
  static	__IID := "{b488300f-d015-4f19-9c29-bb595e3645ef}"
    ,	__PatternID := 10017

  ScrollIntoView() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
}

/*
  Provides access to a control that acts as a scrollable container for a collection of child elements. The children of this element support IUIAutomationScrollItemPattern.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationscrollpattern
*/
class UIA_ScrollPattern extends UIA_Base {
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee696167
  static	__IID := "{88f4d42a-e881-459d-a77c-73bbbb7e02dc}"
    ,	__PatternID := 10004

  ; ---------- UIA_ScrollPattern properties ----------

  CurrentHorizontalScrollPercent[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentVerticalScrollPercent[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentHorizontalViewSize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentVerticalViewSize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentHorizontallyScrollable[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentVerticallyScrollable[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedHorizontalScrollPercent[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedVerticalScrollPercent[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedHorizontalViewSize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedVerticalViewSize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedHorizontallyScrollable[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedVerticallyScrollable[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_ScrollPattern methods ----------
    
  Scroll(horizontal:=-1, vertical:=-1) { ; Default is ScrollAmount_NoAmount
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "uint",horizontal, "uint",vertical))
  }
  SetScrollPercent(horizontal:=-1, vertical:=-1) { ; Default is ScrollAmount_NoAmount
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "double",horizontal, "double",vertical))
  }
  /*	UIA_ScrollPatternNoScroll	=	-1
    ScrollAmount_LargeDecrement	= 0,
    ScrollAmount_SmallDecrement	= 1,
    ScrollAmount_NoAmount	= 2,
    ScrollAmount_LargeIncrement	= 3,
    ScrollAmount_SmallIncrement	= 4
  */
}

/*
  Provides access to the selectable child items of a container control that supports SelectionPattern
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationselectionitempattern
*/
class UIA_SelectionItemPattern extends UIA_Base { ; UNTESTED
  static	__IID := "{A8EFA66A-0FDA-421A-9194-38021F3578EA}"
    ,	__PatternID := 10010

  ; ---------- UIA_SelectionItemPattern properties ----------

  CurrentIsSelected[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentSelectionContainer[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CachedIsSelected[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedSelectionContainer[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }

  ; ---------- UIA_SelectionItemPattern methods ----------

  Select() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
  AddToSelection() {
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value))
  }
  RemoveFromSelection() {
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value))
  }
}

/*
  Provides access to a control that contains selectable child items. The children of this element support SelectionItemPattern.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationselectionpattern
*/
class UIA_SelectionPattern extends UIA_Base {
  static	__IID := "{5ED5202E-B2AC-47A6-B638-4B0BF140D78E}"
    ,	__PatternID := 10001

  ; ---------- UIA_SelectionPattern properties ----------

  CurrentCanSelectMultiple[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsSelectionRequired[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCanSelectMultiple[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsSelectionRequired[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_SelectionPattern methods ----------

  GetCurrentSelection() { ; Returns an array of selected elements
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCachedSelection() {
    local
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
}

class UIA_SelectionPattern2 extends UIA_SelectionPattern { ; UNTESTED
  static	__IID := "{0532bfae-c011-4e32-a343-6d642d798555}"
    ,	__PatternID := 10034

  ; ---------- UIA_SelectionPattern2 properties ----------

  CurrentFirstSelectedItem[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CurrentLastSelectedItem[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CurrentCurrentSelectedItem[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CurrentItemCount[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedFirstSelectedItem[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CachedLastSelectedItem[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CachedCurrentSelectedItem[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CachedItemCount[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
}

/*
  Enables a client application to retrieve information about an item (cell) in a spreadsheet. 
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationspreadsheetitempattern
*/
class UIA_SpreadsheetItemPattern extends UIA_Base { ; UNTESTED
  static	__IID := "{7D4FB86C-8D34-40E1-8E83-62C15204E335}"
    ,	__PatternID := 10027

  ; ---------- UIA_SpreadsheetItemPattern properties ----------

  CurrentFormula[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedFormula[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }

  ; ---------- UIA_SpreadsheetItemPattern methods ----------

  GetCurrentAnnotationObjects() {
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCurrentAnnotationTypes() {
    local
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr", UIA_Variant(out:="")))?UIA_VariantData(out):UIA_VariantClear(out)
  }
  GetCachedAnnotationObjects() {
    local
    return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCachedAnnotationTypes() {
    local
    return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr", UIA_Variant(out:="")))?UIA_VariantData(out):UIA_VariantClear(out)
  }
}

/*
  Enables a client application to access the items (cells) in a spreadsheet
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationspreadsheetpattern
*/
class UIA_SpreadsheetPattern extends UIA_Base { ; UNTESTED
  static	__IID := "{7517A7C8-FAAE-4DE9-9F08-29B91E8595C1}"
    ,	__PatternID := 10026

  GetItemByName(name) {
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr", &name, "ptr*",out:=""))? UIA_Element(out):
  }
}

/*
  Enables Microsoft UI Automation clients to retrieve the visual styles associated with an element in a document.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationstylespattern
*/
class UIA_StylesPattern extends UIA_Base { ; UNTESTED
  static	__IID := "{85B5F0A2-BD79-484A-AD2B-388C9838D5FB}"
    ,	__PatternID := 10025

  ; ---------- UIA_StylesPattern properties ----------

  CurrentStyleId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentStyleName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentFillColor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentFillPatternStyle[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentShape[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentFillPatternColor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentExtendedProperties[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedStyleId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedStyleName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedFillColor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedFillPatternStyle[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedShape[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedFillPatternColor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedExtendedProperties[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(17), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_StylesPattern methods ----------

  GetCurrentExtendedPropertiesAsArray(byref propertyCount) {
    local
    return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*", propertyArray:="", "int*", propertyCount:=""))?UIA_SafeArrayToAHKArray(ComObj(0x2003,propertyArray,1)):
  }
  GetCachedExtendedPropertiesAsArray(byref propertyCount) {
    local
    return UIA_Hr(DllCall(this.__Vt(18), "ptr",this.__Value, "ptr*", propertyArray:="", "int*", propertyCount:=""))?UIA_SafeArrayToAHKArray(ComObj(0x2003,propertyArray,1)):
  }
}

/*
  Provides access to the keyboard or mouse input of a control.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationsynchronizedinputpattern
*/
class UIA_SynchronizedInputPattern extends UIA_Base { ; UNTESTED
  static	__IID := "{2233BE0B-AFB7-448B-9FDA-3B378AA5EAE1}"
    ,	__PatternID := 10021

  StartListening(inputType) {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "int",inputType))
  }
  Cancel() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
}

/*
  Provides access to a child element in a container that supports TablePattern
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtableitempattern
*/
class UIA_TableItemPattern extends UIA_Base {
  static	__IID := "{0B964EB3-EF2E-4464-9C79-61D61737A27E}"
    ,	__PatternID := 10013

  GetCurrentRowHeaderItems() {
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCurrentColumnHeaderItems() {
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCachedRowHeaderItems() {
    local
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCachedColumnHeaderItems() {
    local
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
}

/*
  Provides access to a control that acts as a container for a collection of child elements. The children of this element support TableItemPattern and are organized in a two-dimensional logical coordinate system that can be traversed by row and column.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtablepattern
*/
class UIA_TablePattern extends UIA_Base {
  static	__IID := "{620E691C-EA96-4710-A850-754B24CE2417}"
    ,	__PatternID := 10012

  ; ---------- UIA_TablePattern properties ----------

  CurrentRowOrColumnMajor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedRowOrColumnMajor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_TablePattern methods ----------

  GetCurrentRowHeaders() {
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCurrentColumnHeaders() {
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCachedRowHeaders() {
    local
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCachedColumnHeaders() {
    local
    return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
}

/*
  Provides access to a control that contains text. Note that TextPattern nor TextRange can't be used to change the text itself, only to get information about the text or select text. To change the text, UIA_Element.SetValue(val) can be used.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtextpattern
*/
class UIA_TextPattern extends UIA_Base {
  static	__IID := "{32EBA289-3583-42C9-9C59-3B6D9A1E9B6A}"
    ,	__PatternID := 10014

  ; ---------- UIA_TextPattern properties ----------

  ; DocumentRange returns a TextRange that encloses the main text of a document.
  DocumentRange[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?UIA_TextRange(out):
    }
  }
  SupportedTextSelection[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_TextPattern methods ----------

  ; Retrieves an empty TextRange nearest to the specified screen coordinates
  RangeFromPoint(x, y) { 
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "int64",x&0xFFFFFFFF|y<<32, "ptr*",out:=""))?UIA_TextRange(out):
  }
  ; Retrieves a text range enclosing a child element such as an image, hyperlink, Microsoft Excel spreadsheet, or other embedded object.
  RangeFromChild(child) { 
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr",child.__Value, "ptr*",out:=""))?UIA_TextRange(out):
  }
  ; Returns the currently selected text
  GetSelection() { 
    local
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?UIA_TextRangeArray(out):
  }
  ; Retrieves an array of disjoint text ranges from a text-based control where each text range represents a contiguous span of visible text
  GetVisibleRanges() { 
    local
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_TextRangeArray(out):
  }
}

class UIA_TextPattern2 extends UIA_TextPattern {
  static	__IID := "{506A921A-FCC9-409F-B23B-37EB74106872}"
    ,	__PatternID := 10024

  RangeFromAnnotation(annotation) {
    local
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr", annotation.__Value, "ptr*",out:=""))?UIA_TextRange(out):
  }
  GetCaretRange(ByRef isActive:="") {
    local
    return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*", isActive, "ptr*",out:=""))?UIA_TextRange(out):
  }
}

/*
  Provides access to a control that modifies text, for example a control that performs auto-correction or enables input composition through an Input Method Editor (IME).
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtexteditpattern
*/
class UIA_TextEditPattern extends UIA_TextPattern { ; UNTESTED
  static	__IID := "{17E21576-996C-4870-99D9-BFF323380C06}"
    ,	__PatternID := 10032

  GetActiveComposition() {
    local
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?UIA_TextRange(out):
  }
  GetConversionTarget() {
    local
    return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?UIA_TextRange(out):
  }
}

/*
  Provides access a text-based control (or an object embedded in text) that is a child or descendant of another text-based control.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtextchildpattern
*/
class UIA_TextChildPattern extends UIA_Base { ; UNTESTED
  static	__IID := "{6552B038-AE05-40C8-ABFD-AA08352AAB86}"
    ,	__PatternID := 10029

  ; ---------- UIA_TextChildPattern properties ----------

  TextContainer[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  TextRange[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?UIA_TextRange(out):
    }
  }
}

/*
  Provides access to a control that can cycle through a set of states, and maintain a state after it is set.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtogglepattern
*/
class UIA_TogglePattern extends UIA_Base
{
    ; https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtogglepattern
    static __IID := "{94cf8058-9b8d-4ab9-8bfd-4cd0a33c8c70}"
  , __PatternID := 10015

  ; ---------- UIA_TogglePattern properties ----------

  CurrentToggleState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
    set { ; Custom
      if (this.CurrentToggleState != value)
        this.Toggle()
    }
  }
  CachedToggleState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_TogglePattern methods ----------

    Toggle() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
    }
}

/*
  Provides access to a control that can be moved, resized, or rotated.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtransformpattern 
*/
class UIA_TransformPattern extends UIA_Base {
  static	__IID := "{A9B55844-A55D-4EF0-926D-569C16FF89BB}"
    ,	__PatternID := 10016

  ; ---------- UIA_TransformPattern properties ----------

  CurrentCanMove[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentCanResize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentCanRotate[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCanMove[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCanResize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCanRotate[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_TransformPattern methods ----------

  Move(x, y) {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "double",x, "double",y))
  }
  Resize(w, h) {
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "double",w, "double",h))
  }
  Rotate(degrees) {
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "double",degrees))
  }
}

class UIA_TransformPattern2 extends UIA_TransformPattern { ; UNTESTED 
  static	__IID := "{6D74D017-6ECB-4381-B38B-3C17A48FF1C2}"
    ,	__PatternID := 10028

  ; ---------- UIA_TransformPattern2 properties ----------

  CurrentCanZoom[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCanZoom[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentZoomLevel[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedZoomLevel[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(17), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentZoomMinimum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(18), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedZoomMinimum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(19), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CurrentZoomMaximum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(20), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }
  CachedZoomMaximum[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(21), "ptr",this.__Value, "double*",out:=""))?out:
    }
  }

  ; ---------- UIA_TransformPattern2 methods ----------

  Zoom(zoomValue) {
    return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "double",zoomValue))
  }
  ZoomByUnit(ZoomUnit) {
    return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "uint",ZoomUnit))
  }
}

/*
  Provides access to a control that presents a range of values.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationvaluepattern
*/
class UIA_ValuePattern extends UIA_Base {
  static	__IID := "{A94CD8B1-0844-4CD6-9D2D-640537AB39E9}"
    ,	__PatternID := 10002

  ; ---------- UIA_ValuePattern properties ----------

  CurrentValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
    set {
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr",&value))
    }
  }
  CurrentIsReadOnly[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedValue[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedIsReadOnly[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_ValuePattern methods ----------

  SetValue(val) {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr",&val))
  }
}

/*
  Represents a virtualized item, which is an item that is represented by a placeholder automation element in the Microsoft UI Automation tree.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationvirtualizeditempattern
*/
class UIA_VirtualizedItemPattern extends UIA_Base {
  static	__IID := "{6BA3D7A6-04CF-4F11-8793-A8D1CDE9969F}"
    ,	__PatternID := 10020

  Realize() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
}

/*
  Provides access to the fundamental functionality of a window.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationwindowpattern
*/
class UIA_WindowPattern extends UIA_Base {
  static __IID := "{0FAEF453-9208-43EF-BBB2-3B485177864F}"
    , __PatternID := 10009

  ; ---------- UIA_WindowPattern properties ----------

  CurrentCanMaximize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentCanMinimize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsModal[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentIsTopmost[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentWindowVisualState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentWindowInteractionState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCanMaximize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedCanMinimize[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsModal[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsTopmost[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedWindowVisualState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedWindowInteractionState[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(17), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_WindowPattern methods ----------

  Close() {
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value))
  }
  WaitForInputIdle(milliseconds) {
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "int",milliseconds, "Int*", out:=""))?out:
  }
  SetWindowVisualState(state) {
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "int",state))
  }
}

/*
  Provides access to the properties of an annotation in a document.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationannotationpattern
*/
class UIA_AnnotationPattern extends UIA_Base {	
  static __IID := "{9A175B21-339E-41B1-8E8B-623F6B681098}"
    , __PatternID := 10023

  ; ---------- UIA_AnnotationPattern properties ----------

  CurrentAnnotationTypeId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentAnnotationTypeName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentAuthor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentDateTime[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentTarget[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
  CachedAnnotationTypeId[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedAnnotationTypeName[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedAuthor[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedDateTime[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedTarget[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value, "ptr*",out:=""))?UIA_Element(out):
    }
  }
}

/*
  Provides access to information exposed by a UI Automation provider for an element that can be dragged as part of a drag-and-drop operation.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationdragpattern
*/
class UIA_DragPattern extends UIA_Base { ; UNTESTED, couldn't find a window that supported this
  static __IID := "{1DC7B570-1F54-4BAD-BCDA-D36A722FB7BD}"
    , __PatternID := 10030

  ; ---------- UIA_DragPattern properties ----------

  CurrentIsGrabbed[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CachedIsGrabbed[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }
  CurrentDropEffect[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedDropEffect[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentDropEffects[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(7), "ptr",this.__Value, "ptr",UIA_Variant(out:="")))&&out?UIA_VariantData(out):UIA_VariantClear(out)
    }
  }
  CachedDropEffects[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value, "ptr",UIA_Variant(out:="")))&&out?UIA_VariantData(out):UIA_VariantClear(out)
    }
  }

  ; ---------- UIA_DragPattern methods ----------
  GetCurrentGrabbedItems() {
    local
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetCachedGrabbedItems() {
    local
    return UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
}

/*
  Provides access to drag-and-drop information exposed by a Microsoft UI Automation provider for an element that can be the drop target of a drag-and-drop operation.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationdroptargetpattern
*/
class UIA_DropTargetPattern extends UIA_Base { ; UNTESTED
  static __IID := "{69A095F7-EEE4-430E-A46B-FB73B1AE39A5}"
    , __PatternID := 10031

  ; ---------- UIA_DropTargetPattern properties ----------

  CurrentDropTargetEffect[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CachedDropTargetEffect[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "ptr*",out:=""))?UIA_GetBSTRValue(out):
    }
  }
  CurrentDropTargetEffects[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value, "ptr",UIA_Variant(out:="")))&&out?UIA_VariantData(out):UIA_VariantClear(out)
    }
  }
  CachedDropTargetEffects[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value, "ptr",UIA_Variant(out:="")))&&out?UIA_VariantData(out):UIA_VariantClear(out)
    }
  }
}

/*
  Provides access to the underlying object model implemented by a control or application.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationobjectmodelpattern
*/
class UIA_ObjectModelPattern extends UIA_Base {			; Windows 8 [desktop apps only]
  ;~ http://msdn.microsoft.com/en-us/library/windows/desktop/hh437262(v=vs.85).aspx
  static	__IID := "{71c284b3-c14d-4d14-981e-19751b0d756d}"
    ,	__PatternID := 10022
  GetUnderlyingObjectModel() { ; UNTESTED. Returns IUnknown interface used to access the underlying object model of the provider.
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
  }
}

;~ class UIA_PatternHandler extends UIA_Base {
;~ class UIA_PatternInstance extends UIA_Base {

/*
  Provides access to a span of continuous text in a container that supports the TextPattern interface. TextRange can be used to select, compare, and retrieve embedded objects from the text span. The interface uses two endpoints to delimit where the text span starts and ends. Disjoint spans of text are represented by a TextRangeArray, which is an array of TextRange interfaces.
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtextrange
*/
class UIA_TextRange extends UIA_Base {
  static __IID := "{A543CC6A-F4AE-494B-8239-C814481187A8}"

  ; Returns a copy of the TextRange (retrieves a new IUIAutomationTextRange identical to the original and inheriting all properties of the original).
  Clone() { 
    local
    return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?UIA_TextRange(out):
  }
  ; Compares whether this TextRange has the same endpoints as comparisonTextRange
  Compare(comparisonTextRange) { 
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value,"ptr",comparisonTextRange.__Value, "ptr*",out:=""))?out:
  }
  ; Retrieves a value that specifies whether the start or end endpoint of this text range is the same as the start or end endpoint of comparisonTextRange. Returns a negative value if the caller's endpoint occurs earlier in the text than the target endpoint; 0 if the caller's endpoint is at the same location as the target endpoint; or a positive value if the caller's endpoint occurs later in the text than the target endpoint. srcEndPoint and targetEndPoint need to be TextPatternRangeEndpoint enums.
  CompareEndPoints(srcEndPoint, comparisonTextRange, targetEndPoint) { 
    local
    return UIA_Hr(DllCall(this.__Vt(5), "ptr",this.__Value,"int", srcEndPoint,"ptr",comparisonTextRange.__Value, "int", targetEndPoint,"ptr*",out:=""))?out:
  }
  ; Normalizes the text range by the specified text unit. The range is expanded if it is smaller than the specified unit, or shortened if it is longer than the specified unit. unit needs to be a TextUnit enum (default is TextUnit_Document == 6)
  ExpandToEnclosingUnit(unit:=6) { 
    return UIA_Hr(DllCall(this.__Vt(6), "ptr",this.__Value,"int",unit))
  }
  ; Retrieves a text range subset that has the specified text attribute value. attr needs to be a UIA_TextAttributeId enum, and val the desired value (some can be strings, others text attribute enums such as BulletStyle enum)
  FindAttribute(attr, val, backward:=False) { 
    local var, out
    if attr is not integer
      attr := UIA_Enum.UIA_AttributeId(attr)
    var := UIA_ComVar(UIA_Enum.UIA_AttributeVariantType(attr), val)
    return UIA_Hr((A_PtrSize == 4) ? DllCall(this.__Vt(7), "ptr",this.__Value,"int",attr,"int64",NumGet(var.ptr+0, 0, "int64"),"int64",NumGet(var.ptr+0, 8, "int64"),"int",backward, "ptr*",out:="") : DllCall(this.__Vt(7), "ptr",this.__Value,"int",attr,"ptr",var.ptr,"int",backward,"ptr*",out:=""))?UIA_TextRange(out):
  }
  ; Retrieves a text range subset that contains the specified text.
  FindText(text, backward:=False, ignoreCase:=False) { 
    local
    return UIA_Hr(DllCall(this.__Vt(8), "ptr",this.__Value,"ptr", &text,"int",backward, "int", ignoreCase,"ptr*",out:=""))?UIA_TextRange(out):
  }					
  ; Retrieves the value of the specified text attribute across the entire text range. attr needs to be a UIA_TextAttributeId enum.
  GetAttributeValue(attr) { 
    local
    return UIA_Hr(DllCall(this.__Vt(9), "ptr",this.__Value,"int", attr,"ptr",UIA_Variant(out:="")))?UIA_VariantData(out):UIA_VariantClear(out)
  }
  ; Returns an array of bounding rectangle objects {x:top left X-coord,y:top left Y-coord,w:width,h:height} for each fully or partially visible line of text in a text range.
  GetBoundingRectangles() { 
    local
    static b:={__Class:"object",__Type:"RECT",Struct:Func("UIA_RectStructure")}
    if UIA_Hr(DllCall(this.__Vt(10), "ptr",this.__Value,"ptr*",out:="")) {
      DllCall("oleaut32\SafeArrayGetVartype", "ptr", out, "ushort*", baseType:="")
      sa := UIA_GetSafeArrayValue(out, baseType), retArr := []
      Loop, % sa.MaxIndex() / 4
        retArr.Push({x:Floor(sa[4*(A_Index-1)+1]),y:Floor(sa[4*(A_Index-1)+2]),w:Floor(sa[4*(A_Index-1)+3]),h:Floor(sa[4*(A_Index-1)+4]),base:b})
      return retArr
    }
  }
  ; Returns the innermost UI Automation element that encloses the text range.
  GetEnclosingElement() { 
    local
    return UIA_Hr(DllCall(this.__Vt(11), "ptr",this.__Value,"ptr*",out:=""))?UIA_Element(out):
  }
  ; Returns the plain text of the text range. maxLength is the maximum length of the string to return, or -1 if no limit is required.
  GetText(maxLength:=-1) { 
    local
    return UIA_Hr(DllCall(this.__Vt(12), "ptr",this.__Value,"int", maxLength,"ptr*",out:=""))?StrGet(out) (DllCall("oleaut32\SysFreeString", "ptr", out)?"":""):
  }
  ; Moves the text range forward or backward by the specified number of text units. unit needs to be a TextUnit enum.
  Move(unit, count) { 
    local
    return UIA_Hr(DllCall(this.__Vt(13), "ptr",this.__Value,"int", unit,"int",count, "ptr*",out:=""))?out:
  }
  ; Moves one endpoint of the text range the specified number of text units within the document range. endpoint needs to be TextPatternRangeEndpoint enum. unit needs to be a TextUnit enum.
  MoveEndpointByUnit(endpoint, unit, count) { 
    local
    return UIA_Hr(DllCall(this.__Vt(14), "ptr",this.__Value,"int", endpoint,"int", unit, "int", count, "ptr*",out:=""))?out:
  }
  ; Moves one endpoint of the current text range to the specified endpoint of a second text range. srcEndPoint and targetEndPoint need to be TextPatternRangeEndpoint enums.
  MoveEndpointByRange(srcEndPoint, range, targetEndPoint) { 
    local
    return UIA_Hr(DllCall(this.__Vt(15), "ptr",this.__Value,"int", srcEndPoint,"ptr",range.__Value, "int", targetEndPoint,"ptr*",out:=""))
  }
  ; Selects the span of text that corresponds to this text range, and removes any previous selection.
  Select() { 
    return UIA_Hr(DllCall(this.__Vt(16), "ptr",this.__Value))
  }
  ; Adds the text range to the collection of selected text ranges in a control that supports multiple, disjoint spans of selected text.
  AddToSelection() { 
    return UIA_Hr(DllCall(this.__Vt(17), "ptr",this.__Value))
  }
  ; Removes the text range from an existing collection of selected text in a text container that supports multiple, disjoint selections.
  RemoveFromSelection() { 
    return UIA_Hr(DllCall(this.__Vt(18), "ptr",this.__Value))
  }
  ; Causes the text control to scroll until the text range is visible in the viewport. alignToTop is a boolean value.
  ScrollIntoView(alignToTop) { 
    local
    return UIA_Hr(DllCall(this.__Vt(19), "ptr",this.__Value,"int", alignToTop))
  }
  ; Retrieves a collection of all embedded objects that fall within the text range.
  GetChildren() { 
    local
    return UIA_Hr(DllCall(this.__Vt(20), "ptr",this.__Value,"ptr*",out:=""))?UIA_ElementArray(out):
  }
}

class UIA_TextRange2 extends UIA_TextRange {
  static __IID := "{BB9B40E0-5E04-46BD-9BE0-4B601B9AFAD4}"

  ShowContextMenu() {
    local
    return UIA_Hr(DllCall(this.__Vt(21), "ptr",this.__Value,"ptr*",out:=""))
  }
}
class UIA_TextRange3 extends UIA_TextRange2 { ; UNTESTED
  static __IID := "{6A315D69-5512-4C2E-85F0-53FCE6DD4BC2}"

  GetEnclosingElementBuildCache(cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(22), "Ptr", this.__Value, "Ptr", cacheRequest.__Value, "ptr*",out:=""))?UIA_Element(out):
  }
  GetChildrenBuildCache(cacheRequest) {
    local
    return UIA_Hr(DllCall(this.__Vt(23), "Ptr", this.__Value, "Ptr", cacheRequest.__Value, "ptr*",out:=""))?UIA_ElementArray(out):
  }
  GetAttributeValues(attributeIds, attributeIdCount) { ; currently returns a AHK array
    local
    if ComObjValue(attributeIds)&0x2000
      SafeArray:=attributeIds
    else {
      SafeArray:=ComObj(0x2003,DllCall("oleaut32\SafeArrayCreateVector", "uint",13, "uint",0, "uint",attributeIds.MaxIndex()),1)
      for i,c in attributeIds
        SafeArray[A_Index-1]:=c.__Value, ObjAddRef(c.__Value) ; AddRef - SafeArrayDestroy will release UIA_Conditions - they also release themselves
    }
    return UIA_Hr(DllCall(this.__Vt(24), "ptr",this.__Value, "ptr", ComObjValue(SafeArray), "int", attributeIdCount, "ptr*",out:=""))? UIA_SafeArrayToAHKArray(ComObj(0x2003,out,1)):
  }
}

/*
  Represents a collection (array) of TextRange objects
  Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationtextrangearray
*/
class UIA_TextRangeArray extends UIA_Base {
  static __IID := "{CE4AE76A-E717-4C98-81EA-47371D028EB6}"

  ; ---------- UIA_TextRangeArray properties ----------

  Length[] {
    get {
      local
      return UIA_Hr(DllCall(this.__Vt(3), "ptr",this.__Value, "ptr*",out:=""))?out:
    }
  }

  ; ---------- UIA_TextRangeArray methods ----------
  
  GetElement(i) {
    local
    return UIA_Hr(DllCall(this.__Vt(4), "ptr",this.__Value, "int",i, "ptr*",out:=""))?UIA_TextRange(out):
  }
}

;~ UIA Functions

/*
  UIAInterface function initializes the UIAutomation interface and returns a UIA_Interface object. After calling this function, all UIA_Interface class properties and methods can be accessed through the returned object. 
    maxVersion can be used to limit the UIA_Interface version being created. By default the highest version available is used (usually IUIAutomation7 interface). 
    Specifiying maxVersion:=2 would try to initialize IUIAutomation2 interface, and if that fails then IUIAutomation interface.
  In addition some extra variables are initialized: 
    CurrentVersion contains the version number of IUIAutomation interface
    TrueCondition contains a UIA_TrueCondition
    TreeWalkerTrue contains an UIA_TreeWalker that was created with UIA_TrueCondition
  On subsequent calls of UIA_Interface(), the previously created UIA interface object is returned to avoid multiple connections being made. To bypass this, specify a maxVersion
  Note that a new UIA_Interface object can't be created with the "new" keyword. 
*/
UIA_Interface(maxVersion:="", activateScreenReader:=1) {
  local max, uiaBase, e 
  static uia := "", cleanup := ""
  if (IsObject(uia) && (maxVersion == ""))
    return uia
  if (!IsObject(cleanup))
    cleanup := new UIA_Cleanup(activateScreenReader)
  ; enable screenreader flag if disabled
  max := (maxVersion?maxVersion:UIA_Enum.UIA_MaxVersion_Interface)+1
  while (--max) {
      
    if (!IsObject(UIA_Interface%max%) || (max == 1))
      continue

    try {
      if uia:=ComObjCreate("{e22ad333-b25f-460c-83d0-0581107395c9}",UIA_Interface%max%.__IID) {
        uia:=new UIA_Interface%max%(uia, 1, max), uiaBase := uia.base
        Loop, %max%
          uiaBase := uiaBase.base
        uiaBase.__UIA:=uia, uiaBase.TrueCondition:=uia.CreateTrueCondition(), uiaBase.TreeWalkerTrue := uia.CreateTreeWalker(uiaBase.TrueCondition)
        return uia
      }
    }
  }
  ; If all else fails, try the first IUIAutomation version
  try {
    if uia:=ComObjCreate("{ff48dba4-60ef-4201-aa87-54103eef594e}","{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
      return uia:=new UIA_Interface(uia, 1, 1), uia.base.base.__UIA:=uia, uia.base.base.CurrentVersion:=1, uia.base.base.TrueCondition:=uia.CreateTrueCondition(), uia.base.base.TreeWalkerTrue := uia.CreateTreeWalker(uia.base.base.TrueCondition)
    throw "UIAutomation Interface failed to initialize."
  } catch e
    MsgBox, 262160, UIA Startup Error, % IsObject(e)?"IUIAutomation Interface is not registered.":e.Message
  return
}
class UIA_Cleanup {
  __New(screenreader) {
    this.ScreenReaderActivate := screenreader, this.ScreenReaderStartingState := UIA_GetScreenReader()
    if (this.ScreenReaderActivate && !this.ScreenReaderStartingState)
      UIA_SetScreenReader(1)
  }
  __Delete() {
    if (this.ScreenReaderActivate)
      UIA_SetScreenReader(this.ScreenReaderStartingState)
  }
}
UIA_GetScreenReader() {
  local screenreader := 0
  if (A_PtrSize = 4)
    DllCall("user32.dll\SystemParametersInfo", "uint", 0x0046, "uint", 0, "ptr*", screenreader, "uint", 0)
  else
    DllCall("user32.dll\SystemParametersInfo", "uint", 0x0046, "uint", 0, "ptr*", screenreader) ; SPI_GETSCREENREADER
  return screenreader
}
UIA_SetScreenReader(state, fWinIni:=2) {
  DllCall("user32.dll\SystemParametersInfo", "uint", 0x0047, "uint", state, "ptr", 0, "uint", fWinIni) ; SPI_SETSCREENREADER
}
; Converts an error code to the corresponding error message
UIA_Hr(hr) {
  local
  ;~ http://blogs.msdn.com/b/eldar/archive/2007/04/03/a-lot-of-hresult-codes.aspx
  static err:={0x8000FFFF:"Catastrophic failure.",0x80004001:"Not implemented.",0x8007000E:"Out of memory.",0x80070057:"One or more arguments are not valid.",0x80004002:"Interface not supported.",0x80004003:"Pointer not valid.",0x80070006:"Handle not valid.",0x80004004:"Operation aborted.",0x80004005:"Unspecified error.",0x80070005:"General access denied.",0x800401E5:"The object identified by this moniker could not be found.",0x80040201:"UIA_E_ELEMENTNOTAVAILABLE",0x80040200:"UIA_E_ELEMENTNOTENABLED",0x80131509:"UIA_E_INVALIDOPERATION",0x80040202:"UIA_E_NOCLICKABLEPOINT",0x80040204:"UIA_E_NOTSUPPORTED",0x80040203:"UIA_E_PROXYASSEMBLYNOTLOADED",0x80131505:"COR_E_TIMEOUT"} ; //not completed
  if hr&&(hr&=0xFFFFFFFF) {
    RegExMatch(Exception("",-2).what,"(\w+).(\w+)",i)
    throw Exception(UIA_Hex(hr) " - " err[hr], -2, i2 "  (" i1 ")")
  }
  return !hr
}
UIA_NotImplemented() {
  local
  RegExMatch(Exception("",-2).What,"(\D+)\.(\D+)",m)
  MsgBox, 262192, UIA Message, Class:`t%m1%`nMember:`t%m2%`n`nMethod has not been implemented yet.
}
; Used by UIA methods to create new UIA_Element objects of the highest available version. The highest version to try can be changed by modifying UIA_Enum.UIA_CurrentVersion_Element value.
UIA_Element(e,flag:=1) {
  local max, riid
  static v := "", previousVersion := ""
  if !e
    return
  if (previousVersion != UIA_Enum.UIA_CurrentVersion_Element) ; Check if the user wants an element with a different version
    v := ""
  else if v
    return (v==1)?new UIA_Element(e,flag,1):new UIA_Element%v%(e,flag,v)
  max := UIA_Enum.UIA_CurrentVersion_Element+1
  While (--max) {
    if UIA_GUID(riid, UIA_Element%max%.__IID)
      return new UIA_Element%max%(e,flag,v:=max)
  }
  return new UIA_Element(e,flag,v:=1)
}
; Used by UIA methods to create new UIA_TextRange objects of the highest available version. The highest version to try can be changed by modifying UIA_Enum.UIA_CurrentVersion_TextRange value.
UIA_TextRange(e,flag:=1) {
  local max, riid
  static v := "", previousVersion := ""
  if (previousVersion != UIA_Enum.UIA_CurrentVersion_TextRange) ; Check if the user wants an element with a different version
    v := ""
  else if v
    return (v==1)?new UIA_TextRange(e,flag,1):new UIA_TextRange%v%(e,flag,v)
  max := UIA_Enum.UIA_MaxVersion_TextRange+1
  While (--max) {
    if UIA_GUID(riid, UIA_TextRange%max%.__IID)
      return new UIA_TextRange%max%(e,flag,v:=max)
  }
  return new UIA_TextRange(e,flag,v:=1)
}
; Used by UIA methods to create new Pattern objects of the highest available version for a given pattern.
UIA_Pattern(p, el) {
  local i, patternName, patternAvailableId
  static maxPatternVersions := {Selection:2, Text:2, TextRange:3, Transform:2}
  if p is integer 
    return patternName := UIA_Enum.UIA_Pattern(p)
  else
    patternName := InStr(p, "Pattern") ? p : p "Pattern", i:=2
  
  Loop {
    i++
    if !(UIA_Enum.UIA_PatternId(patternName i) && IsObject(UIA_%patternName%%i%) && UIA_%patternName%%i%.__iid && UIA_%patternName%%i%.__PatternID)
      break
  }
  While (--i > 1) {
    if ((patternAvailableId := UIA_Enum["UIA_Is" patternName i "AvailablePropertyId"]) && el.GetCurrentPropertyValue(patternAvailableId))
      return patternName i
  }
  return patternName
}
; Used to fetch constants and enumerations from the UIA_Enum class. The "UIA_" part of a variable name can be left out (eg UIA_Enum("ButtonControlTypeId") will return 50000).
UIA_Enum(e) {
  if ObjHasKey(UIA_Enum, e)
    return UIA_Enum[e]
  else if ObjHasKey(UIA_Enum, "UIA_" e)
    return UIA_Enum["UIA_" e]
}
UIA_ElementArray(p, uia:="",flag:=1) { ; Should AHK Object be 0 or 1 based? Currently 1 based.
  local
  global UIA_ElementArray
  if !p
    return
  a:=new UIA_ElementArray(p,flag),out:=[]
  Loop % a.Length
    out[A_Index]:=a.GetElement(A_Index-1)
  return out, out.base:={UIA_ElementArray:a}
}
UIA_TextRangeArray(p, uia:="",flag:=1) { ; Should AHK Object be 0 or 1 based? Currently 1 based.
  local
  global UIA_TextRangeArray
  a:=new UIA_TextRangeArray(p,flag),out:=[]
  Loop % a.Length
    out[A_Index]:=a.GetElement(A_Index-1)
  return out, out.base:={UIA_TextRangeArray:a}
}
UIA_RectToObject(ByRef r) { ; rect.__Value work with DllCalls?
  static b:={__Class:"object",__Type:"RECT",Struct:Func("UIA_RectStructure")}
  return {l:NumGet(r,0,"Int"),t:NumGet(r,4,"Int"),r:NumGet(r,8,"Int"),b:NumGet(r,12,"Int"),base:b}
}
UIA_RectStructure(this, ByRef r) {
  static sides:="ltrb"
  VarSetCapacity(r,16)
  Loop Parse, sides
    NumPut(this[A_LoopField],r,(A_Index-1)*4,"Int")
}
UIA_SafeArrayToAHKArray(safearray) {
  local
  b:={__Class:"object",__Type:"SafeArray",__Value:safearray}
  out := []
  for k in safearray
    out.Push(k)
  return out, out.base:=b
}
UIA_SafeArraysToObject(keys,values) {
;~	1 dim safearrays w/ same # of elements
  local
  out:={}
  for key in keys
    out[key]:=values[A_Index-1]
  return out
}
UIA_Hex(p) {
  local
  setting:=A_FormatInteger
  SetFormat,IntegerFast,H
  out:=p+0 ""
  SetFormat,IntegerFast,%setting%
  return out
}
UIA_GUID(ByRef GUID, sGUID) { ;~ Converts a string to a binary GUID and returns its address.
  if !sGUID
    return
  VarSetCapacity(GUID,16,0)
  return DllCall("ole32\CLSIDFromString", "wstr",sGUID, "ptr",&GUID)>=0?&GUID:""
}
UIA_Variant(ByRef var,type:=0,val:=0) {
  ; https://www.autohotkey.com/boards/viewtopic.php?t=6979
  static SIZEOF_VARIANT := 8 + (2 * A_PtrSize)
  VarSetCapacity(var, SIZEOF_VARIANT), ComObject(0x400C, &var)[] := type&&(type!=8)?ComObject(type,type=0xB?(!val?0:-1):val):val
  return &var ; The variant probably doesn't need clearing, because it is passed to UIA and UIA should take care of releasing it.
  ; Old implementation:
  ; return (VarSetCapacity(var,8+2*A_PtrSize)+NumPut(type,var,0,"short")+NumPut(type=8? DllCall("oleaut32\SysAllocString", "ptr",&val):val,var,8,"ptr"))*0+&var
}

UIA_ComVar(Type := 0xC, val:=0) {
    static base := { __Get: Func("ComVarGet"), __Set: Func("ComVarSet")
  , __Delete: Func("ComVarDel") }
  cv := {base: base}
    cv.SetCapacity("buf", 24), ptr := cv.GetAddress("buf")
    NumPut(0, NumPut(0, ptr+0, "int64"), "int64")
  cv.ref := ComObject(0x400C, ptr)
  cv.ref[] := (type!=0xC)&&(type!=8)?ComObject(type,type=0xB?(!val?0:-1):val):val
  cv.ptr := ComObjValue(cv.ref)
  return cv
}
ComVarGet(cv, p*) { ; Called when script accesses an unknown field.
    if p.MaxIndex() = "" ; No name/parameters, i.e. cv[]
        return cv.ref[]
}
ComVarSet(cv, v, p*) { ; Called when script sets an unknown field.
    if p.MaxIndex() = "" ; No name/parameters, i.e. cv[]:=v
        return cv.ref[] := v
}
ComVarDel(cv) { ; Called when the object is being freed.
    ; Depending on type, this may be needed to free the value, if set.
    DllCall("oleaut32\VariantClear", "ptr", cv.GetAddress("buf"))
}

UIA_IsVariant(ByRef vt, ByRef type:="", offset:=0, flag:=1) {
  local
  size:=VarSetCapacity(vt),type:=NumGet(vt,offset,"UShort")
  return size>=16&&size<=24&&type>=0&&(type<=23||type|0x2000)
}
UIA_VariantType(type){
  static _:={2:[2,"short"]
  ,3:[4,"int"]
  ,4:[4,"float"]
  ,5:[8,"double"]
  ,0xA:[4,"uint"]
  ,0xB:[2,"short"]
  ,0x10:[1,"char"]
  ,0x11:[1,"uchar"]
  ,0x12:[2,"ushort"]
  ,0x13:[4,"uint"]
  ,0x14:[8,"int64"]
  ,0x15:[8,"uint64"]}
  return _.haskey(type)?_[type]:[A_PtrSize,"ptr"]
}
UIA_VariantData(ByRef p, flag:=1, offset:=0) {
  local
  if flag {
    var := !UIA_IsVariant(p,vt, offset)?"Invalid Variant":ComObject(0x400C, &p)[] ; https://www.autohotkey.com/boards/viewtopic.php?t=6979
    UIA_VariantClear(&p) ; Clears variant, except if it contains a pointer to an object (eg IDispatch). BSTR is automatically freed.
  } else {
    vt:=NumGet(p+0,offset,"UShort"), var := !(vt>=0&&(vt<=23||vt|0x2000))?"Invalid Variant":ComObject(0x400C, p)[]
    UIA_VariantClear(p)
  }
  return vt=11?-var:var ; Negate value if VT_BOOL (-1=True, 0=False)
  ; Old implementation, based on Sean's COM_Enumerate function
  ; return !UIA_IsVariant(p,vt, offset)?"Invalid Variant"
  ;		:vt=0?"" ; VT_EMPTY
  ;		:vt=3?NumGet(p,offset+8,"int")
  ;		:vt=8?StrGet(NumGet(p,offset+8))
  ;		:vt=11?-NumGet(p,offset+8,"short")
  ;		:vt=9||vt=13||vt&0x2000?ComObj(vt,NumGet(p,offset+8),flag)
  ;		:vt<0x1000&&UIA_VariantChangeType(&p,&p)=0?StrGet(NumGet(p,offset+8)) UIA_VariantClear(&p)
  ;		:NumGet(p,offset+8)
/*
  VT_EMPTY     =      0  		; No value
  VT_NULL      =      1 		; SQL-style Null
  VT_I2        =      2 		; 16-bit signed int
  VT_I4        =      3 		; 32-bit signed int
  VT_R4        =      4 		; 32-bit floating-point number
  VT_R8        =      5 		; 64-bit floating-point number
  VT_CY        =      6 		; Currency
  VT_DATE      =      7  		; Date
  VT_BSTR      =      8 		; COM string (Unicode string with length prefix)
  VT_DISPATCH  =      9 		; COM object 
  VT_ERROR     =    0xA  10	; Error code (32-bit integer)
  VT_BOOL      =    0xB  11	; Boolean True (-1) or False (0)
  VT_VARIANT   =    0xC  12	; VARIANT (must be combined with VT_ARRAY or VT_BYREF)
  VT_UNKNOWN   =    0xD  13	; IUnknown interface pointer
  VT_DECIMAL   =    0xE  14	; (not supported)
  VT_I1        =   0x10  16	; 8-bit signed int
  VT_UI1       =   0x11  17	; 8-bit unsigned int
  VT_UI2       =   0x12  18	; 16-bit unsigned int
  VT_UI4       =   0x13  19	; 32-bit unsigned int
  VT_I8        =   0x14  20	; 64-bit signed int
  VT_UI8       =   0x15  21	; 64-bit unsigned int
  VT_INT       =   0x16  22	; Signed machine int
  VT_UINT      =   0x17  23	; Unsigned machine int
  VT_RECORD    =   0x24  36	; User-defined type
  VT_ARRAY     = 0x2000  		; SAFEARRAY
  VT_BYREF     = 0x4000  		; Pointer to another type of value
          = 0x1000  4096

  COM_SysAllocString(str) {
    Return	DllCall("oleaut32\SysAllocString", "Uint", &str)
  }
  COM_SysFreeString(pstr) {
      DllCall("oleaut32\SysFreeString", "Uint", pstr)
  }
  COM_SysString(ByRef wString, sString) {
    VarSetCapacity(wString,4+nLen:=2*StrLen(sString))
    Return	DllCall("kernel32\lstrcpyW","Uint",NumPut(nLen,wString),"Uint",&sString)
  }
  DllCall("oleaut32\SafeArrayGetVartype", "ptr*",ComObjValue(SafeArray), "uint*",pvt)
  HRESULT SafeArrayGetVartype(
    _In_   SAFEARRAY *psa,
    _Out_  VARTYPE *pvt
  );
  DllCall("oleaut32\SafeArrayDestroy", "ptr",ComObjValue(SafeArray))
  HRESULT SafeArrayDestroy(
    _In_  SAFEARRAY *psa
  );
*/
}
UIA_VariantChangeType(pvarDst, pvarSrc, vt:=8) { ; written by Sean
  return DllCall("oleaut32\VariantChangeTypeEx", "ptr",pvarDst, "ptr",pvarSrc, "Uint",1024, "Ushort",0, "Ushort",vt)
}
UIA_VariantClear(pvar) { ; Written by Sean
  DllCall("oleaut32\VariantClear", "ptr",pvar)
}
UIA_GetSafeArrayValue(p,type,flag:=1){ ; Credit: https://github.com/neptercn/UIAutomation/blob/master/UIA.ahk
  local
  t:=UIA_VariantType(type),item:={},pv:=NumGet(p+8+A_PtrSize,"ptr")
  loop % NumGet(p+8+2*A_PtrSize,"uint") {
    item.Insert((type=8)?StrGet(NumGet(pv+(A_Index-1)*t.1,t.2),"utf-16"):NumGet(pv+(A_Index-1)*t.1,t.2))
  }
  if flag
    DllCall("oleaut32\SafeArrayDestroy","ptr", p)
  return item
}
UIA_GetBSTRValue(ByRef bstr) {
  local
  val := StrGet(bstr)
  DllCall("oleaut32\SysFreeString", "ptr", bstr)
  return val
}
/*
  UIA_CreateEventHandler(funcName, handlerType) returns a new handler object that can be used with methods that create EventHandlers (eg AddAutomationEventHandler)
    funcName: name of the function that will receive the calls when an event happens
    handlerType: needed by some of the newer Add...EventHandler functions. In the case of AddAutomationEventHandler, this should be left empty. For other Add...EventHandler cases, specify the ... part: FocusChanged, StructureChanged, TextEditTextChanged, Changes, Notification. So for AddFocusChangedEventHandler, set this value to "FocusChanged"
  
  The function funcName needs to be able to receive a certain number of arguments that depends on the type on handler being created:
    HandleAutomationEvent(sender, eventId)  <--- this is the most common handler type created with AddAutomationEventHandler, and the handler function needs to have exactly two arguments: sender (the element which sent the event), and eventId.
    HandleFocusChangedEvent(sender)
    HandlePropertyChangedEvent(sender, propertyId, newValue)
    HandleStructureChangedEvent(sender, changeType, runtimeId)
    HandleTextEditTextChangedEvent(sender, changeType, eventStrings)
    HandleChangesEvent(sender, uiaChanges, changesCount)
    HandleNotificationEvent(sender, notificationKind, notificationProcessing, displayString, activityId)
*/
UIA_CreateEventHandler(funcName, handlerType:="") { ; Possible handlerType values: empty, FocusChanged, StructureChanged, TextEditTextChanged, Changes, Notification.
  local handler, ptr
  if !(IsFunc(funcName) || IsObject(funcName)) ; Figuring out if the Object is callable is way too difficult to bother with. 
    throw Exception(funcName "is not a function!", -1)
  ptr := DllCall("GlobalAlloc", "UInt",0x40, "UInt",A_PtrSize*5, "Ptr" )
  handler := new _UIA_%handlerType%EventHandler(ptr,2,funcName) ; deref will be done on destruction of EventHandler. Function name piggybacks on the __Version property
  ,NumPut(ptr+A_PtrSize,ptr+0)
  ,NumPut(RegisterCallback("_UIA_QueryInterface","F"),ptr+0,A_PtrSize*1)
  ,NumPut(RegisterCallback("_UIA_AddRef","F"),ptr+0,A_PtrSize*2)
  ,NumPut(RegisterCallback("_UIA_Release","F"),ptr+0,A_PtrSize*3)
  ,NumPut(RegisterCallback("_UIA_" handlerType "EventHandler.Handle" (handlerType == "" ? "Automation" : handlerType) "Event","F",,&handler),ptr+0,A_PtrSize*4)
  return handler
}
_UIA_QueryInterface(pSelf, pRIID, pObj){ ; Credit: https://github.com/neptercn/UIAutomation/blob/master/UIA.ahk
  local
  DllCall("ole32\StringFromIID","ptr",pRIID,"ptr*",sz:=""),str:=StrGet(sz) ; sz should not be freed here
  return (str="{00000000-0000-0000-C000-000000000046}")||(str="{146c3c17-f12e-4e22-8c27-f894b9b79c69}")||(str="{40cd37d4-c756-4b0c-8c6f-bddfeeb13b50}")||(str="{e81d1b4e-11c5-42f8-9754-e7036c79f054}")||(str="{c270f6b5-5c69-4290-9745-7a7f97169468}")||(str="{92FAA680-E704-4156-931A-E32D5BB38F3F}")||(str="{58EDCA55-2C3E-4980-B1B9-56C17F27A2A0}")||(str="{C7CB2637-E6C2-4D0C-85DE-4948C02175C7}")?NumPut(pSelf,pObj+0)*0:0x80004002 ; E_NOINTERFACE
}
_UIA_AddRef(pSelf){
}
_UIA_Release(pSelf){
}


/*
  UIA_Enum contains UIA constants and enumerations. 
  
  There are multiple ways to access the constants:
  1) Use the returned object of UIA_Interface:
    After UIA := UIA_Interface()
    UIA.UIA_InvokePatternId would return the corresponding ID of 10000. Similarly UIA.TreeScope_Descendants would return 0x4
    If a property starts with "UIA_" then that part may be omitted: UIA.ButtonControlTypeId would return 50000.
    
    Calling UIA_Enum methods is also supported:
    UIA.UIA_EventId(20000) would return "ToolTipOpened"
  2) Use UIA_Enum prototype. This requires using exact property and method names:
    UIA_Enum.UIA_InvokePatternId
    UIA_Enum.UIA_PatternId(10000)
  
  3) Use a UIA_Enum object:
    After UIAc := new UIA_Enum
    UIAc.InvokePatternId returns 10000
    UIAc.PatternId(10000) returns "InvokePattern"
  
  4) Use the UIA_Enum function:
    UIA_Enum("ButtonControlTypeId") would return 50000
*/

class UIA_Enum { ; main source: https://github.com/Ixiko/AHK-libs-and-classes-collection/blob/master/libs/o-z/UIAutomationClient_1_0_64bit.ahk

  __Get(member) {
    if member not in base 
    {
      if ((SubStr(member, 1, 4) != "UIA_") && ObjHasKey(UIA_Enum, "UIA_" member)) {
        return this["UIA_" member]
      }
    }
    return UIA_Enum.member
  }
  __Call(member, params*) {
    if member not in base 
    {
      if ((SubStr(member, 1, 4) != "UIA_") && IsFunc("UIA_Enum.UIA_" member))
        return this["UIA_" member](params*)
    }
  }

  ; UIA_Interface specific enums, which define maximum available version numbers for interfaces (eg currently the highest version for UIA_Interface is 7). CurrentVersion specifies the version used by any new objects created, this can be changed dynamically.
  static UIA_MaxVersion_Interface := 7
  static UIA_MaxVersion_Element := 7
  static UIA_CurrentVersion_Element := 7
  static UIA_MaxVersion_TextRange := 3
  static UIA_CurrentVersion_TextRange := 3
  
  ; The following are not strictly enumerations but constants, it makes more sense to include them here
  ; module UIA_PatternIds
  static UIA_InvokePatternId := 10000
  static UIA_SelectionPatternId := 10001
  static UIA_ValuePatternId := 10002
  static UIA_RangeValuePatternId := 10003
  static UIA_ScrollPatternId := 10004
  static UIA_ExpandCollapsePatternId := 10005
  static UIA_GridPatternId := 10006
  static UIA_GridItemPatternId := 10007
  static UIA_MultipleViewPatternId := 10008
  static UIA_WindowPatternId := 10009
  static UIA_SelectionItemPatternId := 10010
  static UIA_DockPatternId := 10011
  static UIA_TablePatternId := 10012
  static UIA_TableItemPatternId := 10013
  static UIA_TextPatternId := 10014
  static UIA_TogglePatternId := 10015
  static UIA_TransformPatternId := 10016
  static UIA_ScrollItemPatternId := 10017
  static UIA_LegacyIAccessiblePatternId := 10018
  static UIA_ItemContainerPatternId := 10019
  static UIA_VirtualizedItemPatternId := 10020
  static UIA_SynchronizedInputPatternId := 10021
  static UIA_ObjectModelPatternId := 10022
  static UIA_AnnotationPatternId := 10023
  static UIA_TextPattern2Id := 10024
  static UIA_StylesPatternId := 10025
  static UIA_SpreadsheetPatternId := 10026
  static UIA_SpreadsheetItemPatternId := 10027
  static UIA_TransformPattern2Id := 10028
  static UIA_TextChildPatternId := 10029
  static UIA_DragPatternId := 10030
  static UIA_DropTargetPatternId := 10031
  static UIA_TextEditPatternId := 10032
  static UIA_CustomNavigationPatternId := 10033
  static UIA_SelectionPattern2Id := 10034 

  UIA_PatternId(n:="") {
    static name:={10000:"InvokePattern",10001:"SelectionPattern",10002:"ValuePattern",10003:"RangeValuePattern",10004:"ScrollPattern",10005:"ExpandCollapsePattern",10006:"GridPattern",10007:"GridItemPattern",10008:"MultipleViewPattern",10009:"WindowPattern",10010:"SelectionItemPattern",10011:"DockPattern",10012:"TablePattern",10013:"TableItemPattern",10014:"TextPattern",10015:"TogglePattern",10016:"TransformPattern",10017:"ScrollItemPattern",10018:"LegacyIAccessiblePattern",10019:"ItemContainerPattern",10020:"VirtualizedItemPattern",10021:"SynchronizedInputPattern",10022:"ObjectModelPattern",10023:"AnnotationPattern",10024:"TextPattern2",10025:"StylesPattern",10026:"SpreadsheetPattern",10027:"SpreadsheetItemPattern",10028:"TransformPattern2",10029:"TextChildPattern",10030:"DragPattern",10031:"DropTargetPattern",10032:"TextEditPattern",10033:"CustomNavigationPattern",10034:"SelectionPattern2"}, id:={InvokePattern:10000,SelectionPattern:10001,ValuePattern:10002,RangeValuePattern:10003,ScrollPattern:10004,ExpandCollapsePattern:10005,GridPattern:10006,GridItemPattern:10007,MultipleViewPattern:10008,WindowPattern:10009,SelectionItemPattern:10010,DockPattern:10011,TablePattern:10012,TableItemPattern:10013,TextPattern:10014,TogglePattern:10015,TransformPattern:10016,ScrollItemPattern:10017,LegacyIAccessiblePattern:10018,ItemContainerPattern:10019,VirtualizedItemPattern:10020,SynchronizedInputPattern:10021,ObjectModelPattern:10022,AnnotationPattern:10023,TextPattern2:10024,StylesPattern:10025,SpreadsheetPattern:10026,SpreadsheetItemPattern:10027,TransformPattern2:10028,TextChildPattern:10029,DragPattern:10030,DropTargetPattern:10031,TextEditPattern:10032,CustomNavigationPattern:10033,SelectionPattern2:10034}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n "Pattern")
      return id[n "Pattern"]
    else if ObjHasKey(id, n)
      return id[n]
    return id[RegexReplace(n, "(?:UIA_)?(.+?)(?:Id)?$", "$1")]
  }

  ; module UIA_EventIds
  static UIA_ToolTipOpenedEventId := 20000
  static UIA_ToolTipClosedEventId := 20001
  static UIA_StructureChangedEventId := 20002
  static UIA_MenuOpenedEventId := 20003
  static UIA_AutomationPropertyChangedEventId := 20004
  static UIA_AutomationFocusChangedEventId := 20005
  static UIA_AsyncContentLoadedEventId := 20006
  static UIA_MenuClosedEventId := 20007
  static UIA_LayoutInvalidatedEventId := 20008
  static UIA_Invoke_InvokedEventId := 20009
  static UIA_SelectionItem_ElementAddedToSelectionEventId := 20010
  static UIA_SelectionItem_ElementRemovedFromSelectionEventId := 20011
  static UIA_SelectionItem_ElementSelectedEventId := 20012
  static UIA_Selection_InvalidatedEventId := 20013
  static UIA_Text_TextSelectionChangedEventId := 20014
  static UIA_Text_TextChangedEventId := 20015
  static UIA_Window_WindowOpenedEventId := 20016
  static UIA_Window_WindowClosedEventId := 20017
  static UIA_MenuModeStartEventId := 20018
  static UIA_MenuModeEndEventId := 20019
  static UIA_InputReachedTargetEventId := 20020
  static UIA_InputReachedOtherElementEventId := 20021
  static UIA_InputDiscardedEventId := 20022
  static UIA_SystemAlertEventId := 20023
  static UIA_LiveRegionChangedEventId := 20024
  static UIA_HostedFragmentRootsInvalidatedEventId := 20025
  static UIA_Drag_DragStartEventId := 20026
  static UIA_Drag_DragCancelEventId := 20027
  static UIA_Drag_DragCompleteEventId := 20028
  static UIA_DropTarget_DragEnterEventId := 20029
  static UIA_DropTarget_DragLeaveEventId := 20030
  static UIA_DropTarget_DroppedEventId := 20031
  static UIA_TextEdit_TextChangedEventId := 20032
  static UIA_TextEdit_ConversionTargetChangedEventId := 20033
  static UIA_ChangesEventId := 20034
  static UIA_NotificationEventId := 20035
  static UIA_ActiveTextPositionChangedEventId := 20036

  UIA_EventId(n:="") {
    static id:={ToolTipOpened:20000,ToolTipClosed:20001,StructureChanged:20002,MenuOpened:20003,AutomationPropertyChanged:20004,AutomationFocusChanged:20005,AsyncContentLoaded:20006,MenuClosed:20007,LayoutInvalidated:20008,Invoke_Invoked:20009,SelectionItem_ElementAddedToSelection:20010,SelectionItem_ElementRemovedFromSelection:20011,SelectionItem_ElementSelected:20012,Selection_Invalidated:20013,Text_TextSelectionChanged:20014,Text_TextChanged:20015,Window_WindowOpened:20016,Window_WindowClosed:20017,MenuModeStart:20018,MenuModeEnd:20019,InputReachedTarget:20020,InputReachedOtherElement:20021,InputDiscarded:20022,SystemAlert:20023,LiveRegionChanged:20024,HostedFragmentRootsInvalidated:20025,Drag_DragStart:20026,Drag_DragCancel:20027,Drag_DragComplete:20028,DropTarget_DragEnter:20029,DropTarget_DragLeave:20030,DropTarget_Dropped:20031,TextEdit_TextChanged:20032,TextEdit_ConversionTargetChanged:20033,Changes:20034,Notification:20035,ActiveTextPositionChanged:20036}, name:={20000:"ToolTipOpened",20001:"ToolTipClosed",20002:"StructureChanged",20003:"MenuOpened",20004:"AutomationPropertyChanged",20005:"AutomationFocusChanged",20006:"AsyncContentLoaded",20007:"MenuClosed",20008:"LayoutInvalidated",20009:"Invoke_Invoked",20010:"SelectionItem_ElementAddedToSelection",20011:"SelectionItem_ElementRemovedFromSelection",20012:"SelectionItem_ElementSelected",20013:"Selection_Invalidated",20014:"Text_TextSelectionChanged",20015:"Text_TextChanged",20016:"Window_WindowOpened",20017:"Window_WindowClosed",20018:"MenuModeStart",20019:"MenuModeEnd",20020:"InputReachedTarget",20021:"InputReachedOtherElement",20022:"InputDiscarded",20023:"SystemAlert",20024:"LiveRegionChanged",20025:"HostedFragmentRootsInvalidated",20026:"Drag_DragStart",20027:"Drag_DragCancel",20028:"Drag_DragComplete",20029:"DropTarget_DragEnter",20030:"DropTarget_DragLeave",20031:"DropTarget_Dropped",20032:"TextEdit_TextChanged",20033:"TextEdit_ConversionTargetChanged",20034:"Changes",20035:"Notification",20036:"ActiveTextPositionChanged"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrReplace(StrReplace(n, "EventId"), "UIA_")]
  }

  ; module UIA_PropertyIds
  static UIA_RuntimeIdPropertyId := 30000
  static UIA_BoundingRectanglePropertyId := 30001
  static UIA_ProcessIdPropertyId := 30002
  static UIA_ControlTypePropertyId := 30003
  static UIA_LocalizedControlTypePropertyId := 30004
  static UIA_NamePropertyId := 30005
  static UIA_AcceleratorKeyPropertyId := 30006
  static UIA_AccessKeyPropertyId := 30007
  static UIA_HasKeyboardFocusPropertyId := 30008
  static UIA_IsKeyboardFocusablePropertyId := 30009
  static UIA_IsEnabledPropertyId := 30010
  static UIA_AutomationIdPropertyId := 30011
  static UIA_ClassNamePropertyId := 30012
  static UIA_HelpTextPropertyId := 30013
  static UIA_ClickablePointPropertyId := 30014
  static UIA_CulturePropertyId := 30015
  static UIA_IsControlElementPropertyId := 30016
  static UIA_IsContentElementPropertyId := 30017
  static UIA_LabeledByPropertyId := 30018
  static UIA_IsPasswordPropertyId := 30019
  static UIA_NativeWindowHandlePropertyId := 30020
  static UIA_ItemTypePropertyId := 30021
  static UIA_IsOffscreenPropertyId := 30022
  static UIA_OrientationPropertyId := 30023
  static UIA_FrameworkIdPropertyId := 30024
  static UIA_IsRequiredForFormPropertyId := 30025
  static UIA_ItemStatusPropertyId := 30026
  static UIA_IsDockPatternAvailablePropertyId := 30027
  static UIA_IsExpandCollapsePatternAvailablePropertyId := 30028
  static UIA_IsGridItemPatternAvailablePropertyId := 30029
  static UIA_IsGridPatternAvailablePropertyId := 30030
  static UIA_IsInvokePatternAvailablePropertyId := 30031
  static UIA_IsMultipleViewPatternAvailablePropertyId := 30032
  static UIA_IsRangeValuePatternAvailablePropertyId := 30033
  static UIA_IsScrollPatternAvailablePropertyId := 30034
  static UIA_IsScrollItemPatternAvailablePropertyId := 30035
  static UIA_IsSelectionItemPatternAvailablePropertyId := 30036
  static UIA_IsSelectionPatternAvailablePropertyId := 30037
  static UIA_IsTablePatternAvailablePropertyId := 30038
  static UIA_IsTableItemPatternAvailablePropertyId := 30039
  static UIA_IsTextPatternAvailablePropertyId := 30040
  static UIA_IsTogglePatternAvailablePropertyId := 30041
  static UIA_IsTransformPatternAvailablePropertyId := 30042
  static UIA_IsValuePatternAvailablePropertyId := 30043
  static UIA_IsWindowPatternAvailablePropertyId := 30044
  static UIA_ValueValuePropertyId := 30045
  static UIA_ValueIsReadOnlyPropertyId := 30046
  static UIA_RangeValueValuePropertyId := 30047
  static UIA_RangeValueIsReadOnlyPropertyId := 30048
  static UIA_RangeValueMinimumPropertyId := 30049
  static UIA_RangeValueMaximumPropertyId := 30050
  static UIA_RangeValueLargeChangePropertyId := 30051
  static UIA_RangeValueSmallChangePropertyId := 30052
  static UIA_ScrollHorizontalScrollPercentPropertyId := 30053
  static UIA_ScrollHorizontalViewSizePropertyId := 30054
  static UIA_ScrollVerticalScrollPercentPropertyId := 30055
  static UIA_ScrollVerticalViewSizePropertyId := 30056
  static UIA_ScrollHorizontallyScrollablePropertyId := 30057
  static UIA_ScrollVerticallyScrollablePropertyId := 30058
  static UIA_SelectionSelectionPropertyId := 30059
  static UIA_SelectionCanSelectMultiplePropertyId := 30060
  static UIA_SelectionIsSelectionRequiredPropertyId := 30061
  static UIA_GridRowCountPropertyId := 30062
  static UIA_GridColumnCountPropertyId := 30063
  static UIA_GridItemRowPropertyId := 30064
  static UIA_GridItemColumnPropertyId := 30065
  static UIA_GridItemRowSpanPropertyId := 30066
  static UIA_GridItemColumnSpanPropertyId := 30067
  static UIA_GridItemContainingGridPropertyId := 30068
  static UIA_DockDockPositionPropertyId := 30069
  static UIA_ExpandCollapseExpandCollapseStatePropertyId := 30070
  static UIA_MultipleViewCurrentViewPropertyId := 30071
  static UIA_MultipleViewSupportedViewsPropertyId := 30072
  static UIA_WindowCanMaximizePropertyId := 30073
  static UIA_WindowCanMinimizePropertyId := 30074
  static UIA_WindowWindowVisualStatePropertyId := 30075
  static UIA_WindowWindowInteractionStatePropertyId := 30076
  static UIA_WindowIsModalPropertyId := 30077
  static UIA_WindowIsTopmostPropertyId := 30078
  static UIA_SelectionItemIsSelectedPropertyId := 30079
  static UIA_SelectionItemSelectionContainerPropertyId := 30080
  static UIA_TableRowHeadersPropertyId := 30081
  static UIA_TableColumnHeadersPropertyId := 30082
  static UIA_TableRowOrColumnMajorPropertyId := 30083
  static UIA_TableItemRowHeaderItemsPropertyId := 30084
  static UIA_TableItemColumnHeaderItemsPropertyId := 30085
  static UIA_ToggleToggleStatePropertyId := 30086
  static UIA_TransformCanMovePropertyId := 30087
  static UIA_TransformCanResizePropertyId := 30088
  static UIA_TransformCanRotatePropertyId := 30089
  static UIA_IsLegacyIAccessiblePatternAvailablePropertyId := 30090
  static UIA_LegacyIAccessibleChildIdPropertyId := 30091
  static UIA_LegacyIAccessibleNamePropertyId := 30092
  static UIA_LegacyIAccessibleValuePropertyId := 30093
  static UIA_LegacyIAccessibleDescriptionPropertyId := 30094
  static UIA_LegacyIAccessibleRolePropertyId := 30095
  static UIA_LegacyIAccessibleStatePropertyId := 30096
  static UIA_LegacyIAccessibleHelpPropertyId := 30097
  static UIA_LegacyIAccessibleKeyboardShortcutPropertyId := 30098
  static UIA_LegacyIAccessibleSelectionPropertyId := 30099
  static UIA_LegacyIAccessibleDefaultActionPropertyId := 30100
  static UIA_AriaRolePropertyId := 30101
  static UIA_AriaPropertiesPropertyId := 30102
  static UIA_IsDataValidForFormPropertyId := 30103
  static UIA_ControllerForPropertyId := 30104
  static UIA_DescribedByPropertyId := 30105
  static UIA_FlowsToPropertyId := 30106
  static UIA_ProviderDescriptionPropertyId := 30107
  static UIA_IsItemContainerPatternAvailablePropertyId := 30108
  static UIA_IsVirtualizedItemPatternAvailablePropertyId := 30109
  static UIA_IsSynchronizedInputPatternAvailablePropertyId := 30110
  static UIA_OptimizeForVisualContentPropertyId := 30111
  static UIA_IsObjectModelPatternAvailablePropertyId := 30112
  static UIA_AnnotationAnnotationTypeIdPropertyId := 30113
  static UIA_AnnotationAnnotationTypeNamePropertyId := 30114
  static UIA_AnnotationAuthorPropertyId := 30115
  static UIA_AnnotationDateTimePropertyId := 30116
  static UIA_AnnotationTargetPropertyId := 30117
  static UIA_IsAnnotationPatternAvailablePropertyId := 30118
  static UIA_IsTextPattern2AvailablePropertyId := 30119
  static UIA_StylesStyleIdPropertyId := 30120
  static UIA_StylesStyleNamePropertyId := 30121
  static UIA_StylesFillColorPropertyId := 30122
  static UIA_StylesFillPatternStylePropertyId := 30123
  static UIA_StylesShapePropertyId := 30124
  static UIA_StylesFillPatternColorPropertyId := 30125
  static UIA_StylesExtendedPropertiesPropertyId := 30126
  static UIA_IsStylesPatternAvailablePropertyId := 30127
  static UIA_IsSpreadsheetPatternAvailablePropertyId := 30128
  static UIA_SpreadsheetItemFormulaPropertyId := 30129
  static UIA_SpreadsheetItemAnnotationObjectsPropertyId := 30130
  static UIA_SpreadsheetItemAnnotationTypesPropertyId := 30131
  static UIA_IsSpreadsheetItemPatternAvailablePropertyId := 30132
  static UIA_Transform2CanZoomPropertyId := 30133
  static UIA_IsTransformPattern2AvailablePropertyId := 30134
  static UIA_LiveSettingPropertyId := 30135
  static UIA_IsTextChildPatternAvailablePropertyId := 30136
  static UIA_IsDragPatternAvailablePropertyId := 30137
  static UIA_DragIsGrabbedPropertyId := 30138
  static UIA_DragDropEffectPropertyId := 30139
  static UIA_DragDropEffectsPropertyId := 30140
  static UIA_IsDropTargetPatternAvailablePropertyId := 30141
  static UIA_DropTargetDropTargetEffectPropertyId := 30142
  static UIA_DropTargetDropTargetEffectsPropertyId := 30143
  static UIA_DragGrabbedItemsPropertyId := 30144
  static UIA_Transform2ZoomLevelPropertyId := 30145
  static UIA_Transform2ZoomMinimumPropertyId := 30146
  static UIA_Transform2ZoomMaximumPropertyId := 30147
  static UIA_FlowsFromPropertyId := 30148
  static UIA_IsTextEditPatternAvailablePropertyId := 30149
  static UIA_IsPeripheralPropertyId := 30150
  static UIA_IsCustomNavigationPatternAvailablePropertyId := 30151
  static UIA_PositionInSetPropertyId := 30152
  static UIA_SizeOfSetPropertyId := 30153
  static UIA_LevelPropertyId := 30154
  static UIA_AnnotationTypesPropertyId := 30155
  static UIA_AnnotationObjectsPropertyId := 30156
  static UIA_LandmarkTypePropertyId := 30157
  static UIA_LocalizedLandmarkTypePropertyId := 30158
  static UIA_FullDescriptionPropertyId := 30159
  static UIA_FillColorPropertyId := 30160
  static UIA_OutlineColorPropertyId := 30161
  static UIA_FillTypePropertyId := 30162
  static UIA_VisualEffectsPropertyId := 30163
  static UIA_OutlineThicknessPropertyId := 30164
  static UIA_CenterPointPropertyId := 30165
  static UIA_RotationPropertyId := 30166
  static UIA_SizePropertyId := 30167
  static UIA_IsSelectionPattern2AvailablePropertyId := 30168
  static UIA_Selection2FirstSelectedItemPropertyId := 30169
  static UIA_Selection2LastSelectedItemPropertyId := 30170
  static UIA_Selection2CurrentSelectedItemPropertyId := 30171
  static UIA_Selection2ItemCountPropertyId := 30172
  static UIA_HeadingLevelPropertyId := 30173
  static UIA_IsDialogPropertyId := 30174

  UIA_PropertyId(n:="") {
    local
    static ids:="RuntimeId:30000,BoundingRectangle:30001,ProcessId:30002,ControlType:30003,LocalizedControlType:30004,Name:30005,AcceleratorKey:30006,AccessKey:30007,HasKeyboardFocus:30008,IsKeyboardFocusable:30009,IsEnabled:30010,AutomationId:30011,ClassName:30012,HelpText:30013,ClickablePoint:30014,Culture:30015,IsControlElement:30016,IsContentElement:30017,LabeledBy:30018,IsPassword:30019,NativeWindowHandle:30020,ItemType:30021,IsOffscreen:30022,Orientation:30023,FrameworkId:30024,IsRequiredForForm:30025,ItemStatus:30026,IsDockPatternAvailable:30027,IsExpandCollapsePatternAvailable:30028,IsGridItemPatternAvailable:30029,IsGridPatternAvailable:30030,IsInvokePatternAvailable:30031,IsMultipleViewPatternAvailable:30032,IsRangeValuePatternAvailable:30033,IsScrollPatternAvailable:30034,IsScrollItemPatternAvailable:30035,IsSelectionItemPatternAvailable:30036,IsSelectionPatternAvailable:30037,IsTablePatternAvailable:30038,IsTableItemPatternAvailable:30039,IsTextPatternAvailable:30040,IsTogglePatternAvailable:30041,IsTransformPatternAvailable:30042,IsValuePatternAvailable:30043,IsWindowPatternAvailable:30044,ValueValue:30045,ValueIsReadOnly:30046,RangeValueValue:30047,RangeValueIsReadOnly:30048,RangeValueMinimum:30049,RangeValueMaximum:30050,RangeValueLargeChange:30051,RangeValueSmallChange:30052,ScrollHorizontalScrollPercent:30053,ScrollHorizontalViewSize:30054,ScrollVerticalScrollPercent:30055,ScrollVerticalViewSize:30056,ScrollHorizontallyScrollable:30057,ScrollVerticallyScrollable:30058,SelectionSelection:30059,SelectionCanSelectMultiple:30060,SelectionIsSelectionRequired:30061,GridRowCount:30062,GridColumnCount:30063,GridItemRow:30064,GridItemColumn:30065,GridItemRowSpan:30066,GridItemColumnSpan:30067,GridItemContainingGrid:30068,DockDockPosition:30069,ExpandCollapseExpandCollapseState:30070,MultipleViewCurrentView:30071,MultipleViewSupportedViews:30072,WindowCanMaximize:30073,WindowCanMinimize:30074,WindowWindowVisualState:30075,WindowWindowInteractionState:30076,WindowIsModal:30077,WindowIsTopmost:30078,SelectionItemIsSelected:30079,SelectionItemSelectionContainer:30080,TableRowHeaders:30081,TableColumnHeaders:30082,TableRowOrColumnMajor:30083,TableItemRowHeaderItems:30084,TableItemColumnHeaderItems:30085,ToggleToggleState:30086,TransformCanMove:30087,TransformCanResize:30088,TransformCanRotate:30089,IsLegacyIAccessiblePatternAvailable:30090,LegacyIAccessibleChildId:30091,LegacyIAccessibleName:30092,LegacyIAccessibleValue:30093,LegacyIAccessibleDescription:30094,LegacyIAccessibleRole:30095,LegacyIAccessibleState:30096,LegacyIAccessibleHelp:30097,LegacyIAccessibleKeyboardShortcut:30098,LegacyIAccessibleSelection:30099,LegacyIAccessibleDefaultAction:30100,AriaRole:30101,AriaProperties:30102,IsDataValidForForm:30103,ControllerFor:30104,DescribedBy:30105,FlowsTo:30106,ProviderDescription:30107,IsItemContainerPatternAvailable:30108,IsVirtualizedItemPatternAvailable:30109,IsSynchronizedInputPatternAvailable:30110,OptimizeForVisualContent:30111,IsObjectModelPatternAvailable:30112,AnnotationAnnotationTypeId:30113,AnnotationAnnotationTypeName:30114,AnnotationAuthor:30115,AnnotationDateTime:30116,AnnotationTarget:30117,IsAnnotationPatternAvailable:30118,IsTextPattern2Available:30119,StylesStyleId:30120,StylesStyleName:30121,StylesFillColor:30122,StylesFillPatternStyle:30123,StylesShape:30124,StylesFillPatternColor:30125,StylesExtendedProperties:30126,IsStylesPatternAvailable:30127,IsSpreadsheetPatternAvailable:30128,SpreadsheetItemFormula:30129,SpreadsheetItemAnnotationObjects:30130,SpreadsheetItemAnnotationTypes:30131,IsSpreadsheetItemPatternAvailable:30132,Transform2CanZoom:30133,IsTransformPattern2Available:30134,LiveSetting:30135,IsTextChildPatternAvailable:30136,IsDragPatternAvailable:30137,DragIsGrabbed:30138,DragDropEffect:30139,DragDropEffects:30140,IsDropTargetPatternAvailable:30141,DropTargetDropTargetEffect:30142,DropTargetDropTargetEffects:30143,DragGrabbedItems:30144,Transform2ZoomLevel:30145,Transform2ZoomMinimum:30146,Transform2ZoomMaximum:30147,FlowsFrom:30148,IsTextEditPatternAvailable:30149,IsPeripheral:30150,IsCustomNavigationPatternAvailable:30151,PositionInSet:30152,SizeOfSet:30153,Level:30154,AnnotationTypes:30155,AnnotationObjects:30156,LandmarkType:30157,LocalizedLandmarkType:30158,FullDescription:30159,FillColor:30160,OutlineColor:30161,FillType:30162,VisualEffects:30163,OutlineThickness:30164,CenterPoint:30165,Rotation:30166,Size:30167,IsSelectionPattern2Available:30168,Selection2FirstSelectedItem:30169,Selection2LastSelectedItem:30170,Selection2CurrentSelectedItem:30171,Selection2ItemCount:30173,IsDialog:30174"
    if !n
      return ids		
    if n is integer 
    {
      RegexMatch(ids, "([^,]+):" n, m)
      return m1
    }
    
    n := StrReplace(StrReplace(n, "UIA_"), "PropertyId")
    if (SubStr(n,1,7) = "Current")
      n := SubStr(n,8)
    RegexMatch(ids, "i)(?:^|,)" n "(?:" n ")?(?:Id)?:(\d+)", m)
    if (!m1 && (n = "type"))
      return 30003
    return m1
  }

  UIA_PropertyVariantType(id){
    static type:={30000:0x2003,30001:0x2005,30002:3,30003:3,30004:8,30005:8,30006:8,30007:8,30008:0xB,30009:0xB,30010:0xB,30011:8,30012:8,30013:8,30014:0x2005,30015:3,30016:0xB,30017:0xB,30018:0xD,30019:0xB,30020:3,30021:8,30022:0xB,30023:3,30024:8,30025:0xB,30026:8,30027:0xB,30028:0xB,30029:0xB,30030:0xB,30031:0xB,30032:0xB,30033:0xB,30034:0xB,30035:0xB,30036:0xB,30037:0xB,30038:0xB,30039:0xB,30040:0xB,30041:0xB,30042:0xB,30043:0xB,30044:0xB,30045:8,30046:0xB,30047:5,30048:0xB,30049:5,30050:5,30051:5,30052:5,30053:5,30054:5,30055:5,30056:5,30057:0xB,30058:0xB,30059:0x200D,30060:0xB,30061:0xB,30062:3,30063:3,30064:3,30065:3,30066:3,30067:3,30068:0xD,30069:3,30070:3,30071:3,30072:0x2003,30073:0xB,30074:0xB,30075:3,30076:3,30077:0xB,30078:0xB,30079:0xB,30080:0xD,30081:0x200D,30082:0x200D,30083:0x2003,30084:0x200D,30085:0x200D,30086:3,30087:0xB,30088:0xB,30089:0xB,30090:0xB,30091:3,30092:8,30093:8,30094:8,30095:3,30096:3,30097:8,30098:8,30099:0x200D,30100:8}, type2:={30101:8,30102:8,30103:0xB,30104:0xD,30105:0xD,30106:0xD,30107:8,30108:0xB,30109:0xB,30110:0xB,30111:0xB,30112:0xB,30113:3,30114:8,30115:8,30116:8,30117:0xD,30118:0xB,30119:0xB,30120:3,30121:8,30122:3,30123:8,30124:8,30125:3,30126:8,30127:0xB,30128:0xB,30129:8,30130:0x200D,30131:0x2003,30132:0xB,30133:0xB,30134:0xB,30135:3,30136:0xB,30137:0xB,30138:0xB,30139:8,30140:0x2008,30141:0xB,30142:8,30143:0x2008,30144:0x200D,30145:5,30146:5,30147:5,30148:0x200D,30149:0xB,30150:0xB,30151:0xB,30152:3,30153:3,30154:3,30155:0x2003,30156:0x2003,30157:3,30158:8,30159:8,30160:3,30161:0x2003,30162:3,30163:3,30164:0x2005,30165:0x2005,30166:5,30167:0x2005,30168:0xB} ; missing VTs from 30169 and on
    return ObjHasKey(type, id) ? type[id] : type2[id]
  }

  ; module UIA_TextAttributeIds
  static UIA_AnimationStyleAttributeId := 40000
  static UIA_BackgroundColorAttributeId := 40001
  static UIA_BulletStyleAttributeId := 40002
  static UIA_CapStyleAttributeId := 40003
  static UIA_CultureAttributeId := 40004
  static UIA_FontNameAttributeId := 40005
  static UIA_FontSizeAttributeId := 40006
  static UIA_FontWeightAttributeId := 40007
  static UIA_ForegroundColorAttributeId := 40008
  static UIA_HorizontalTextAlignmentAttributeId := 40009
  static UIA_IndentationFirstLineAttributeId := 40010
  static UIA_IndentationLeadingAttributeId := 40011
  static UIA_IndentationTrailingAttributeId := 40012
  static UIA_IsHiddenAttributeId := 40013
  static UIA_IsItalicAttributeId := 40014
  static UIA_IsReadOnlyAttributeId := 40015
  static UIA_IsSubscriptAttributeId := 40016
  static UIA_IsSuperscriptAttributeId := 40017
  static UIA_MarginBottomAttributeId := 40018
  static UIA_MarginLeadingAttributeId := 40019
  static UIA_MarginTopAttributeId := 40020
  static UIA_MarginTrailingAttributeId := 40021
  static UIA_OutlineStylesAttributeId := 40022
  static UIA_OverlineColorAttributeId := 40023
  static UIA_OverlineStyleAttributeId := 40024
  static UIA_StrikethroughColorAttributeId := 40025
  static UIA_StrikethroughStyleAttributeId := 40026
  static UIA_TabsAttributeId := 40027
  static UIA_TextFlowDirectionsAttributeId := 40028
  static UIA_UnderlineColorAttributeId := 40029
  static UIA_UnderlineStyleAttributeId := 40030
  static UIA_AnnotationTypesAttributeId := 40031
  static UIA_AnnotationObjectsAttributeId := 40032
  static UIA_StyleNameAttributeId := 40033
  static UIA_StyleIdAttributeId := 40034
  static UIA_LinkAttributeId := 40035
  static UIA_IsActiveAttributeId := 40036
  static UIA_SelectionActiveEndAttributeId := 40037
  static UIA_CaretPositionAttributeId := 40038
  static UIA_CaretBidiModeAttributeId := 40039
  static UIA_LineSpacingAttributeId := 40040
  static UIA_BeforeParagraphSpacingAttributeId := 40041
  static UIA_AfterParagraphSpacingAttributeId := 40042
  static UIA_SayAsInterpretAsAttributeId := 40043

  UIA_AttributeId(n:="") {
    static id:={AnimationStyle:40000,BackgroundColor:40001,BulletStyle:40002,CapStyle:40003,Culture:40004,FontName:40005,FontSize:40006,FontWeight:40007,ForegroundColor:40008,HorizontalTextAlignment:40009,IndentationFirstLine:40010,IndentationLeading:40011,IndentationTrailing:40012,IsHidden:40013,IsItalic:40014,IsReadOnly:40015,IsSubscript:40016,IsSuperscript:40017,MarginBottom:40018,MarginLeading:40019,MarginTop:40020,MarginTrailing:40021,OutlineStyles:40022,OverlineColor:40023,OverlineStyle:40024,StrikethroughColor:40025,StrikethroughStyle:40026,Tabs:40027,TextFlowDirections:40028,UnderlineColor:40029,UnderlineStyle:40030,AnnotationTypes:40031,AnnotationObjects:40032,StyleName:40033,StyleId:40034,Link:40035,IsActive:40036,SelectionActiveEnd:40037,CaretPosition:40038,CaretBidiMode:40039,LineSpacing:40040,BeforeParagraphSpacing:40041,AfterParagraphSpacing:40042,SayAsInterpretAs:40043}, name:={40000:"AnimationStyle",40001:"BackgroundColor",40002:"BulletStyle",40003:"CapStyle",40004:"Culture",40005:"FontName",40006:"FontSize",40007:"FontWeight",40008:"ForegroundColor",40009:"HorizontalTextAlignment",40010:"IndentationFirstLine",40011:"IndentationLeading",40012:"IndentationTrailing",40013:"IsHidden",40014:"IsItalic",40015:"IsReadOnly",40016:"IsSubscript",40017:"IsSuperscript",40018:"MarginBottom",40019:"MarginLeading",40020:"MarginTop",40021:"MarginTrailing",40022:"OutlineStyles",40023:"OverlineColor",40024:"OverlineStyle",40025:"StrikethroughColor",40026:"StrikethroughStyle",40027:"Tabs",40028:"TextFlowDirections",40029:"UnderlineColor",40030:"UnderlineStyle",40031:"AnnotationTypes",40032:"AnnotationObjects",40033:"StyleName",40034:"StyleId",40035:"Link",40036:"IsActive",40037:"SelectionActiveEnd",40038:"CaretPosition",40039:"CaretBidiMode",40040:"LineSpacing",40041:"BeforeParagraphSpacing",40042:"AfterParagraphSpacing",40043:"SayAsInterpretAs"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrReplace(StrReplace(n, "AttributeId"), "UIA_")]
  }

  UIA_AttributeVariantType(id){
    Static type:={40000:3,40001:3,40002:3,40003:3,40004:3,40005:8,40006:5,40007:3,40008:3,40009:3,40010:5,40011:5,40012:5,40013:0xB,40014:0xB,40015:0xB,40016:0xB,40017:0xB,40018:5,40019:5,40020:5,40021:5,40022:3,40023:3,40024:3,40025:3,40026:3,40027:0x2005,40028:3,40029:3,40030:3,40031:0x2003,40032:0x200D,40033:8,40034:3,40035:0xD,40036:0xB,40037:3,40038:3,40039:3,40040:8,40041:5,40042:5,40043:8} ; 40032 and 40043 might be incorrect
    return type[id]
  }

  ; module UIA_ControlTypeIds
  static UIA_ButtonControlTypeId := 50000
  static UIA_CalendarControlTypeId := 50001
  static UIA_CheckBoxControlTypeId := 50002
  static UIA_ComboBoxControlTypeId := 50003
  static UIA_EditControlTypeId := 50004
  static UIA_HyperlinkControlTypeId := 50005
  static UIA_ImageControlTypeId := 50006
  static UIA_ListItemControlTypeId := 50007
  static UIA_ListControlTypeId := 50008
  static UIA_MenuControlTypeId := 50009
  static UIA_MenuBarControlTypeId := 50010
  static UIA_MenuItemControlTypeId := 50011
  static UIA_ProgressBarControlTypeId := 50012
  static UIA_RadioButtonControlTypeId := 50013
  static UIA_ScrollBarControlTypeId := 50014
  static UIA_SliderControlTypeId := 50015
  static UIA_SpinnerControlTypeId := 50016
  static UIA_StatusBarControlTypeId := 50017
  static UIA_TabControlTypeId := 50018
  static UIA_TabItemControlTypeId := 50019
  static UIA_TextControlTypeId := 50020
  static UIA_ToolBarControlTypeId := 50021
  static UIA_ToolTipControlTypeId := 50022
  static UIA_TreeControlTypeId := 50023
  static UIA_TreeItemControlTypeId := 50024
  static UIA_CustomControlTypeId := 50025
  static UIA_GroupControlTypeId := 50026
  static UIA_ThumbControlTypeId := 50027
  static UIA_DataGridControlTypeId := 50028
  static UIA_DataItemControlTypeId := 50029
  static UIA_DocumentControlTypeId := 50030
  static UIA_SplitButtonControlTypeId := 50031
  static UIA_WindowControlTypeId := 50032
  static UIA_PaneControlTypeId := 50033
  static UIA_HeaderControlTypeId := 50034
  static UIA_HeaderItemControlTypeId := 50035
  static UIA_TableControlTypeId := 50036
  static UIA_TitleBarControlTypeId := 50037
  static UIA_SeparatorControlTypeId := 50038
  static UIA_SemanticZoomControlTypeId := 50039
  static UIA_AppBarControlTypeId := 50040

  UIA_ControlTypeId(n:="") {
    static id:={Button:50000,Calendar:50001,CheckBox:50002,ComboBox:50003,Edit:50004,Hyperlink:50005,Image:50006,ListItem:50007,List:50008,Menu:50009,MenuBar:50010,MenuItem:50011,ProgressBar:50012,RadioButton:50013,ScrollBar:50014,Slider:50015,Spinner:50016,StatusBar:50017,Tab:50018,TabItem:50019,Text:50020,ToolBar:50021,ToolTip:50022,Tree:50023,TreeItem:50024,Custom:50025,Group:50026,Thumb:50027,DataGrid:50028,DataItem:50029,Document:50030,SplitButton:50031,Window:50032,Pane:50033,Header:50034,HeaderItem:50035,Table:50036,TitleBar:50037,Separator:50038,SemanticZoom:50039,AppBar:50040}, name:={50000:"Button",50001:"Calendar",50002:"CheckBox",50003:"ComboBox",50004:"Edit",50005:"Hyperlink",50006:"Image",50007:"ListItem",50008:"List",50009:"Menu",50010:"MenuBar",50011:"MenuItem",50012:"ProgressBar",50013:"RadioButton",50014:"ScrollBar",50015:"Slider",50016:"Spinner",50017:"StatusBar",50018:"Tab",50019:"TabItem",50020:"Text",50021:"ToolBar",50022:"ToolTip",50023:"Tree",50024:"TreeItem",50025:"Custom",50026:"Group",50027:"Thumb",50028:"DataGrid",50029:"DataItem",50030:"Document",50031:"SplitButton",50032:"Window",50033:"Pane",50034:"Header",50035:"HeaderItem",50036:"Table",50037:"TitleBar",50038:"Separator",50039:"SemanticZoom",50040:"AppBar"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrReplace(StrReplace(n, "ControlTypeId"), "UIA_")]
  }

; module AnnotationType
  static UIA_AnnotationType_Unknown := 60000
  static UIA_AnnotationType_SpellingError := 60001
  static UIA_AnnotationType_GrammarError := 60002
  static UIA_AnnotationType_Comment := 60003
  static UIA_AnnotationType_FormulaError := 60004
  static UIA_AnnotationType_TrackChanges := 60005
  static UIA_AnnotationType_Header := 60006
  static UIA_AnnotationType_Footer := 60007
  static UIA_AnnotationType_Highlighted := 60008
  static UIA_AnnotationType_Endnote := 60009
  static UIA_AnnotationType_Footnote := 60010
  static UIA_AnnotationType_InsertionChange := 60011
  static UIA_AnnotationType_DeletionChange := 60012
  static UIA_AnnotationType_MoveChange := 60013
  static UIA_AnnotationType_FormatChange := 60014
  static UIA_AnnotationType_UnsyncedChange := 60015
  static UIA_AnnotationType_EditingLockedChange := 60016
  static UIA_AnnotationType_ExternalChange := 60017
  static UIA_AnnotationType_ConflictingChange := 60018
  static UIA_AnnotationType_Author := 60019
  static UIA_AnnotationType_AdvancedProofingIssue := 60020
  static UIA_AnnotationType_DataValidationError := 60021
  static UIA_AnnotationType_CircularReferenceError := 60022
  static UIA_AnnotationType_Mathematics := 60023

  UIA_AnnotationType(n:="") {
    static id:={Unknown:60000,SpellingError:60001,GrammarError:60002,Comment:60003,FormulaError:60004,TrackChanges:60005,Header:60006,Footer:60007,Highlighted:60008,Endnote:60009,Footnote:60010,InsertionChange:60011,DeletionChange:60012,MoveChange:60013,FormatChange:60014,UnsyncedChange:60015,EditingLockedChange:60016,ExternalChange:60017,ConflictingChange:60018,Author:60019,AdvancedProofingIssue:60020,DataValidationError:60021,CircularReferenceError:60022,Mathematics:60023}, name:={60000:"Unknown",60001:"SpellingError",60002:"GrammarError",60003:"Comment",60004:"FormulaError",60005:"TrackChanges",60006:"Header",60007:"Footer",60008:"Highlighted",60009:"Endnote",60010:"Footnote",60011:"InsertionChange",60012:"DeletionChange",60013:"MoveChange",60014:"FormatChange",60015:"UnsyncedChange",60016:"EditingLockedChange",60017:"ExternalChange",60018:"ConflictingChange",60019:"Author",60020:"AdvancedProofingIssue",60021:"DataValidationError",60022:"CircularReferenceError",60023:"Mathematics"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrSplit(n, "_").Pop()]
  }

  ; module StyleId
  static UIA_StyleId_Custom := 70000
  static UIA_StyleId_Heading1 := 70001
  static UIA_StyleId_Heading2 := 70002
  static UIA_StyleId_Heading3 := 70003
  static UIA_StyleId_Heading4 := 70004
  static UIA_StyleId_Heading5 := 70005
  static UIA_StyleId_Heading6 := 70006
  static UIA_StyleId_Heading7 := 70007
  static UIA_StyleId_Heading8 := 70008
  static UIA_StyleId_Heading9 := 70009
  static UIA_StyleId_Title := 70010
  static UIA_StyleId_Subtitle := 70011
  static UIA_StyleId_Normal := 70012
  static UIA_StyleId_Emphasis := 70013
  static UIA_StyleId_Quote := 70014
  static UIA_StyleId_BulletedList := 70015
  static UIA_StyleId_NumberedList := 70016

  UIA_StyleId(n:="") {
    static id:={Custom:70000,Heading1:70001,Heading2:70002,Heading3:70003,Heading4:70004,Heading5:70005,Heading6:70006,Heading7:70007,Heading8:70008,Heading9:70009,Title:70010,Subtitle:70011,Normal:70012,Emphasis:70013,Quote:70014,BulletedList:70015,NumberedList:70016}, name:={70000:"Custom",70001:"Heading1",70002:"Heading2",70003:"Heading3",70004:"Heading4",70005:"Heading5",70006:"Heading6",70007:"Heading7",70008:"Heading8",70009:"Heading9",70010:"Title",70011:"Subtitle",70012:"Normal",70013:"Emphasis",70014:"Quote",70015:"BulletedList",70016:"NumberedList"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrSplit(n, "_").Pop()]
  }

  ; module LandmarkTypeIds
  static UIA_CustomLandmarkTypeId := 80000
  static UIA_FormLandmarkTypeId := 80001
  static UIA_MainLandmarkTypeId := 80002
  static UIA_NavigationLandmarkTypeId := 80003
  static UIA_SearchLandmarkTypeId := 80004
  
  UIA_LandmarkTypeId(n:="") {
    static id:={Custom:80000,Form:80001,Main:80002,Navigation:80003,Search:80004}, name:={80000:"Custom",80001:"Form",80002:"Main",80003:"Navigation",80004:"Search"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrReplace(StrReplace(n, "LandmarkTypeId"), "UIA_")]
  }
 
  ; module HeadingLevelIds
  static UIA_HeadingLevel_None := 80050
  static UIA_HeadingLevel1 := 80051
  static UIA_HeadingLevel2 := 80052
  static UIA_HeadingLevel3 := 80053
  static UIA_HeadingLevel4 := 80054
  static UIA_HeadingLevel5 := 80055
  static UIA_HeadingLevel6 := 80056
  static UIA_HeadingLevel7 := 80057
  static UIA_HeadingLevel8 := 80058
  static UIA_HeadingLevel9 := 80059

  UIA_HeadingLevel(n:="") {
    static id:={None:80050, 1:80051, 2:80052, 3:80053, 4:80054, 5:80055, 6:80056, 7:80057, 8:80058, 9:80059}, name:={80050:"None", 80051:"1", 80052:"2", 80053:"3", 80054:"4", 80055:"5", 80056:"6", 80057:"7", 80058:"8", 80059:"9"}
    if !n
      return id
    if n is integer
      return (n > 80000)?name[n]:id[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrReplace(StrReplace(n, "HeadingLevel"), "UIA_")]
  }

  ; module ChangeIds
  static UIA_SummaryChangeId := 90000
  
  UIA_ChangeId(n:="") {
    static id:={Summary:90000}, name:={90000:"Summary"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrReplace(StrReplace(n, "ChangeId"), "UIA_")]
  }

  ; module MetadataIds
  static UIA_SayAsInterpretAsMetadataId := 100000
  
  UIA_MetadataId(n:="") {
    static id:={SayAsInterpretAs:100000}, name:={100000:"SayAsInterpretAs"}
    if !n
      return id
    if n is integer
      return name[n]
    if ObjHasKey(id, n)
      return id[n]
    return id[StrReplace(StrReplace(n, "MetadataId"), "UIA_")]
  }


  ; Uiautomationcoreapi.h enumerations
  ; enum AsyncContentLoadedState Contains values that describe the progress of asynchronous loading of content.
  static AsyncContentLoadedState_Beginning := 0
  static AsyncContentLoadedState_Progress := 1
  static AsyncContentLoadedState_Completed := 2
  
  AsyncContentLoadedState(Value:="") {
    static v1:={0:"Beginning", 1:"Progress", 2:"Completed"}
    if Value is not integer
      return this["AsyncContentLoadedState_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum AutomationIdentifierType Contains values used in the UiaLookupId function
  static AutomationIdentifierType_Property := 0
  static AutomationIdentifierType_Pattern := 1
  static AutomationIdentifierType_Event := 2
  static AutomationIdentifierType_ControlType := 3
  static AutomationIdentifierType_TextAttribute := 4
  static AutomationIdentifierType_LandmarkType := 5
  static AutomationIdentifierType_Annotation := 6
  static AutomationIdentifierType_Changes := 7
  static AutomationIdentifierType_Style := 8

  AutomationIdentifierType(Value:="") {
    static v1:={0:"Property", 1:"Pattern", 2:"Event", 3:"ControlType", 4:"TextAttribute", 5:"LandmarkType", 6:"Annotation", 7:"Changes", 8:"Style"}
    if Value is not integer
      return this["AutomationIdentifierType_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum ConditionType Contains values that specify a type of UiaCondition.
  static ConditionType_True := 0
  static ConditionType_False := 1
  static ConditionType_Property := 2
  static ConditionType_And := 3
  static ConditionType_Or := 4
  static ConditionType_Not := 5

  ConditionType(Value:="") {
    static v1:={0:"True", 1:"False", 2:"Property", 3:"And", 4:"Or", 5:"Not"}
    if Value is not integer
      return this["ConditionType_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum EventArgsType
  static EventArgsType_Simple := 0
  static EventArgsType_PropertyChanged := 1
  static EventArgsType_StructureChanged := 2
  static EventArgsType_AsyncContentLoaded := 3
  static EventArgsType_WindowClosed := 4
  static EventArgsType_TextEditTextChanged := 5
  static EventArgsType_Changes := 6
  static EventArgsType_Notification := 7
  static EventArgsType_ActiveTextPositionChanged := 8
  static EventArgsType_StructuredMarkup := 9

  EventArgsType(Value:="") {
    static v1:={0:"Simple", 1:"PropertyChanged", 2:"StructureChanged", 3:"AsyncContentLoaded", 4:"WindowClosed", 5:"TextEditTextChanged", 6:"Changes", 7:"Notification", 8:"ActiveTextPositionChanged", 9:"StructuredMarkup"}
    if Value is not integer
      return this["EventArgsType_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; Uiautomationclient.h enumerations
  
  ; enum AutomationElementMode Contains values that specify the type of reference to use when returning UI Automation elements.
  static AutomationElementMode_None := 0x0
  static AutomationElementMode_Full := 0x1

  AutomationElementMode(Value:="") {
    static v1:={0x0:"None", 0x1:"Full"}
    if Value is not integer
      return this["AutomationElementMode_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum CoalesceEventsOptions Contains possible values for the CoalesceEvents property, which indicates whether an accessible technology client receives all events, or a subset where duplicate events are detected and filtered.
  static CoalesceEventsOptions_Disabled := 0x0
  static CoalesceEventsOptions_Enabled := 0x1

  CoalesceEventsOptions(Value:="") {
    static v1:={0x0:"Disabled", 0x1:"Enabled"}
    if Value is not integer
      return this["CoalesceEventsOptions_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum ConnectionRecoveryBehaviorOptions Contains possible values for the ConnectionRecoveryBehavior property, which indicates whether an accessible technology client adjusts provider request timeouts when the provider is non-responsive.
  static ConnectionRecoveryBehaviorOptions_Disabled := 0
  static ConnectionRecoveryBehaviorOptions_Enabled := 0x1

  ConnectionRecoveryBehaviorOptions(Value:="") {
    static v1:={0x0:"Disabled", 0x1:"Enabled"}
    if Value is not integer
      return this["ConnectionRecoveryBehaviorOptions_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum PropertyConditionFlags Contains values used in creating property conditions.
  static PropertyConditionFlags_None := 0x0
  static PropertyConditionFlags_IgnoreCase := 0x1
  static PropertyConditionFlags_MatchSubstring = 0x2

  PropertyConditionFlags(Value:="") {
    static v1:={0x0:"None", 0x1:"IgnoreCase", 0x2:"MatchSubstring"}
    if Value is not integer
      return this["PropertyConditionFlags_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum TreeScope Contains values that specify the scope of various operations in the Microsoft UI Automation tree.
  static TreeScope_None := 0x0
  static TreeScope_Element := 0x1
  static TreeScope_Children := 0x2
  static TreeScope_Descendants := 0x4
  static TreeScope_Parent := 0x8
  static TreeScope_Ancestors := 0x10
  static TreeScope_Subtree := 0x7

  TreeScope(Value:="") {
    static v1:={0x0:"None", 0x1:"Element", 0x2:"Children", 0x4:"Descendants", 0x8:"Parent", 0x10:"Ancestors", 0x7:"Subtree"}
    if Value is not integer
      return this["TreeScope_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ;enum TreeTraversalOptions Defines values that can be used to customize tree navigation order.
  static TreeTraversalOptions_Default := 0x0
  static TreeTraversalOptions_PostOrder := 0x1
  static TreeTraversalOptions_LastToFirstOrder := 0x2

  TreeTraversalOptions(Value:="") {
    static v1:={0x0:"Default", 0x1:"PostOrder", 0x2:"LastToFirstOrder"}
    if Value is not integer
      return this["TreeTraversalOptions_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; Uiautomationcore.h enumerations

  ; enum ActiveEnd Contains possible values for the SelectionActiveEnd text attribute, which indicates the location of the caret relative to a text range that represents the currently selected text.
  static ActiveEnd_None := 0
  static ActiveEnd_Start := 1
  static ActiveEnd_End := 2

  ActiveEnd(Value:="") {
    static v1:={0x0:"None", 0x1:"Start", 0x2:"End"}
    if Value is not integer
      return this["ActiveEnd_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum AnimationStyle Contains values for the AnimationStyle text attribute.
  static AnimationStyle_None := 0
  static AnimationStyle_LasVegasLights := 1
  static AnimationStyle_BlinkingBackground := 2
  static AnimationStyle_SparkleText := 3
  static AnimationStyle_MarchingBlackAnts := 4
  static AnimationStyle_MarchingRedAnts := 5
  static AnimationStyle_Shimmer := 6
  static AnimationStyle_Other := -1

  AnimationStyle(Value:="") {
    static v1:={0:"None", 1:"LasVegasLights",2:"BlinkingBackground", 3:"SparkleText",4:"MarchingBlackAnts", 5:"MarchingRedAnts", 6:"Shimmer", -1:"Other"}
    if Value is not integer
      return this["AnimationStyle_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum BulletStyle Contains values for the BulletStyle text attribute.
  static BulletStyle_None := 0
  static BulletStyle_HollowRoundBullet := 1
  static BulletStyle_FilledRoundBullet := 2
  static BulletStyle_HollowSquareBullet := 3
  static BulletStyle_FilledSquareBullet := 4
  static BulletStyle_DashBullet := 5
  static BulletStyle_Other := -1

  BulletStyle(Value:="") {
    static v1:={0:"None", 1:"HollowRoundBullet",2:"FilledRoundBullet", 3:"HollowSquareBullet",4:"FilledSquareBullet", 5:"DashBullet", -1:"Other"}
    if Value is not integer
      return this["BulletStyle_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum CapStyle Contains values that specify the value of the CapStyle text attribute.
  static CapStyle_None := 0
  static CapStyle_SmallCap := 1
  static CapStyle_AllCap := 2
  static CapStyle_AllPetiteCaps := 3
  static CapStyle_PetiteCaps := 4
  static CapStyle_Unicase := 5
  static CapStyle_Titling := 6
  static CapStyle_Other := -1
  
  CapStyle(Value:="") {
    static v1:={0:"None", 1:"SmallCap",2:"AllCap", 3:"AllPetiteCaps",4:"PetiteCaps", 5:"Unicase",6:"Titling", -1:"Other"}
    if Value is not integer
      return this["CapStyle_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum CaretBidiMode Contains possible values for the CaretBidiMode text attribute, which indicates whether the caret is in text that flows from left to right, or from right to left.
  static CaretBidiMode_LTR := 0
  static CaretBidiMode_RTL := 1

  CaretBidiMode(Value:="") {
    static v1:={0:"LTR", 1:"RTL"}
    if Value is not integer
      return this["CaretBidiMode_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum CaretPosition Contains possible values for the CaretPosition text attribute, which indicates the location of the caret relative to a line of text in a text range.
  static CaretPosition_Unknown := 0
  static CaretPosition_EndOfLine := 1
  static CaretPosition_BeginningOfLine := 2
  
  CaretPosition(Value:="") {
    static v1:={0:"Unknown", 1:"EndOfLine", 2:"BeginningOfLine"}
    if Value is not integer
      return this["CaretPosition_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum DockPosition Contains values that specify the location of a docking window represented by the Dock control pattern.
  static DockPosition_Top := 0x0
  static DockPosition_Left := 0x1
  static DockPosition_Bottom := 0x2
  static DockPosition_Right := 0x3
  static DockPosition_Fill := 0x4
  static DockPosition_None := 0x5

  DockPosition(Value:="") {
    static v1:={0x0:"Top", 0x1:"Left", 0x2:"Bottom", 0x3:"Right", 0x4:"Fill", 0x5:"None"}
    if Value is not integer
      return this["DockPosition_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum ExpandCollapseState Contains values that specify the state of a UI element that can be expanded and collapsed.	
  static ExpandCollapseState_Collapsed := 0x0
  static ExpandCollapseState_Expanded := 0x1
  static ExpandCollapseState_PartiallyExpanded := 0x2
  static ExpandCollapseState_LeafNode := 0x3

  ExpandCollapseState(Value:="") {
    static v1:={0x0:"Collapsed", 0x1:"Expanded", 0x2:"PartiallyExpanded", 0x3:"LeafNode"}
    if Value is not integer
      return this["ExpandCollapseState_" Value]
    return (Value=="")?v1:v1[Value]
  }	
  
  ; enum FillType Contains values for the FillType attribute.
  static FillType_None := 0
  static FillType_Color := 1
  static FillType_Gradient := 2
  static FillType_Picture := 3
  static FillType_Pattern := 4

  FillType(Value:="") {
    static v1:={0x0:"None", 0x1:"Color", 0x2:"Gradient", 0x3:"Picture", 0x4:"Pattern"}
    if Value is not integer
      return this["FillType_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum FlowDirection Contains values for the TextFlowDirections text attribute.
  static FlowDirections_Default := 0
  static FlowDirections_RightToLeft := 0x1
  static FlowDirections_BottomToTop := 0x2
  static FlowDirections_Vertical := 0x4

  FlowDirection(Value:="") {
    static v1:={0x0:"Default", 0x1:"RightToLeft", 0x2:"BottomToTop", 0x4:"Vertical"}
    if Value is not integer
      return this["FlowDirection_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ;enum LiveSetting Contains possible values for the LiveSetting property. This property is implemented by provider elements that are part of a live region.
  static LiveSetting_Off := 0x0
  static LiveSetting_Polite := 0x1
  static LiveSetting_Assertive := 0x2

  LiveSetting(Value:="") {
    static v1:={0x0:"Off", 0x1:"Polite", 0x2:"Assertive"}
    if Value is not integer
      return this["LiveSetting_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum NavigateDirection Contains values used to specify the direction of navigation within the Microsoft UI Automation tree.
  static NavigateDirection_Parent := 0x0
  static NavigateDirection_NextSibling := 0x1
  static NavigateDirection_PreviousSibling := 0x2
  static NavigateDirection_FirstChild := 0x3
  static NavigateDirection_LastChild := 0x4

  NavigateDirection(Value:="") {
    static v1:={0x0:"Parent", 0x1:"NextSibling", 0x2:"PreviousSibling", 0x3:"FirstChild", 0x4:"LastChild"}
    if Value is not integer
      return this["NavigateDirection_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum NotificationKind Defines values that indicate the type of a notification event, and a hint to the listener about the processing of the event. 
  static NotificationKind_ItemAdded := 0
  static NotificationKind_ItemRemoved := 1
  static NotificationKind_ActionCompleted := 2
  static NotificationKind_ActionAborted := 3
  static NotificationKind_Other := 4
  
  NotificationKind(Value:="") {
    static v1:={0x0:"ItemAdded", 0x1:"ItemRemoved", 0x2:"ActionCompleted", 0x3:"ActionAborted", 0x4:"Other"}
    if Value is not integer
      return this["NotificationKind_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum NotificationProcessing Defines values that indicate how a notification should be processed.
  static NotificationProcessing_ImportantAll := 0
  static NotificationProcessing_ImportantMostRecent := 1
  static NotificationProcessing_All := 2
  static NotificationProcessing_MostRecent := 3
  static NotificationProcessing_CurrentThenMostRecent := 4

  NotificationProcessing(Value:="") {
    static v1:={0x0:"ImportantAll", 0x1:"ImportantMostRecent", 0x2:"All", 0x3:"MostRecent", 0x4:"CurrentThenMostRecent"}
    if Value is not integer
      return this["NotificationProcessing_" Value]
    return (Value=="")?v1:v1[Value]
  }	

  ; enum OrientationType Contains values that specify the orientation of a control.
  static OrientationType_None := 0x0
  static OrientationType_Horizontal := 0x1
  static OrientationType_Vertical := 0x2

  OrientationType(Value:="") {
    static v1:={0x0:"None", 0x1:"Horizontal", 0x2:"Vertical"}
    if Value is not integer
      return this["OrientationType_" Value]
    return (Value=="")?v1:v1[Value]
  }
  
  ; enum OutlineStyles Contains values for the OutlineStyle text attribute.
  static OutlineStyles_None := 0
  static OutlineStyles_Outline := 1
  static OutlineStyles_Shadow := 2
  static OutlineStyles_Engraved := 4
  static OutlineStyles_Embossed := 8
  
  OutlineStyles(Value:="") {
    static v1:={0:"None", 1:"Outline", 2:"Shadow", 4:"Engraved", 8:"Embossed"}
    if Value is not integer
      return this["OutlineStyles_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ;enum ProviderOptions
  static ProviderOptions_ClientSideProvider := 0x1
  static ProviderOptions_ServerSideProvider := 0x2
  static ProviderOptions_NonClientAreaProvider := 0x4
  static ProviderOptions_OverrideProvider := 0x8
  static ProviderOptions_ProviderOwnsSetFocus := 0x10
  static ProviderOptions_UseComThreading := 0x20
  static ProviderOptions_RefuseNonClientSupport := 0x40
  static ProviderOptions_HasNativeIAccessible := 0x80
  static ProviderOptions_UseClientCoordinates := 0x100

  ProviderOptions(Value:="") {
    static v1:={0x1:"ClientSideProvider", 0x2:"ServerSideProvider", 0x4:"NonClientAreaProvider", 0x8:"OverrideProvider", 0x10:"ProviderOwnsSetFocus", 0x20:"UseComThreading", 0x40:"RefuseNonClientSupport", 0x80:"HasNativeIAccessible", 0x100:"UseClientCoordinates"}
    if Value is not integer
      return this["ProviderOptions_" Value]
    return (Value=="")?v1:v1[Value]
  }	

  ; enum RowOrColumnMajor Contains values that specify whether data in a table should be read primarily by row or by column.	
  static RowOrColumnMajor_RowMajor := 0x0
  static RowOrColumnMajor_ColumnMajor := 0x1
  static RowOrColumnMajor_Indeterminate := 0x2

  RowOrColumnMajor(Value:="") {
    static v1:={0x0:"RowMajor", 0x1:"ColumnMajor", 0x2:"Indeterminate"}
    if Value is not integer
      return this["RowOrColumnMajor_" Value]
    return (Value=="")?v1:v1[Value]
  }	
  
  ; enum SayAsInterpretAs Defines the values that indicate how a text-to-speech engine should interpret specific data.
  static SayAsInterpretAs_None := 0
  static SayAsInterpretAs_Spell := 1
  static SayAsInterpretAs_Cardinal := 2
  static SayAsInterpretAs_Ordinal := 3
  static SayAsInterpretAs_Number := 4
  static SayAsInterpretAs_Date := 5
  static SayAsInterpretAs_Time := 6
  static SayAsInterpretAs_Telephone := 7
  static SayAsInterpretAs_Currency := 8
  static SayAsInterpretAs_Net := 9
  static SayAsInterpretAs_Url := 10
  static SayAsInterpretAs_Address := 11
  static SayAsInterpretAs_Alphanumeric := 12
  static SayAsInterpretAs_Name := 13
  static SayAsInterpretAs_Media := 14
  static SayAsInterpretAs_Date_MonthDayYear := 15
  static SayAsInterpretAs_Date_DayMonthYear := 16
  static SayAsInterpretAs_Date_YearMonthDay := 17
  static SayAsInterpretAs_Date_YearMonth := 18
  static SayAsInterpretAs_Date_MonthYear := 19
  static SayAsInterpretAs_Date_DayMonth := 20
  static SayAsInterpretAs_Date_MonthDay := 21
  static SayAsInterpretAs_Date_Year := 22
  static SayAsInterpretAs_Time_HoursMinutesSeconds12 := 23
  static SayAsInterpretAs_Time_HoursMinutes12 := 24
  static SayAsInterpretAs_Time_HoursMinutesSeconds24 := 25
  static SayAsInterpretAs_Time_HoursMinutes24 := 26
  
  SayAsInterpretAs(Value:="") {
    static v1:={0:"None", 1:"Spell", 2:"Cardinal", 3:"Ordinal", 4:"Number", 5:"Date", 6:"Time", 7:"Telephone", 8:"Currency", 9:"Net", 10:"Url", 11:"Address", 13:"Name", 14:"Media", 15:"Date_MonthDayYear", 16:"Date_DayMonthYear", 17:"Date_YearMonthDay", 18:"Date_YearMonth", 19:"Date_MonthYear", 20:"Date_DayMonth", 21:"Date_MonthDay", 22:"Date_Year", 23:"Time_HoursMinutesSeconds12", 24:"Time_HoursMinutes12", 25:"Time_HoursMinutesSeconds24", 26:"Time_HoursMinutes24"}
    if Value is not integer
      return this["SayAsInterpretAs_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum ScrollAmount Contains values that specify the direction and distance to scroll.	
  static ScrollAmount_LargeDecrement := 0x0
  static ScrollAmount_SmallDecrement := 0x1
  static ScrollAmount_NoAmount := 0x2
  static ScrollAmount_LargeIncrement := 0x3
  static ScrollAmount_SmallIncrement := 0x4

  ScrollAmount(Value:="") {
    static v1:={0x0:"LargeDecrement", 0x1:"SmallDecrement", 0x2:"NoAmount", 0x3:"LargeIncrement", 0x4:"SmallIncrement"}
    if Value is not integer
      return this["ScrollAmount_" Value]
    return (Value=="")?v1:v1[Value]
  }	
  
  ; enum StructureChangeType Contains values that specify the type of change in the Microsoft UI Automation tree structure.	
  static StructureChangeType_ChildAdded := 0x0
  static StructureChangeType_ChildRemoved := 0x1
  static StructureChangeType_ChildrenInvalidated := 0x2
  static StructureChangeType_ChildrenBulkAdded := 0x3
  static StructureChangeType_ChildrenBulkRemoved := 0x4
  static StructureChangeType_ChildrenReordered := 0x5

  StructureChangeType(Value:="") {
    static v1:={0x0:"ChildAdded", 0x1:"ChildRemoved", 0x2:"ChildrenInvalidated", 0x3:"ChildrenBulkAdded", 0x4:"ChildrenBulkRemoved", 0x5:"ChildrenReordered"}
    if Value is not integer
      return this["StructureChangeType_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum SupportedTextSelection Contains values that specify the supported text selection attribute.	
  static SupportedTextSelection_None := 0x0
  static SupportedTextSelection_Single := 0x1
  static SupportedTextSelection_Multiple := 0x2

  SupportedTextSelection(Value:="") {
    static v1:={0x0:"None", 0x1:"Single", 0x2:"Multiple"}
    if Value is not integer
      return this["SupportedTextSelection_" Value]
    return (Value=="")?v1:v1[Value]
  }	

  ; enum SynchronizedInputType Contains values that specify the type of synchronized input.	
  static SynchronizedInputType_KeyUp := 0x1
  static SynchronizedInputType_KeyDown := 0x2
  static SynchronizedInputType_LeftMouseUp := 0x4
  static SynchronizedInputType_LeftMouseDown := 0x8
  static SynchronizedInputType_RightMouseUp := 0x10
  static SynchronizedInputType_RightMouseDown := 0x20

  SynchronizedInputType(Value:="") {
    static v1:={0x1:"KeyUp", 0x2:"KeyDown", 0x4:"LeftMouseUp", 0x8:"LeftMouseDown", 0x10:"RightMouseUp", 0x20:"RightMouseDown"}
    if Value is not integer
      return this["SynchronizedInputType_" Value]
    return (Value=="")?v1:v1[Value]
  }	

  ; enum TextDecorationLineStyle Contains values that specify the OverlineStyle, StrikethroughStyle, and UnderlineStyle text attributes.
  static TextDecorationLineStyle_None := 0
  static TextDecorationLineStyle_Single := 1
  static TextDecorationLineStyle_WordsOnly := 2
  static TextDecorationLineStyle_Double := 3
  static TextDecorationLineStyle_Dot := 4
  static TextDecorationLineStyle_Dash := 5
  static TextDecorationLineStyle_DashDot := 6
  static TextDecorationLineStyle_DashDotDot := 7
  static TextDecorationLineStyle_Wavy := 8
  static TextDecorationLineStyle_ThickSingle := 9
  static TextDecorationLineStyle_DoubleWavy := 11
  static TextDecorationLineStyle_ThickWavy := 12
  static TextDecorationLineStyle_LongDash := 13
  static TextDecorationLineStyle_ThickDash := 14
  static TextDecorationLineStyle_ThickDashDot := 15
  static TextDecorationLineStyle_ThickDashDotDot := 16
  static TextDecorationLineStyle_ThickDot := 17
  static TextDecorationLineStyle_ThickLongDash := 18
  static TextDecorationLineStyle_Other := -1

  TextDecorationLineStyle(Value:="") {
    static v1:={0:"None", 1:"Single", 2:"WordsOnly", 3:"Double", 4:"Dot", 5:"Dash", 6:"DashDot", 7:"DashDotDot", 8:"Wavy", 9:"ThickSingle", 11:"DoubleWavy", 12:"ThickWavy", 13:"LongDash", 14:"ThickDash", 15:"ThickDashDot", 16:"ThickDashDotDot", 17:"ThickDot", 18:"ThickLongDash", -1:"Other"}
    if Value is not integer
      return this["TextDecorationLineStyle_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum TextEditChangeType Describes the text editing change being performed by controls when text-edit events are raised or handled.
  static TextEditChangeType_None := 0x0
  static TextEditChangeType_AutoCorrect := 0x1
  static TextEditChangeType_Composition := 0x2
  static TextEditChangeType_CompositionFinalized := 0x3
  static TextEditChangeType_AutoComplete := 0x4

  TextEditChangeType(Value:="") {
    static v1:={0x0:"None", 0x1:"AutoCorrect", 0x2:"Composition", 0x3:"CompositionFinalized", 0x4:"AutoComplete"}
    if Value is not integer
      return this["TextEditChangeType_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum TextPatternRangeEndpoint Contains values that specify the endpoints of a text range.
  static TextPatternRangeEndpoint_Start := 0x0
  static TextPatternRangeEndpoint_End := 0x1

  TextPatternRangeEndpoint(Value:="") {
    static v1:={0x0:"Start", 0x1:"End"}
    if Value is not integer
      return this["TextPatternRangeEndpoint_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum TextUnit Contains values that specify units of text for the purposes of navigation.	
  static TextUnit_Character := 0x0
  static TextUnit_Format := 0x1
  static TextUnit_Word := 0x2
  static TextUnit_Line := 0x3
  static TextUnit_Paragraph := 0x4
  static TextUnit_Page := 0x5
  static TextUnit_Document := 0x6

  TextUnit(Value:="") {
    static v1:={0x0:"Character", 0x1:"Format", 0x2:"Word", 0x3:"Line", 0x4:"Paragraph", 0x5:"Page", 0x6:"Document"}
    if Value is not integer
      return this["TextUnit_" Value]
    return (Value=="")?v1:v1[Value]
  }	
  
  ; enum ToggleState Contains values that specify the toggle state of a Microsoft UI Automation element that implements the Toggle control pattern.
  static ToggleState_Off := 0x0
  static ToggleState_On := 0x1
  static ToggleState_Indeterminate := 0x2

  ToggleState(Value:="") {
    static v1:={0x0:"Off", 0x1:"On", 0x2:"Indeterminate"}
    if Value is not integer
      return this["ToggleState_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ;enum ZoomUnit Contains possible values for the IUIAutomationTransformPattern2::ZoomByUnit method, which zooms the viewport of a control by the specified unit.
  static ZoomUnit_NoAmount := 0x0
  static ZoomUnit_LargeDecrement := 0x1
  static ZoomUnit_SmallDecrement := 0x2
  static ZoomUnit_LargeIncrement := 0x3
  static ZoomUnit_SmallIncrement := 0x4

  ZoomUnit(Value:="") {
    static v1:={0x0:"NoAmount", 0x1:"LargeDecrement", 0x2:"SmallDecrement", 0x3:"LargeIncrement", 0x4:"SmallIncrement"}
    if Value is not integer
      return this["ZoomUnit_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum WindowVisualState Contains values that specify the visual state of a window.
  static WindowVisualState_Normal := 0x0
  static WindowVisualState_Maximized := 0x1
  static WindowVisualState_Minimized := 0x2

  WindowVisualState(Value:="") {
    static v1:={0x0:"Normal", 0x1:"Maximized", 0x2:"Minimized"}
    if Value is not integer
      return this["WindowVisualState_" Value]
    return (Value=="")?v1:v1[Value]
  }

  ; enum WindowInteractionState Contains values that specify the current state of the window for purposes of user interaction.
  static WindowInteractionState_Running := 0x0
  static WindowInteractionState_Closing := 0x1
  static WindowInteractionState_ReadyForUserInteraction := 0x2
  static WindowInteractionState_BlockedByModalWindow := 0x3
  static WindowInteractionState_NotResponding := 0x4

  WindowInteractionState(Value:="") {
    static v1:={0x0:"Running", 0x1:"Closing", 0x2:"ReadyForUserInteraction", 0x3:"BlockedByModalWindow", 0x4:"NotResponding"}
    if Value is not integer
      return this["WindowInteractionState_" Value]
    return (Value=="")?v1:v1[Value]
  }
}

class IAccessible_Enum { ; from UIA2.ahk (https://github.com/neptercn/UIAutomation/blob/master/UIA2.ahk)
  ; enum SELFLAG specify how an accessible object becomes selected or takes the focus. http://msdn.microsoft.com/en-us/library/dd373634(v=vs.85).aspx
  static SELFLAG_NONE := 0
  static SELFLAG_TAKEFOCUS := 0x1
  static SELFLAG_TAKESELECTION := 0x2
  static SELFLAG_EXTENDSELECTION := 0x4
  static SELFLAG_ADDSELECTION := 0x8
  static SELFLAG_REMOVESELECTION := 0x10
  static SELFLAG_VALID := 0x1f
  
  ; enum Roles describe the roles of various UI objects in an application. http://msdn.microsoft.com/en-us/library/dd373608%28v=vs.85%29.aspx
  static ROLE_SYSTEM_TITLEBAR := 0x1
  static ROLE_SYSTEM_MENUBAR := 0x2
  static ROLE_SYSTEM_SCROLLBAR := 0x3
  static ROLE_SYSTEM_GRIP := 0x4
  static ROLE_SYSTEM_SOUND := 0x5
  static ROLE_SYSTEM_CURSOR := 0x6
  static ROLE_SYSTEM_CARET := 0x7
  static ROLE_SYSTEM_ALERT := 0x8
  static ROLE_SYSTEM_WINDOW := 0x9
  static ROLE_SYSTEM_CLIENT := 0xa
  static ROLE_SYSTEM_MENUPOPUP := 0xb
  static ROLE_SYSTEM_MENUITEM := 0xc
  static ROLE_SYSTEM_TOOLTIP := 0xd
  static ROLE_SYSTEM_APPLICATION := 0xe
  static ROLE_SYSTEM_DOCUMENT := 0xf
  static ROLE_SYSTEM_PANE := 0x10
  static ROLE_SYSTEM_CHART := 0x11
  static ROLE_SYSTEM_DIALOG := 0x12
  static ROLE_SYSTEM_BORDER := 0x13
  static ROLE_SYSTEM_GROUPING := 0x14
  static ROLE_SYSTEM_SEPARATOR := 0x15
  static ROLE_SYSTEM_TOOLBAR := 0x16
  static ROLE_SYSTEM_STATUSBAR := 0x17
  static ROLE_SYSTEM_TABLE := 0x18
  static ROLE_SYSTEM_COLUMNHEADER := 0x19
  static ROLE_SYSTEM_ROWHEADER := 0x1a
  static ROLE_SYSTEM_COLUMN := 0x1b
  static ROLE_SYSTEM_ROW := 0x1c
  static ROLE_SYSTEM_CELL := 0x1d
  static ROLE_SYSTEM_LINK := 0x1e
  static ROLE_SYSTEM_HELPBALLOON := 0x1f
  static ROLE_SYSTEM_CHARACTER := 0x20
  static ROLE_SYSTEM_LIST := 0x21
  static ROLE_SYSTEM_LISTITEM := 0x22
  static ROLE_SYSTEM_OUTLINE := 0x23
  static ROLE_SYSTEM_OUTLINEITEM := 0x24
  static ROLE_SYSTEM_PAGETAB := 0x25
  static ROLE_SYSTEM_PROPERTYPAGE := 0x26
  static ROLE_SYSTEM_INDICATOR := 0x27
  static ROLE_SYSTEM_GRAPHIC := 0x28
  static ROLE_SYSTEM_STATICTEXT := 0x29
  static ROLE_SYSTEM_TEXT := 0x2a
  static ROLE_SYSTEM_PUSHBUTTON := 0x2b
  static ROLE_SYSTEM_CHECKBUTTON := 0x2c
  static ROLE_SYSTEM_RADIOBUTTON := 0x2d
  static ROLE_SYSTEM_COMBOBOX := 0x2e
  static ROLE_SYSTEM_DROPLIST := 0x2f
  static ROLE_SYSTEM_PROGRESSBAR := 0x30
  static ROLE_SYSTEM_DIAL := 0x31
  static ROLE_SYSTEM_HOTKEYFIELD := 0x32
  static ROLE_SYSTEM_SLIDER := 0x33
  static ROLE_SYSTEM_SPINBUTTON := 0x34
  static ROLE_SYSTEM_DIAGRAM := 0x35
  static ROLE_SYSTEM_ANIMATION := 0x36
  static ROLE_SYSTEM_EQUATION := 0x37
  static ROLE_SYSTEM_BUTTONDROPDOWN := 0x38
  static ROLE_SYSTEM_BUTTONMENU := 0x39
  static ROLE_SYSTEM_BUTTONDROPDOWNGRID := 0x3a
  static ROLE_SYSTEM_WHITESPACE := 0x3b
  static ROLE_SYSTEM_PAGETABLIST := 0x3c
  static ROLE_SYSTEM_CLOCK := 0x3d
  static ROLE_SYSTEM_SPLITBUTTON := 0x3e
  static ROLE_SYSTEM_IPADDRESS := 0x3f
  static ROLE_SYSTEM_OUTLINEBUTTON := 0x40
  
  ; enum State describe the state of objects in an application UI. http://msdn.microsoft.com/en-us/library/dd373609%28v=vs.85%29.aspx
  static STATE_SYSTEM_NORMAL := 0
  static STATE_SYSTEM_UNAVAILABLE := 0x1
  static STATE_SYSTEM_SELECTED := 0x2
  static STATE_SYSTEM_FOCUSED := 0x4
  static STATE_SYSTEM_PRESSED := 0x8
  static STATE_SYSTEM_CHECKED := 0x10
  static STATE_SYSTEM_MIXED := 0x20
  static STATE_SYSTEM_INDETERMINATE := 0x20
  static STATE_SYSTEM_READONLY := 0x40
  static STATE_SYSTEM_HOTTRACKED := 0x80
  static STATE_SYSTEM_DEFAULT := 0x100
  static STATE_SYSTEM_EXPANDED := 0x200
  static STATE_SYSTEM_COLLAPSED := 0x400
  static STATE_SYSTEM_BUSY := 0x800
  static STATE_SYSTEM_FLOATING := 0x1000
  static STATE_SYSTEM_MARQUEED := 0x2000
  static STATE_SYSTEM_ANIMATED := 0x4000
  static STATE_SYSTEM_INVISIBLE := 0x8000
  static STATE_SYSTEM_OFFSCREEN := 0x10000
  static STATE_SYSTEM_SIZEABLE := 0x20000
  static STATE_SYSTEM_MOVEABLE := 0x40000
  static STATE_SYSTEM_SELFVOICING := 0x80000
  static STATE_SYSTEM_FOCUSABLE := 0x100000
  static STATE_SYSTEM_SELECTABLE := 0x200000
  static STATE_SYSTEM_LINKED := 0x400000
  static STATE_SYSTEM_TRAVERSED := 0x800000
  static STATE_SYSTEM_MULTISELECTABLE := 0x1000000
  static STATE_SYSTEM_EXTSELECTABLE := 0x2000000
  static STATE_SYSTEM_ALERT_LOW := 0x4000000
  static STATE_SYSTEM_ALERT_MEDIUM := 0x8000000
  static STATE_SYSTEM_ALERT_HIGH := 0x10000000
  static STATE_SYSTEM_PROTECTED := 0x20000000
  static STATE_SYSTEM_VALID := 0x7fffffff
  static STATE_SYSTEM_HASPOPUP := 0x40000000
  
  ; enum Event describes the events that are generated by the operating system and by server applications. http://msdn.microsoft.com/en-us/library/dd318066%28v=vs.85%29.aspx
  static EVENT_MIN := 0x00000001
  static EVENT_MAX := 0x7FFFFFFF
  static EVENT_SYSTEM_SOUND := 0x0001
  static EVENT_SYSTEM_ALERT := 0x0002
  static EVENT_SYSTEM_FOREGROUND := 0x0003
  static EVENT_SYSTEM_MENUSTART := 0x0004
  static EVENT_SYSTEM_MENUEND := 0x0005
  static EVENT_SYSTEM_MENUPOPUPSTART := 0x0006
  static EVENT_SYSTEM_MENUPOPUPEND := 0x0007
  static EVENT_SYSTEM_CAPTURESTART := 0x0008
  static EVENT_SYSTEM_CAPTUREEND := 0x0009
  static EVENT_SYSTEM_MOVESIZESTART := 0x000A
  static EVENT_SYSTEM_MOVESIZEEND := 0x000B
  static EVENT_SYSTEM_CONTEXTHELPSTART := 0x000C
  static EVENT_SYSTEM_CONTEXTHELPEND := 0x000D
  static EVENT_SYSTEM_DRAGDROPSTART := 0x000E
  static EVENT_SYSTEM_DRAGDROPEND := 0x000F
  static EVENT_SYSTEM_DIALOGSTART := 0x0010
  static EVENT_SYSTEM_DIALOGEND := 0x0011
  static EVENT_SYSTEM_SCROLLINGSTART := 0x0012
  static EVENT_SYSTEM_SCROLLINGEND := 0x0013
  static EVENT_SYSTEM_SWITCHSTART := 0x0014
  static EVENT_SYSTEM_SWITCHEND := 0x0015
  static EVENT_SYSTEM_MINIMIZESTART := 0x0016
  static EVENT_SYSTEM_MINIMIZEEND := 0x0017
  static EVENT_SYSTEM_DESKTOPSWITCH := 0x0020
  static EVENT_SYSTEM_END := 0x00FF
  static EVENT_OEM_DEFINED_START := 0x0101
  static EVENT_OEM_DEFINED_END := 0x01FF
  static EVENT_UIA_EVENTID_START := 0x4E00
  static EVENT_UIA_EVENTID_END := 0x4EFF
  static EVENT_UIA_PROPID_START := 0x7500
  static EVENT_UIA_PROPID_END := 0x75FF
  static EVENT_CONSOLE_CARET := 0x4001
  static EVENT_CONSOLE_UPDATE_REGION := 0x4002
  static EVENT_CONSOLE_UPDATE_SIMPLE := 0x4003
  static EVENT_CONSOLE_UPDATE_SCROLL := 0x4004
  static EVENT_CONSOLE_LAYOUT := 0x4005
  static EVENT_CONSOLE_START_APPLICATION := 0x4006
  static EVENT_CONSOLE_END_APPLICATION := 0x4007
  static EVENT_CONSOLE_END := 0x40FF
  static EVENT_OBJECT_CREATE := 0x8000
  static EVENT_OBJECT_DESTROY := 0x8001
  static EVENT_OBJECT_SHOW := 0x8002
  static EVENT_OBJECT_HIDE := 0x8003
  static EVENT_OBJECT_REORDER := 0x8004
  static EVENT_OBJECT_FOCUS := 0x8005
  static EVENT_OBJECT_SELECTION := 0x8006
  static EVENT_OBJECT_SELECTIONADD := 0x8007
  static EVENT_OBJECT_SELECTIONREMOVE := 0x8008
  static EVENT_OBJECT_SELECTIONWITHIN := 0x8009
  static EVENT_OBJECT_STATECHANGE := 0x800A
  static EVENT_OBJECT_LOCATIONCHANGE := 0x800B
  static EVENT_OBJECT_NAMECHANGE := 0x800C
  static EVENT_OBJECT_DESCRIPTIONCHANGE := 0x800D
  static EVENT_OBJECT_VALUECHANGE := 0x800E
  static EVENT_OBJECT_PARENTCHANGE := 0x800F
  static EVENT_OBJECT_HELPCHANGE := 0x8010
  static EVENT_OBJECT_DEFACTIONCHANGE := 0x8011
  static EVENT_OBJECT_ACCELERATORCHANGE := 0x8012
  static EVENT_OBJECT_INVOKED := 0x8013
  static EVENT_OBJECT_TEXTSELECTIONCHANGED := 0x8014
  static EVENT_OBJECT_CONTENTSCROLLED := 0x8015
  static EVENT_SYSTEM_ARRANGMENTPREVIEW := 0x8016
  static EVENT_OBJECT_END := 0x80FF
  static EVENT_AIA_START := 0xA000
  static EVENT_AIA_END := 0xAFFF
  
  ; enum Navigation indicate the spatial (up, down, left, and right) or logical (first child, last, next, and previous) direction observed when clients use IAccessible::accNavigate to navigate from one user interface element to another within the same container. http://msdn.microsoft.com/en-us/library/dd373600%28v=vs.85%29.aspx
  static NAVDIR_MIN := 0
  static NAVDIR_UP := 1
  static NAVDIR_DOWN := 2
  static NAVDIR_LEFT := 3
  static NAVDIR_RIGHT := 4
  static NAVDIR_NEXT := 5
  static NAVDIR_PREVIOUS := 6
  static NAVDIR_FIRSTCHILD := 7
  static NAVDIR_LASTCHILD := 8
  static NAVDIR_MAX := 9
  
  ; enum Object Identifiers determine the object to which a WM_GETOBJECT message request refers. http://msdn.microsoft.com/en-us/library/dd373606%28v=vs.85%29.aspx
  static OBJID_WINDOW := 0
  static OBJID_SYSMENU := -1
  static OBJID_TITLEBAR := -2
  static OBJID_MENU := -3
  static OBJID_CLIENT := -4
  static OBJID_VSCROLL := -5
  static OBJID_HSCROLL := -6
  static OBJID_SIZEGRIP := -7
  static OBJID_CARET := -8
  static OBJID_CURSOR := -9
  static OBJID_ALERT := -10
  static OBJID_SOUND := -11
  static OBJID_QUERYCLASSNAMEIDX := -12
  static OBJID_NATIVEOM := -16
}


 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。