Introduction
This article explains how
my class CDXSurfaceMgr
can be used to facilitate
Double Buffered drawing/graphics.
Double Buffered Drawing
Normally when
drawing using the
GDI you do all your painting
straight into the HDC
that's provided by either
BeginPaint
or a
CDC
(if you are
using MFC). Iif you draw a
line it immediately appears
on the surface of the window
you are
drawing on. If
you draw a lot of
graphic items the
screen is updated with each
item and this can result in
flicker or stuttering as the
surface is filled with the
drawing.
Double Buffering
can be used to create smooth
updates, you build a "frame"
of graphics in a non visible
place first then copy the
whole thing onto the main
windows surface.
There a lots of ways to
implement
double buffering,
one way is to create a
compatible HDC
in memory somewhere and draw
into that then Blit (copy)
that memory into the visible
windows HDC
. My
approach uses a subset of
DirectX
called
DirectDraw
which can be used to
draw 2d
Graphics.
CDXSurfaceMgr
is
written using the DirectDraw
interfaces supplied in VC6
(ddraw.h/lib) and should
work on 95/98/Me/2k/XP and
NT 4.0 (sp3 - I think).
Using
CDXSurfaceMgr
Create an instance of
CDXSurfaceMgr
Collapse |
Copy Code
#include "DXSurfaceMgr.h"
...
...
CDXSurfaceManager_NBP dxMgr_;
Initialise the instance like
so
Collapse |
Copy Code
int CMfcdxView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
if(!dxMgr_.Initialise(m_hWnd)) return -1;
return 0;
}
This should be done just
once, the parameter to the
Initialise
method is the Handle to the
window you want to draw on.
Then when handling the
WM_PAINT
message (the
place you would normally do
the drawing) call the
BeginPaint
Method
Collapse |
Copy Code
void CMfcdxView::OnDraw(CDC* pDC)
{
CMfcdxDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
HDC& hdc = dxMgr_.BeginPaint(GetSysColor(COLOR_3DFACE));
if(NULL !=hdc)
{
....
The parameter to
BeginPaint
is a
COLORREF
that
BeginPaint
will use
to fill the background with.
BeginPaint
returns an HDC
that that you can then use
to draw things with, either
via the standard GDI API;
Collapse |
Copy Code
::SetBkMode(hdc,TRANSPARENT);
::TextOut(hdc,10,10,"Please don't call me reg its not my name", 40);
Or if you are using MFC;
Collapse |
Copy Code
CDC* cdc = CDC::FromHandle(hdc);
cdc->SetBkMode(TRANSPARENT);
cdc->(10,10, CString("All aboard Brendas iron sledge"));
Note all the usual GDI
rules apply - if you select
a brush remember to reselect
the old one etc. When you
have finished
drawing, call the
EndPaint
method
like so;
Collapse |
Copy Code
dxMgr_.EndPaint();
This will "flip" your
drawing onto the main
windows surface. and the
drawing will
instantaneously appear.
What CDXSurfaceMgr
does
CDXSurfaceMgr
creates a primary surface -
one that is visible - and a
secondary off screen surface
that is the same size as the
primary one but invisible.
When you call
BeginPaint
an
HDC
attached to the
secondary surface is
returned; you do all your
drawing into
this; then EndPaint
Blits(copies) the whole of
the secondary surface onto
the primary one and it
appears on the window. If
you have a capable
graphics adapter
on your machine then the
Blit is very very fast, if
you don't then the operation
is obviously not as fast,
but still very functional.
Demos
There are three demos
included one that uses WFC
and draws rectangles and
ellipses moving up and down
the screen, one that uses
MFC,
and draws a few lines and a
bit of text, and one that
does exactly the same again
but is just a Win32 program.