Solved

CMemDC (double buffering) not working now I'm using .NET

Posted on 2004-08-25
17
461 Views
Last Modified: 2013-11-20
Hi there,

I have recently moved my MFC project into Visual Studio .NET.  I'm still using MFC and the bulk of the project is unmanaged code, but I'm also now using ADO .NET, so I'm #using <mscorlib.dll> and have "Use Managed Extensions" set to "Yes" in the project properties.

I have been using CMemDC which encapsulates double-buffering to cut down on flicker; you can see it here:
http://www.codeproject.com/gdi/flickerfree.asp

It worked fine for me in the past.  However, it is not working any more.  It doesn't crash or anything, it just doesn't put anything onto the screen when it gets to the BitBlt call.  I'm using CMemDC in a dozen different places in my project and it's the same everywhere.  I haven't made any changes to the GUI and certainly not to the CMemDC class since I moved over to VS .NET so I'm at a loss to explain why it's not working any more.  Does anyone know?

Thank you.


0
Comment
Question by:wilsonian
17 Comments
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 11900124
I assume you have rebuilt all the code with .net
Have you put a breakpoint in the code and single stepped - check things like position/dimension of bitmap.
0
 
LVL 6

Expert Comment

by:nabehs
ID: 11900131
Can you post the problematic part? I will need to have a closer look. I dont think it is a vs.net issue.
0
 

Author Comment

by:wilsonian
ID: 11908412
Thanks for your comments guys

Andy- Yeah I've single stepped through and looked at that stuff- the values are exactly the same as in the old version.  Even if I paint the whole MemDC some other colour, nothing shows up.

nabehs- What do you want? The CMemDC class itself (which I changed *slightly* from what's in the link I posted above, back when I first started using it) and one of the places where I'm using it?
0
 
LVL 6

Expert Comment

by:nabehs
ID: 11909139
try adding a line in the constructor of CMemDC in memdc.h

...
            if (m_bMemDC) {
                  // Create a Memory DC
                  CreateCompatibleDC(pDC);
                  pDC->LPtoDP(&m_rect);

                  m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
                  m_oldBitmap = SelectObject(&m_bitmap);

                  SetMapMode(pDC->GetMapMode());

                  SetWindowExt(pDC->GetWindowExt());
                  SetViewportExt(pDC->GetViewportExt());

                  pDC->DPtoLP(&m_rect);
                  SetWindowOrg(m_rect.left, m_rect.top);
                                                //******************
                                                // Add the following line
                                                //******************
                                                BitBlt(0, 0, m_rect.Width(), m_rect.Height(), pDC, m_rect.left, m_rect.top, SRCCOPY);

            } else {
....




ALSO IN THE DESTRUCTOR OF CMemDC of memdc.h modify the BitBlt line to the following

m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height, this, 0, 0, SRCCOPY);

.....

IF THIS DOES NOT WORK THEN m_bMemDC in the destructor was not true.

hope this works.
0
 

Author Comment

by:wilsonian
ID: 11909786
Sorry, I won't have the code in front of me until Tuesday but I can tell you that the flow of executioin was definitely reaching the BitBlt in the destructor, which I guess is why you wanted me to check that m_bMemDC was true?
0
 

Author Comment

by:wilsonian
ID: 11928722
Do you want me to post that code tomorrow?
0
 
LVL 6

Expert Comment

by:nabehs
ID: 11928736
sure. that will help
0
 

Author Comment

by:wilsonian
ID: 11935949
Ok, here's the version of CMemDC I'm using.  All that I've changed is I'm using CRects representing both the client window area and the area to be drawn.  I can't remember the specific reason why I did this, cos it was about 18 months ago, but it has been working fine for all that time.

#ifndef _MEMDC_H_
#define _MEMDC_H_

#include "Drawing.h"

//////////////////////////////////////////////////
// CMemDC - memory DC
//
// Author: Keith Rule
// Email:  keithr@europa.com
// Copyright 1996-1997, Keith Rule
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
// This class implements a memory Device Context

class CMemDC : public CDC {
private:
      CBitmap*      m_bitmap;
      CBitmap*      m_oldBitmap;
      CDC*            m_pDC;
      CRect            m_rcBounds;
      CRect            m_inner;
public:
      CMemDC(CDC* pDC, const CRect& rcBounds, CRect& inner) : CDC()
      {
            CreateCompatibleDC(pDC);
            m_bitmap = new CBitmap;
            m_bitmap->CreateCompatibleBitmap(pDC, rcBounds.Width(), rcBounds.Height());
            m_oldBitmap = SelectObject(m_bitmap);
            m_pDC = pDC;
            m_rcBounds = rcBounds;
            m_inner = inner;
            CBrush* tempBrush = new CBrush(Drawing::GREY);
            CBrush* oldBrush = SelectObject(tempBrush);
            
            DWORD      color = ::GetSysColor( COLOR_BTNFACE );
            FillRect(m_rcBounds, tempBrush);
            SelectObject(oldBrush);
            delete tempBrush;

      }
      ~CMemDC()
      {
            m_pDC->BitBlt(m_inner.left, m_inner.top, m_inner.Width(), m_inner.Height(),
                              this, m_inner.left, m_inner.top, SRCCOPY);
            SelectObject(m_oldBitmap);
            if (m_bitmap != NULL) delete m_bitmap;
      }
      CMemDC* operator->() {
            return this;
      }
};

#endif
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:wilsonian
ID: 11936056
Oh and I tried it with the completely original copy of the file and it made no difference, ie there continued to be no drawing.

Here's an example of where I'm using CMemDC in the code:

void ConfigPage::writeSyms(CDC* dc) {
    CRect inner(660*getRatioX(), 95*getRatioY(), 1115*getRatioX(), 125*getRatioY());
    CRect      rcBounds;
    GetClientRect(&rcBounds);
    CMemDC memDC(dc, rcBounds, inner);

    for (int i = 0; i < highlightingPhonemes.GetSize(); i++) {
      (highlightingPhonemes.GetAt(i))->write(&memDC);
    }      
}

Er... I don't think it matters what it actually does, but the point is that the code as written there does nothing, but if I can't the line inside the for loop to
(highlightingPhonemes.GetAt(i))->write(dc);
it draws it as I expect (but with flicker).  

The area enclosed by inner is definitely the area I am drawing to.

Also, I have OnEraseBkgnd returning false; this is definitely working.  And the function writeSyms is also called in OnPaint() with the CPaintDC as its argument.

Is there other stuff you want to know?
0
 
LVL 6

Expert Comment

by:nabehs
ID: 11939036
I pasted the code in a vc++ project and tested it and it is working fine. The only change I had to make is the following line in memdc.h:

         CBrush* tempBrush = new CBrush(Drawing::GREY);
to
         CBrush* tempBrush = new CBrush(RGB(192, 192, 192));

In OnPaint( ) I wrote the following:

CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(&rect);
CMemDC pDC(&dc, rect, rect);
srand( 1000 );
for(int i = 0; i < 10000; i++)
{
    pDC->MoveTo(rand() % 1000, rand() % 1000);
    pDC->LineTo(rand() % 1000, rand() % 1000);
}

and I forced the window on refreshing. it is working fine.

0
 

Author Comment

by:wilsonian
ID: 11958016
I have quite co-incidentally solved the problem- I noticed that display of images (ones where I wasn't using double buffering) was slower than it used to, and I tracked the problem down to the function that converts my jpeg files into HBITMAPs.  The function is this one here:

http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20646637.html

So I replaced it with the use of the class here:

http://www.codeproject.com/bitmap/cpicture.asp

which seeemed to cut down the time it took. And lo and behold, the images in my CMemDCs started appearing on the screen again!

I'm still willling to give out the points if someone can tell me *why* this is the case, because I have no idea.
0
 

Author Comment

by:wilsonian
ID: 11959313
Ok, so on further consideration it seems I have not solved the problem after all.  I am in fact more confused now than when I started.  

When I use the CPicture class, things appear just fine inside the CMemDC, whether they are jpegs or bitmaps.  _Outside_ the CMemDC (ie when I just BitBlt things straight onto the screen) they always appear opaquely, ie they have a white box around them.

When I just use bitmaps and load them in with (HBITMAP)::LoadImage() etc, they appear fine outside the the CMemDC.  BUT they will not appear inside the CMemDC(nothing shows up). Moreover, if I blt a mixture of jpegs (using CPicture) and bitmaps (not using CPicture) onto a CMemDC, nothing appears, not even the jpegs which would appear fine on their own.

I really don't know what's going on.  Does anyone know?
0
 

Author Comment

by:wilsonian
ID: 12050134
Right, I've had the problem pointed out to me. The problem was that in the function I was using to draw the bitmaps, I was selecting the bitmap into a CDC like so:

CDC dcMem;
dcMem.CreateCompatibleDC(dc);
CBitmap* oldBmp = dcMem.SelectObject(&myBitmap);

and then putting the old one back in:

dc->SelectObject(oldBmp);

Whoops.  Those ain't the same CDC.

Sorry about the complicated question when the problem was so simple.
0
 

Author Comment

by:wilsonian
ID: 12050189
I'll ask to close the question if that's ok with you nabehs
0
 
LVL 6

Expert Comment

by:nabehs
ID: 12051451
sure, no problem.
0
 

Accepted Solution

by:
PashaMod earned 0 total points
ID: 12094566
Closed, 500 points refunded.
PashaMod
Community Support Moderator
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…

912 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now