Winfrom和WPF中弹出和关闭对话框的不同处理方式
在使用UI Automation对Winform和WPF的程序测试中发现有一些不同的地方,而这些不同来自于Winform与WPF的处理机制不同。下面我们通过一个简单的实例来加以说明:
实例描述
我们使用InvokePattern来点击按钮弹出一个对话框,然后点击对话框中的“确定”按钮关闭对话框。
两种方式对比
首先我们使用如下代码来针对Winfom和WPF分别进行测试:
Code
1public static void ClickButtonById(int processId, string buttonId) 2{ 3 AutomationElement element = FindElementById(processId, buttonId); 4 if (element == null) 5 { 6 throw new NullReferenceException(string.Format("Element with AutomationId '{0}' can not be find.", element.Current.Name)); 7 } 8 InvokePattern currentPattern = GetInvokePattern(element); 9 currentPattern.Invoke(); 10} |
上面的代码主要是用来点击按钮,我们的目的是点击按钮弹出MessageBox,然后点击MessageBox中的“OK”按钮关闭此对话框。
通过测试结果发现,上面的代码在WPF程序中完全可以通过,但是在Winform程序中,点击按钮弹出对话框之后发生阻塞现象,导致程序无法向下执行,所以我们通过如上代码视图点击MessageBox中的按钮来关闭此MessageBox将不可能实现,原因就在于Winform中的MessageBox弹出后就会出现阻塞现象,而WPF中使用了另一种处理方式(对此笔者解释的不够深刻,欢迎广大高手帮忙指正, 另外,此问题在Windows 7操作系统上面不会呈现,也可能与操作系统中API对UI Automation的支持有关)。
解决方案
那么我们通过什么方式来解决此问题呢?很多人会想到多线程,但是我们也可以通过发送异步消息来达到相应的效果。下面我们就通过多线程和发送异步消息的方式来方式来点击Winform中MessageBox中的“OK”按钮,此方法同样可以点击WPF中MessageBox中的按钮达到关闭对话框的效果。
1. 多线程的方式
Code
1public static void ClickButtonById(int processId, string buttonId) 2{ 3 AutomationElement element = FindElementById(processId, buttonId); 4 5 if (element == null) 6 { 7 throw new NullReferenceException(string.Format("Element with AutomationId '{0}' can not be find.", element.Current.AutomationId)); 8 } 9 10 ThreadStart start2 = null; 11 12 if (start2 == null) 13 { 14 start2 = delegate 15 { 16 object obj2; 17 if (!element.TryGetCurrentPattern(InvokePattern.Pattern, out obj2)) 18 { 19 throw new Exception(string.Format("Button element with AutomationId '{0}' does not support the InvokePattern.", element.Current.AutomationId)); 20 } 21 (obj2 as InvokePattern).Invoke(); 22 }; 23 } 24 ThreadStart start = start2; 25 new Thread(start).Start(); 26 Thread.Sleep(0xbb8); 27} |