【问题标题】:How to get the handle of 3rd party application's button using c#?如何使用 c# 获取 3rd 方应用程序按钮的句柄?
【发布时间】:2011-01-17 16:19:14
【问题描述】:

我正在尝试在第三方应用程序中生成点击事件。作为开始,我尝试在计算器中模拟点击。这是代码”

IntPtr hwnd = IntPtr.Zero;
IntPtr hwndChild = IntPtr.Zero;
//Get a handle for the Calculator Application main window
hwnd = FindWindow(null, "Calculator");

hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Button", "1");

//send BN_CLICKED message
SendMessage(hwndChild, BM_CLICK, IntPtr.Zero, IntPtr.Zero);

但是使用这段代码我没有得到按钮的句柄。有人可以帮忙吗。有没有其他方法可以模拟第三方应用程序的按钮点击?

谢谢。

【问题讨论】:

  • BM_CLICK 不应该是 WM_CLICK 吗?
  • 我认为翻转是正确的,因为您需要将其作为窗口消息发送,如果您想轻松做到这一点,您可以使用 Spy++ 查找名称甚至特定句柄,然后将其放入您的代码中。
  • @FlipScript:我认为它们都有效,不是吗?
  • @FlipScript, @Jesus:实际上,BM_CLICK 是正确的按钮。 Win32 API 中没有通用的WM_CLICK 消息,因为并非所有控件都支持“单击”的概念。
  • 您确定您的计算器应用程序使用单独的窗口作为其按钮。有时他们只是将按钮直接绘制到画布上,然后使用命中测试。你检查过间谍吗?

标签: c# winapi click handle simulate


【解决方案1】:

您的一般方法是正确的,但您的代码存在两个潜在问题:

  1. FindWindowEx 仅查找指定窗口的直接子级。计算器按钮可能布置在作为主窗口子窗口的容器窗口中,因此该按钮不会是主窗口的直接子窗口。

  2. BM_CLICK 的文档说它通过发送鼠标向下和向上消息来模拟单击,因此您可能必须在发送此消息之前激活父窗口。

【讨论】:

  • 这种用法是否正确。我在开头 public const uint BM_CLICK = 0x00F5;
【解决方案2】:

当我更换它开始工作

public const uint BM_CLICK = 0x00F5;

public const uint WM_LBUTTONDOWN = 0x0201; 
public const uint WM_LBUTTONUP = 0x0202;

使用过

SendMessage(buttonHandle, WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero); 
SendMessage(buttonHandle, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);

【讨论】:

    【解决方案3】:

    先用SPY++找到那个是有Handle的按钮。

    在某些情况下,看起来像 Button 的控件可以是图形控件。 不同的是图形控件不会有句柄,但Windows控件会有句柄。 如果该控件具有有效的句柄。然后使用 FindWindowEx

    还要给父窗口句柄(我认为第一个参数,可能你必须使用 GetWindow() 使用标题)

    然后发送点击消息。

    【讨论】:

      【解决方案4】:

      如果你没有按钮的句柄,你可以模拟鼠标点击坐标:

      class User32
       { 
          [Flags]
          public enum MouseEventFlags
          {
              LEFTDOWN = 0x00000002,
              LEFTUP = 0x00000004,
              MIDDLEDOWN = 0x00000020,
              MIDDLEUP = 0x00000040,
              MOVE = 0x00000001,
              ABSOLUTE = 0x00008000,
              RIGHTDOWN = 0x00000008,
              RIGHTUP = 0x00000010
          }
      
          [DllImport("user32.dll")]
          public static extern bool SetCursorPos(int X, int Y);
      
          [DllImport("user32.dll")]
          public static extern void mouse_event(uint dwFlags, 
                                         uint dx, 
                                         uint dy, 
                                         uint dwData,
                                         int dwExtraInfo);
      
          [DllImport("user32.dll")]
          public static extern void mouse_event(uint dwFlags, 
                                         uint dx, 
                                         uint dy, 
                                         uint dwData,
                                         UIntPtr dwExtraInfo);
      }
      
      class Program
      {
           static void Main()
           {
               User32.SetCursorPos(25, 153);
               User32.mouse_event((uint)User32.MouseEventFlags.LEFTDOWN, 25, 153, 0, 0);
               User32.mouse_event((uint)User32.MouseEventFlags.LEFTUP, 25, 153, 0, 0);
           }
      }
      

      但是,SetCursorPos 函数将光标位置设置在屏幕的全局坐标中,所以首先你应该得到第三方应用程序窗口的位置。

      【讨论】:

      • 谢谢,但我明白了。
      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 2020-04-07
      • 1970-01-01
      • 2012-08-30
      • 2015-04-17
      • 2012-04-15
      • 2011-08-06
      • 2010-11-19
      相关资源
      最近更新 更多