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

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

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

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

Ищу e. г. здесь http://msdn.microsoft.com/en-us/library/dd375731(v=VS.85).aspx или в пространстве имен System.Windows.Input.Key я могу легко найти ключи для Num0..Num9, а также для NumLock. Но .. Ничего не могу найти для Num /, Num +, NumEnter и т. Д.

Я написал быстрое приложение froms, чтобы поймать событие нажатия клавиши, вывести параметры события и получил некоторые интересные результаты:

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 + Key (и так далее) кажется клавишами, которые Windows вызывает функциональные клавиши (например, F18 для клавиши Num +). Так .. это странно, но ладно.

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

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

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

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


person Andreas Reiff    schedule 13.05.2011    source источник
comment
не очень полезно, но я могу подтвердить: у нас есть приложение, отслеживающее ввод данных пользователем, и прямо сейчас оно выдает тот же ключевой код для NumEnter из Enter, поэтому я не мог различить.   -  person Cilvic    schedule 13.05.2011


Ответы (3)


Я обнаружил, что это здесь работает для меня!

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);
      }
}
person V4Vendetta    schedule 13.05.2011
comment
Спасибо большое, это было действительно полезно. Хотя это наоборот, к тому, что я ищу :), в нем есть вся информация для решения моей проблемы. Сразу напишу ответ .. - person Andreas Reiff; 13.05.2011
comment
Большое спасибо за ответы! Специально для твоей идеи, Вендетта! Поскольку вы говорите об обратном решении, обнаруживающем событие, и я хочу его поднять, мне даже не нужно переопределять WndProc. Я могу просто отправлять свои сообщения. Из вашего решения я посмотрел на SendMessage, а затем на WM_KEYDOWN и WM_KEYUP. Документация действительно дает вам информацию (если вы действительно очень внимательно посмотрите). msdn.microsoft.com/en-us/library /ms646280(v=vs.85).aspx msdn.microsoft.com/en-us/library/ms646281 (v = vs.85) .aspx - person Andreas Reiff; 13.05.2011
comment
Итак, мое решение (компилируется, но не тестируется) выглядит следующим образом: введите bool keyDown; // true = вниз, false = вверх const uint WM_KEYDOWN = 0x0100; const uint WM_KEYUP = 0x0101; const int VK_RETURN = 0x0D; // Получить дескриптор активного окна. IntPtr handle = GetForegroundWindow (); int lParam = 1 ‹---------------- 24; // это определяет ключ NumPad (расширенный ключ) lParam | = (keyDown)? 0: (1 ‹* 30 | 1 ‹› 31); // помечаем клавишу как нажатую, если мы используем сообщение клавиатуры PostMessage (handle, (keyDown)? WM_KEYDOWN: WM_KEYUP, VK_RETURN, lParam); - person Andreas Reiff; 13.05.2011
comment
Единственная проблема: он переходит в активное окно, а не в активный элемент управления (например, textedit). Надеюсь, для меня это не проблема. Надеюсь, это будет полезно и кому-то другому. И ... если у вас есть лучшее решение, скажите об этом! (извините за множество комментариев - не могу ответить на свои вопросы в следующие 8 часов ..) - person Andreas Reiff; 13.05.2011
comment
ну, я обязательно попробую .. тем временем вы можете разместить вышеупомянутые комментарии в самих своих вопросах .. позже вы можете добавить в качестве ответа - person V4Vendetta; 13.05.2011

спасибо 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
}
person Ben H    schedule 23.03.2012

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

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

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

person Andreas Reiff    schedule 14.05.2011