c#FindWindow及mouse_event

有时候需要用代码控制外部APP的一些操作,比如点击注册或者其他,这就需要用findwinow去抓取界面的句柄等,或者用mouse_event直接点击屏幕的某些位置。
首先,引用命名空间及调用dll

using System.Runtime.InteropServices;
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "SendMessageA")]
static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, StringBuilder lParam);
[DllImport("user32.dll")]
static extern bool SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);       
[DllImport("user32.dll")]
static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
//如果 CallBack 返回的是true,则会继续枚举,否则就会终止枚举。
public delegate bool EnumChildCallback(IntPtr hwnd, ref IntPtr lParam);
[DllImport("User32.dll")]
public static extern bool EnumChildWindows(IntPtr hWndParent, EnumChildCallback lpEnumFunc, ref IntPtr lParam);
[DllImport("user32.dll")]
static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);

dll方法列举比较多,实际可以挑选自己需要的引用。
使用SPY++工具抓取当前页面。抓取页面时要从主页面一层层往下抓取。

mainWnd_DW_Main = FindWindow("WindowsForms10.Window.8.app.0.33c0d9d", null);
if (mainWnd_DW_Main == IntPtr.Zero)
 {
   ListBoxMessageShow("Can't find MainProcess");
 }
 else                   
 {
   ListBoxMessageShow("Handle: " + mainWnd_DW_Main);
   ListBoxMessageShow("Find  MainProcess");
   SetActiveWindow(mainWnd_DW_Main);
   SetForegroundWindow(mainWnd_DW_Main);  
 } 

上面这段代码是抓取主页面。并且把主页面设置activewindow,抓取用的是 static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

hwnd_Collect = FindWindowEx(mainWnd_DW_Main, new IntPtr(0), "WindowsForms10.MDICLIENT.app.0.33c0d9d", null);

IntPtr hwnd_RobotManage = FindWindowEx(hwnd_Collect, new IntPtr(0), null, "机器人管理器");

上面这两句都是用的从父窗体找的方式,static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); 可以看到,可以用class也可以用window名。

有时候,会出现同一个父窗体下有好几个控件,完全相同,层级也相同,没有可以将之区分开的名字。那么我们只好一个一个控件的next。

 IntPtr hwnd_Collect3_1 = FindWindowEx(hwnd_Collect2, new IntPtr(0), "WindowsForms10.Window.8.app.0.33c0d9d", null); //第一个控件
  IntPtr hwnd_Collect3_2 = FindWindowEx(hwnd_Collect2, hwnd_Collect3_1, "WindowsForms10.Window.8.app.0.33c0d9d", null);//第二个控件

可以看出来,以上的 3_1和3_2都是继承与同一父窗体,3_1之前没有同一级别其他控件,所以它是IntPtr(0),但是3_2之前有,所以它的是3_1。

findwindow大约到这,加点sendkey

 IntPtr hwnd_Install_DW_Next = FindWindowEx(install_mainWnd_DW, new IntPtr(0), null, "&Next >");
  SendMessage(hwnd_Install_DW_Next, WM_CLICK, 0, IntPtr.Zero);
  //************************
  SendKeys.Send("{Enter}");
 

上面这段,分割前是先抓窗体上的button,再用sendmessage发送点击,分割后这一句就是很简单的直接sendkey,如果说这句效果就是直接按了下键盘的“enter”键。这种sendkey一般可以在这种抓窗体走流程时候有那种一个个的小弹框,弹框开始光标的焦点就是OK键或者next之类的,我们不需要做别的,只有再出现这个小弹框时候按下回车就行的时候,用这个sendkeys很方便,但是因为没有抓窗体动作,假如之间出现问题,那就会乱掉。所以sendkeys慎用吧,可以自己添加点判断条件什么的。或者和别的语句合用。

最后,写点mouse_event

SetCursorPos(315, 56);//鼠标点到 机器人管理 位置                
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 1, 0);//鼠标左键单击(静默)

 static void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo)
 {
   int x = dx, y = dy;
   edit_position(dwFlags, dx, dy, ref x, ref y);
   IntPtr hWndFromPoint = WindowFromPoint(x, y);
   screen_to_client(hWndFromPoint, ref x, ref y);
   send_message(hWndFromPoint, dwFlags, cButtons, x, y);
 }
static void edit_position(int dwFlags, int dx, int dy, ref int x, ref int y)
 {
   Point pos = MousePosition;
   x = x + pos.X;
   y = y + pos.Y;
   if ((dwFlags | MOUSEEVENTF_ABSOLUTE) == dwFlags)
    SetCursorPos(dx, dy);
   if ((dwFlags | MOUSEEVENTF_MOVE) == dwFlags)
    SetCursorPos(x, y);
 }
static void send_message(IntPtr hWnd, int dwFlags, int cButtons, int x, int y)
 {
   if ((dwFlags | MOUSEEVENTF_LEFTDOWN) == dwFlags)
    SendMessage(hWnd, WM_LBUTTONDOWN, cButtons, MakeDWord(x, y));
  if ((dwFlags | MOUSEEVENTF_LEFTUP) == dwFlags)
    SendMessage(hWnd, WM_LBUTTONUP, cButtons, MakeDWord(x, y));
  if ((dwFlags | MOUSEEVENTF_RIGHTDOWN) == dwFlags)
    SendMessage(hWnd, WM_RBUTTONDOWN, cButtons, MakeDWord(x, y));
  if ((dwFlags | MOUSEEVENTF_RIGHTUP) == dwFlags)
    SendMessage(hWnd, WM_RBUTTONUP, cButtons, MakeDWord(x, y));
  if ((dwFlags | MOUSEEVENTF_MIDDLEDOWN) == dwFlags)
    SendMessage(hWnd, WM_MBUTTONDOWN, cButtons, MakeDWord(x, y));
  if ((dwFlags | MOUSEEVENTF_MIDDLEUP) == dwFlags)
    SendMessage(hWnd, WM_MBUTTONUP, cButtons, MakeDWord(x, y));
  }
static int MakeDWord(int low, int high)
  {
   return low + (high * Abs(~ushort.MaxValue));
  }
static int Abs(int value)
 {
   return ((value >> 31) ^ value) - (value >> 31);
 }
static bool screen_to_client(IntPtr hwnd, ref int x, ref int y)
 {
   bool bRetVal = false;
   Point lpptPos = new Point(x, y);
   if ((bRetVal = ScreenToClient(hwnd, ref lpptPos)))
    {
      x = lpptPos.X;
      y = lpptPos.Y;
    }
  return bRetVal;
 }  

先把鼠标的焦点移动到要点击的位置,这个点我是用微信截图的坐标取得,还挺准。然后点击。语句很简单,关联函数很多,全部贴上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值