Originally posted by: Josh
The best way to get flicker free paints in tandem
with a MemDC is to get rid of the background
altogether rather than overide OnEraseBkgnd.
Example using CView derived class:
BOOL CDataView::PreCreateWindow(CREATESTRUCT& cs)
{
//THIS FORCES BACKGROUND TO BE NULL
cs.lpszClass = AfxRegisterWndClass( CS_DBLCLKS|CS_BYTEALIGNWINDOW|CS_BYTEALIGNCLIENT,
0, (HBRUSH)GetStockObject( HOLLOW_BRUSH ) );
return CView::PreCreateWindow(cs);
}
Originally posted by: Kirill Sherman
Unfortunately, CMemDC works only in MM_TEXT mode. Is there any way, I could implement this class with MM_ANISOTROPIC?
Thanks ahead for any COOL advices.
ReplyOriginally posted by: Yoh-hei
Yes it's a good code !
But when I have many lines make graphic
(I use VC++6.0 MFC Scrollview class)and then move
(use scroll bar),zoom it's need waiting one or two
second time.(That's said the the screen is nothing
when waiting!)and move it is slow.I test if use bitmap
move and zoom is quick.how to make all lines change
to a bitmap ,use CMemDC.h?
Originally posted by: Brad Larsen
Here's what I've done:
1) Created a "global" bitmap in my CView/CDialog that can
2) Placed the refill code within the CMemDC class. The
3) Replaced code as to how the bitmap was being refilled.
Here's my version of the CMemDC constructor (I place it in a .cpp file)
CMemDC::CMemDC(CDC* pDC, COLORREF crFill, CBitmap* pBmp)
ASSERT_VALID(pDC);
// Memory DC is we're not printing
// Step 2 - Get the clip area
// BITMAP CASE 1: User passed bitmap, use it
SetWindowOrg(m_rcClip.left, m_rcClip.top);
// Step 3 - "Erase" the background using passed color
// CASE 1: White background, use PatBlt, it's a speed demon
Final Note: For CPaintDCs, GetClipBox() would always
Brad
I've updated the CMemDC class so that it runs quicker.
I found the big bottlenecks were the bitmap construction
in the constructor (obvious to most) and the "refill"
segment in the Draw/Paint function that called the CMemDC
constructor.
be passed to the CMemDC constructor. This is a tip given
in many MS/Programming articles. With this implementation
you're not creating the bitmap each time the constructor is
called.
colour to refill with is passed as a COLORREF in the CMemDC
constructor. You'll probably want to use GetSysColor() to
pass the proper fill colour.
Using FillRect is slow! A much faster way is to use
FillSolidRect for non-white/black colours and PatBlt
w/WHITENESS or BLACKNESS for white and black fills. The
PatBlt method is extremely quick.
{
/* This is the device context constructor, used for normal device contexts */
// crFill = color to fill background with
// pBmp - bitmap to be drawn to
m_pDC = pDC;
m_pOldBmp = NULL;
m_bMemDC = !pDC->IsPrinting();
if (m_bMemDC)
{
// Step 1 - Create a Memory DC
CreateCompatibleDC(pDC);
pDC->GetClipBox(&m_rcClip);
pDC->LPtoDP(&m_rcClip);
if (pBmp != NULL)
m_pOldBmp = SelectObject(pBmp);
// BITMAP CASE 2: Create our own bitmap
else
{
m_bmp.CreateCompatibleBitmap(pDC, m_rcClip.Width(), m_rcClip.Height());
m_pOldBmp = SelectObject(&m_bmp);
}
SetMapMode(pDC->GetMapMode());
pDC->DPtoLP(&m_rcClip);
if (crFill == WHITE)
PatBlt(m_rcClip.left, m_rcClip.top, m_rcClip.Width(), m_rcClip.Height(), WHITENESS);
// CASE 2: Black background, use PatBlt, it's a speed demon
else if (crFill == BLACK)
PatBlt(m_rcClip.left, m_rcClip.top, m_rcClip.Width(), m_rcClip.Height(), BLACKNESS);
// CASE 3: Non-White/Black background, use FillSolidRect
else
{
COLORREF crOldBK = GetBkColor();
FillSolidRect(m_rcClip, crFill);
SetBkColor(crOldBK);
}
}
else
{
// Make a copy of the relevent parts of the current DC for printing
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
return (0,0,0,0). Instead of using m_rcClip = pDC
->GetClipBox(), try using m_rcClip = pPaintDC->m_ps.rcPaint
instead. Works for me.
Originally posted by: LEE SANG HUN
CMemDC(CDC* pDC) : CDC()
m_pDC = pDC;
SetMapMode(pDC->GetMapMode()) ;
CMemDC class cannot work if pDC is not MM_TEXT Mapping mode. ex) MM_LOMETRIC mode
So I changed the code.
{
ASSERT(pDC != NULL);
m_pOldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();
if (m_bMemDC) // Create a Memory DC
{
pDC->GetClipBox(&m_rect);
pDC->LPtoDP(&m_rect) ;
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_pOldBitmap = SelectObject(&m_bitmap);
pDC->DPtoLP(&m_rect) ;
SetWindowOrg(m_rect.left, m_rect.top);
}
else // Make a copy of the relevent parts of the current DC for printing
{
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
Originally posted by: Theo Vosse
A minor thing:
The constructor of CMemDC cannot be used with the code example given.
Instead, it should read
CMemDC(CDC* pDC, const CRect& rcBounds) : CDC(), m_oldBitmap(NULL), m_pDC(pDC), m_rect(rcBounds)