...pokračování a dokončení článku z
předchozí části.
4. Monitorování zpráv od myši
V následujícím příkladu použijeme mechanismu hookování pro monitorování všech
zpráv od myši. Připomeňme jen, že reagováním v okénkové proceduře, odchytáváme
tyto zprávy pouze tehdy, nachází-li se myš nad příslušným oknem. To samozřejmě
nemusí v některých případech postačovat. Protože budeme vytvářet globální hook,
musíme monitorovací proceduru umístit do DLL knihovny. Tato knihovna se pak bude
automaticky nahrávat do dalších procesů.
4.1 DLL knihovna
V této DLL knihovně vytvoříme dvě globální proměnné. První z nich je theInstance,
která bude obsahovat handle DLL knihovny a druhá ghMouseHook, která bude
obsahovat handle hookovací procedury. Jejich definice je následující.
HINSTANCE theInstance = NULL;
HHOOK ghMouseHook = NULL; |
První dvě funkce, které implementujeme jsou HookMouse a UnhookMouse.
Jako vždy se nejdříve podíváme na jejich zdrojový kód.
BOOL HookMouse()
{
ghMouseHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC) MouseHookCallback,
theInstance, 0);
return (ghMouseHook != NULL);
}
BOOL UnhookMouse()
{
return UnhookWindowsHookEx(ghMouseHook);
} |
Funkce HookMouse zajišťuje instalaci hookovací procedury a inicializuje
globální proměnnou ghMouseHook. Funkce UnhookMouse tuto proceduru
jednoduše odinstaluje. Obě dvě funkce musí být z DLL knihovny exportovány. Export
těchto funkcí zajistíme hlavičkovým souborem, který bude společný pro DLL
knihovnu i pro aplikaci (tzn. musíme jej vložit do DLL i do EXE). Jeho obsah je
následující.
__declspec(dllexport) BOOL HookMouse();
__declspec(dllexport) BOOL UnhookMouse(); |
Poslední funkcí v knihovně je samotná monitorovací procedura.
LRESULT CALLBACK MouseHookCallback( int nCode, WPARAM wParam,
LPARAM lParam )
{
if (nCode < 0)
return CallNextHookEx(ghMouseHook, nCode, wParam, lParam);
if (wParam == WM_MOUSEMOVE || wParam == WM_NCMOUSEMOVE)
{
LPMOUSEHOOKSTRUCT mhs = (LPMOUSEHOOKSTRUCT) lParam;
CWnd* poWnd = CWnd::FindWindow(NULL, "MouseHook");
if (poWnd != NULL)
{
poWnd->PostMessage((UINT) wParam, 0,
MAKELPARAM(mhs->pt.x, mhs->pt.y));
}
}
return CallNextHookEx(ghMouseHook, nCode, wParam, lParam);
} |
V prvním parametru nCode obdrží funkce kód, který specifikuje způsob
zpracování zprávy. Pokud je tento parametr nastaven na hodnotu HC_ACTION
nebo HC_NOREMOVE je jisté, že v parametrech wParam a lParam
jsou další informace. Hodnota HC_NOREMOVE dále říká, že zpráva
nebude vyjmuta z fronty (aplikace volala PeekMessage s příznakem PM_NOREMOVE).
Pokud je parametr menší než 0 musíme funkci okamžitě ukončit voláním CallNextHookEx.V
parametru wParam obdrží tato metoda kód zprávy od myši a v parametru lParam
ukazatel na strukturu MOUSEHOOKSTRUCT, která obsahuje další informace
(např. souřadnice myši). Následující zdrojový kód ukazuje členské proměnné
této struktury.
V případě, že byla odchycena zpráva WM_MOUSEMOVE, nebo WM_NCMOUSEMOVE
pokusíme se pomocí metody FindWindow vyhledat okno s aplikací a
zaslat mu zprávu o pohybu myši. Tato metoda ve svém druhém parametru očekává jméno
okna.
4.2 Aplikace
Nyní vytvoříme aplikaci, která bude přijímat zprávy od hookovací procedury a
bude zobrazovat aktuální polohu myši. Pro náš příklad zvolíme jednoduchý model dialog-based
aplikace. V okamžiku vytvoření dialogu (v reakci na zprávu WM_CREATE)
nainstalujeme hook voláním exportované funkce HookMouse a při zavírání
dialogu (v reakci na WM_DESTROY), tzn. při ukončování aplikace,
zavoláme druhou exportovanou funkci UnhookMouse a proceduru odinstalujeme.
int CMouseHookDlgAPP::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
if (!HookMouse())
return -1;
return 0;
}
void CMouseHookDlgAPP::OnDestroy()
{
UnhookMouse();
CDialog::OnDestroy();
} |
Poslední reakce bude na zprávy WM_MOUSEMOVE a WM_NCMOUSEMOVE,
ve kterých budeme nastavovat statický text v dialogu tak, aby zobrazoval aktuální
souřadnice. Podívejme se na zdrojový kód těchto funkcí.
void CMouseHookDlgAPP::OnMouseMove(UINT nFlags, CPoint point)
{
m_sMousePosition.Format("Pozice myši x:%d, y:%d", point.x, point.y);
UpdateData(FALSE);
CDialog::OnMouseMove(nFlags, point);
}
void CMouseHookDlgAPP::OnNcMouseMove(UINT nHitTest, CPoint point)
{
m_sMousePosition.Format("Pozice myši x:%d, y:%d", point.x, point.y);
UpdateData(FALSE);
CDialog::OnNcMouseMove(nHitTest, point);
} |
Proměnná m_sMousePosition je typu CString a je
"namapovaná" na statický text v dialogové šabloně.

|