RedrawWindow() issue on child windows
In my win32 application, I created a pop-up window which I use it to display contents of other windows.
For example, I have a Photoshop application running. I grab a handle to its main window and make its style a child window and set its parent as my own window. This places Photoshop in my application.
Afterwards, I hide the photoshop window (set opacity to 0), and instead grab its Device Context contents into a bitmap that I created, and I draw this bitmap on my window. To do this, I set up a timer that ticks every 16 milliseconds (60 hz). This is the timer:
void CALLBACK drawProc( HWND hwnd, UINT uMsg, UINT_PTR开发者_如何学编程 idEvent, DWORD dwTime )
{
updateFrames();
RECT r;
GetClientRect( hwnd, &r );
//Erase background
HBRUSH eraseBrush = CreateSolidBrush( RGB( 255, 255, 255 ) );
FillRect( bbHDC, &r, eraseBrush );
DeleteObject( eraseBrush );
//Draw frames
drawFrames( bbHDC );
RedrawWindow( hwnd, 0, 0, RDW_INVALIDATE | RDW_NOCHILDREN );
}
The problem is, this slows photoshop (and some other applications down). By commenting lines out I found out that redrawWindow causes this. I thought redrawing main window maybe causes photoshop to redraw its contents as well, so I added RDW_NOCHILDREN but still the slowness remains.
I'll be glad if someone can help me out on this.
Thanks.
I'm not even going to comment on why this is a weird thing to do :)
Why it's slow:
RedrawWindow
is probably forcing a full repaint every time you call it. After all, you are invalidating the entire window. That will be an expensive operation - normally in a Windows app, you only paint when you know you need to (by invalidating a rectangle or region, which is a very cheap operation, and at some point processing a WM_PAINT
message, and when handling that painting only the invalidated area, which is the minimum work possible.)
It is worth reading up on painting and drawing in Windows, especially when to draw in a window.
Now, to try to give an answer your question:
Most of the time, your embedded Photoshop window will not have changed. In other words, the vast, vast majority of the painting work your program is doing is completely unnecessary. What you should do instead is only paint to your window when the Photoshop window has changed and needs to repaint itself - and ideally, even then, only repaint the section that needs to be repainted. (An example is a button reacting to a mouseover: you only need to repaint the button, or the rectangle inside which the button is located, not the entire window.)
What you're doing is a general case of polling. It's very inefficient since you do a lot of work even when none needs to be done. You want instead to be notified when you need to do work, which is much more efficient.
The following is a suggestion, I haven't tried it but it should work. Windows already has a built-in framework so an application knows when it needs to paint: a WM_PAINT
message will be present in its message queue. You can peek into a window's message queue and see what messages are there, without removing any, using PeekMessage. That will tell you when the window needs to be painted: repaint then. Alternatively, hook the message function or subclass the window and when a WM_PAINT message is received pass it to the original message function, and then repaint. You could use GetUpdateRect
to see what area will be painted, and then after the WM_PAINT
processing is complete, copy that area only to your own window. Etc.
This is a general answer: try some of those things and see what happens. Remember, if you have problems with particular parts, you can post another question!
精彩评论