Как я могу создать приложение для Windows, которое перехватывает нажатия клавиш и мыши и передает их другим приложениям? - PullRequest
5 голосов
/ 20 апреля 2011

Я работаю с клиентом, который хочет добавить функциональность в устаревшее приложение. Приложение, чей поставщик бесполезен, имеет пользовательский интерфейс Windows Forms. Мой клиент хочет, чтобы определенные функции вне этого приложения запускались, когда пользователь нажимал на часть информации в приложении.

Я видел простую версию, сделанную для другого клиента. В этом случае есть приложение, состоящее из формы, для которой установлено верхнее окно с помощью SetWindowPos. Когда пользователь нажимает кнопку в этой форме, приложение находит окно для старого приложения и получает информацию из заголовка окна. Это не элегантно - есть эта плавающая кнопка, которая никогда не исчезнет, ​​даже если старое приложение не открыто - но оно работает.

Мне было интересно, возможно ли сделать что-то подобное, используя прозрачное окно WPF без полей с установленным свойством Topmost. Приложение, о котором я думаю, проанализирует содержимое в окне старого приложения и определит список горячих точек. Он будет перехватывать и обрабатывать любые щелчки мышью в горячей точке и передавать все оставшиеся щелчки мышью в устаревшее приложение.

У меня нет ужасного опыта работы с Windows API, поэтому я не знаю, насколько просто (или даже возможно) реализовать такую ​​возможность. И мне приходит в голову, что, если бы я создавал инструменты для защиты от вредоносных программ, я имел в виду именно то приложение, которое пытался бы нанести вред.

Если это действительно жизнеспособный проект, каков наилучший способ сделать это? Какие неожиданные проблемы я должен высматривать?

Ответы [ 5 ]

3 голосов
/ 20 апреля 2011

Это можно сделать без хитрости с наложенными кнопками с помощью WH_CALLWNDPROC и / или WH_GETMESSAGE крючков.

1 голос
/ 29 апреля 2011

Подклассы, по моему мнению, - это то, что вы ищете.

Когда создается приложение Windows, оно генерирует окно, а затем добавляет к этому окну суб-Windows (суб-Windows называется Controls и actТочно так же, как Windows! Это могут быть кнопки, текстовые области и т. Д.).

В каждом окне есть оконная процедура, и каждый раз, когда пользователь / программа взаимодействует с вашим окном, ваша оконная процедура будет получать сообщение, содержащее информацию о взаимодействии.Довольно часто элементы управления совместно используют одну оконную процедуру со своим родителем, и внутри этой оконной процедуры код определяет, что делать, исходя из идентификатора (hwnd) окна / элемента управления, который описывает сообщение, то есть: «закрытьЗапрограммируйте, если сообщение 'click' описывает управление кнопкой выхода. Ничего не предпринимайте, если сообщение 'click' описывает родительское окно. ".

Чтобы узнать больше о Windows, посмотрите здесь: http://msdn.microsoft.com/en-us/library/aa383738%28v=vs.85%29.aspx

Подклассы - это процесс перехвата и / или перехвата сообщений, предназначенных для другой процедуры Window.Обычно он служит способом расширения поведения элементов управления и окон сторонних приложений.Можно создать подкласс другого процесса, используя DLL , GetWindowLong(), SetWindowLong(), CallWindowProcedure() и собственную пользовательскую оконную процедуру.Это довольно просто - вот как вы это сделаете:

  • Найдите целевое окно, которое вы хотите создать подклассом, используя FindWindow()
  • Получите предыдущую оконную процедуру и сохраните ее.

WNDPROC wpOrigEditProc = GetWindowLong(hTargetWnd, GWL_WNDPROC)

  • Замените процедуру окна своей собственной.

SetWindowLong(hTargetWnd, GWL_WNDPROC, HookWndProcedure);

Затем,когда выгрузите, восстановите старую оконную процедуру снова.Процедура Window - это то, где произойдет вся ваша магия.Внутри этой функции вы сможете решить, какие сообщения вы хотите обработать и какие сообщения вы хотите передать в старую оконную процедуру.Вот пример оконной процедуры:

LRESULT APIENTRY HookWndProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 
    if(hwnd == hTargetWndButton_OK) {
        // This is the button we wish to intercept... do some processing, then send it back to Windows
        return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } else {
        // Allow the message to pass through to the original application's window procedure.
        return CallWindowProc(wpOrigEditProc, hwnd, uMsg, 
            wParam, lParam); 
    }
} 

`

Хитрость заключается в загрузке вашей DLL в целевой процесс.Я полагаю, что лучший способ сделать это - добавить в приложение запись импорта, которая указывает на вашу DLL, так как приложение и ваша DLL должны все равно оставаться вместе.Чтобы добавить импорт, используйте CFF Explorer!

Уверен, у вас возникнут дополнительные вопросы, потому что может отсутствовать некоторая информация.Я постараюсь ответить на любые другие вопросы, которые возникают из моего поста, но если я не отвечу сразу, прочитайте ссылку MSDN выше: D.Надеюсь, это станет отличным опытом для вас:)

1 голос
/ 24 апреля 2011

Я бы определенно попробовал UI Automation .Это может не сработать, но, по крайней мере, это должно быть довольно легко попробовать.И, в большинстве случаев, если он не работает, это означает, что другого «легкого» пути не будет.

UI Automation уходит своими корнями в вспомогательные технологии для людей с ограниченными возможностями, которые являютсявремя, что мы хотим делать с приложениями, которые нам не принадлежат: делать вещи из внешнего приложения, не имея возможности реально сделать это «стандартным способом».

В нем также логически есть понятие событий, см.официальный документ здесь: Обзор событий автоматизации пользовательского интерфейса

0 голосов
/ 30 апреля 2011

Проверьте diz: http://www.autohotkey.com/

Это сценарий, он может читать заголовки окон и т. Д. И т. Д. (Когда я использовал MS-Windows, я написал крошечный скрипт, который выскочил в окно с суммой цены товара и стоимости p + p, которая Значения были проанализированы при выборе веб-страницы ebay. Кроме того, я изменил ее на свою валюту. Итак, я просто отметил цену товара и p + p, нажал клавишу и вуаля.)

0 голосов
/ 24 апреля 2011

Альтернативный метод для предложения Дэвидса - использовать GetWindowLong, SetWindowLong и CallWindowProc для перехвата proc окна приложений, хотя это немного проще, чем использование метода перехвата окон, но он все еще может быть перехваченэтот метод и / или подкласс снова.см. подклассы окна в msdn для краткого примера: http://msdn.microsoft.com/en-us/library/ms633570(v=vs.85).aspx#subclassing_window

...