【问题标题】:Send Windows key keypress into application [duplicate]将 Windows 按键发送到应用程序 [重复]
【发布时间】:2012-08-22 11:01:14
【问题描述】:

可能重复:
How to detect the currently pressed key?

(编辑:对于它的价值,这不是重复的......不知道为什么会这样投票)

我有一个小型计时器应用程序,我们在办公室使用它来跟踪项目花费的时间。有一个开始和停止按钮,以及一个项目和任务字段。当我们休息、吃午饭和其他事情时,我们会停止该项目的计时器,然后重新启动它。这是一项重复性的任务,通常涉及从其他几个窗口后面挖出窗口,然后在休息后做同样的事情。

我想要做的是将 WindowKey+W 分配给工作计时器应用程序,让它不仅将计时器应用程序带到前面并聚焦它,而且让它切换开始/停止。

我尝试了多次搜索,但似乎无法将示例范围缩小到我想要的范围。我确实知道您可以打开 Windows 快捷方式的属性并分配一个快捷键来启动程序,并且(我猜?)如果您已经打开了该应用程序并且它被设置为只允许它的一个程序实例会把那个程序带到最前面???也许……

无论如何.. 但该方法不会接受 WindowsKey 作为有效的组合键。而且我不知道它是否可以以某种方式将该组合键传递给程序。

我很感激这里的任何帮助或指导!

编辑 - 答案更新

感谢@huadianz 的回答!我将您的代码转换为 VB:

Public Const MOD_WIN As Integer = &H8
Public Const KEY_W As Integer = &H57

<DllImport("user32.dll")> _
Public Shared Function RegisterHotKey(hWnd As IntPtr, id As Integer, fsModifiers As Integer, vlc As Integer) As Boolean
End Function

<DllImport("user32.dll")> _
Public Shared Function UnregisterHotKey(hWnd As IntPtr, id As Integer) As Boolean
End Function

Public Sub RegisterKeys()
    RegisterHotKey(Me.Handle, 1, MOD_WIN, KEY_W)
End Sub

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    MyBase.WndProc(m)

    If (m.Msg = &H312) Then
        Me.TopMost = True
        Me.PlayPauseTimer()
        Me.TopMost = False
    End If
End Sub

有趣的是,Me.BringToFront() 在 Win7 中的这种情况下实际上不会将应用程序置于最前面,Me.Focus() 也不会。但是,Me.TopMost = True 起作用了,但它具有使窗口始终位于顶部的次要效果。将其设置为True,切换计时器,然后将其设置回False 效果很好!

【问题讨论】:

  • 检查 WINAPI。您可以注册热键。
  • 在问我之前我确实读过这个问题。问题的重点是应用程序当前处于活动状态的时间。问题的重点不是我要找的,所以我觉得需要另一个问题。

标签: c# .net vb.net keyboard-shortcuts keyboard-events


【解决方案1】:

如果您想要完整的操作系统集成,您可以使用 PInvoke 挂钩到内核输入函数。

您正在寻找的是 explorer.exe Windows API 函数,这里有详细描述:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx

使用 PInvoke,您可以调用此 C++ 函数

[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

public const int MOD_WIN = 0x00000008;
public const int KEY_W = 0x00000057

public static void RegisterKeys()
{
    RegisterHotKey((IntPtr)this.Handle, 1, MOD_WIN, KEY_W);
}

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == 0x0312)
        this.Visible = !this.Visible;
}

【讨论】:

  • 出于好奇,以免人们以后生气:Message 在什么命名空间?
  • @ColeJohnson System.Windows.Forms.Message。这是System.Windows.Forms 中用于进程间通信的标准回调。 msdn.microsoft.com/en-us/library/…
  • 那么,如果我不使用 WinForms,我使用 WPF 怎么办? (注:我不是问自己,但这里有一些n00bs)
  • @ColeJohnson 我远离 WPF,就像它是瘟疫一样,因为它夺走了我的控制权。因此,我不知道那个答案。
  • 它是如何夺走控制权的? IMO 所做的只是为您提供更多功能。当然,如果您使用 VB,还有更多需要学习的东西,但我不使用 VB。
【解决方案2】:

我还建议查看自动热键:http://www.autohotkey.com/。如果您所追求的只是在按键时将窗口发送到前面,那么您可能会发现学习 AHK 并编写脚本来执行此操作(只需 1 或 2 行)比用 C# 或 VB 编写东西更快。

*edit*关于自动按下按钮,如果它被设置为默认按钮,那么你可以发送回车键击给它。否则,您甚至可能需要向窗口发送鼠标单击。完成第一部分后,两者都不是特别困难。

#W::MsgBox "This is a message box. You just need to use something like send to send keystrokes and other commands to the window you want to control, instead of the this message box."

【讨论】:

  • 这不是他要求的。
  • 如果我不能让它与本机应用程序编程一起工作,这可能是一个有效的选择。我怀疑这条路线需要 2 次击键:1 次使用 AHK 启动应用程序,1 次用于切换计时器。
【解决方案3】:

您可以使用 Windows SendKeys。如果您查看该链接,它会显示应用 ctrl、alt 或 shift 键的代码和语法。我想您可以将这些键发送到您的应用程序以模拟快捷键。

【讨论】:

    猜你喜欢
    • 2014-04-06
    • 2011-07-19
    • 1970-01-01
    • 2013-06-20
    • 2014-11-02
    • 2011-10-02
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多