BOOKS i'm reading
Alternative to MFC for GDI programming
I got the idea of developing this project after I started to study MFC GDI related classes. I saw a lot of code for features that I have never used. From there, I wanted to perform an experiment where I could verify if by using a stripped down version of GDI classes, it would translate to a better painting performance. As you will see in the conclusion, I did not obtain the results I was hoping for, and I hesitated to write a
C++ Windows programming tutorial about the code I wrote. I concluded that if a fellow programmer was looking for an OO GDI encapsulation in a non MFC project, this code could be useful to him. In this
C++ Windows programming tutorial, I will first describe what I did not like in MFC code, highlight the important points of the new class set, present the demo program, and conclude by presenting the result of the experiment.
CDC::m_hAttribDC is one of these features. Most of the time
m_hAttribDC == m_hDC and the presence of
m_hAttribDC just add superfluous overhead all over
CDC code. Here is an example:
CPoint CDC::MoveTo(int x, int y)
ASSERT(m_hDC != NULL);
if (m_hDC != m_hAttribDC)
VERIFY(::MoveToEx(m_hDC, x, y, &point));
if (m_hAttribDC != NULL)
VERIFY(::MoveToEx(m_hAttribDC, x, y, &point));
Also, related to
m_hAttribDC, the class
CMetafileDC is flawed. It forces its users to explicitly set
CMetafileDC forbids you to set
m_hDC, but this is wrong! It should work because the first parameter of
pDCRef - Identifies a reference device for the enhanced metafile.
When it is
NULL, the reference device will be the display. The reason why MFC ignores
pDCRef and sets
NULL is probably because
CMetaFileDC also supports the old Windows 1.0 metafile format and these metafiles have no notion of reference devices. Most of the functions overridden in
CDC are virtual, and in almost all cases, it was done like that only to enforce the flawed rule that a metafile attribute DC should not equal the output DC. Hence, virtual function calls overhead is applied to all
CDC objects for nothing.
And finally, the last source of overhead in MFC GDI classes is the handle maps. Handle maps are essential for window objects but I still have to see a situation with GDI objects where the handle maps are crucial. Handle maps are invoked when the functions
FromHandle() are called. You could think that if you are not calling these functions then you are not using them, right? Well, this is wrong. Every time an object is selected in a
CDC object, the object pointer returned by the
SelectObject() function comes from
CGdiObject::FromHandle(). To get an idea of the magnitude of this source of overhead, consider the pseudocode for
- Try to find the requested handle in the permanent object map.
- If not found, try to find the requested handle in the temporary object map.
- If not found, create a temporary object.
All these temporary objects will then be deleted the next time the MFC framework enters its idle function.