无论从功能上还是代码隔离的角度来看,用于消息处理的窗口函数应该封装成一个独立的类。这个类提供了消息处理能力,它是所有消息去向的目的地,所以将这个类命名为CCmdTarget,意为命令目标类。
1.窗口函数的简单封装
窗口函数WndProc()是一个全局函数,不能直接把它封装到CCmdTarget类中,只能把它留在类外,把它的函数体封装到CCmdTarget类的成员函数中,如,AfxWndProc()。这样,既把原窗口的功能封装到了类中,又保留了系统与该功能之间的联系通道。AfxWndProc()与原窗口函数WndProc()的关系及事件消息的流动方式如下图:
把消息处理功能封装到一个单独的CCmdTarget类中还有另一个优点,凡是希望具有消息处理能力的类都可以自CCmdTarget来派生。这样一来,在整个类体系中就又多了一个类CCmdTarget,而一个Windows程序的结构也变成下图所示:
其引入CCmdTarget类的代码如下:
//需要包含的头文件-------------------------------------------------------------------------
#include "stdafx.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "MFCTest.h"
#include<Windows.h>
//定义全局变量和函数------------------------------------------------------------------------
HINSTANCE hInstance;
HINSTANCE hInst;
MSG msg;
char lpszClassName[] = "window_class";
char* ShowText;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//窗口函数
//CCmdTarget------------------------------------------------------------------------------
class CCmdTarget1
{
public:
HWND hWnd;
int WndProc1(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
virtual void OnLButtonDown();
void OnPaint(HDC hdc);
virtual void OnDestroy();
};
int CCmdTarget1::WndProc1(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
OnLButtonDown();
break;
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hWnd, &ps);
OnPaint(hdc);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
OnDestroy();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void CCmdTarget1::OnLButtonDown()
{
}
void CCmdTarget1::OnPaint(HDC hdc)
{
TextOut(hdc, 50, 50, ShowText, 16);
}
void CCmdTarget1::OnDestroy()
{
PostQuitMessage(0);
}
//窗口类------------------------------------------------