C# 在Numpad上发送特定键,如+;,-,/或输入(模拟按键)

C# 在Numpad上发送特定键,如+;,-,/或输入(模拟按键),c#,.net,keyboard,automation,sendkeys,C#,.net,Keyboard,Automation,Sendkeys,我正在从事一个项目,在这个项目中,有必要模拟按键以在不同的应用程序中产生特定的行为 使用正在导入的keybd_事件函数,一切都运行良好(可能有更好的方法,但工作正常) 现在我想为所有的numpad添加特定的支持 看起来像e。G在这里或System.Windows.Input.Key命名空间中,我可以轻松找到Num0..Num9以及NumLock的键。但是我找不到Num/、Num+、nummenter等的任何内容 我编写了一个快速froms应用程序来捕获keydown事件,输出事件参数,并得到了一

我正在从事一个项目,在这个项目中,有必要模拟按键以在不同的应用程序中产生特定的行为

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

现在我想为所有的numpad添加特定的支持

看起来像e。G在这里或System.Windows.Input.Key命名空间中,我可以轻松找到Num0..Num9以及NumLock的键。但是我找不到Num/、Num+、nummenter等的任何内容

我编写了一个快速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键。这些对我的应用程序来说是不同的,所以我必须为两者发送特定的密钥代码

这就是我的问题:我如何发送一个普通的回车键和一个NumEnter键

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

谢谢你的任何想法

我发现这对我很有用

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

既然您正在讨论一个相反的解决方案,即检测事件,我想提出它,我甚至不必重写WndProc。我可以简单地发送我自己的信息

从您的解决方案中,我查看了SendMessage/PostMessage,然后是WM_KEYDOWN和WM_keydup。文档实际上为您提供了信息(如果您仔细查看的话)


因此,我的解决方案(编译,现在找到正确的窗口(输入文本的位置))如下所示:

 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
bool keyDown=true;//真=向下,假=向上
常数WM_KEYDOWN=0x0100;
常数WM_KEYUP=0x0101;
const int VK_RETURN=0x0D;
IntPtr handle=IntPtr.Zero;
//获取前景窗口的句柄(活动窗口和焦点窗口仅与我们自己的线程相关!!)
IntPtr foregroundindow=getforegroundindow();
//现在获取前景窗口的进程id
uint进程id;
uint threadID=GetWindowThreadProcessId(foreGroundWindow,OutProcessID);
if(processID!=0)
{
//现在从进程中获取具有(键盘)焦点的元素
GUITHREADINFO threadInfo=新的GUITHREADINFO();
threadInfo.cbSize=Marshal.SizeOf(threadInfo);
GetGuitThreadInfo(threadID,OutThreadInfo);
handle=(IntPtr)threadInfo.hwndFocus;
}

int lParam=1感谢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
}
[DllImport(“user32.dll”)]
私有静态外部IntPtr PostMessage(IntPtr hWnd、uint Msg、IntPtr wParam、IntPtr lParam);
[DllImport(“user32.dll”)]
私有静态外部IntPtr GetForegroundWindow();
[DllImport(“user32.dll”)]
私有静态外部单元GetWindowThreadProcessId(IntPtr hWnd,out单元lpdwProcessId);
[DllImport(“user32.dll”)]
私有静态外部bool GetGUIThreadInfo(uint-idThread,out-GUITHREADINFO-lpgui);
公共结构信息
{
公共机构的规模;
公共国旗;
公共卫生署;
公众关注;
公共int hwndCapture;
公共内部hwndMenuOwner;
公共int hwndMoveSize;
公共内联卫生保健中心;
公共系统.Drawing.rcCaret;
}
私有void sendNumpadEnter()
{
bool keyDown=true;//true=down,false=up
常数WM_KEYDOWN=0x0100;
常数WM_KEYUP=0x0101;
const int VK_RETURN=0x0D;
IntPtr handle=IntPtr.Zero;
//获取前景窗口的句柄(活动窗口和焦点窗口仅与我们自己的线程相关!!)
IntPtr foregroundindow=getforegroundindow();
//现在获取前景窗口的进程id
uint进程id;
uint threadID=GetWindowThreadProcessId(foreGroundWindow,OutProcessID);
if(processID!=0)
{
//现在从进程中获取具有(键盘)焦点的元素
GUITHREADINFO threadInfo=新的GUITHREADINFO();
threadInfo.cbSize=Marshal.SizeOf(threadInfo);
GetGuitThreadInfo(threadID,OutThreadInfo);
handle=(IntPtr)threadInfo.hwndFocus;
}

int lParam=1不是很有帮助,但我可以确认:我们有一个应用程序跟踪用户输入,现在它为NumEnter生成与Enter相同的键码,所以我无法区分。Thx很多,这真的很有帮助。尽管这与我正在寻找的相反:)它有解决我问题的所有信息。我将编写一个直接回答..谢谢你的回答!特别是对于你的想法,复仇!因为你正在谈论一个相反的解决方案,检测事件,我想提出它,我甚至不需要覆盖WndProc。我可以简单地发送我自己的消息。从你的解决方案中,我看了SendMessage,然后是WM_KEYDOWN和WM_KEYUP.文档实际上为您提供了信息(如果您看起来非常困难的话)。因此,我的解决方案(编译但未测试)如下所示:输入bool keyDown;//true=down,false=up const uint WM_keyDown=0x0100;const uint WM_keydup=0x0101;const int VK_RETURN=0x0D;//获取活动窗口的句柄。IntPtr handle=GetForegroundWindow();int lParam=1唯一的问题是:它会转到活动窗口,而不是活动控件(像文本编辑)。这对我来说不是(真的)问题-我希望。希望它对其他人也有用。而且..如果你有更好的解决方案,请这么说!(很抱歉有这么多评论-在接下来的8小时内无法回答我自己的问题..)好的,我一定会尝试。同时,你可以在你的问题中容纳上述评论。稍后,你可以选择添加作为答案