If you subclass a window and want to draw something on top of it, is there any way to prevent flicker? Right now I'm invoking CallWindowProc and then doing my painting (so it goes on top of the window's normal appearance), and it seems to flicker a lot. Any help would be greatly appreciated. In fact, thanks for reading this, even if you don't reply.
Posted on 2001-10-28 14:00:45 by Irving W.
Try doing all your drawing on a compatible DC then blit from this
to the child window DC. If you need more help, check out the ESF
(eliminate screen flicker) tut by Chris Hobbs. You can find it on
Iczelions site. Good Luck !
Posted on 2001-10-28 19:26:43 by anon
That's what I was thinking, but how do you tell a subclassed window what DC to draw into? Can you just change the arguments to CallWindowProc or something?
Posted on 2001-10-28 20:56:42 by Irving W.
At startup or when necessary:

1. hMemDC = CreateCompatibleDC(..., ..., ...)
2. Draw on that DC


Then:

In the subclass proc's WM_PAINT Handler use
BitBlt to "blit" hMemDC onto ps.hdc ...
Posted on 2001-10-29 10:32:53 by Xtreme
Yeah, I see what you're saying. I know how I could BitBlt a memoroy DC to the PaintStruct DC. But say I subclass a textbox. When I invoke CallWindowProc to get the textbox to redraw itself as normal, it draws itself normally onto the PaintStruct DC. Sorry I wasn't clear about this. Here's what's getting me stuck:

Is there some way to get the textbox draw itself to my memory DC? Even if I do all MY drawing in a separate memory DC and then BitBlt to the textbox DC, there's still going to be flicker as the textbox draws itself and I BitBlt over it. It's not flicker between drawing commands that I'm doing, it's flicker between the end of the textbox's re-drawing and the start of mine. I'm looking for a way to change the hDC that the textbox gets to draw on so it draws on my memory DC instead, but I don't know how.
Posted on 2001-10-29 11:41:50 by Irving W.
If *you* are going to draw on the textbox, why let the textbox
draw itself? Or are you only adding a few things to it?
Posted on 2001-10-29 12:41:27 by f0dder
Yeah, exactly. I'm just adding a couple new things on top of the textbox. So the flicker is only over a small area of the textbox, but I still think it's annoying.
Posted on 2001-10-29 13:34:10 by Irving W.
I don't think there is a way to make a standard Windows control draw on your device context. I've had the same problem with a listbox, where I added a background image. It flickers when the scrollbar is scrolled, but its really not that much. I've been having ideas of completely taking over painting of the listbox (no owner-draw), this should do it. It is too possible for a textbox I suppose.
Posted on 2001-10-29 19:14:25 by comrade
A. The following shouldn't filcker unless you "type" over your drawing:

1. Subclass the control (SetWindowLong)
2. Call DefWindowProc from WM_PAINT
3. Draw you own stuff



B. (Method 1) Getting a snapshot of the textbox on a memdc:

1. Create a popup window with a NULL background brush.
2. Give it the same size and position as the textbox
3. "Show" the popup (but you won't be able to see it)
4. Copy the popup's dc to a memdc



C. (Method 2) Getting a snapshot of the textbox on a memdc:

1. Rip the source from the "Magnifier" applet in the PSDK.
2. Change the handle to the desktop to the textbox hwnd.
Posted on 2001-10-30 08:36:01 by Xtreme
Wow, I never thought about that (snapshot of the textbox), but it sounds like it'd work. I'll try it. Thanks for the help, everyone! :)
Posted on 2001-10-30 10:16:00 by Irving W.
HEY, Wait a minute.....

To copy a "snapshot" of a control all you have to do is use BitBlt!
The first HDC is your MemDC the second is the control HDC..

May not work on combos, etc because its made of two controls:
edit and listbox...



HDC hdcTextBox = GetDC(hWndTextBox);

HDC hdcCompatible = CreateCompatibleDC( hdcTextBox );

HBITMAP hbmTextBox = CreateCompatibleBitmap(hdcTextBox, dwWidth, dwHeight);

SelectObject(hdcCompatible, hbmTextBox);

BitBlt(hdcCompatible, 0,0, dwWidth, dwHeight, hdcTextBox, 0,0, SRCCOPY);
Posted on 2001-10-30 11:33:57 by Xtreme
I'm not sure if that would reduce flicker though. By the time the data is on its hDC, it's also on the screen and so it's too late. If I understand the popup window thing correctly, its null brush saves a snapshot of the text box BEFORE the drawing and the drawing takes place behind it. Then when the drawing is done, the popup can be hidden to let the newly-redrawn texbox show. I wonder if that would create an infinite loop of WM_PAINT messages though, since when the window is uncovered it needs to be re-painted and when it's repainted it gets covered back up. Hmmm...
Posted on 2001-10-30 11:44:20 by Irving W.
I wonder if you can change the hdc in a PAINTSTRUCT inside
a WM_PAINT handler to get windows to draw on a "foreign"
hdc....

SORRY FOR THE "C" :grin:



case WM_PAINT:

PAINTSTRUCT ps;
BeginPaint(...);

ps.hdc = MemDC;

[Call Default Procedure Here]

EndPaint(...);
Posted on 2001-10-30 11:55:16 by Xtreme
The thing is, the default window procedure will probalby call BeginPaint too. I wonder if that'll mess things up, or if the changes won't "take" or something. If it just drew into the hDC specified by wParam, it'd be a lot easier (just change the argument to CallWindowProc), but I don't think it does. I don't know much about how BeginPaint and EndPaint work either. It'd be interesting to try it though. Maybe I'll build a test project and see what happens.
Posted on 2001-10-30 14:13:39 by Irving W.
It's a pretty good idea to use BeingPaint/EndPaint inside a WM_PAINT, and that's the only place you should use them as well.
Try it and see what happens :).
Posted on 2001-10-31 04:09:31 by f0dder
I tried it from WndProc and nothing happened. I think I more fully appreciate the magic of BeginPaint/EndPaint now. How do they know? More importantly, how do they determine what hDC to draw into, and is there any way to change that?
Posted on 2001-10-31 11:05:35 by Irving W.