MFC程序员WTL指南(2)ATL界面类
2008-01-19 20:26:41 来源:WEB开发网构造函数和析构函数都相当简单,只是创建和销毁Windows画刷,这个画刷由参数t_crBrushColor决定颜色。接着是消息映射链,它响应WM_ERASEBKGND消息,最后由响应函数OnEraseBkgnd()用构造函数创建的画刷填充窗口的背景。在OnEraseBkgnd()中有两件事需要注意,一个是它使用了一个派生的窗口类的方法(即GetClientRect()),我们如何知道派生类中有GetClientRect()方法呢?如果派生类中没有这个方法我们的代码也不会有任何抱怨,由编译器确认派生类T是从CWindow派生的。另一个是OnEraseBkgnd()没有将消息参数wParam展开为设备上下文(DC)。(WTL最终会解决这个问题,我们很快就可以看到,我保证)
要在我们的窗口中使用这个嵌入类需要做两件事:首先,将它加入到继承列表:
class CMyWindow : public CWindowImpl<CMyWindow, CWindow, CFrameWinTraits>,
public CPaintBkgnd<CMyWindow, RGB(0,0,255)>
其次,需要CMyWindow将消息传递给CPaintBkgnd,就是将其链入到消息映射链,在CMyWindow的消息映射链中加入CHAIN_MSG_MAP宏:
class CMyWindow : public CWindowImpl<CMyWindow, CWindow, CFrameWinTraits>,
public CPaintBkgnd<CMyWindow, RGB(0,0,255)>
{
...
typedef CPaintBkgnd<CMyWindow, RGB(0,0,255)> CPaintBkgndBase;
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_HANDLER(IDC_ABOUT, OnAbout)
CHAIN_MSG_MAP(CPaintBkgndBase)
END_MSG_MAP()
...
};
任何CMyWindow没有处理的消息都被传递给CPaintBkgnd。应该注意的是WM_CLOSE,WM_DESTROY和IDC_ABOUT消息将不会传递,因为这些消息一旦被处理消息映射链的查找就会中止。使用typedef是必要地,因为宏是预处理宏,只能有一个参数,如果我们将CPaintBkgnd<CMyWindow, RGB(0,0,255)>作为参数传递,那个“,”会使预处理器认为我们使用了多个参数。
你可以在继承列表中使用多个嵌入类,每一个嵌入类使用一个CHAIN_MSG_MAP宏,这样消息映射链就会将消息传递给它。这与MFC不同,MFC地CWnd派生类只能有一个基类,MFC自动将消息传递给基类。
ATL程序的结构到目前为止我们已经有了一个完整地主窗口类(即使不完全有用),让我们看看如何在程序中使用它。一个ATL程序包含一个CComModule类型的全局变量_Module,这和MFC的程序都有一个CWinApp类型的全局变量theApp有些类似,唯一不同的是在ATL中这个变量必须命名为_Module。
下面是stdafx.h文件的开始部分:
// stdafx.h:
#define STRICT
#define VC_EXTRALEAN
#include <atlbase.h> // 基本的ATL类
extern CComModule _Module; // 全局_Module
#include <atlwin.h> // ATL窗口类
atlbase.h已经包含最基本的Window编程的头文件,所以我们不需要在包含windows.h,tchar.h之类的头文件。在CPP文件中声明了_Module变量:
// main.cpp:
CComModule _Module;
CComModule含有程序的初始化和关闭函数,需要在WinMain()中显示的调用,让我们从这里开始:
// main.cpp:
CComModule _Module;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev,
LPSTR szCmdLine, int nCmdShow)
{
_Module.Init(NULL, hInst);
_Module.Term();
}
Init()的第一个参数只有COM的服务程序才有用,由于我们的EXE不含有COM对象,我们只需将NULL传递给Init()就行了。ATL不提供自己的WinMain()和类似MFC的消息泵,所以我们需要创建CMyWindow对象并添加消息泵才能使我们的程序运行。
更多精彩
赞助商链接