I have pretty good ideas about how I'm going to do it but there's a detail
that has me confused.
I thought a control was sent the WM_PAINT message whenever it had to be
redrawn (a window passed over it, it has been resize etc...).
Well, I don't get them.
All I have are WM_ERASEBKGND messages which I process since I didn't provide
a brush for the background in my class definition ( was that even a good
idea in the first place ?)
So I don't know, am I supposed to do a UpdateWindow() at the end of my
WM_ERASEBKGND processing ? Maybe that would work but, I don't know, that
doesn't sound "right" to me.
I'm pretty sure that the BeginPaint() function sends the WM_ERASEBKGND
message when it's called. Are you subclassing an existing control or
something? When I make my own control, I just use a vanilla window so
I can handle/ignore all the messages myself. If you make up a name for
the window class, then you just get a plain window. Or am I
misunderstanding your problem?
Matt Gregory
Yes, I'm not subclassing, the problem is I don't receive any WM_PAINT
messages, here is the code :
ATOM RegisterTOC( HINSTANCE hInst);
LRESULT CALLBACK TextOutputControlProc( HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
int PaintBKGND( HWND hWnd);
ATOM RegisterTOC( HINSTANCE hInst)
{
WNDCLASSEX wcx;
ZeroMemory( &wcx, sizeof( WNDCLASSEX));
wcx.cbSize = sizeof( WNDCLASSEX);
wcx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcx.lpfnWndProc = (WNDPROC) TextOutputControlProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInst;
wcx.hIcon = NULL;
wcx.hCursor = LoadCursor( NULL, IDC_ARROW);
wcx.hbrBackground = NULL;
wcx.lpszMenuName = NULL;
wcx.lpszClassName = "TEXTOUTPUT";
wcx.hIconSm = NULL;
return RegisterClassEx( &wcx);
}
LRESULT CALLBACK TextOutputControlProc( HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
HFONT hfont;
switch( uMsg)
{
case WM_ERASEBKGND:
return PaintBKGND( hWnd);
break;
case WM_PAINT:
// WM_PAINT Stuff
break;
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam);
}
return 0;
}
// Paints the background of the control
int PaintBKGND( HWND hWnd)
{
HDC hdc;
HBRUSH hbrBkgnd;
PAINTSTRUCT ps;
RECT r;
GetClientRect( hWnd, &r);
hdc = BeginPaint( hWnd, &ps);
hbrBkgnd = CreateSolidBrush( RGB( 255,255,255));
FillRect( hdc, &r, hbrBkgnd);
EndPaint( hWnd, &ps);
return 1;
}
Do not call BeginPaint/EndPaint in the WM_ERASEBKGND handler.
These functions should be called inside a WM_PAINT handler only.
The DC to use in the WM_ERASEBKGND handler is passed in the
WPARAM parameter.
Regards,
Frank
Yes, Thank you, I just figured that out, but how am I supposed to know the
rect I have to fill ? Is WM_ERASEBKGND only called to redraw the whole
control background ? in this case, should I use WindowFromDC and then
GetClientRect ?
Thanks. I find this part really poorly described on MSDN.
You can do your erasing in WM_PAINT. Return FALSE in WM_ERASEBKGND and
check the fErase member of the PAINTSTRUCT in WM_PAINT.
--
Sev
> You can do your erasing in WM_PAINT. Return FALSE in WM_ERASEBKGND and
> check the fErase member of the PAINTSTRUCT in WM_PAINT.
You can just return true in WM_ERASEBKGND and that will take care of
the flag.
Matt Gregory
I believe returning TRUE says "I did erase it, so nothing else has to
worry about it." If you didn't actually do the necessary painting, you
may have unexpected results.
IIRC, returning TRUE will clear the fErase flag -- which is best as
long as you have no need to know if you need to erase the background
in WM_PAINT (such as if you're copying the *entire* window area from a
bitmap.) But if you need to actually know later if you need to erase
background areas, I think it's better to return false.
I could be wrong, but I looked at existing code and tried changing my
WM_ERASEBKGND return to TRUE, and found areas outside of the image
that occupied my window were not erased. However, the code is quite
complicated and this could be due to some other influence.
--
Sev
> I believe returning TRUE says "I did erase it, so nothing else has to
> worry about it." If you didn't actually do the necessary painting, you
> may have unexpected results.
>
> IIRC, returning TRUE will clear the fErase flag -- which is best as
> long as you have no need to know if you need to erase the background
> in WM_PAINT (such as if you're copying the *entire* window area from a
> bitmap.) But if you need to actually know later if you need to erase
> background areas, I think it's better to return false.
Ah ok. I've never used that flag. I figured if you're erasing in
WM_PAINT, then you're not really using that background feature at all,
but painting the whole window every time or whatever. All I know is, if
you return false from WM_ERASEBKGND, then Windows will erase it, unless
your background brush is null. But if Windows erases the background,
wouldn't the fErase flag always be cleared in WM_PAINT? I would think
if Windows erases the background it would clear the flag.
Matt Gregory