Хуки и DLL
* окна сервера.
****************************************************************/
__declspec(dllexport) BOOL WINAPI setMyHook(HWND hWnd)
{
if(hWndServer != NULL)
return FALSE;
hook = SetWindowsHookEx(
WH_GETMESSAGE,
(HOOKPROC)msghook,
hInstance,
0);
if(hook != NULL)
{ /* удача */
hWndServer = hWnd;
return TRUE;
} /* удача */
return FALSE;
} // SetMyHook
/****************************************************************
* clearMyHook
* Вход:
* HWND hWnd: Окно, чей хук должен быть снят
* Выход: BOOL
* TRUE если хук успешно снят
* FALSE если вы передали неверный параметр
* Действие:
* Снимает установленный хук.
****************************************************************/
__declspec(dllexport) BOOL clearMyHook(HWND hWnd)
{
if(hWnd != hWndServer)
return FALSE;
BOOL unhooked = UnhookWindowsHookEx(hook);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
/****************************************************************
* msghook
* Вход:
* int nCode: Значение кода
* WPARAM wParam: параметр
* LPARAM lParam: параметр
* Выход: LRESULT
*
* Действие:
* Если сообщение является сообщением о перемещении мыши, отправляет его
* окну сервера с координатами мыши
* Замечания:
* Функция должна быть CALLBACK-функцией, или она не будет работать!
****************************************************************/
static LRESULT CALLBACK msghook(int nCode, WPARAM wParam, LPARAM lParam)
{
// If the value of nCode is < 0, just pass it on and return 0
// this is required by the specification of hook handlers
// Если значение nCode < 0, просто передаем его дальше и возвращаем 0
// этого требует спецификация обработчиков хуков
if(nCode < 0)
{ /* передаем дальше */
CallNextHookEx(hook, nCode,
wParam, lParam);
return 0;
} /* передаем дальше */
// Прочитайте документацию, чтобы выяснить смысл параметров WPARAM и LPARAM
// Для хука WH_MESSAGE, LPARAM определяется как указатель на структуру MSG,
// таким образом следующий код делает эту структуру доступной
LPMSG msg = (LPMSG)lParam;
// Если это сообщение о перемещении мыши, либо в клиентской (client), либо
// в не клиентской (non-client) области, мы хотим уведомить родителя о его
// возникновении. Заметим, что вместо SendMessage используется PostMessage
if(msg->message == WM_MOUSEMOVE ||
msg->message == WM_NCMOUSEMOVE)
PostMessage(hWndServer,
UWM_MOUSEMOVE,
0, 0);
// Передаем сообщение следующему хуку
return CallNextHookEx(hook, nCode,
wParam, lParam);
} // msghook
Приложение сервера
В заголовочном файле добавьте следующее в секцию protected класса:
afx_msg LRESULT OnMyMouseMove(WPARAM,LPARAM); |
В фале приложения добавьте это где-нибудь в начале файла:
UINT UWM_MOUSEMOVE = ::RegisterWindowMessage(UWM_MOUSEMOVE_MSG); |
Добавьте следующее в MESSAGE_MAP вне специальных комментариев //{AFX_MSG:
ON_REGISTERED_MESSAGE(UWM_MOUSEMOVE, OnMyMouseMove) |
В файл приложения добавьте следующую функцию:
LRESULT CMyClass::OnMyMouseMove(WPARAM, LPARAM) { // ...тут что-то делаем return 0; } |
Я написал небольшой пример для демонстрации, но поскольку я утомился создавать функцию глобального хука в n+1 раз, я сделал ему отличный пользовательский интерфейс. Кот смотрит из окна и следит за мышью. Но будьте осторожны! Подойдите достаточно близко к коту, и он схватит мышь!
Вы можете скачать этот проект и собрать его. Ключевое значение имеет подпроект DLL; остальное - это использующая ее декоративная мишура.
В этом примере показаны несколько других приемов, включая различные приемы рисования, использование ClipCursor и SetCapture, выбор региона, обновление экрана, и т.д. Таким образом, помимо демонстрации использования перехватывающей функции, для начинающих программистов этот пример имеет ценность в различных аспектах программирования под Windows.