Як я можу програмно генерувати події клавіш у C #?


107

Як я можу програмно створити подію, яка б імітувала натискання клавіші на клавіатурі?


6
Вам просто потрібна подія, щоб звільнити?
Даніель А. Білий

Я думаю, вам доведеться вступити в некерований код, щоб імітувати "справжнє" натискання клавіш.
Йонас Б

Так, мені просто потрібна подія, щоб звільнити.
Дан Вогель

1
@GONeale: Вау, трирічний коментар. Добре тоді. Так, для цього є дійсними способами використання, тому в першу чергу існує API. Однак їх мало і далеко між ними. З мого досвіду багато людей роблять це, тому що вони насправді не розуміють найкращого способу вирішення проблеми, тобто "я хочу зателефонувати до коду в моєму обробці подій натискання кнопки, але не тільки при натисканні на кнопку". Отже, для початківця здається логічним імітувати натискання кнопки, коли те, що вони насправді повинні зробити, це взяти цей код, перекинути його у функцію та викликати його з інших місць коду.
Ед С.

6
@EdS: Питання було досить зрозумілим. Я міг би додати багато зайвих деталей щодо створення клавіатури, і все ж отримав ту саму відповідь. Зважаючи на те, що я отримав саме те, що мені потрібно, це не здається мені "неякісним" питанням.
Дан Вогель

Відповіді:


147

Питання позначено WPF, але відповіді поки що конкретні WinForms та Win32.

Для цього в WPF просто побудуйте KeyEventArgs та зателефонуйте на ціль RaiseEvent. Наприклад, щоб надіслати ключовий вигляд KeyDown клавіші Вставити в даний момент сфокусований елемент:

var key = Key.Insert;                    // Key to send
var target = Keyboard.FocusedElement;    // Target element
var routedEvent = Keyboard.KeyDownEvent; // Event to send
     target.RaiseEvent(
  new KeyEventArgs(
    Keyboard.PrimaryDevice,
    PresentationSource.FromVisual(target),
    0,
    key)
  { RoutedEvent=routedEvent }
);

Це рішення не покладається на власні дзвінки чи внутрішні Windows та має бути набагато надійнішим за інші. Це також дозволяє імітувати натискання клавіші на певному елементі.

Зауважте, що цей код застосовується лише для подій PreviewKeyDown, KeyDown, PreviewKeyUp та KeyUp. Якщо ви хочете надіслати події TextInput, ви зробите це:

var text = "Hello";
var target = Keyboard.FocusedElement;
var routedEvent = TextCompositionManager.TextInputEvent;

target.RaiseEvent(
  new TextCompositionEventArgs(
    InputManager.Current.PrimaryKeyboardDevice,
    new TextComposition(InputManager.Current, target, text))
  { RoutedEvent = routedEvent }
);

Також зауважте, що:

  • Контролери очікують отримання подій попереднього перегляду, наприклад PreviewKeyDown повинен передувати KeyDown

  • Використання target.RaiseEvent (...) посилає подію безпосередньо до цілі без метаобробки, таких як прискорювачі, композиція тексту та IME. Це зазвичай те, що ви хочете. З іншого боку, якщо ви дійсно робите те, що чомусь імітують фактичні клавіші клавіатури, ви скористаєтесь InputManager.ProcessInput ().


1
Я просто спробував вашу пропозицію, я не бачу ефекту. Я приєднав обробник подій keyDown до зосередженого елемента. Подія, яку я підняв, отримується, але KeyState є None, ScanCode - 0, а isDown - помилковим. Я припускаю, що я отримую ці значення, оскільки це фактичний стан клавіатури. Натискання клавіші на фактичній клавіатурі, KeyState = Вниз, isDown = true, і ScanCode має значення.
Дан Вогель

25
коли я спробував перший код примикання клавіш, я отримав помилку в "target" не можу перетворити його у візуальний чому?
картал

3
Ден, ти знаєш, як емулювати натискання клавіші з модифікатором (ctrl / alt / shift)? Деталі, які мені потрібні для моделювання InputBinding: m_shell.InputBindings.Add (новий KeyBinding (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
Шрайк

14
Про цільової проблеми, я працював його за допомогою Keyboard.PrimaryDevice.ActiveSourceсм stackoverflow.com/questions/10820990 / ...
OscarRyz

4
Ця відповідь дуже хороша, але її не можна використовувати для надсилання ключа з модифікатором, як зазначав @Shrike. (Напр Ctrl+C.)
ANeves

27

Щоб створити ключові події без контексту Windows Forms, ми можемо використовувати наступний метод,

[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

зразок коду наведено нижче:

const int VK_UP = 0x26; //up key
const int VK_DOWN = 0x28;  //down key
const int VK_LEFT = 0x25;
const int VK_RIGHT = 0x27;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
int press()
{
    //Press the key
    keybd_event((byte)VK_UP, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
    return 0;
}

Список віртуальних клавіш визначені тут .

Щоб отримати повне зображення, скористайтеся посиланням нижче, http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html


Підходить, якщо ваше вікно буде зверху. Це частково вирішило мою ситуацію, дякую!
Сергій

Доповненням до відповіді Rajesh, якщо ви хочете зробити це на мобільній платформі, ви повинні імпортувати "coredll.ddl"
user1123236

21

Я його не використовував, але SendKeys може робити все, що завгодно.

Використовуйте SendKeys, щоб надсилати активні програми комбінації клавіш та натискань клавіш. Цей клас не може бути ініційований. Щоб надіслати клавішу клавіші класу та негайно продовжити потік вашої програми, використовуйте Надіслати. Щоб дочекатися будь-яких процесів, запущених натисканням клавіші, використовуйте SendWait.

System.Windows.Forms.SendKeys.Send("A");
System.Windows.Forms.SendKeys.Send("{ENTER}");

Microsoft має ще кілька прикладів використання тут .


3
Я спробував використовувати SendKeys.Send, і я отримав це InvalidOperationException: "SendKeys не може працювати у цій програмі, оскільки програма не обробляє повідомлення Windows. Або змініть програму для обробки повідомлень, або використовуйте метод SendKeys.SendWait." Використання SendKey.SendWait не впливає.
Дан Вогель

Переконайтеся, що ви не надсилаєте до себе ключову подію. Перш ніж надсилати подію, переключіть фокус на належний процес. Друга пов'язана стаття має певну допомогу з цього приводу.
Майкл Петротта

11

Легко! (адже хтось уже зробив роботу за нас ...)

Провівши багато часу, намагаючись на це запропонувати відповіді, я натрапив на цей проект кодеклексу Windows Input Simulator, який спростив, як можна, імітувати клавішу:

  1. Встановити пакет можна за допомогою менеджера пакунків NuGet або з консолі диспетчера пакунків:

    Встановити-пакетний вхідний симулятор

  2. Використовуйте цей 2 рядок коду:

    inputSimulator = new InputSimulator() inputSimulator.Keyboard.KeyDown(VirtualKeyCode.RETURN)

І це все!

------- РЕДАКЦІЯ --------

Сторінка проекту в кодеплексі чомусь позначена, це посилання на галерею NuGet.


Це працює дуже добре, проте мені не вдалося знайти, як зробити цю роботу за допомогою комбінації клавіш,
user1234433222

Коли ви говорите комбінацію клавіш, ви маєте на увазі CTRL-C?
Райвід Голденберг

так, або навіть якщо ви хотіли, щоб програма консолі перейшла на весь екран, наприклад, Alt-Enter, я знаю, ви можете використовувати F11 для входу в повний екран, але було б добре побачити, чи працює Alt-Enter :)
користувач1234433222

1
Добре ви можете це зробити, хоча я ще не пробував цього, просто використовуйте inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
Райвід Голденберг

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.