【问题标题】:Sending specific keys on the Numpad like +, -, / or Enter (simulating a keypress)在小键盘上发送特定键,例如 +、-、/ 或 Enter(模拟按键)
【发布时间】:2011-08-24 18:24:06
【问题描述】:

我正在做一个项目,需要模拟按键以在不同的应用程序中引起特定行为。

使用正在导入的 keybd_event 函数,一切运行良好(可能有更好的方法,但运行良好)。

现在我想为所有小键盘添加特定的支持。

看起来 e. G。在 http://msdn.microsoft.com/en-us/library/dd375731(v=VS.85).aspx 或 System.Windows.Input.Key 命名空间中,我可以轻松找到 Num0..Num9 以及 NumLock 的密钥。但是.. 我找不到 Num/、Num+、NumEnter 等的任何内容。

我写了一个快速的froms应用来捕捉keydown事件,输出事件参数,得到了一些有趣的结果:

e.KeyCode NumLock e.KeyData NumLock e.KeyValue 144 e.Modifiers None  
e.KeyCode Divide e.KeyData Divide e.KeyValue 111 e.Modifiers None  
e.KeyCode Multiply e.KeyData Multiply e.KeyValue 106 e.Modifiers None  
e.KeyCode Subtract e.KeyData Subtract e.KeyValue 109 e.Modifiers None  
e.KeyCode Add e.KeyData Add e.KeyValue 107 e.Modifiers None  
e.KeyCode NumLock e.KeyData NumLock e.KeyValue 144 e.Modifiers None  
e.KeyCode NumLock e.KeyData NumLock e.KeyValue 144 e.Modifiers None  
e.KeyCode Divide e.KeyData Divide e.KeyValue 111 e.Modifiers None  
e.KeyCode Multiply e.KeyData Multiply e.KeyValue 106 e.Modifiers None  
e.KeyCode Subtract e.KeyData Subtract e.KeyValue 109 e.Modifiers None  
e.KeyCode Add e.KeyData Add e.KeyValue 107 e.Modifiers None  
e.KeyCode Return e.KeyData Return e.KeyValue 13 e.Modifiers None

Num+ 键(等等)似乎是 Windows 调用功能键的键(例如 Num+ 键的 F18)。所以..这很奇怪,但没关系。

但是.. 我无法区分 Enter-Key 和 NumEnter 键。这些对于我的应用程序是不同的,所以我必须为两者发送特定的键码。

这就是我的问题:如何发送普通的回车键以及如何发送 NumEnter 键?

(我不知道这是否有任何区别,我使用的是德语键盘布局。)

感谢任何想法!

【问题讨论】:

  • 不是很有帮助,但我可以确认:我们有一个跟踪用户输入的应用程序,现在它为 NumEnter 和 Enter 生成相同的键码,所以我无法区分。

标签: c# .net keyboard automation sendkeys


【解决方案1】:

我发现这个here 适合我!

protected override void WndProc(ref Message m)
{
     if (m.Msg == 256 && m.WParam.ToInt32() == 13)
     {   // WM_KEYDOWN == 256, Enter == 13
         if ((m.LParam.ToInt32() >> 24) == 0)
         {
             MessageBox.Show("main enter pressed!");
         }
         else
         {
             MessageBox.Show("numpad enter pressed!");
         }
      }
      else
      {
         base.WndProc(ref m);
      }
}

【讨论】:

  • 非常感谢,这真的很有帮助。虽然它与我正在寻找的东西相反:) 它包含解决我的问题的所有信息。我会马上写一个答案..
  • 非常感谢您的回答!特别是对于你的想法,Vendetta!由于您正在谈论另一种解决方案,检测事件,并且我想提出它,所以我什至不必重写 WndProc。我可以简单地发送我自己的消息。从您的解决方案中,我查看了 SendMessage,然后查看了 WM_KEYDOWN 和 WM_KEYUP。该文档实际上为您提供了信息(如果您看起来真的很努力)。 msdn.microsoft.com/en-us/library/ms646280(v=vs.85).aspxmsdn.microsoft.com/en-us/library/ms646281(v=vs.85).aspx
  • 所以我的解决方案(编译但未测试)是这样的: enter bool keyDown; // true = down, false = up const uint WM_KEYDOWN = 0x0100;常量 uint WM_KEYUP = 0x0101;常量 int VK_RETURN = 0x0D; // 获取活动窗口的句柄。 IntPtr 句柄 = GetForegroundWindow(); int lParam = 1
  • 唯一的问题:它进入活动窗口,而不是活动控件(如 textedit)。这对我来说(真的)不是问题——我希望如此。希望它对其他人也有用。而且..如果您有更好的解决方案,请说出来! (对于许多 cmets 感到抱歉 - 在接下来的 8 小时内无法回答我自己的问题..)
  • 好吧,我一定会尝试..同时你可以在你的问题本身中容纳上述cmets..稍后你可以选择添加为答案
【解决方案2】:

感谢 andreas 提供了一个解决方案的开始。这是一个更完整的版本:

[DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern bool GetGUIThreadInfo(uint idThread, out GUITHREADINFO lpgui);

public struct GUITHREADINFO
{
    public int cbSize;
    public int flags;
    public int hwndActive;
    public int hwndFocus;
    public int hwndCapture;
    public int hwndMenuOwner;
    public int hwndMoveSize;
    public int hwndCaret;
    public System.Drawing.Rectangle rcCaret;
}

private void sendNumpadEnter()
{
    bool keyDown = true; // true = down, false = up
    const uint WM_KEYDOWN = 0x0100;
    const uint WM_KEYUP = 0x0101;
    const int VK_RETURN = 0x0D;

    IntPtr handle = IntPtr.Zero;
    // Obtain the handle of the foreground window (active window and focus window are only relative to our own thread!!)
    IntPtr foreGroundWindow = GetForegroundWindow();
    // now get process id of foreground window
    uint processID;
    uint threadID = GetWindowThreadProcessId(foreGroundWindow, out processID);
    if (processID != 0)
    {
        // now get element with (keyboard) focus from process
        GUITHREADINFO threadInfo = new GUITHREADINFO();
        threadInfo.cbSize = Marshal.SizeOf(threadInfo);
        GetGUIThreadInfo(threadID, out threadInfo);
        handle = (IntPtr)threadInfo.hwndFocus;
    }

    int lParam = 1 << 24; // this specifies NumPad key (extended key)
    lParam |= (keyDown) ? 0 : (1 << 30 | 1 << 31); // mark key as pressed if we use keyup message

    PostMessage(handle, (keyDown) ? WM_KEYDOWN : WM_KEYUP, VK_RETURN, lParam); // send enter
}

【讨论】:

    【解决方案3】:

    由于您正在谈论另一种解决方案,检测事件,并且我想提出它,所以我什至不必重写 WndProc。我可以简单地发送自己的消息。

    根据您的解决方案,我查看了 SendMessage/PostMessage,然后查看了 WM_KEYDOWN 和 WM_KEYUP。文档实际上为您提供了信息(如果您看起来真的很努力)。

    http://msdn.microsoft.com/en-us/library/ms646280(v=vs.85).aspx
    http://msdn.microsoft.com/en-us/library/ms646281(v=vs.85).aspx

    所以我的解决方案(编译,现在找到正确的窗口(在哪里输入文本))是这样的:

     bool keyDown = true; // true = down, false = up
     const uint WM_KEYDOWN = 0x0100;
     const uint WM_KEYUP = 0x0101;
     const int VK_RETURN = 0x0D;
    
     IntPtr handle = IntPtr.Zero;
     // Obtain the handle of the foreground window (active window and focus window are only relative to our own thread!!)
     IntPtr foreGroundWindow = GetForegroundWindow();
     // now get process id of foreground window
     uint processID;
     uint threadID = GetWindowThreadProcessId(foreGroundWindow, out processID);
     if (processID != 0)
     {
     // now get element with (keyboard) focus from process
     GUITHREADINFO threadInfo = new GUITHREADINFO();
     threadInfo.cbSize = Marshal.SizeOf(threadInfo);
     GetGUIThreadInfo(threadID, out threadInfo);
     handle = (IntPtr)threadInfo.hwndFocus;
     }
    
     int lParam = 1 << 24; // this specifies NumPad key (extended key)
     lParam |= (keyDown) ? 0 : (1 << 30 | 1 << 31); // mark key as pressed if we use keyup message
     PostMessage(handle, (keyDown) ? WM_KEYDOWN : WM_KEYUP, VK_RETURN, lParam); // send enter
    

    希望它对其他人也有用。正如 Vendetta 给我的小费一样。

    而且..如果您有更好的解决方案,请说出来!

    【讨论】:

      猜你喜欢
      • 2012-03-11
      • 1970-01-01
      • 2019-11-19
      • 2011-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多