【问题标题】:How can I do something ~after~ an event has fired in C#?在 C# 中触发了一个事件之后,我该怎么做?
【发布时间】:2011-02-14 21:10:45
【问题描述】:

我正在使用以下project 来处理我的 C# 应用程序中的全局键盘和鼠标挂钩。

这个项目基本上是使用 WH_MOUSE_LL 或 WH_KEYBOARD_LL 常量围绕 Win API 调用 SetWindowsHookEx 的包装器。它还管理某些状态,并且通常使这种挂钩非常轻松。

我正在将它用于我正在开发的鼠标手势识别软件。基本上,我设置了它,以便它检测何时按下全局热键(比如 CTRL),然后用户以预定义手势的形状移动鼠标,然后释放全局热键。

处理 KeyDown 事件并告诉我的程序开始记录鼠标位置,直到它接收到 KeyUp 事件。这工作正常,它允许用户轻松进入鼠标手势模式。一旦 KeyUp 事件触发并检测到适当的手势,它就会向用户为他们刚刚绘制的特定手势定义的活动窗口发送某些击键。

我正在使用 SendKeys.Send/SendWait 方法将输出发送到当前窗口。

我的问题是:当用户释放他们的全局热键(比如 CTRL)时,它会触发 KeyUp 事件。我的程序获取其记录的鼠标点并检测相关手势并尝试通过 SendKeys 发送正确的输入。

但是,由于所有这些都在 KeyUp 事件中,因此该全局热键尚未完成处理。因此,例如,如果我定义了一个手势以在检测到键“A”时发送它,并且我的全局热键是 CTRL,当检测到它时,SendKeys 将发送“A”,但 CTRL 仍然是“向下”。所以,我得到的不是仅仅发送 A,而是 CTRL-A。因此,在此示例中,它不是物理发送单个字符“A”,而是通过 CTRL-A 快捷方式选择全部。即使用户释放了 CTRL(全局热键),系统仍会认为它已关闭。

一旦我的 KeyUp 事件触发,我怎样才能让我的程序等待一段时间或等待某个事件,这样我才能确定全局热键确实不再被系统注册,然后才发送正确的输入通过 SendKeys?

【问题讨论】:

    标签: c# keyboard-hook


    【解决方案1】:

    您可以简单地设置一个计时器并在几分之一秒后(例如 100 毫秒)触发 SendKeys,用户不会注意到轻微的延迟,但它发生在事件处理程序之外就足够了KeyUp。

    另一种选择是在您自己的窗口(使用PostMessage)发布自定义消息,以在它应该“触发”效果并在该自定义消息处理程序中实际执行 SendKeys 时发出信号。这具有不使用一些任意“延迟”的优点。不过设置起来稍微复杂一些(尤其是在 .NET 中,您必须 P/Invoke 更多 API 调用才能使其工作,覆盖 WndProc 函数等等......

    【讨论】:

    • 他可以使用BeginInvoke 来获得PostMessage 的道德等价物,而无需对P/Invoke 进行繁琐的处理。
    • 你们能更详细地描述一下我到底要调用什么吗?我会使用 BeginInvoke 来调用什么?
    • 你会做window.BeginInvoke(DoStuff);,其中 DoStuff 是执行 SendKeys 内容的方法。
    • 哇,我刚试过这个,第一次测试它有效。这是如何工作的?通过异步调用 SendKeys 的东西,我确保 KeyUp 事件已经完成?
    • @Siracuse 您将使用 BeginInvoke 来调用一个委托,该委托将执行您现在在 KeyUp 中所做的事情。从 KeyUp 中调用 BeginInvoke 基本上会排队一些代码在 KeyUp 之后运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 2018-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多