如何在 F# 中模拟鼠标点击和按键

发布于 2024-10-02 13:14:11 字数 518 浏览 0 评论 0 原文

我正在编写一个程序,该程序应该移动鼠标并在我在代码中指定的位置自动按下。现在我已经成功地使用这一行移动光标: Cursor.Position <- System.Drawing.Point(x,y)

我还没有找到的是如何模拟鼠标单击或按键。我发现的唯一的事情是来自 MSDN 的 SendKeys 类 (http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx)。我尝试用此类模拟按键,但收到运行时错误消息。

我使用的线路是: SendKeys.Send("{ENTER}")

我收到的错误消息: “SendKeys 无法在此应用程序内运行,因为该应用程序不处理 Windows 消息。要么更改应用程序来处理消息,要么使用 SendKeys.SendWait 方法。”

所以我用SendWait方法替换它,但它似乎仍然没有发送按键。我该怎么做?我真正希望完成的程序能够做到的是将按键和鼠标点击发送到另一个已经在后台打开的程序。例如,在“画图”中自动绘制图像。

I'm doing a program that's supposed to move the mouse around and press automatically at places where I specify in the code. Right now i've managed to move the cursor by using this line:
Cursor.Position <- System.Drawing.Point(x,y)

What I haven't found out yet is how to simulate mouseclicks or keypresses. The only thing I found about this is the SendKeys Class from MSDN (http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx). I tried to simulate a keypress with this class, but I get a run-time error message.

The line I use is:
SendKeys.Send("{ENTER}")

The error message I get:
"SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method."

So I replaced it with the SendWait method, but it still doesn't seem to send the keypress. How do I do this? What I really want the finished program to be able to do, is sending keys and mouse clicks to another program that is already open in the background. For example, painting an image in Paint automatically.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

北座城市 2024-10-09 13:14:11

如果您想避免 Win32 本机互操作,Windows 输入模拟器 是一个看起来很有前途的托管包装器 SendInput。但最新版本不支持鼠标模拟。但是,活动主干有一个支持鼠标模拟的补丁(请参阅这个 讨论)。该项目使用 VS2010 C#,您可以在此处从 subversion 存储库导出并构建自己。

如果您对 Win32 本机互操作感兴趣,我整理了如何通过 F# 使用 SendInput API 的演示。该应用程序模拟右键单击。

open System
open System.Runtime.InteropServices

type MOUSEINPUT = struct
    val dx:int
    val dy:int
    val mouseData:int
    val dwFlags:int
    val time:int
    val dwExtraInfo:int
    new(_dx, _dy, _mouseData, _dwFlags, _time, _dwExtraInfo) = {dx=_dx; dy=_dy; mouseData=_mouseData; dwFlags=_dwFlags; time=_time; dwExtraInfo=_dwExtraInfo}
end

type INPUT = struct
    //need to escape traditional INPUT identifier here since "type" is a reserved word
    //though could use any other identifier name if so desired
    val ``type``:int //0 is mouse
    val mi:MOUSEINPUT
    new(_type, _mi) = {``type``=_type; mi=_mi}
end

let MOUSEEVENTF_RIGHTDOWN = 0x0008
let MOUSEEVENTF_RIGHTUP = 0x0010

[<DllImport("user32.dll", SetLastError=true)>]
extern uint32 SendInput(uint32 nInputs, INPUT* pInputs, int cbSize)

let mutable inputRightDown = INPUT(0, MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTDOWN, 0, 0))
let mutable inputRightUp = INPUT(0, MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTUP, 0, 0))

SendInput(uint32 1, &&inputRightDown, Marshal.SizeOf(inputRightDown))
SendInput(uint32 1, &&inputRightUp, Marshal.SizeOf(inputRightUp))

在第二次阅读您的问题时,我发现您最终希望将模拟的鼠标和键盘事件发送到在后台运行的应用程序,在这种情况下 发送消息 / PostMessage 可能是更合适的 API。这仍然需要本机互操作,希望我使用 SendInput 的示例会有所帮助。 这里是一个相关问题。

If you want to avoid Win32 native interop, Windows Input Simulator is a promising looking managed wrapper around SendInput. But the latest release doesn't support mouse simulation. However, the active trunk has a patch for supporting mouse simulation (see this discussion). The project is using VS2010 C#, and you can export and build yourself from the subversion repository here.

If you are interested in Win32 native interop, I put together a demonstration of how to use the SendInput API with F#. This application simulates a right click.

open System
open System.Runtime.InteropServices

type MOUSEINPUT = struct
    val dx:int
    val dy:int
    val mouseData:int
    val dwFlags:int
    val time:int
    val dwExtraInfo:int
    new(_dx, _dy, _mouseData, _dwFlags, _time, _dwExtraInfo) = {dx=_dx; dy=_dy; mouseData=_mouseData; dwFlags=_dwFlags; time=_time; dwExtraInfo=_dwExtraInfo}
end

type INPUT = struct
    //need to escape traditional INPUT identifier here since "type" is a reserved word
    //though could use any other identifier name if so desired
    val ``type``:int //0 is mouse
    val mi:MOUSEINPUT
    new(_type, _mi) = {``type``=_type; mi=_mi}
end

let MOUSEEVENTF_RIGHTDOWN = 0x0008
let MOUSEEVENTF_RIGHTUP = 0x0010

[<DllImport("user32.dll", SetLastError=true)>]
extern uint32 SendInput(uint32 nInputs, INPUT* pInputs, int cbSize)

let mutable inputRightDown = INPUT(0, MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTDOWN, 0, 0))
let mutable inputRightUp = INPUT(0, MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTUP, 0, 0))

SendInput(uint32 1, &&inputRightDown, Marshal.SizeOf(inputRightDown))
SendInput(uint32 1, &&inputRightUp, Marshal.SizeOf(inputRightUp))

On second reading of your question, I see that ultimately you want to send simulated mouse and keyboard events to an application running in the background, in which case SendMessage / PostMessage may be more appropriate APIs. This will still require native interop, and hopefully my example using SendInput will help. Here is a related question.

眉黛浅 2024-10-09 13:14:11

您正在寻找 SendInput Win32 API 调用。

You're looking for the SendInput Win32 API call.

∞琼窗梦回ˉ 2024-10-09 13:14:11
open System.Runtime.InteropServices

module InteropWithNative = 
    [<DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)>]
    extern void mouse_event(System.Int64, System.Int64, System.Int64, System.Int64, System.Int64)

    let MOUSEEVENTF_LEFTDOWN    = 0x02L
    let MOUSEEVENTF_LEFTUP      = 0x04L
    let MOUSEEVENTF_RIGHTDOWN   = 0x08L
    let MOUSEEVENTF_RIGHTUP     = 0x10L

    let  MouseLeftClick () = 
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0L, 0L, 0L, 0L)
        mouse_event(MOUSEEVENTF_LEFTUP, 0L, 0L, 0L, 0L)

然后使用:

    InteropWithNative.MouseLeftClick ()
open System.Runtime.InteropServices

module InteropWithNative = 
    [<DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)>]
    extern void mouse_event(System.Int64, System.Int64, System.Int64, System.Int64, System.Int64)

    let MOUSEEVENTF_LEFTDOWN    = 0x02L
    let MOUSEEVENTF_LEFTUP      = 0x04L
    let MOUSEEVENTF_RIGHTDOWN   = 0x08L
    let MOUSEEVENTF_RIGHTUP     = 0x10L

    let  MouseLeftClick () = 
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0L, 0L, 0L, 0L)
        mouse_event(MOUSEEVENTF_LEFTUP, 0L, 0L, 0L, 0L)

Then to use:

    InteropWithNative.MouseLeftClick ()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文