这是一种 UI 自动化方法,可以检测系统中任何位置的 Window Opened 事件,使用其子元素的 Text 识别 Window,并在确定后关闭 Window。
使用带有WindowPattern.WindowOpenedEvent和 Automation Element 参数设置为AutomationElement.RootElement的Automation.AddAutomationEventHandler初始化检测,它没有其他祖先,标识整个桌面(任何窗口)。
该类WindowWatcher
公开了一个公共方法 ( WatchWindowBySubElementText
),该方法允许指定刚刚打开的窗口的子元素之一中包含的文本。如果找到指定的 Text,则该方法关闭 Window 并使用自定义事件处理程序通知操作,订阅者可以使用该事件处理程序来确定已检测到并关闭了监视的 Window。
示例用法,使用问题中提供的文本字符串:
WindowWatcher watcher = new WindowWatcher();
watcher.ElementFound += (obj, evt) => { MessageBox.Show("Found and Closed!"); };
watcher.WatchWindowBySubElementText("Original message");
WindowWatcher
班级:
此类需要对这些程序集的项目引用:
UIAutomationClient
UIAutomationTypes
请注意,在识别后,类事件会在通知订阅者之前删除自动化事件处理程序。这只是一个例子:它指出处理程序需要在某些时候被删除。处理时,该类可以实现IDisposable
和删除处理程序。
编辑:
更改了不考虑在当前进程中创建的窗口的条件:
if (element is null || element.Current.ProcessId != Process.GetCurrentProcess().Id)
如评论中所述,它施加了一个可能不必要的限制:对话框也可能属于当前进程。我把null
支票留在那里。
using System.Diagnostics;
using System.Windows.Automation;
public class WindowWatcher
{
public delegate void ElementFoundEventHandler(object sender, EventArgs e);
public event ElementFoundEventHandler ElementFound;
public WindowWatcher() { }
public void WatchWindowBySubElementText(string ElementText) =>
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
AutomationElement.RootElement, TreeScope.Subtree, (UIElm, evt) => {
AutomationElement element = UIElm as AutomationElement;
try {
if (element is null) return;
AutomationElement childElm = element.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.NameProperty, ElementText));
if (childElm != null) {
(element.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern).Close();
OnElementFound(new EventArgs());
}
}
catch (ElementNotAvailableException) {
// Ignore: generated when a Window is closed. Its AutomationElement
// is no longer available. Usually a modal dialog in the current process.
}
});
public void OnElementFound(EventArgs e)
{
// Automation.RemoveAllEventHandlers(); <= If single use. Add to IDisposable.Dispose()
ElementFound?.Invoke(this, e);
}
}