In order to hook a wndproc, I write a wndprochook and use SetWindowLong:
wndproc=(WNDPROC)GetWindowLong(hwnd_1,GWL_WNDPROC);
SetWindowLong(hwnd_1,GWL_WNDPROC,(LONG)wndprochook);
Now I have to do something in wndproc and at the end of the function, I call the original wndproc:
return wndproc(hwnd, uMsg, wParam, lParam);
It fails, but thank god I find CallWindowProc:
return CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam);
Now it's working. So Question1: Why do we have to use CallWindowProc? What's missing when simply calling wndproc?
The hook is working good, but when I quit the program, it crashes. Of course, everything is done and the crash doesn't actually affect anything. But it's still bad to see a crash.
So Question2: What may happened here and how to fix it?
I'm sorry that I have no information about how the original program closes itself, since all that I do is just hooking the wndproc to capture some messages. So I'm just hoping someone experienced enough who have ever encountered similar situations before could help.
From the documentation of CallWindowProc:
“If this value is obtained by calling the GetWindowLong function with the nIndex parameter set to GWL_WNDPROC or DWL_DLGPROC, it is actually either the address of a window or dialog box procedure, or a special internal value meaningful only to CallWindowProc”
You can't call the “special internal value“ except by doing the same as CallWindowProc does, and the easiest way to do that is to call CalLWindowProc…
By the way, have a look at SetWindowSubclass, it may ease things for you.
Regarding Question 2:
From comments on another answer, it sounds like your subclass wndprochook is in a DLL that's injected into a process. If that's the case, then during exit, your DLL may be unloaded while there are still messages pending for the window. So the Window's class still points to your wndproc, but that code is unloaded, so it crashes.
The safest thing to do is probably to restore the original wndproc before you shut down. For example, when your subclass sees WM_DESTROY or perhaps WM_NCDESTROY, you essentially reverse the steps you did when you subclassed the window: restore the original wndproc field in the window class, before doing your CallWindowProc with that message. Your code will no longer be called, even if a few more messages trickle in for that window.
thx to Adrian McCarthy.
Private Function WndProc(ByVal hWnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case MSG
Case WM_CUT, WM_PASTE, WM_CLEAR
WndProc= 1
Case WM_DESTROY, WM_NCDESTROY
Call UnHookRKey(hWnd)
Case Else
WndProc= CallWindowProc(lngPrevWndProc, hWnd, MSG, wParam, lParam)
End Select
End Function
Related
I am looking into reworking an old CBT windows hook, and am slightly confused as to how it is currently working. The way it is setup is one dll handles the Windows hooking and its logic, while another program calls into that dll when the hook should be set. It looks like this:
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
// this is the function the other program calls into
void InstallHook()
{
// hdll is this dll's address
SetWindowsHookEx(WH_CBT, HookProc, hDLL, 0);
}
Then we have our DllMain function. That dllmain function seems to get called whenever the hookProc function is invoked, and I do not understand this behavior. I've examined the fdwReason and it is getting called due to a dll process attach event.
How is this event being fired every time the HookProc is called? Since it is a global hook, I thought windows would load the dll and just persist it, calling the HookProc when the need arose. But from what I'm seeing, it acts like it is loaded back up anytime HookProc is called. Is this how it usually works, or could another part of the code base be causing this?
DLLs that implement global hooks get loaded into any process in the system that triggers the hook.
(This is precisely why global hooks must be implemented as DLLs - so they can be loaded into other processes).
For those of you who do not know what I am talking about:
http://www.teamviewer.com/images/presse/quickconnect_en.jpg
Teamviewer overlays that button on all windows to allow you to quickly share a window with someone else. I would like any ideas on implementing something similar -- if you have example code, even better (specifically, the button -- not the sharing). I am interested in C++ and QT... but I would be interested in good solutions in other languages/libraries if there are any.
Thanks.
To draw buttons or other stuff in foreign windows, you need to inject code into the foreign processes.
Check the SetWindowsHookEx method for that:
You most probably want to install a hook for WH_CALLWNDPROCRET and watch out for the WM_NCPAINT message. This would be the right place to draw your button.
However, I'm not really sure, if you can place a window within a Non-Client-Area, so in the worst case, you'd have to paint the button "manually".
Just call this from your main application (or from within a DLL)
SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, hModule, 0);
Note that myCallWndRetProc must reside within a DLL and hModule is the Module-HANDLE for this DLL.
Your myCallWndRetProc could look like:
LRESULT CALLBACK myCallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HT_ACTION) {
CWPRETSTRUCT* cwpret = (CWPRETSTRUCT*)lParam;
if (cwpret->message == WM_NCPAINT) {
// The non-client area has just been painted.
// Now it's your turn to draw your buttons or whatever you like
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
When starting with your implementation, I'd suggest, you just create a simple dialog application and hook your own process only:
SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, NULL, GetCurrentThreadId());
Installing a global hook injects the DLL into all processes, which makes debugging pretty hard, and your DLL may be write-protected while it's in use.
Hello everyone I am new to windows32 programming and I have a couple of questions-:
When I use the following code in a program it works fine -:
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
But when I replace null of GetMessage to hwnd(the handle of the window just created) the doesn't seem to close it still remains running in the background. Why does this happen when I replace NULL with hwnd means I am receiving messages for only one window then why doesn't it work????
while(GetMessage(&msg,hwnd,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
By the way the windows function is-:
LRESULT CALLBACK WinProc(HWND hWnd, UINT message,
WPARAM wparam, LPARAM lparam){
switch(message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wparam, lparam);
}
return 0;
}
Secondly-:
Is there any way I can see all the messages sent to any particular window????
Thirdly-:
What is the reason behind writing __stdcall(WINAPI) when compiling my windows programs ????
A quick reply would be appreciated.Thank You.
GetMessage returns 0 (making the loop end) only when it receives a WM_QUIT, but a WM_QUIT is not associated to any particular window, so it is never received if you have a GetMessage that asks only messages for a certain hWnd.
If it's a window of yours, you already see them inside their window procedure; if you want to filter them before dispatching them to their window procedure, you can check the msg structure that is populated by GetMessage before calling DispatchMessage.
The whole Windows API uses the stdcall calling convention (I think because it is slightly faster/produces less boilerplate code than the usual cdecl), so also your callbacks must follow that calling convention. Notice that you must use WINAPI (i.e. stdcall) only on functions that are called by Windows API functions, for the other ones you are free to use whatever calling convention you like best.
PostQuitMessage generates WM_QUIT which is processed by the message queue, but not associated with a particular window. By filtering only hwnd messages in your call to GetMessage, you don't process WM_QUIT.
Regarding seeing all messages being sent to a window / thread / process, see https://stackoverflow.com/questions/4038730/i-am-looking-for-a-windows-spy-application
Finally, regarding __stdcall, see What does "WINAPI" in main function mean?
i guess there is some reasonable and an easy solution. So for instance i have:
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
time(2)
// anything else in the about class....
//return code
}
The problem is that the whole application almost freezes and i cannot do anything but "wait for the timer".
How can i make the timer runs irrespectively to any other operation? 10x!
You want to do a SetTimer call and either give it a pointer to a callback function, or respond to the WM_TIMER message that comes back.
I want to do some processing when a particular dialog is opened but I am not able to find any way to get notification when that dialog is opened.
Is there any way to get notification in application for opening of a particular windows dialog?
The only available information about the dialog is its title and its unique.
The general solution is to use windows hooks, filter to WH_CBT, filter to WM_CREATE, or something like that, get the window text and see if it is the one of your interest.
One more important point: in hook you should use SetWindowLongPtr() to set window process to your own function, that will actually receive WM_CREATE event. In all calls this function should call the original window procedure.
You can also use a CBT Hook to watch window creation messages. You'll have access to the CREATSTRUCT used to create the actual window, eg, the title and class name. You can prevent the window from being created in your hook, modify the size, etc.
EDIT: sorry didn't notice that you don't have the code yourself but only the title. So I think the other posts solution is what you need
The event handling in win32 applications is done via a so called windows procedure which is a callback function with the following signature:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
This callback gets called by windows every time there is a message for windows which are registered with this callback function. One of the first messages send to a new window is the WM_CREATE message.
If you are creating your windows "by hand" with win32 API, then there should be a static callback function like the one below where you can filter for the WM_CREATE message.
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_CREATE:
// do what ever you want
return 0;
case default:
return DefWndProc( hwnd, message, wParam, lParam );
}
}
If you use MFC dialogs (CDialog) then you can overwrite the function CDialog::OnInitDialog().
OK, the way to do this is to use SetWindowsHookEx(WH_SYSMSGFILTER,...)
You'll be getting a lot more callbacks than you really need. and global hooks are a real drain on system performance (they can force the system to serialize things that would normally run independently)
be sure to read the Remarks, especially this part:
SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.
Your hook must live in a dll, and the dll will end up loaded into other process's address space, so you won't it won't have access to your procees's address space, you will have to set up some sort of interprocess communication between your hook and your app.
On the whole I'd say this sounds like a really bad idea.