Article View: borland.public.cppbuilder.nativeapi
Article #344Moving hooke callback to thread - suggestions? (was:Hooks, once again)
From: Anders Johansen
Date: Wed, 07 May 2008 09:40
Date: Wed, 07 May 2008 09:40
188 lines
6807 bytes
6807 bytes
Hi all,
The code below has a potential flaw: The callback code is
running in the main thread, and so may block the system event
processing or at least delay it.
Is there an easy/obvious/recommended way to do this? A
suggestion that has one of the listed attibutes is fine, but
I would of course love one that has all three :)
Anders
"Anders Johansen" <home@dduck.dk> wrote:
>
>Hi all.
>
>I have so far been using the "old fashioned" approach to
>keyboard and mouse hooking, meaning putting the hook procedures
>in a DLL, and using the SetWindowsHookEx with WH_KEYBOARD and
>WH_MOUSE. Now Vista arrives, and this approach is apparently
>blocked for some applications (notable IE) when not running as
>Administrator. I understand the rationale is that this allows
>for code injection, which I guess is fair enough.
>
>This is my alternate approach, submitted for comments and
>inspiration.
>
>I understand that the _LL versions of the hooks will work. They
>have the disadvantage of not being available on systems older
>than NT4 SP3. On the other hand, the callback does not have to
>be in a DLL, which seems to work - can anybody confirm that this
>is correct, e.g. that a DLL is NOT needed when using the _LL
>hooks?
>
>If, as my testing seems to validate, the hooking does not have
>to happen in a DLL, this allows for a much nicer implementation
>than the usual approach. Here's my first attempt, in case
>anybody wants to comment or inspect...
>
>Header:
>#ifndef HookMasterH
>#define HookMasterH
>//---------------------------------------------------------------------------
>
>#include <windows.h>
>#include <map>
>#include <set>
>
>class HookObserver {
> public:
> virtual void keyDown(const UINT vkey, const bool altDown, const int keyDownNumber) = 0;
>};
>
>/*
>The HookMaster uses hooks to monitor keyboard and mouse, and MSAA to
>monitor focus change and window move/resize.
>*/
>class HookMaster {
> private:
> static HHOOK LLKeyHook;
> static HHOOK LLMouseHook;
> static int keyDownNumber;
> static std::set<HookObserver*> observers;
>
> static LRESULT CALLBACK LLKeyHookProc(int nCode, WPARAM wParam, LPARAM lParam);
> static LRESULT CALLBACK LLMouseHookProc(int nCode, WPARAM wParam, LPARAM lParam);
> static void notifyKeyDown(const UINT vkey, const bool altDown);
> public:
> static void addObserver(HookObserver *o);
> static void removeObserver(HookObserver *o);
> static int getKeyDownNumber();
> static bool setHooks();
> static bool removeHooks();
>};
>
>
>CPP file:
>//---------------------------------------------------------------------------
>
>
>#pragma hdrstop
>
>#include "HookMaster.h"
>#include <SysInit.hpp>
>//---------------------------------------------------------------------------
>
>#pragma package(smart_init)
>
>
>HHOOK HookMaster::LLKeyHook = NULL;
>HHOOK HookMaster::LLMouseHook = NULL;
>int HookMaster::keyDownNumber = 0;
>std::set<HookObserver*> HookMaster::observers;
>
>LRESULT CALLBACK HookMaster::LLKeyHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
> try {
> if (nCode<0 || nCode==HC_NOREMOVE )
> return CallNextHookEx(LLKeyHook, nCode, wParam, lParam);
> KBDLLHOOKSTRUCT * pData = ( KBDLLHOOKSTRUCT *) lParam;
> bool Down = (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN);
> bool Alt=(pData->flags & LLKHF_ALTDOWN); // Alt is down
> UINT vkey = pData->vkCode;
> if (Down) {
> if (GetKeyState(VK_CONTROL)>=0 ) {
> notifyKeyDown(vkey, Alt);
> }
> }
> } catch (...) {
> }
> return CallNextHookEx(LLKeyHook, nCode, wParam, lParam);
>}
>
>LRESULT CALLBACK HookMaster::LLMouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
> try {
> if (nCode==HC_ACTION) {
> switch (wParam) {
> case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
> notifyKeyDown(VK_RBUTTON, false);
> break;
> case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
> notifyKeyDown(VK_LBUTTON, false);
> break;
> case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
> notifyKeyDown(VK_MBUTTON, false);
> break;
> }
> }
> } catch (...) {
> }
> return CallNextHookEx(LLMouseHook, nCode, wParam, lParam);
>}
>
>void HookMaster::addObserver(HookObserver *o) {
> observers.insert(o);
>}
>
>void HookMaster::removeObserver(HookObserver *o) {
> observers.erase(o);
>}
>
>int HookMaster::getKeyDownNumber() {
> return keyDownNumber;
>}
>
>bool HookMaster::setHooks() {
> if (LLKeyHook == NULL) {
> LLKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)LLKeyHookProc, HInstance, 0);
> }
> if (LLMouseHook == NULL) {
> LLMouseHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LLMouseHookProc, HInstance, 0);
> }
> return (LLKeyHook != NULL && LLMouseHook != NULL);
>}
>
>bool HookMaster::removeHooks() {
> if (LLKeyHook != NULL) {
> if (UnhookWindowsHookEx(LLKeyHook)) {
> LLKeyHook = NULL;
> }
> }
> if (LLMouseHook != NULL) {
> if (UnhookWindowsHookEx(LLMouseHook)) {
> LLMouseHook = NULL;
> }
> }
> return (LLKeyHook == NULL && LLMouseHook == NULL);
>}
>
>
>void HookMaster::notifyKeyDown(const UINT vkey, const bool altDown) {
> for (std::set<HookObserver*>::iterator i = observers.begin(); i != observers.end(); ++i) {
> try {
> HookObserver *obs = *i;
> obs->keyDown(vkey, altDown, keyDownNumber);
> } catch (...) {
> // Something bad happened with the observer
> }
> }
> ++keyDownNumber;
>}
>
>
>Yes, it needs a little clean-up in sethooks, as it may return
>false and leave a keyboard hook dangling if setting the mouse
>hook fails...
>
>A
Technical Details
Message-ID:
<48217905$1@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news2.google.com!news1.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!198.186.194.250.MISMATCH!news-out.readnews.com!news-xxxfer.readnews.com!70.47.10.52.MISMATCH!newspeer1.nac.net!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mailReferences:
<47c935cb$1@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,4ebd883022a89a5d X-Google-Attributes: gid10cc67,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit From: "Anders Johansen" <home@dduck.dk> Sender: "Anders Johansen" <home@dduck.dk> Reply-To: "Anders Johansen" <home@dduck.dk> Subject: Moving hooke callback to thread - suggestions? (was:Hooks, once again) Newsgroups: borland.public.cppbuilder.nativeapi X-User-Info: 130.226.221.25 References: <47c935cb$1@newsgroups.borland.com> NNTP-Posting-Host: 207.105.83.66 Message-ID: <48217905$1@newsgroups.borland.com> Date: 7 May 2008 02:40:21 -0700 X-Trace: newsgroups.borland.com 1210153221 207.105.83.66 (7 May 2008 02:40:21 -0700) Lines: 189 Path: arc1-ca.pugleaf.net!g2news2.google.com!news1.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!198.186.194.250.MISMATCH!news-out.readnews.com!news-xxxfer.readnews.com!70.47.10.52.MISMATCH!newspeer1.nac.net!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail