Click to See Complete Forum and Search --> : How to block messages going to an application by using a hook?
mingwah
May 14th, 1999, 07:29 AM
Hi,
I am writing an application which examines WM_CHAR messages (using a system-wide WH_GETMESSAGE hook) going to any active application with the keyboard focus. If the message contains the character I am looking for, I'll route this keystroke message to my application instead (using SendMessage). In addition, I would want to prevent the original message from reaching the window with the keyboard focus.
How can I block WM_CHAR messages from reaching their destinations in my hook? Could I change the hWnd param stored in the WM_CHAR message (substitute with my application's hWnd) and deceive the system? In fact if I do this, I could kill two birds with one stone. I did try this idea, but it didn't seem to work. Maybe I did something wrong somewhere?
Could anyone help me out here? Thanx.
Ming Wah.
PS: Also, I did explore using the keyboard hook, which *could* prevent WM_KEYDOWN and WM_KEYUP messages from going to their destinations. However, this doesn't really serve my purpose because without translating these keyups and keydowns, I don't get capital letters.
muscicapa
May 14th, 1999, 08:11 AM
From What I understood, you wanted to translate all characters typed to CAPITALS. I have tried this using WH_KEYBOARD by eating up the messages by returning 1; and just before that SendMessage To the same target after manipulating the wParams and lParams. I am told that one cant change the message with a Keyboard Hook but can change messages using a MsgFilter Hook.
I should like to know more about this too ..
mingwah
May 15th, 1999, 12:30 AM
MsgFilter Hook? Hmm... Okay, I'm going to check up on that. Actually, do you mean the WH_GETMESSAGE hook? I've tried that. I can indeed modify anything in the message, except to stop it from being delivered.
Anyway, I need all keyboard "typable" characters like 0-9, A-Z, a-z, and all punctuation marks. When I use the WH_KEYBOARD hook, I only get WM_KEYUPs and WM_KEYDOWNS, which are very "raw" to me. For example, 'A' is actually composed of VK_SHIFT and 'a'. In the Keyboard hook, I will see keyups and downs for VK_SHIFT and 'a', not 'A'. The function TranslateMessage (called by the active app, I suppose) will then interprete VK_SHIFT + 'a' and create a WM_CHAR message with the character code of 'A'. That is what I want, the end-product character code, because I can then determine if the character is what I want. Also I don't want to interfere with macro keys like Ctrl-A, Ctrl-F, etc, which can be easily detected in the WM_CHAR message (by checking the ascii range).
By the way, this morning I just tried changing the hwnd param in the MSG structure of the WM_CHAR message to point to my application instead (that means the message will be re-routed to my app) and guess what? I crashed the active application (I'm experimenting on Word97). Another failure for me. 8-(
Anybody has any other suggestions?
Ming Wah.
Dan Haddix
May 15th, 1999, 08:57 PM
I'm just curious but what exactly are you trying to do??? As far as I can tell from the documentation the WH_GETMESSAGE hook only allows you to modify the message before it is routed to the window that has input focus. So there is no way to prevent the window from recieving the message, only a way to change what message it recieves (or the messages parameters). Perhaps you could try changing the message type to WM_NULL, this may cause the application to ignor the message and create the effect your looking for.
Dan
P.S. Let me know if it actually works!!!
muscicapa
May 17th, 1999, 08:54 AM
Blocking messages seems to work with WH_KEYBOARD by just returning 1;
Heres the fragment that prevents CAPITALS from being entered
THIS PART IN AN EXE
--------------
hmod=NULL;
hmod=LoadLibrary("hookdll");
typedef LRESULT (*func)(int,WPARAM,LPARAM);
func kbhfun=NULL;
kbhfun=(func)GetProcAddress(hmod,"KeyboardHook");
if (hmod)
{
hkbdhook=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)kbhfun,hmod,0);
}
THIS PART IN A DLL
------------------
extern "C" LRESULT PASCAL CALLBACK KeyboardHook(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// handle only for HC_ACTION
if (code!=HC_ACTION) return 1;
// pass on to other hooks down the chain
if (code<0)
return CallNextHookEx(NULL, code, wParam, lParam);
// quit if key_up message generated
SHORT keystate=GetKeyState(wParam);
if ((keystate & 0x80)==0) return 0;
// if (lParam & 0x80000000) return 0;//another way
// get the state of Caps lock and shift key
SHORT shift=GetKeyState(VK_SHIFT);
SHORT caps=GetKeyState(VK_CAPITAL);
BOOL capson=(caps&0x1!=0); // caps lock on
BOOL shifton=((shift!=0)&&(shift!=1)); //shift key down
// debugcode
// char s[21]; // buffer for storing key name
// GetKeyNameText(lParam,s,20);//get key name
// CString msg;msg.Format("shift:%x\ncaps:%x\nwParam:%x\nlParam:%x",shift,caps,wParam,lParam);
// AfxMessageBox(msg,MB_OK,0);
/*
// isCapitals ? then filter out else allow
if (((shifton)&&(!capson))||((!shifton)&&(capson)))
return 1;
else */
return 0;
}
How to mutate a message on its way is still a question ...
mingwah
May 26th, 1999, 11:10 PM
Hi,
It is an excellent idea to convert the WM_CHAR message to WM_NULL !
I was actually looking for such an "inert and harmless" message but I just didn't find its documentation anywhere else. Thanx!
After implementing this idea, in normal cases, it worked fine. But one thing I couldn't understand is that sometimes, the original destination application of the messages (I used Word97) actually displays a null character, even though I had already converted the WM_CHAR messages to WM_NULL messages with NULL parameters! I worked around this problem by changing the focus from the active document in Word97 to Word97 itself, and then back to the active document again. Not much difference to the user, but it stops the active document from displaying null characters. I don't understand this behaviour at all.
Anyway, I stumbled upon another solution. While I was reading the documentation of DispatchMessage, I found that DispatchMessage actually *ignores* any messages with a NULL hWnd. So, in my hook, I simply change the hWnd field in the MSG structure to NULL and the message indeed did not show up in the original destination (the active document in Word97) anymore!
Thank you for the wonderful suggestion.
scharf
May 27th, 1999, 12:35 AM
I would not use keyboard hooks in this case, as EVERY message from the keyboard is routed through this hook procedure.
BE sure if yiu return 1 this message is lost forever, also for other apps which are interested in this message, because they keyboard hook is called BEFORE this message gets into the MFC message pump.
What would better is using the PreTranslateMessage within your application, and just filtering this special key out. So you can be sure, that you onmly dismiss messages which are intended for your app. (You must have the keyboard input focus).
Be also aware to unsinstall the hook when closing you process.................
muscicapa
May 27th, 1999, 10:37 PM
I think the original question required the message to a thridparty product to be changed - which has to be done via a hook.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.