Sign in to follow this  
Sp00n00n

Capturing WM_PAINT messages

Recommended Posts

My application is required to draw onto another processes Windows. I am doing this by creating a hook with SetWindowsHookEx(). I can see the thread processing WM_PAINT messages with WH_CALLWNDPROC and WH_GETMESSAGE style hooks, but not WH_CALLWNDPROCRET. I require a WH_CALLWNDPROCRET style hook because I need to draw after the recipient Window has done its drawing, so I can draw on top of it. The reason I think that I can not see WM_PAINT messages, is that WH_CALLWNDPROCRET only receives messages sent by SendMessage() and WM_PAINT is not sent in this way. If anyone has any other solutions of drawing on another Processes/Threads Windows avoiding constant flickering, or how I can modify my current solution to solve the problem, let me know, because I am stumped! [Edited by - Sp00n00n on January 20, 2009 12:03:23 PM]

Share this post


Link to post
Share on other sites
As far as I can find out, Window subclassing intercepts messages before they reach the wndproc. I need to capture WM_PAINT messages after they have been processed by the message handler. I can't think of a way to intercept messages before they reach the message handler and then wait until after they have been processed to begin drawing, but am I missing something?

Share this post


Link to post
Share on other sites
If you subclass the window you replace the old window proc with your one.
Then your window proc is called in place of the original one to process messages.
Couldn't you call the original window proc and make your stuff after the call when you receive the WM_PAINT message ?
I mean, when the call to the original window proc ends the message processing has been done, then you can execute your own code after the original handler no ?

Share this post


Link to post
Share on other sites
Quote:
Original post by Sp00n00n
As far as I can find out, Window subclassing intercepts messages before they reach the wndproc. I need to capture WM_PAINT messages after they have been processed by the message handler. I can't think of a way to intercept messages before they reach the message handler and then wait until after they have been processed to begin drawing, but am I missing something?
Subclassing a window is a way of replacing the windows WndProc with your own function, so your replacement can call the original WndProc, and if the message is WM_PAINT, then you do your drawing - which is after the original WndProc has been called.

However, I'm not sure if you can subclass a window in another process, so you may have to inject code into the target process.

Share this post


Link to post
Share on other sites
Thanks I'm working on a solution now using subclassing. I am already injecting dll's into the processes, so that won't be a problem Evil Steve! Thanks for help, will let you know if I run into troubles.

Share this post


Link to post
Share on other sites
From MSDN: "Subclassing is allowed only within a process. An application cannot subclass a window or class that belongs to another process."

oh dear! I will try my method of creating a blanket child window over the client area.

Share this post


Link to post
Share on other sites
Of course, you can't subclass a window from another process, because the window proc adress must be in the target process adress space.
As you are injecting a dll in the target process, you can subclass the window easily, just do it in DllMain ().

Share this post


Link to post
Share on other sites
Hi Dear members,

I'm facing the same problem: I set a hook on a window in a third party application and catch the WM_PAINT message without problem. My trouble is that my added drawing is not on that window.

Here is my hook setting:
DWORD dwThreadID = GetWindowThreadProcessId(mpParent->m_hWnd, NULL);
mhHook = SetWindowsHookEx(WH_CALLWNDPROCRET ,CallWndRetProc,NULL,dwThreadID);

And Here is my drawing inside the catched WM_PAINT event in CallWndRetProc:

HWND hwnd = mpParent->GetSafeHwnd();
HDC hDC = GetDC(hwnd);
RECT lRect;
mpParent->GetClientRect(&lRect);
int mapmode = GetMapMode(hDC);
CDC* pDC = CDC::FromHandle(hDC);
pDC->SelectStockObject(WHITE_BRUSH);
pDC->Rectangle(&lRect);
mpParent->InvalidateRect(&lRect, true);
ReleaseDC(hwnd ,hDC);

It should a white rectangle in that window but it change nothing.

Please help me or tell me how to fix the problem.

Great thanks!

Share this post


Link to post
Share on other sites
If you inject a DLL into another process, you can do it, as long as the DLL contains everything (the new WndProc). You can write a wrapper WndProc that communicates with the main app, but that will probably HORRIBLY degrade performance.

Steps for injecting:

- Get the proper security privlidges to mess with the target process
- VirtualAllocEx to allocate an area for a string
- WriteProcessMemory to copy a string from your process into that virtual memory
- CreateRemoteThread to start the "LoadLibrary" procedure and pass the string address as the parameter.
- BAM! Your DLL loads and does anything it wants within the target process.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nypyren
If you inject a DLL into another process, you can do it, as long as the DLL contains everything (the new WndProc). You can write a wrapper WndProc that communicates with the main app, but that will probably HORRIBLY degrade performance.

Steps for injecting:
- blabla...


No, it has nothing to do with remote subclassing.

Share this post


Link to post
Share on other sites
The problem I had with SetWindowsHookEx, was that it was only passed messages sent by SendMessage, which is not how the vast majority of WM_PAINT messages are sent to a message loop by Windows. To avoid flickering you need to inject a dll into the remote process using the method someone stated above, and capture messages by subclassing each window you want to draw on(or an entire class, typically by creating a hidden window and using SetSubClass, unfortunately this only affect subsequently created Windows). Performance dies quite bad with this solution, but I can't think of any better ones. When communicating with the main app, try to use PostMessage as appose to SendMessage wherever possible, as this will reduce some strain on the IPC.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this