|
That was the way I originally implemented the hooks. The problem is that there doesn't seem to be a way to block both of the types of messages. The classic way seems to be to return -1, but that means that either the mouse or keyboard callback won't get called. Also, setting wParam=WM_NULL doesn't seem to work. So thats the reason I was trying to use a WH_GETMESSAGE hook. I'm open to suggestions on how to approach it though.
modified 12-Jul-20 21:01pm.
|
|
|
|
|
If you use WH_KEYBOARD_LL and WH_MOUSE_LL hooks and DO NOT call the CallNextHookEx, then the message will be blocked.
From the MSDN:
"Calling the CallNextHookEx function to chain to the next hook procedure is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications."
We use the WH_KEYBOARD_LL to block ALT+TAB and other key combinations and it works great!
|
|
|
|
|
The problem is, that if I first hook the keyboard and then the mouse, and I don't call CallNextHookEx from the keyboard hook, the mouse hook won't be called, so I can't get the messages. Same applies if its the other way around. That's why I was thinking the WH_GETMESSAGE hook would be preferable.
modified 12-Jul-20 21:01pm.
|
|
|
|
|
Don't use the same function for each hook, or figure out why you are being called and decode the message and decide to send it further on or not.
There is no fundamental reason one hook should be interfering with the other, unless you inadvertently coded it that way.
|
|
|
|
|
I'm using separate functions for the hook. They are below:
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(HC_ACTION==nCode)
{
switch(wParam)
{
case WM_MOUSEMOVE:
case WM_NCMOUSEMOVE:
PostMessage(g_hWnd,g_hMouseMove,wParam,lParam);
break;
default:
PostMessage(g_hWnd,g_hMouseAct,wParam,lParam);
break;
}
}
if(g_bBlock)
return -1;
return CallNextHookEx(g_hHookMouse,nCode,wParam,lParam);
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(HC_ACTION==nCode)
{
PostMessage(g_hWnd,g_hKeyboard,wParam,lParam);
}
if(g_bBlock)
return -1;
return CallNextHookEx(g_hHookKey,nCode,wParam,lParam);
}
I install the hooks with this:
g_hHookMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,g_hInst,0);
if(NULL==g_hHookMouse)
return FALSE;
g_hHookKey=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,g_hInst,0);
if(NULL==g_hHookKey)
return FALSE;
If g_bBlock is true, then it will block the mouse messages and the keyboard messages, though my app will still be able to process the mouse messages, but not the keyboard messages.
Maybe I misunderstood you, please tell me if I did.
modified 12-Jul-20 21:01pm.
|
|
|
|
|
This looks fine, mostly.
Also, you have to 'ignore' your block code if the nCode is less than zero:
<br />
LRESULT CALLBACK MouseProc(<br />
int nCode, <br />
WPARAM wParam, <br />
LPARAM lParam<br />
){<br />
if( HC_ACTION == nCode ){<br />
<br />
switch( wParam ){<br />
case WM_MOUSEMOVE:<br />
case WM_NCMOUSEMOVE:<br />
PostMessage(g_hWnd,g_hMouseMove,wParam,lParam);<br />
break;<br />
default:<br />
PostMessage(g_hWnd,g_hMouseAct,wParam,lParam);<br />
break;<br />
}<br />
<br />
if( g_bBlock ){<br />
return -1;<br />
}<br />
}<br />
<br />
return CallNextHookEx(g_hHookMouse,nCode,wParam,lParam);<br />
}<br />
You should do similarly for the mouse handler.
If you process a hook message while the nCode is NOT HC_ATION you will see bizarre results.
I notice you 'dont pass on' based upon the same global variable: g_bBlock
So, it would seem to me, if your 'block' variable is true, you won't see mouse or keyboard messages posted to anything but your global window.
Except, you might try changing it to
<br />
g_hHookMouse=SetWindowsHookEx(WH_MOUSE_LL,MouseProc,g_hInst,0);<br />
and
<br />
g_hHookKey=SetWindowsHookEx(WH_KEYBOARD_LL,KeyboardProc,g_hInst,0);<br />
So you get raw events, and not ones that have been translated.
Also, in your install code, you will leak a hook handle:
If you keyboard hook install fials, you should unhook the mouse hook before returning false...
|
|
|
|
|
Good caught on the blocking statement, my fault on copying and pasting, it was in the right place originally.
After making your changes it works to some extent. All the messages are sent, but they're strange. Keyboard events lParam seem to be intact, I can still see if it was key up or down, but the key that was pressed seems to be scrambled, it doesn't map out to the right key, if it maps out at all. And the mouse move messages send the point that the mouse was last at, which I guess makes sense, and I guess I didn't specify that I need the coordinates of the mouse where it would be on screen if the mouse moved.
Sorry to be so whiny , but here's what I have now:
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(HC_ACTION==nCode && nCode>=0)
{
switch(wParam)
{
case WM_MOUSEMOVE:
case WM_NCMOUSEMOVE:
PostMessage(g_hWnd,g_hMouseMove,wParam,lParam);
break;
default:
PostMessage(g_hWnd,g_hMouseAct,wParam,lParam);
break;
}
if(g_bBlock)
return -1;
}
return CallNextHookEx(g_hHookMouse,nCode,wParam,lParam);
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(HC_ACTION==nCode && nCode>=0)
{
if(wParam==VK_F12)
InputBlock(FALSE);
PostMessage(g_hWnd,g_hKeyboard,wParam,lParam);
if(g_bBlock)
return -1;
}
return CallNextHookEx(g_hHookKey,nCode,wParam,lParam);
}
...
g_hHookKey=SetWindowsHookEx(WH_KEYBOARD_LL,KeyboardProc,g_hInst,0);
if(NULL==g_hHookKey)
return FALSE;
g_hHookMouse=SetWindowsHookEx(WH_MOUSE_LL,MouseProc,g_hInst,0);
if(NULL==g_hHookMouse)
return FALSE;
I imagine its a case of the code working perfectly (well, it always does, but you know what I mean), and that I need to be more specific on what I want. Basically, I need the mouse to actually move, so I can get the need coordinates and I need the actual key pressed.
Thanks for all the help so far!
Oh, and the leak is handled, when the DLL is unloaded it uninstalls and hooks that were installed.
modified 12-Jul-20 21:01pm.
|
|
|
|
|
When you use the low level keyboard hook, the lParam is different:
"lParam [in] Pointer to a KBDLLHOOKSTRUCT structure."
When you use the low level mouse hook, the lParam is different:
"lParam [in] Pointer to an MSLLHOOKSTRUCT structure."
You need to decode the data structure and pass the information to your program.
You can decode these data structures and pack the information intersting to your program into the lParam posted to your window, or else make a thread-safe queue and copy data to the queue, and then retrieve the queued data when a special message is processed by your window - perhaps a registered message indicating that new data is in the queue.
|
|
|
|
|
Thanks, making those changes it works great. Also, if I selectively don't return -1 while blocking the messages, the cursor moves and I get the coordinates I need. Thanks again for all you help and patience!
By the way, sometimes after removing the hook the start key is mapped to escape, even though I didn't touch those, it goes away after a little bit, but I was wondering if that was my fault or just a sympton?
-Aaron
modified 12-Jul-20 21:01pm.
|
|
|
|
|
Inside your hook functions, if you modify the lParam to post to your window, you should use a temporary variable like mylParam, instead of modifying the ORIGINAL lParam, in case you need to contionue to pass the original lParam onto the next keyboard hook. Possibly that has happened - you changed the original lParam, so there is now a side effect? Or you changed the data that was being pointed to by the hook structure. You should not modify the original data if you pass it on to the next hook handler.
|
|
|
|
|
I don't actually modify the lParam at anypoint, I just copy it and pass it on.
modified 12-Jul-20 21:01pm.
|
|
|
|
|
Well,I've personally been trying to modify the original lParam in order to change key presses. In some instances, I need to change an "L" press to an "S". I thought that by installing a low level keyboardhook, I would be able to do this. I can eat the keypresses, so I know that my hook is installed, but I can't seem to get the substitution to occur.
Regardless of how I change the lParam, the original keypress still happens. I've tried changing the vkCode and scanCode to different keys, and I can see that the changes are there in my callnexthook, but I don't see any changes in the key output.
I've been attempting forever and I can't seem to get it to work. I've tried creating my own lParam with the necessary info and passing that -- still without it working. I really feel like I'm missing something fundamental.
|
|
|
|
|
I am sorry, but I do not know.
I reviewd the MSDN documentation and could not locate anything to confirm or deny that you SHOULD be able to modify the input. A whole lot of talk about passing it on or denying, but nothing about modification. We used our hook for blocking purposes only.
|
|
|
|
|
The delay in your release of the keys might be a symptom of this, directly from MSDN:
"You can release a global hook procedure by using UnhookWindowsHookEx, but this function does not free the DLL containing the hook procedure. This is because global hook procedures are called in the process context of every application in the desktop, causing an implicit call to the LoadLibrary function for all of those processes. Because a call to the FreeLibrary function cannot be made for another process, there is then no way to free the DLL. The system eventually frees the DLL after all processes explicitly linked to the DLL have either terminated or called FreeLibrary and all processes that called the hook procedure have resumed processing outside the DLL."
|
|
|
|
|
AM super new to the MFC
but i like it cause it easy to learn
so am making a project
i have 2 edit box and i want to write to 2 different files how will i do this with out removing all the data
for the file.
a small code sample will help alot
thanks alot
|
|
|
|
|
There are several solutions. Using raw C++, you could open the file in binary mode, seek the end of the file pointer, and append data.
Kuphryn
|
|
|
|
|
|
Can anyone direct me to a source that explains ways to code 'zoom ins and outs'? What I basically need is an algorithm to blow up or shrink down an image by clicking a button or, better, by rubberbanding an area of the image.
Thanks,
Ralf.
ralf.riedel@usm.edu
|
|
|
|
|
Just type cximage in search box it will take you to the project which does all this and more
|
|
|
|
|
StretchBlt is all you need.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
Christian Graus wrote:
StretchBlt is all you need.
But it's non-intelligent in its operation as it doesn't resample the image but merely cuts pixels off or blows pixels up. CxImage[^] gets my vote.
--
Dad, how strange it is that the pig can speak. *thoughtful pause* It must have lost its "oink". (my 3-year old daughter Moa, while watching Babe)
Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so. (Douglas Adams)
|
|
|
|
|
Johann Gerell wrote:
But it's non-intelligent in its operation
True, but we're assuming that this guy needs the complexity that comes from adding another class to his project ( not saying that CxImage is hard to use, I've not looked at it ). If you set the right stretch mode, StretchBlt gives reasonable results, why uses a jack hammer to nail in a tack ?
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
Christian Graus wrote:
If you set the right stretch mode, StretchBlt gives reasonable results
Well, I develop for CE, where the stretch mode can't be set (it's carved in stone).
Christian Graus wrote:
why uses a jack hammer to nail in a tack
That's often the normal scenario when dealing with CE's limited API set.
Anyway, the resampling code can easily be broken out from CxImage and be used separately.
--
Dad, how strange it is that the pig can speak. *thoughtful pause* It must have lost its "oink". (my 3-year old daughter Moa, while watching Babe)
Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so. (Douglas Adams)
|
|
|
|
|
Johann Gerell wrote:
Well, I develop for CE, where the stretch mode can't be set (it's carved in stone).
That's a whole different ball game then
Johann Gerell wrote:
That's often the normal scenario when dealing with CE's limited API set.
*grin* well, no-one had mentioned CE before this, so...
Johann Gerell wrote:
Anyway, the resampling code can easily be broken out from CxImage and be used separately.
Sure - that stuff is pretty easy to write in any case.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
Thanks for all that discussion. I'll try both, one for a quick and dirty image processing and the other for situations when a more accurate processing is justified. Best,
Ralf.
ralf.riedel@usm.edu
|
|
|
|
|