My GDI program runs fine on Windows XP but on Windows Vista and 7 it looks pretty terrible due to the lack of GDI hardware acceleration. I recall reading an article a few years back saying that Windows 7 added hardware acceleration to some GDI functions, including BitBlt() function. Supposedly, if you if you draw to a memory bitmap and then use BitBlt() to copy the image to your main window it runs about the same speed as XP. Is that true?
If it is true, how do you do it? I'm terrible at programming and am having a bit of trouble. I created the below class to to try and get it working:
class CMemBmpTest
{
private:
CDC m_dcDeviceContext;
CBitmap m_bmpDrawSurface;
public:
CMemBmpTest();
~CMemBmpTest();
void Init();
void Draw();
};
CMemBmpTest::CMemBmpTest()
{
}
CMemBmpTest::~CMemBmpTest()
{
m_bmpDrawSurface.DeleteObject();
m_dcDeviceContext.DeleteDC();
}
void CMemBmpTest::Init()
{
m_dcDeviceContext.CreateCompatibleDC(NULL);
m_bmpDrawSurface.CreateCompatibleBitmap(&m_dcDeviceContext, 100, 100);
}
void CMemBmpTest::Draw()
{
m_dcDeviceContext.SelectObject(I.m_brshRedBrush);
m_dcDeviceContext.PatBlt(0, 0, 100, 100, BLACKNESS);
}
In the OnPaint() function of the window I added the line:
pDC->BitBlt(2, 2, 100, 100, &m_MemBmp, 0, 0, SRCCOPY);
I was hoping to see a 100x100 black box in the corner of the window but it didn't work. I'm probably doing everything horrifically wrong, so would be grateful if somebody could advise me as to how to do this correctly.
Thanks for any advice you can offer.
AFAIK you get hardware acceleration on GDI functions on all versions of Windows (I'm happy to stand corrected on this if someone can explain it in more detail). But either way, you're correct that double buffering (which is what you're talking about) provides a massive performance boost (and more importantly no flickering) relative to drawing direct to the screen.
I've done quite a lot of this and have come up with a method to allow you to use GDI and GDI+ at the same time in your drawing functions, but benefit from the hardware acceleration of the BitBlt in drawing to screen. GDI+ isn't hardware accelerated AFAIK but can be very useful in many more complex drawing techniques so it can be useful to have the option of.
So, my basic view class will have the following members :
Then the class itself will have code something like this
So, you can then either just draw direct to the memory DC and call InvalidateRect() or put all your drawing code in rcUpdateBitmap() which was more convenient for the way I was using it. You'll need to call vCreateScreenBuffer() in OnSize().
Hopefully that gives you some ideas anyway. Double buffering is definitely the way to go for speed and non-flickering UI. It can take a little bit of effort to get going but it's definitely worth it.
CMemDC: http://www.codeproject.com/Articles/33/Flicker-Free-Drawing-In-MFC http://msdn.microsoft.com/en-us/library/cc308997(v=vs.90).aspx