Следующий код зарегистрирует крючок нижнего уровня для отслеживания событий мыши по всему миру.
Это самый простой рабочий пример, который я могу получить.
Собран с VC++ 2010: cl test.cpp /link /entry:mainCRTStartup /subsystem:windows
WinApi: Может ли цикл сообщения прерываться вызовом процедуры Async?
#include <windows.h>
HWND label1 ;
//THE HOOK PROCEDURE
LRESULT CALLBACK mouseHookProc(int aCode, WPARAM wParam, LPARAM lParam){
static int msgCount = 0 ;
static char str[20] ;
SetWindowText(label1, itoa(++msgCount, str, 10)) ;
return CallNextHookEx(NULL, aCode, wParam, lParam) ;
}
int main(){
/**/// STANDARD WINDOW CREATION PART //////////////////////////////////////////////////////
/**/
/**/ WNDCLASSEX classStruct = { sizeof(WNDCLASSEX), 0, DefWindowProc, 0, 0, GetModuleHandle(NULL), NULL,
/**/ LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_BTNFACE+1), NULL, "winClass", NULL } ;
/**/ RegisterClassEx(&classStruct) ;
/**/
/**/ HWND mainWin = CreateWindow("winClass", "", 0, 200,200, 100,100, NULL, NULL, NULL, NULL) ;
/**/ ShowWindow(mainWin, SW_SHOWDEFAULT) ;
/**/
/**/ label1 = CreateWindow("static", "0", WS_CHILD, 5,5, 80,20, mainWin, NULL, NULL, NULL) ;
/**/ ShowWindow(label1, SW_SHOWNOACTIVATE) ;
/**/
/**/// END OF WINDOW CREATION PART ////////////////////////////////////////////////////////
//HOOK INSTALATION
HHOOK hookProc = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, GetModuleHandle(NULL), 0) ;
//MESSAGE LOOP
MSG msg ;
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg) ;
DispatchMessage(&msg) ;
}
UnhookWindowsHookEx(hookProc) ;
}
Это основной один поток, одно окно, один из примеров сообщение насоса. За исключением крючка для мыши.
Мои сомнения в том, что то, что этот код делает противоречит две вещи я прочитал снова и снова в SO, MSDN, форумы, блоги и т.д ..
Глобальные процедуры крюков должны находиться в DLL
MSDN documentation forSetWindowsHookEx
подтверждает это, говоря:Если dwThreadId параметр равен нулю, параметр lpfn MUST указывают на подключаемую процедуру в DLL
Невозможно прервать нить GUI (одна с сообщением), так как состояние ожидания
GetMessase
не является предупреждающим. Это означает, что когдаGetMessage
блокирует больше сообщений, он не может получить сигнал, который прерывает его состояние ожидания.
Однако, нет никакого DLL в любом месте, чтобы увидеть здесь, а также подключаемая процедура должна прерывать нить, иначе программа не будет работать, и это (я предполагаю, что есть только один поток в эта программа).
Таким образом, либо я полностью неверно истолковал эти две точки, либо этот код работает таким образом, который не соответствует асинхронному подходу вызова процедур, который я ожидал.
В любом случае, я не знаю, что здесь происходит.
Не могли бы вы объяснить, как работает этот код.
Это однопоточная программа?
Является ли процедура крюка прерыванием нитки?
Действительно ли какие-либо из двух точек выше?
Теперь все имеет смысл. Вы просто забыли связать страницу MSDN со всей этой информацией: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644986.aspx – GetFree
Итак, я полагаю, что 'DispatchMessage' решает, следует ли вызвать WindowProcedure или HookProcedure в зависимости от типа сообщения. – GetFree
@GetFree: Нет. Процедура hook вызывается, ** перед ** очередь сообщений целевой нити даже видит входное событие. К моменту, когда ваш код вызывает 'DispatchMessage', процедура hook уже давно вернулась. – IInspectable