Windows API: Double Buffering image draws
2002-09-16 -- Andy Ireland
Newsgroups: TopSpeed.Topic.Third_Party
Hi Ville,
> Yes, this message is sent to a window when it's background needs to
> be erased . This happens because windows are usually painted using
> a 2-stage process:
>
> - WM_ERASEBKGND: clear the background
> - WM_PAINT: draw the contents on top
It is quicker to draw everything on WM_ERASEBKGND. As for memory overhead
and speed for double buffering, it's not really noticeable. Most
applications use double buffering and it's not a problem. Likewise so does
the OS. IMO double buffering is absolutely a requirement for skinning. You
do not necessarily have to do the whole image everytime either, you could
just do the invalidated portion using the extents sent to you.
> This makes it easy to draw a windows contents, every time you receive
> a WM_PAINT message, you know that you have a nice fresh canvas to
> draw on.
> However, drawing a window twice (once with WM_ERASEBKGND and
> once again with WM_PAINT) will cause the window to flicker.
> Open up notepad, type something and then resize the window and see
> how Microsoft is demonstrating the flickering ;-)
Do the same on a professional product. Double buffering is worth it.
> Dunno what is the fundamental purpose for this property... Andy?
Double buffering probably I think it causes the image to be persisted to
a DC and all other operations drawn to same, then flushed but only SV would
know for sure. I suppose I could check this out in Boundschecker and see
what it calls.
IMO, not buffering looks worse every time. The speed hit is negligable in
the grand scheme of things and if it's not noticeable but not doing it is, I
know what I'd choose and do choose.
Here's a clarion example....
AppClient.OnPaint procedure(PWDevice DC, <*_RECT_ UpdateRect>)
Bmp PWBitmap
sizeBmp like(SIZE),auto
rcClient like(_RECT_),auto
rcImage like(_RECT_),auto
hdcMem long,auto
hCompatBmp long,auto
hBmpOld long,auto
DCM PWDevice
AppWin &AppWindow
code
AppWin &= address(self.AppWin)
if GetClientRect(self.GetHandle(), rcClient)
hdcMem = CreateCompatibleDC(DC.GetHandle())
if hdcMem
hCompatBmp = CreateCompatibleBitmap(DC.GetHandle(), rcClient.right -
rcClient.left, |
rcClient.bottom - rcClient.top)
if hCompatBmp
hBmpOld = SelectObject(hdcMem, hCompatBmp)
if DCM.Init(hdcMem, false)
if AppWin.fActive
if Bmp.LoadBitmap(IDB_IM1)
if Bmp.GetBitmapDimensions(sizeBmp, DCM.GetHandle())
GetClientRect(self.GetHandle(), rcClient)
rcImage.left = ((rcClient.right - rcClient.left) / 2) -
(sizeBmp.cx / 2)
rcImage.top = ((rcClient.bottom - rcClient.top) / 2) -
(sizeBmp.cy / 2)
rcImage.right = rcImage.left + sizeBmp.cx
rcImage.bottom = rcImage.top + sizeBmp.cy
assert(DCM.DrawImageAt(, rcImage.left, rcImage.top,
IDB_IM1, rcImage, 000ffffffh))
end
Bmp.Destruct()
end
end
end
BitBlt(DC.GetHandle(), rcClient.left, rcClient.top,
rcClient.right, rcClient.bottom, DCM.GetHandle(), 0, 0, SRCCOPY)
SelectObject(hdcMem, hBmpOld)
DeleteObject(hCompatBmp)
end
DeleteDC(hdcMem)
end
end
AppWin.PaintCnt += 1
if AppWin.PaintCnt = 2
AppWin.fActive = true.
return true
It draws to the memory DC first DCM, the to the DC for the window.
Regards
Andy
Plugware Solutions.com Ltd, taking the puzzle out of I.T
Tel : +44 1249 813335
Fax : +44 1249 813462
Printed November 21, 2024, 7:04 am This article has been viewed/printed 35207 times.
Google search
has resulted in 154 hits on this article since January 25, 2004.
|