发送数字键盘上的特定按键,如 +、-、/ 或 Enter(模拟按键)

发布于 2024-11-06 19:28:15 字数 1563 浏览 2 评论 0原文

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

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

现在我想添加对所有数字键盘的特定支持。

例如在这里 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 称之为功能键的按键(例如 F18 代表 Num+ 键)。所以..这很奇怪,但是没关系。

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

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

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

谢谢您的任何想法!

I am working on a project where it is necessary to simulate key-presses to cause specific behaviours in a different application.

All is running well and fine, using the keybd_event function that is being imported (there might be better ways, but it is working fine).

Now I want to add specific support for all of the numpad.

Looking e. g. here http://msdn.microsoft.com/en-us/library/dd375731(v=VS.85).aspx or in the System.Windows.Input.Key namespace, I can easily find keys for Num0..Num9, as well as for NumLock. But.. I cannot find anything for Num/, Num+, NumEnter etc.

I wrote a quick froms app to catch the keydown event, outputting the event paramters, and got some interesting results:

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

The Num+ Key (and so on) seem to be keys that Windows calls function keys (like F18 for the Num+ key). So.. that is strange, but ok.

But.. I cannot distinguish the Enter-Key from the NumEnter Key. Those are different for my application, so I have to send specific key-codes for both.

And that is my question: how can I send an ordinary enter-key and how can I send a NumEnter key?

(I don't know whether it makes any difference, I am on a German keyboard layout.)

Thx for any ideas!

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

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

发布评论

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

评论(3

只有影子陪我不离不弃 2024-11-13 19:28:15

我发现这个这里对我有用!

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);
      }
}

I found this here works for me !

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);
      }
}
眼泪都笑了 2024-11-13 19:28:15

感谢 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
}

thanks to andreas for providing the beginning of a solution. here's a more complete version:

[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
}
七度光 2024-11-13 19:28:15

由于您正在谈论一种相反的解决方案,即检测事件,并且我想引发它,所以我什至不必重写 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

希望是对别人也有用。正如《仇杀队》给我的提示一样。

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

Since you are talking about a the-other-way-round solution, detecting the event, and I want to raise it, I don't even have to override the WndProc. I can simply send my own messages.

From your solution, I had a look at SendMessage/PostMessage, and then WM_KEYDOWN and WM_KEYUP. The documentation actually gives you the info (if you look really really hard).

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

So my solution (compiles and now with finding the right window (where to enter the text)) is like this:

 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

Hope it is useful to someone else as well. As was Vendetta's tip to me.

And.. if you do have a better solution, please say so!

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