Отправка определенных клавиш на цифровой клавиатуре, таких как +, -, / или Enter (имитация нажатия клавиши) - PullRequest
6 голосов
/ 13 мая 2011

Я работаю над проектом, в котором необходимо смоделировать нажатия клавиш, чтобы вызвать определенное поведение в другом приложении.

Все работает хорошо, используя импортируемую функцию keybd_event (тамможет быть, лучше, но он работает нормально).

Теперь я хочу добавить конкретную поддержку для всех цифровых устройств.

Глядя, например, здесь http://msdn.microsoft.com/en-us/library/dd375731(v=VS.85).aspx или в системеПространство имен .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 +).Итак ... это странно, но хорошо.

Но .. Я не могу отличить клавишу ввода от клавиши NumEnter.Они различны для моего приложения, поэтому я должен отправить конкретные коды клавиш для обоих.

И это мой вопрос: как я могу отправить обычный ключ ввода и как я могу отправить ключ NumEnter?

(Я не знаю, имеет ли это какое-то значение, я на немецкой раскладке клавиатуры.)

Спасибо за любые идеи!

Ответы [ 3 ]

3 голосов
/ 13 мая 2011

Я нашел это здесь работает для меня!

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);
      }
}
1 голос
/ 23 марта 2012

благодаря Андреасу за предоставление начала решения. вот более полная версия:

[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
}
0 голосов
/ 14 мая 2011

Поскольку вы говорите об альтернативном решении, обнаружении события, и я хочу его поднять, мне даже не нужно переопределять 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

Надеюсь, это полезно и кому-то еще. Как и совет Вендетты мне.

И ... если у вас есть лучшее решение, скажите, пожалуйста!

...