Отправить быстрый текстовый ввод другому процессу (Окно) - PullRequest
3 голосов
/ 25 сентября 2011

Я пишу программу C # WPF, которая отправляет текстовые сообщения в окно другой программы. У меня есть макропрограмма как часть моих драйверов клавиатуры (Logitech G15), которая уже делает это, хотя она не посылает нажатия клавиш непосредственно процессу, а в текущее окно. Это работает хорошо, но мне нужно иметь возможность отправлять входные данные из моей программы. Есть другие люди, использующие этот процесс, поэтому ввод текстовых сообщений из моей программы должен быть достаточно быстрым, чтобы мой текст не мешал их вводу. Проблема в том, что когда я пытаюсь сделать это с помощью программы на c #, я получаю слишком большую задержку. Макропрограмма (Logitech G-Series Profiler) отправляет команду мгновенно. Я попробовал следующие три команды для отправки сообщений для обработки. (Перечислено по порядку от самого медленного до самого быстрого)

SetForegroundWindow(_hWnd);
SendKeys.SendWait("{Enter}This is a keystroke input.{Enter}");

Это, вероятно, в названии, но это выполняет команду настолько медленно, что я могу фактически следить за текстом, поскольку он вводится буква за буквой. Я пытался использовать метод «SendKeys.Send», но получаю сообщение об ошибке: «SendKeys не может работать внутри этого приложения, поскольку приложение не обрабатывает сообщения Windows».

PostMessage((IntPtr)_hWnd, (uint)WMessages.WM_KEYUP, (int)key, (int)key);

PostMessage немного быстрее, но все еще недостаточно быстро для целей моей программы. Кроме того, метод возвращается до того, как процесс прочитал сообщение, что означает, что два последовательных вызова PostMessage могут не отправлять последовательные сообщения.

SendMessage(_hWnd, 0x100, (int) VKeys.VK_2, (int) VKeys.VK_2);

Это быстрее, чем PostMessage, но не так быстро, как макропрограмма от Logitech. Кроме того, принимающая программа обрабатывает ввод странным образом, очевидно, не обрабатывая его так же, как «подлинный» ввод с клавиатуры.

SetForegroundWindow(_hWnd);

const string text = "This is a keystroke input.";
IInputElement  target = Keyboard.FocusedElement;

IInputElement target = InputManager.Current.PrimaryKeyboardDevice.FocusedElement;

var routedEvent = TextCompositionManager.TextInputEvent;

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

Это последнее, что я попробовал. Кажется, мгновенно, когда текст отправляется в процесс. Тем не менее, я смог отправить это только моей собственной программе, так как Keyboard.FocusedElement возвращает ноль, когда у меня есть другая программа, установленная в качестве окна переднего плана. Если кто-то может сказать мне, как получить IInputElement другого окна, я бы хотел знать. В качестве альтернативы, если у кого-то есть предложение по лучшему методу отправки ввода, я бы очень хотел его услышать.

Характеристики: Windows 7, 64-битная Visual Studio 2010, Framework 4

Ответы [ 2 ]

2 голосов
/ 26 сентября 2011

Прежде всего, вы намеренно используете WM_KEYDOWN (0x0100) вместо WM_KEYUP (0x0101) в вашем SendMessage примере?Это будет просто нажимать клавиши и никогда не отпускать их, поэтому приложение не будет обрабатывать их должным образом.

Еще один способ, который стоит попробовать, - отправить WM_SETTEXT , предполагая, что элемент управления интерпретирует его правильно (как элементы управления редактирования или комбинированные блоки).

Последний вариант - использовать SendInput , который синтезирует ввод с клавиатуры и мыши на очень низком уровне, но, как и в вашей макрос-программе клавиатуры, для этого требуетсяВы должны активировать правильное окно и установить фокус, который может быть довольно болезненным.

0 голосов
/ 26 сентября 2011

В зависимости от типа окна другой программы вы можете использовать UI Automation .Смотрите этот пример здесь:

Добавление содержимого в текстовое поле с помощью автоматизации пользовательского интерфейса

...