Windows programs do most of their drawing in response to WM_PAINT messages. Using the Microsoft Foundation classes, your derived window class can handle the WM_PAINT message by implementing the OnPaint message handler function and defining a message-map entry with the ON_WM_PAINT macro. The following list describes the steps necessary to handle WM_PAINT messages using the Microsoft Foundation classes:
1.Derive your window class from a Foundation window class.
2.Define the OnPaint message-handler member function for your derived window class.
3.Define a message-map entry with the ON_WM_PAINT macro.
The following class declaration shows how to derive a window class from a Microsoft Foundation window class and declare the OnPaint message-handler member function necessary to handle the WM_PAINT member function. It also shows the required inclusion of the DECLARE_MESSAGE_MAP macro to enable the Foundation message-map mechanism for the derived window class.
class CMainWnd : public CFrameWnd
{
public:
// constructor is required for derived window classes
CMainWnd();
// message-handler function for WM_PAINT message
afx_msg void OnPaint();
// enable message-map mechanism
DECLARE_MESSAGE_MAP()
};
The OnPaint message-handler function for a derived window class is called when the window receives a WM_PAINT message. In a traditional Windows program, you call BeginPaint to get a device context for the window, draw your window contents, and finally call EndPaint to release the device context when responding to a WM_PAINT message.
When using the Microsoft Foundation classes, you can create a CPaintDC object instead of calling BeginPaint and EndPaint. The constructor for this object automatically calls BeginPaint and its destructor calls EndPaint. You must specify a pointer to a CWnd object when creating the CPaintDC object. Since you typically create a CPaintDC object in the OnPaint member function of your derived window class, you can pass this as the CWnd pointer argument, as shown in the following example implementation of OnPaint:
void CMainWnd::OnPaint()
{
CPaintDC dc( this );
// do painting here with dc...
}
When the CPaintDC object is created, its constructor calls BeginPaint. Notice that since the CPaintDC is created on the stack, it is automatically deallocated when you exit OnPaint. This automatic deallocation implies that the destructor for the object, which calls EndPaint, will be invoked as the function terminates.
The CPaintDC device context can be used to perform any drawing operation that you could normally do in a normal Windows device context since all the device context GDI drawing functions are available as member function in the device context class. For example, to draw text in the window, you can use the TextOut member function, which is equivalent to the Windows Graphical Device Interface function TextOut. The following code fragment shows how to use a CPaintDC device context to draw in a window during the WM_PAINT message.
void CMainWnd::OnPaint()
{
CString s = "Hello, Windows!";
CPaintDC dc( this );
CRect rect;
GetClientRect( &rect );
dc.SetTextAlign( TA_BASELINE | TA_CENTER );
dc.TextOut( ( rect.right / 2 ), ( rect.bottom / 2 ),
s, s.GetLength() );
}
To associate the OnPaint message-handler function with the WM_PAINT message, you must define a message-map entry for the derived window class. The following message-map definition shows how this is done:
BEGIN_MESSAGE_MAP( CMainWnd, CFrameWnd )
ON_WM_PAINT()
END_MESSAGE_MAP()