现在正式开始介绍WTL!在这一部分我讲的内容包括生成一个基本的主窗口和WTL提供的一些友好的改进,比如UI界面的更新(如菜单上的选择标记)和更好的消息映射机制。为了更好地掌握本章的内容,你应该安装WTL并将WTL库的头文件目录添加到VC的搜索目录中,还要将WTL的应用程序生成向导复制到正确的位置。WTL的发布版本中有文档具体介绍如何做这些设置,如果遇到困难可以查看这些文档。
WTL 总体印象
WTL的类大致可以分为几种类型:
·主框架窗口的实现- CFrameWindowImpl, CMDIFrameWindowImpl
·控件的封装- CButton, CListViewCtrl
·GDI 对象的封装- CDC, CMenu
·一些特殊的界面特性 - CSplitterWindow, CUpdateUI, CDialogResize, CCustomDraw
·实用的工具类和宏- CString, CRect, BEGIN_MSG_MAP_EX
本篇文章将深入地介绍框架窗口类,还将简要地讲一下有关的界面特性类和工具类,这些界面特性类和工具类中绝大多数都是独立的类,尽管有一些是嵌入类,例如:CDialogResize。
开始写WTL程序 如果你没有用WTL的应用程序生成向导也没关系(我将在后面介绍这个向导的用法), WTL的程序的代码结构很像ATL的程序,本章使用的例子代码有别于第一章的例子,主要是为了显示WTL的特性,没有什么实用价值。
这一节我们将在WTL生成的代码基础上添加代码,生成一个新的程序,程序主窗口的客户区显示当前的时间。stdafx.h的代码如下:
#define STRICT #define WIN32_LEAN_AND_MEAN #define _WTL_USE_CSTRING
#include <atlbase.h> // 基本的ATL类 #include <atlapp.h> // 基本的WTL类 extern CAppModule _Module; // WTL 派生的CComModule版本 #include <atlwin.h> // ATL 窗口类 #include <atlframe.h> // WTL 主框架窗口类 #include <atlmisc.h> // WTL 实用工具类,例如:CString #include <atlcrack.h> // WTL 增强的消息宏 |
atlapp.h 是你的工程中第一个包含的头文件,这个文件内定义了有关消息处理的类和CAppModule,CAppModule是从CComModule派生的类。如果你打算使用CString类,你需要手工定义_WTL_USE_CSTRING标号,因为CString类是在atlmisc.h中定义的,而许多包含在atlmisc.h之前的头文件都会用到CString,定义_WTL_USE_CSTRING之后,atlapp.h就会向前声明CString类,其他的头文件就知道CString类的存在,从而避免编译器为此大惊小怪。
接下来定义框架窗口。我们的SDI窗口是从CFrameWindowImpl派生的,在定义窗口类时使用DECLARE_FRAME_WND_CLASS代替前面使用的DECLARE_WND_CLASS。下面时MyWindow.h中窗口定义的开始部分:
class CMyWindow : public CFrameWindowImpl<CMyWindow> { public: DECLARE_FRAME_WND_CLASS(_T("First WTL window"), IDR_MAINFRAME);
BEGIN_MSG_MAP(CMyWindow) CHAIN_MSG_MAP(CFrameWindowImpl<CMyWindow>) END_MSG_MAP() }; |
DECLARE_FRAME_WND_CLASS有两个参数,窗口类名(类名可以是NULL,ATL会替你生成一个类名)和资源ID,创建窗口时WTL用这个ID装载图标,菜单和加速键表。我们还要象CFrameWindowImpl中的消息处理(例如WM_SIZE和WM_DESTROY消息)那样将消息链入窗口的消息中。
现在来看看WinMain()函数,它和第一部分中的例子代码中的WinMain()函数几乎一样,只是创建窗口部分的代码略微不同。
// main.cpp:#include "stdafx.h"#include "MyWindow.h" CAppModule _Module; int APIENTRY WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { _Module.Init ( NULL, hInstance ); CMyWindow wndMain;MSG msg; // Create the main window if ( NULL == wndMain.CreateEx() ) return 1; // Window creation failed // Show the window wndMain.ShowWindow ( nCmdShow ); wndMain.UpdateWindow(); // Standard Win32 message loop while ( GetMessage ( &msg, NULL, 0, 0 ) > 0 ) { TranslateMessage ( &msg ); DispatchMessage ( &msg ); } _Module.Term(); return msg.wParam; } |
CFrameWindowImpl中的CreateEx()函数的参数使用了常用的默认值,所以我们不需要特别指定任何参数。正如前面介绍的,CFrameWindowImpl会处理资源的装载,你只需要使用IDR_MAINFRAME作为ID定义你的资源就行了(译者注:主要是图标,菜单和加速键表),你也可以直接使用本章的例子代码。
如果你现在就运行程序,你会看到主框架窗口,事实上它没有做任何事情。我们需要手工添加一些消息处理,所以现在是介绍WTL的消息映射宏的最佳时间。