WM_ERASEBKGND
-
I am making a small Win32 API application. I wanted to have a coloured background. When I tried to handle WM_ERASEBKGND, I got too much flicker. I tried to make a memory dc and use it, but that did not improve the flicker. Is it something I do wrong? Could you please show me how to handle WM_ERASEBKGND without flicker? Note: I noticed that the flicker was gone when I created a brush and made myWndClass.hbrBackground point to it. But the problem is that I may want to draw in WM_ERASEBKGND, not just have a single brush.
Hosam Aly Mahmoud
-
I am making a small Win32 API application. I wanted to have a coloured background. When I tried to handle WM_ERASEBKGND, I got too much flicker. I tried to make a memory dc and use it, but that did not improve the flicker. Is it something I do wrong? Could you please show me how to handle WM_ERASEBKGND without flicker? Note: I noticed that the flicker was gone when I created a brush and made myWndClass.hbrBackground point to it. But the problem is that I may want to draw in WM_ERASEBKGND, not just have a single brush.
Hosam Aly Mahmoud
Do everything in response to
WM_PAINT
and use a memory DC. HandleWM_ERASEBKGND
and do nothing there. Hope this helps,Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
-
Do everything in response to
WM_PAINT
and use a memory DC. HandleWM_ERASEBKGND
and do nothing there. Hope this helps,Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
Thank you for your reply. I thought that
WM_PAINT
would only allow me to draw a certain region of the window, not all of it. Also, the docs said that to make a background (for example a picture) you should handle WM_ERASEBKGND. Am I wrong?Hosam Aly Mahmoud
-
Thank you for your reply. I thought that
WM_PAINT
would only allow me to draw a certain region of the window, not all of it. Also, the docs said that to make a background (for example a picture) you should handle WM_ERASEBKGND. Am I wrong?Hosam Aly Mahmoud
Hosam Aly Mahmoud wrote: I thought that WM_PAINT would only allow me to draw a certain region of the window, not all of it. The device context given as a parameter to a
WM_PAINT
message is set up to only draw to the regions of the window which have been invalidated. By definition, any region that is not invalidated, does not need painting, so you shouldn't have a problem. Hosam Aly Mahmoud wrote: Also, the docs said that to make a background (for example a picture) you should handle WM_ERASEBKGND. Am I wrong?WM_ERASEBKGND
is sent wheneverInvalidateRect()
orInvalidateRgn()
are called withfErase=TRUE
. If thefErase
flag isFALSE
, thenWM_ERASEBKGND
is not sent. It is quite ok to draw the background inWM_PAINT
however. In fact, to get true flicker-free drawing, it is the only way.Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
-
Hosam Aly Mahmoud wrote: I thought that WM_PAINT would only allow me to draw a certain region of the window, not all of it. The device context given as a parameter to a
WM_PAINT
message is set up to only draw to the regions of the window which have been invalidated. By definition, any region that is not invalidated, does not need painting, so you shouldn't have a problem. Hosam Aly Mahmoud wrote: Also, the docs said that to make a background (for example a picture) you should handle WM_ERASEBKGND. Am I wrong?WM_ERASEBKGND
is sent wheneverInvalidateRect()
orInvalidateRgn()
are called withfErase=TRUE
. If thefErase
flag isFALSE
, thenWM_ERASEBKGND
is not sent. It is quite ok to draw the background inWM_PAINT
however. In fact, to get true flicker-free drawing, it is the only way.Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
Many thanks for your reply. I am using Win32 API, so I get the
HDC
usingBeginPaint()
. I tried to draw in WM_PAINT, but I get a white background although I havemyWndClass.hbrBackground = NULL
. Here is my code:case WM_PAINT:
{
static PAINTSTRUCT ps;
static dc = BeginPaint(hWnd, &ps);static HDC memDC = CreateCompatibleDC(dc); static HBITMAP memBitmap = CreateCompatibleBitmap(dc, MainWindowRect.right, MainWindowRect.bottom); SelectObject(memDC, memBitmap); FloodFill ( memDC, 20, 20, RGB(255,0,0) ); // red background static HBRUSH oldBrush = (HBRUSH) SelectObject(memDC, myBrush); Rectangle(memDC, myRect.left, myRect.top, myRect.right, myRect.bottom ); SelectObject(memDC, oldBrush); BitBlt(dc, 0, 0, MainWindowRect.right, MainWindowRect.bottom, memDC, 0, 0, SRCCOPY); // in WM\_SIZE I wrote: GetClientRect(&MainWindowRect); EndPaint(hWnd, &ps); return 0;
}
case WM_ERASEBKGND:
return 0; // processed already in WM_PAINT.Hosam Aly Mahmoud
-
Many thanks for your reply. I am using Win32 API, so I get the
HDC
usingBeginPaint()
. I tried to draw in WM_PAINT, but I get a white background although I havemyWndClass.hbrBackground = NULL
. Here is my code:case WM_PAINT:
{
static PAINTSTRUCT ps;
static dc = BeginPaint(hWnd, &ps);static HDC memDC = CreateCompatibleDC(dc); static HBITMAP memBitmap = CreateCompatibleBitmap(dc, MainWindowRect.right, MainWindowRect.bottom); SelectObject(memDC, memBitmap); FloodFill ( memDC, 20, 20, RGB(255,0,0) ); // red background static HBRUSH oldBrush = (HBRUSH) SelectObject(memDC, myBrush); Rectangle(memDC, myRect.left, myRect.top, myRect.right, myRect.bottom ); SelectObject(memDC, oldBrush); BitBlt(dc, 0, 0, MainWindowRect.right, MainWindowRect.bottom, memDC, 0, 0, SRCCOPY); // in WM\_SIZE I wrote: GetClientRect(&MainWindowRect); EndPaint(hWnd, &ps); return 0;
}
case WM_ERASEBKGND:
return 0; // processed already in WM_PAINT.Hosam Aly Mahmoud
Remove the
static
keyword from all of your variable declarations and try again.Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
-
Remove the
static
keyword from all of your variable declarations and try again.Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
I did it but no difference. :((
Hosam Aly Mahmoud
-
Many thanks for your reply. I am using Win32 API, so I get the
HDC
usingBeginPaint()
. I tried to draw in WM_PAINT, but I get a white background although I havemyWndClass.hbrBackground = NULL
. Here is my code:case WM_PAINT:
{
static PAINTSTRUCT ps;
static dc = BeginPaint(hWnd, &ps);static HDC memDC = CreateCompatibleDC(dc); static HBITMAP memBitmap = CreateCompatibleBitmap(dc, MainWindowRect.right, MainWindowRect.bottom); SelectObject(memDC, memBitmap); FloodFill ( memDC, 20, 20, RGB(255,0,0) ); // red background static HBRUSH oldBrush = (HBRUSH) SelectObject(memDC, myBrush); Rectangle(memDC, myRect.left, myRect.top, myRect.right, myRect.bottom ); SelectObject(memDC, oldBrush); BitBlt(dc, 0, 0, MainWindowRect.right, MainWindowRect.bottom, memDC, 0, 0, SRCCOPY); // in WM\_SIZE I wrote: GetClientRect(&MainWindowRect); EndPaint(hWnd, &ps); return 0;
}
case WM_ERASEBKGND:
return 0; // processed already in WM_PAINT.Hosam Aly Mahmoud
Hosam Aly Mahmoud wrote: FloodFill ( memDC, 20, 20, RGB(255,0,0) ); // red background :rolleyes: I should have seen this before... The colour you pass to
FloodFill()
is not the colour of the fill. It's the colour of the border.FloodFill()
fills the area with the currently selected brush. To fill a rectangle with a given colour, either create a solid brush (CreateSolidBrush()
) and useRectangle()
, or use theExtTextOut()
function to draw opaque text without actually drawing text:SetBkColor(memDC, RGB(255,0,0)); // Red background
RECT rect;
// TODO: Setup the rectangle here
ExtTextOut(memDC, 0, 0, ETO_OPAQUE, rect, NULL, 0, NULL);Hope this helps,
Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
-
Hosam Aly Mahmoud wrote: FloodFill ( memDC, 20, 20, RGB(255,0,0) ); // red background :rolleyes: I should have seen this before... The colour you pass to
FloodFill()
is not the colour of the fill. It's the colour of the border.FloodFill()
fills the area with the currently selected brush. To fill a rectangle with a given colour, either create a solid brush (CreateSolidBrush()
) and useRectangle()
, or use theExtTextOut()
function to draw opaque text without actually drawing text:SetBkColor(memDC, RGB(255,0,0)); // Red background
RECT rect;
// TODO: Setup the rectangle here
ExtTextOut(memDC, 0, 0, ETO_OPAQUE, rect, NULL, 0, NULL);Hope this helps,
Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
Thank you very much! That really helped! :-D Now I am wondering, if I want to make the background an image, should I do it in response to WM_PAINT too? Why is WM_ERASEBKGND available then? Why did they put it if I should draw in WM_PAINT? :(( Thank you very much for your patience! :rose:
Hosam Aly Mahmoud
-
Thank you very much! That really helped! :-D Now I am wondering, if I want to make the background an image, should I do it in response to WM_PAINT too? Why is WM_ERASEBKGND available then? Why did they put it if I should draw in WM_PAINT? :(( Thank you very much for your patience! :rose:
Hosam Aly Mahmoud
Hosam Aly Mahmoud wrote: Now I am wondering, if I want to make the background an image, should I do it in response to WM_PAINT too? Yes. That will work fine :) Hosam Aly Mahmoud wrote: Why is WM_ERASEBKGND available then? Why did they put it if I should draw in WM_PAINT? There is nothing wrong with using
WM_ERASEBKGND
for drawing the background. It's simply not possible to do flicker-free drawing using it. I'm not certain why it's there - it's probably been there since Windows 1.0Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
-
Hosam Aly Mahmoud wrote: Now I am wondering, if I want to make the background an image, should I do it in response to WM_PAINT too? Yes. That will work fine :) Hosam Aly Mahmoud wrote: Why is WM_ERASEBKGND available then? Why did they put it if I should draw in WM_PAINT? There is nothing wrong with using
WM_ERASEBKGND
for drawing the background. It's simply not possible to do flicker-free drawing using it. I'm not certain why it's there - it's probably been there since Windows 1.0Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
Ryan Binns wrote: I'm not certain why it's there Well, if you "eat" the WM_ERASEBKGND message, return 1, and forward it to the parent window, you can get transparent effects, because you're telling the parent to erase an area, rather than erasing it yourself with the default brush, which is the normal behavior. This is a neat trick that is played by the Common Controls Toolbar so that it can have a transparent background. It also calls WM_ERASEBACKGND on the parent window whenever it draws anything outside of a WM_PAINT message, so that the background is always erased to the parent's background.
"Blessed are the peacemakers, for they shall be called sons of God." - Jesus
"You must be the change you wish to see in the world." - Mahatma Gandhi -
Ryan Binns wrote: I'm not certain why it's there Well, if you "eat" the WM_ERASEBKGND message, return 1, and forward it to the parent window, you can get transparent effects, because you're telling the parent to erase an area, rather than erasing it yourself with the default brush, which is the normal behavior. This is a neat trick that is played by the Common Controls Toolbar so that it can have a transparent background. It also calls WM_ERASEBACKGND on the parent window whenever it draws anything outside of a WM_PAINT message, so that the background is always erased to the parent's background.
"Blessed are the peacemakers, for they shall be called sons of God." - Jesus
"You must be the change you wish to see in the world." - Mahatma Gandhi:cool: I'll have to remember that :)
Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
-
Hosam Aly Mahmoud wrote: Now I am wondering, if I want to make the background an image, should I do it in response to WM_PAINT too? Yes. That will work fine :) Hosam Aly Mahmoud wrote: Why is WM_ERASEBKGND available then? Why did they put it if I should draw in WM_PAINT? There is nothing wrong with using
WM_ERASEBKGND
for drawing the background. It's simply not possible to do flicker-free drawing using it. I'm not certain why it's there - it's probably been there since Windows 1.0Ryan
"Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
Thank you for your replies, your help and all your patience! :rose:
Hosam Aly Mahmoud
-
Ryan Binns wrote: I'm not certain why it's there Well, if you "eat" the WM_ERASEBKGND message, return 1, and forward it to the parent window, you can get transparent effects, because you're telling the parent to erase an area, rather than erasing it yourself with the default brush, which is the normal behavior. This is a neat trick that is played by the Common Controls Toolbar so that it can have a transparent background. It also calls WM_ERASEBACKGND on the parent window whenever it draws anything outside of a WM_PAINT message, so that the background is always erased to the parent's background.
"Blessed are the peacemakers, for they shall be called sons of God." - Jesus
"You must be the change you wish to see in the world." - Mahatma GandhiThank you for the information!
Hosam Aly Mahmoud