【问题标题】:Click a button from another Application, emulating mouse + coords?单击另一个应用程序中的按钮,模拟鼠标+坐标?
【发布时间】:2011-05-25 04:41:42
【问题描述】:

我尝试使用以下方法点击按钮:

private const int BN_CLICK = 0xF5;
private const uint WM_LBUTTONDOWN = 0x0201;
private const uint WM_LBUTTONUP = 0x0202;
SendMessage(sendButton, BN_CLICK, IntPtr.Zero, IntPtr.Zero);
SendMessage(sendButton, WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
SendMessage(sendButton, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);

以上所有都无法点击按钮,所以我想知道我有其他选择,或者是否可以从它的处理程序中获取按钮位置 X 和 Y

建议,想法会非常好。

【问题讨论】:

  • 请问其他程序是什么?我也遇到过需要单击另一个应用程序中的按钮,例如:使用 Outlook 发送电子邮件会弹出一个烦人的安全对话框“另一个程序正在尝试发送电子邮件......”并单击以编程方式看起来很狡猾的按钮,不可靠并且战斗用鼠标控制用户。相反,我选择购买一个克服了 Outlook 对话框的组件,这对你来说是一个选择吗?否则,您可以在这里找到问题的答案:msdn.microsoft.com/en-us/library/ms171548.aspx
  • @Jeremy 这是一个自制的 Lan House 控件,将所有消息发送到应用程序的调试窗口,我正在过滤这些消息。例如,当检测到被阻止的网站时,我可以选择单击按钮来锁定站点。所以我正在制作一个过滤这些消息的应用程序,如果它找到一些特定的消息,它会采取行动并单击按钮。我已经通过 msdn 和这里的其他几个回复,我的问题不是模拟鼠标或键盘,而是找到按钮的位置来完成这样的任务,如果可能的话完全在后台。
  • 不,我没有它的源代码,开发它的人也完全没有了。

标签: c# controls location mouseclick-event


【解决方案1】:

如果按钮有热键(Alt+...),您可以使用发送有关按下键盘键的消息:

//Presses virtual key in active window.
void PressVK(UINT vk)
{
    //Down Alt.
    keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
    //Press key.
    keybd_event(vk, MapVirtualKey(vk, 0), 0, 0);
    keybd_event(vk, MapVirtualKey(vk, 0), KEYEVENTF_KEYUP, 0);
    //Up Alt.
    keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0);
}

这是一个 C++ 代码。但是您可以将所有这些函数导入 C# 并使用它们。所有你需要的:激活目标窗口并使用正确的键作为参数调用这个函数。

如果您有按钮的句柄,请致电GetWindowRect。它将返回一个指向RECT 结构的指针,该结构接收窗口左上角和右下角的屏幕坐标。因此,无论主窗口大小,您都可以执行点击模拟。

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

使用它:

RECT rect;
if (!GetWindowRect(new HandleRef(this, this.Handle), out rect))
{
    //Error.
}

【讨论】:

  • @archer 感谢您的想法,但没有连接到它的热键:/ 我也尝试发送输入,但如果未选择它也不起作用。可悲的是,所有其他控件都可以与 BN_CLICK 一起正常工作,但这个。
  • @Prix,在发送ENTER之前发送几次TAB和选择按钮怎么样?
  • @archer 我怎么知道该按钮实际上已被选中?我相信标签会通过很多控件。同样使用 Controls.FromHandler 对我不起作用,即使我的 findwindowex 可以很好地挂钩它,它也始终为空。
  • @Prix,尝试自己做并数数...我不知道您实际上在做什么以及使用什么程序,所以只能提供想法。另外,如果您有按钮句柄(如我在示例中看到的),您是否尝试使用 WM_KEYDOWN 消息向它发送 ENTER ?
  • @archer 是的,我也尝试过向它发送输入。好吧,我是查找和使用其他应用程序窗口控件的新手,我目前正在使用 Spy++ 来查找我需要使用的所有东西,但我看不到任何东西可以告诉我是否选择了按钮,如果我可以获得按钮例如,来自处理程序的位置,我可以对该位置执行鼠标单击模拟,但我不确定如何从处理程序的按钮子项中获取该位置,并且由于更改窗口大小会弄乱它,因此需要从处理子更准确。
【解决方案2】:

在使用 sendmessage 进行多次测试后,我已经解决了尝试 PostMessage 的问题...

PostMessage(mainControlChild, WM_KEYDOWN, (int)Keys.Return, 0);
PostMessage(mainControlChild, WM_KEYUP, (int)Keys.Return, 0);

解决了我的问题并将其发送到后台。

【讨论】:

    猜你喜欢
    • 2010-12-16
    • 2012-05-31
    • 2015-12-14
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    相关资源
    最近更新 更多