https://www.microsoft.com/en-us/download/confirmation.aspx?id=8279 下载windowsSDK
https://www.cnblogs.com/silverbullet11/category/354374.html
https://www.cnblogs.com/Luouy/p/4204319.html
https://www.cnblogs.com/ellie-test/p/4427323.html
如鹏网 杨中科
https://www.cnblogs.com/rupeng/p/4876368.html
http://www.voidcn.com/article/p-uztuqsgm-xy.html
https://blog.csdn.net/lassewang/article/details/6693917
使用Win32API模拟点击
API 说明和例子
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
lpClassName 就是win32 RegisterClass的名字。
lpWindowName 是窗口的title,如果第一个参数为null,会搜索所有和lpWindowName匹配的窗口。
[DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow);
找到第一个和指定条件符合(class 和windowName 相符合)的hwndParent的子窗口。
如果hwndParent为null,那么以桌面窗口为父窗口。
hwndChildAfer必须为Parent的子窗口,函数从该子窗口的下一个子窗口开始搜索。如果为null,函数会从parent的第一个子窗口搜索。
[DllImport("user32.dll")] public static extern int EnumChildWindows(IntPtr hWndParent, CallBack lpfn, int lParam); public delegate bool CallBack(IntPtr hwnd, int lParam);
枚举一个父窗口所有的子窗口。
如果回调函数返回true,继续。返回false,终止枚举。
被测试的窗口如下图
点击之后弹出一个messagebox。You Nailed it。
控制程序的代码
private void button1_Click(object sender, EventArgs e) { IntPtr mainHandle = WindowsApi.FindWindow(null, "测试窗口"); if(mainHandle!=IntPtr.Zero) { //MessageBox.Show("find one"); IntPtr ibtn = WindowsApi.FindWindowExtended(mainHandle, "ClickMe", true); if(ibtn!=IntPtr.Zero) { WindowsApi.SendMessage(ibtn, 0xF5, 0, 0); } } }
static class WindowsApi { [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam); [DllImport("user32.dll", EntryPoint = "SetForegroundWindow", SetLastError = true)] public static extern void SetForegroundWindow(IntPtr hwnd); [DllImport("user32.dll")] public static extern int EnumChildWindows(IntPtr hWndParent, CallBack lpfn, int lParam); public delegate bool CallBack(IntPtr hwnd, int lParam); /// <summary> /// 查找窗体上控件句柄 /// </summary> /// <param name="hwnd">父窗体句柄</param> /// <param name="lpszWindow">控件标题</param> /// <param name="bChild">设定是否在子窗体中查找</param> /// <returns>控件句柄,没找到返回IntPtr.Zero</returns> public static IntPtr FindWindowExtended(IntPtr hwnd,string lpszWindow,bool bChild) { IntPtr iResult = IntPtr.Zero; // 首先在父窗体上查找控件 iResult = WindowsApi.FindWindowEx(hwnd, 0, null, lpszWindow); // 如果找到直接返回控件句柄 if (iResult != IntPtr.Zero) return iResult; // 如果设定了不在子窗体中查找 if (!bChild) return iResult; // 枚举子窗体,查找控件句柄 int i = WindowsApi.EnumChildWindows( hwnd, (h, l) => { IntPtr f1 = WindowsApi.FindWindowEx(h, 0, null, lpszWindow); if (f1 == IntPtr.Zero) return true; else { iResult = f1; return false; } }, 0); // 返回查找结果 return iResult; } }
点击button1,被测试的程序的ClickMe按钮被点击,弹出
UI Automation简介
AutomationElement.RootElement 是窗口根元素,桌面。
AutomationElement.FromHandle(IntPtr hwnd)从窗口句柄拿到AutomationElement对象。
AutomationElement.Current.***得到控件的名字,句柄等信息。
例子1:获取所有窗口,打印其名称和classname
获取桌面,通过FindAll 获取其所有Children
private void button2_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; //MessageBox.Show(desktop.Current.ControlType.ProgrammaticName); AutomationElementCollection topWindows=desktop.FindAll(TreeScope.Children, Condition.TrueCondition); StringBuilder sb = new StringBuilder(); foreach(AutomationElement ae in topWindows) { sb.AppendLine("Name: " + ae.Current.Name + " ;ClassName=" + ae.Current.ClassName); } MessageBox.Show(sb.ToString()); }
效果如下
添加查询条件
AutomationElementCollection topWindows=desktop.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty,"Chrome_WidgetWin_1"));
例子2:打印计算器程序的所有按钮信息
private void button2_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; AutomationElement calcApp = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow")); //looking for all buttons var buttons=calcApp.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "Button")); StringBuilder sb = new StringBuilder(); foreach(AutomationElement ae in buttons) { sb.AppendLine(ae.Current.Name); } MessageBox.Show(sb.ToString()); }
教程:如何设置文本,读取文本,点击按钮
设置控件的值
var p1=(ValuePattern)ele.GetCurrentPattern(ValuePattern.Pattern); p1.SetValue(value);
得到文本控件的值
var p2=(TextPattern)e.GetCurrentPattern(TextPattern.Pattern); return p2.DocumentRange.GetText(-1);
调用控件,比如点击按钮
var p3=(InvokePattern)e.GetCurrentPattern(InvokePattern.Pattern); p3.Invoke();
例子3:模拟点击按钮,并且返回最终显示值。
private void button2_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; AutomationElement calcApp = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow")); //looking for all buttons var buttons=calcApp.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "Button")); var button5 = calcApp.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "num5Button")); var display = calcApp.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "CalculatorResults")); var p=(InvokePattern)button5.GetCurrentPattern(InvokePattern.Pattern); p.Invoke(); MessageBox.Show(display.Current.Name); }
例子4:设置文本,点击按钮,获取结果文本框中的值
private void button2_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement;AutomationElement convApp = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "WinXP multibyte app")); var tbInt = convApp.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "1001")); var btnConv = convApp.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "IntToBit")); var tbShow = convApp.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "1006")); var p1 = (ValuePattern)tbInt.GetCurrentPattern(ValuePattern.Pattern); p1.SetValue("25"); var p3 = (InvokePattern)btnConv.GetCurrentPattern(InvokePattern.Pattern); p3.Invoke(); var p2 = (TextPattern)tbShow.GetCurrentPattern(TextPattern.Pattern); string hello=p2.DocumentRange.GetText(-1); MessageBox.Show(hello); }