我正在尝试访问记事本的Context Menu UI AutomationElement,但是我很难这样做:
SELECT ST_MakePoint(-71.1043443253471, 42.3150676015829);
我的问题是,当我运行应用程序时,打开记事本上下文菜单但是UIAutomation似乎永远不会得到它的AutomationElement ......
这是Inspect.exe的截图:
鉴于检查图片及其呈现的结构,我认为没有理由发生这种情况......有谁知道我可能会出错?
P.S。我是VB.NET的新手,但已经和VBA合作了2到3年,所以我为我可能有的任何坏习惯道歉......
答案 0 :(得分:1)
我找到了解决问题的方法。诀窍是订阅UIAutomation OpenMenuEvent。为此,我创建了一个ContextWatcher
类:
Public Class ContextWatcher
Public Shared Menu As AutomationElement
Private Shared _EventHandler As AutomationEventHandler
Public Shared Sub trackContext()
_EventHandler = New AutomationEventHandler(AddressOf OnContextOpened)
Automation.AddAutomationEventHandler(AutomationElement.MenuOpenedEvent, AutomationElement.RootElement, TreeScope.Descendants, _EventHandler)
End Sub
Public Shared Sub untrackContext()
Automation.RemoveAutomationEventHandler(AutomationElement.MenuOpenedEvent, AutomationElement.RootElement, _EventHandler)
End Sub
Private Shared Sub OnContextOpened(src As Object, args As AutomationEventArgs)
Console.WriteLine("Menu opened.")
Dim element = TryCast(src, AutomationElement)
If element Is Nothing Then
Return
Else
Menu = element
End If
End Sub
End Class
要访问上下文菜单,我可以使用:
ContextWatcher.trackContext()
SendKeys.SendWait("+{F10}")
Dim context As AutomationElement
context = ContextWatcher.Menu
While context Is Nothing
Console.WriteLine("Trying to get context again")
Threading.Thread.Sleep(100)
context = ContextWatcher.Menu
End While
' Do Stuff with context menu
ContextWatcher.untrackContext()
Imports System.Windows.Automation
Imports System.Windows.Forms
Module AutomateNotepad
Sub Main()
Dim wNotepad, document As AutomationElement
'Get 'Untitled - Notepad' main window
wNotepad = AutomationElement.RootElement.FindFirst(TreeScope.Children, New PropertyCondition(AutomationElement.NameProperty, "Untitled - Notepad"))
'Get Notepad document element
document = wNotepad.FindFirst(TreeScope.Children, New PropertyCondition(AutomationElement.LocalizedControlTypeProperty, "document"))
'Set focus to document
document.SetFocus()
'Start watching for context menu
ContextWatcher.trackContext()
'Open context menu
SendKeys.SendWait("+{F10}")
'Get context menu from ContextWatcher class
Dim context As AutomationElement
context = ContextWatcher.Menu
While context Is Nothing
Console.WriteLine("Trying to get context again")
Threading.Thread.Sleep(100)
context = ContextWatcher.Menu
End While
'trigger undo
invokeContextMenuItem(context, "Undo")
'Stop watching for context menu
ContextWatcher.untrackContext()
End Sub
Sub invokeContextMenuItem(context As AutomationElement, sMenuItem As String)
'Get context menu children
Dim controls As AutomationElementCollection = context.FindAll(TreeScope.Children, Condition.TrueCondition)
'Loop over controls to find control with name sMenuItem
Dim control As AutomationElement
For Each control In controls
If control.Current.Name = sMenuItem Then
'Invoke control
getInvokePattern(control).Invoke()
Exit Sub
End If
Next
End Sub
'Helper function to get InvokePattern from UI Element
Function getInvokePattern(element As AutomationElement) As InvokePattern
Return element.GetCurrentPattern(InvokePattern.Pattern)
End Function
Public Class ContextWatcher
Public Shared Menu As AutomationElement
Private Shared _EventHandler As AutomationEventHandler
Public Shared Sub trackContext()
_EventHandler = New AutomationEventHandler(AddressOf OnContextOpened)
Automation.AddAutomationEventHandler(AutomationElement.MenuOpenedEvent, AutomationElement.RootElement, TreeScope.Descendants, _EventHandler)
End Sub
Public Shared Sub untrackContext()
Automation.RemoveAutomationEventHandler(AutomationElement.MenuOpenedEvent, AutomationElement.RootElement, _EventHandler)
End Sub
Private Shared Sub OnContextOpened(src As Object, args As AutomationEventArgs)
Console.WriteLine("Menu opened.")
Dim element = TryCast(src, AutomationElement)
If element Is Nothing Then
Return
Else
Menu = element
End If
End Sub
End Class
End Module