接上篇http://blog.csdn.net/uoyevoli/archive/2005/11/25/536879.aspx
CHyperLink允许在程序中嵌入web-links,当按下时会打开一个浏览器显示这个URL。
template <class T, class TBase = CWindow,
class TWinTraits = CControlWinTraits>
class CHyperLinkImpl
: public CWindowImpl< T, TBase, TWinTraits >
class CHyperLink : public CHyperLinkImpl<CHyperLink>
CWaitCursor可以根据输入参数设置光标,默认值为IDC_WAIT。
class CWaitCursor
CMultiPaneStatusBarCtrl 提供了一个包含了“子分割”的状态条(status bar)不同的“分割”上可以放置不同的文本。
template <class T, class TBase = CStatusBarCtrl>
class CMultiPaneStatusBarCtrlImpl
: public CWindowImpl< T, TBase >
class CMultiPaneStatusBarCtrl
: public CMultiPaneStatusBarCtrlImpl<CMultiPaneStatusBarCtrl>
Dynamic Data Exchange(altddx.h)
DDX用来在类的数据成员和对话框控件之间双向交换数据。WTL中的DDX只牵涉到一个模板类CWinDataExchange,和许多和宏,比如DDX_TEXT。
template <class T> class CWinDataExchange
要想使用DDX,你的对话框类应该从CDialogImpl和CWinDataExchange继承并有一个message map,比如
BEGIN_DDX_MAP(CMyDialogDlg)
DDX_INT(IDC_AMOUNT_INT, m_nAmount)
END_DDX_MAP()
目前这个map必须手工创建,但是很有可能在下一版的Visual C++ Wizard中支持通过向导创建(到目前为止VC7仍然不支持——译者注)。
System Dialogs And Property Sheets (atldlgs.h)
WTL对系统对话框提供了全面的支持
template <class T> class CFileDialogImpl
: public CDialogImplBase
WTL Developer’s Guide
class CFileDialog : public CFileDialogImpl<CFileDialog>
template <class T> class CFolderDialogImpl
class CFolderDialog : public CFolderDialogImpl<CFolderDialog>
class CCommonDialogImplBase : public CWindowImplBase
template <class T> class CFontDialogImpl
: public CCommonDialogImplBase
class CFontDialog : public CFontDialogImpl<CFontDialog>
class CRichEditFontDialogImpl : public CFontDialogImpl< T >
class CRichEditFontDialog : public
CRichEditFontDialogImpl<CRichEditFontDialog>
template <class T> class CColorDialogImpl
: public CCommonDialogImplBase
class CColorDialog : public CColorDialogImpl<CColorDialog>
template <class T> class CPrintDialogImpl
: public CCommonDialogImplBase
class CPrintDialog : public CPrintDialogImpl<CPrintDialog> template
<class T> class CPrintDialogExImpl
: public CWindow, public CMessageMap,
public IPrintDialogCallback,
public IObjectWithSiteImpl< T >
class CPrintDialogEx : public CPrintDialogExImpl<CPrintDialogEx>
template <class T> class CPageSetupDialogImpl
: public CCommonDialogImplBase
class CPageSetupDialog
: public CPageSetupDialogImpl<CPageSetupDialog>
template <class T> class CFindReplaceDialogImpl
: public CCommonDialogImplBase
class CFindReplaceDialog
: public CFindReplaceDialogImpl<CFindReplaceDialog>
WTL也为property sheet提供一系列的支持:
class CPropertySheetWindow : public CWindow
template <class T, class TBase = CPropertySheetWindow>
class CPropertySheetImpl : public CWindowImplBaseT< TBase >
class CPropertySheet : public CPropertySheetImpl<CPropertySheet>
class CPropertyPageWindow : public CWindow
template <class T, class TBase = CPropertyPageWindow>
class CPropertyPageImpl : public CDialogImplBaseT< TBase >
template <WORD t_wDlgTemplateID> class CPropertyPage
: public CPropertyPageImpl<CPropertyPage<t_wDlgTemplateID> >
Frames (atlframe.h)
下面的类用来支持frames
CFrameWndClassInfo 是frame window的类
class CFrameWndClassInfo
CFrameWindowImpl 是程序级用来管理frames的基本C++类
template <class TBase = CWindow, class TWinTraits =
CFrameWinTraits> class CFrameWindowImplBase
: public CWindowImplBaseT< TBase, TWinTraits >
template <class T, class TBase = CWindow, class TWinTraits =
CFrameWinTraits> class CFrameWindowImpl
: public CFrameWindowImplBase< TBase, TWinTraits >
为了支持MDI,WTL提供了这些类:
class CMDIWindow : public CWindow
template <class T, class TBase = CMDIWindow, class TWinTraits =
CFrameWinTraits>
class CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase,
TWinTraits >
template <class T, class TBase = CMDIWindow, class TWinTraits =
CMDIChildWinTraits> class CMDIChildWindowImpl
: public CFrameWindowImplBase<TBase, TWinTraits >
COwnerDraw模板为实现owner draw功能提供帮助。它通常通过多重继承来添加到类中的。COwnerDraw和CCustomDraw是有区别的,CCustomDraw处理通过WM_NOTIFY发送的NM_CUSTOMDRAW通知消息。支持这个通知的有下面的通用控件:
Headers,list view, rebar,tooltip,trackbar和tree view控件。COwnerDraw处理WM_DRAWITEM,WM_MEASUREITEM,WM_COMPAREITEM和WM_DELETEITEM消息,这些消息一般是发送给owner-draw button,combobox,list view控件或菜单项目(itmes)。
template <class T> class COwnerDraw
CUpdateUI可以用来动态更新UI元素。菜单项目(items)和toolbar按钮可以用它来实现“可用”和“不可用(禁止)”状态。
class CUpdateUIBase;
template <class T> class CUpdateUI : public CUpdateUIBase
GDI(atlgdi.h)
WTL提供了管理所有GDI对象的模板。每个模板的逻辑型参数t_bManaged指定这个GDI对象是否在模板的析构函数里被删除(delete)。每个模板有两个typedefs,其中一个t_bManaged置true,另一个置false。这些模板包含了所有的win32 GDI APIs,为它们提供了类型安全的(typesafe)C++接口。
template <bool t_bManaged> class CPenT
typedef CPenT<false> CPenHandle;
typedef CPenT<true> CPen;
template <bool t_bManaged> class CBrushT
typedef CBrushT<false> CBrushHandle;
typedef CBrushT<true> CBrush;
template <bool t_bManaged> class CFontT
typedef CFontT<false> CFontHandle;
typedef CFontT<true> CFont;
template <bool t_bManaged> class CBitmapT
typedef CBitmapT<false> CBitmapHandle;
typedef CBitmapT<true> CBitmap;
template <bool t_bManaged> class CPaletteT
typedef CPaletteT<false> CPaletteHandle;
typedef CPaletteT<true> CPalette;
template <bool t_bManaged> class CRgnT
typedef CRgnT<false> CRgnHandle;
typedef CRgnT<true> CRgn;
template <bool t_bManaged> class CDCT
typedef CDCT<false> CDCHandle;
typedef CDCT<true> CDC;
从CDC还继承出来一些工具类(helper classes)用来提供额外的功能。CPaintDC用来处理WM_PAINT消息,它在构造函数里调用了Win32的BeginPaint,在析构函数里调用EndPaint。CClientDC和CWindowDC用来取得一个HWND的客户区和窗口DC。CEnhMetaFileDC用来在一个“增强元文件(enhanced metafile)中绘画,它的构造函数调用了Win32的CreateEnhMetaFile,析构函数调用了CloseEnhMetaFile。
class CPaintDC : public CDC
class CClientDC : public CDC
class CWindowDC : public CDC
class CEnhMetaFileDC : public CDC
WTL还为enhanced metafile提供了额外的支持。CEnhMetaFileT是对一个enhanced metafile句柄的包装。CEnhMetaFileInfo提供了对win32的GetEnhMetaFileBits、GetEnhMetaFileDescription,
GetEnhMetaFileHeader 和 GetEnhMetaFilePixelFormat的调用
template <bool t_bManaged> class CEnhMetaFileT
typedef CEnhMetaFileT<false> CEnhMetaFileHandle;
typedef CEnhMetaFileT<true> CEnhMetaFile;
class CEnhMetaFileInfo
其他(atlmisch)
WTL还为常用数据类型提供了包装类。WTL的CString是MFC CString的完美模仿和代替品。还有CSize,CPoint和CRect
class CSize : public tagSIZE
class CPoint : public tagPOINT
class CRect : public tagRECT
class CString;
处理最近文件列表(recent file list)和文件搜索
class CRecentDocumentList;
class CFindFile;
打印(atlprint.h)
WTL为打印提供了很好的支持。
PrinterInfo数据被template <unsigned int t_nInfo> class CPrinterInfo的支持。下面的模板有来处理打印机句柄:
template <bool t_bManaged> class CPrinterT
typedef CPrinterT<false> CPrinterHandle;
typedef CPrinterT<true> CPrinter;
处理 DEVMODE的模板
template <bool t_bManaged> class CDevModeT;
typedef CDevModeT<false> CDevModeHandle;
typedef CDevModeT<true> CDevMode;
向打印机绘画是使用这个DC类:
class CPrinterDC : public CDC
要获得打印任务(job)的信息,使用
class IPrintJobInfo
class CPrintJobInfo : public IPrintJobInfo
class CPrintJob;
打印预览窗口
class CPrintPreview;
template <class T, class TBase = CWindow, class TWinTraits =
CControlWinTraits>
class CPrintPreviewWindowImpl
:public CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview
class CPrintPreviewWindow
: public CPrintPreviewWindowImpl<CPrintPreviewWindow>
滚动(Scrolling)(atlscrl.h)
窗口滚动是被下面这些类和模板支持的:
template <class T> class CScrollImpl
template <class T, class TBase = CWindow,
class TWinTraits = CControlWinTraits>
class CScrollWindowImpl
:public CWindowImpl<T,TBase,TWinTraits>,public CScrollImpl< T >
template <class T> class CMapScrollImpl: public CScrollImpl< T >
template <class T, class TBase = CWindow,
class TWinTraits = CControlWinTraits>
class CMapScrollWindowImpl : public CWindowImpl< T, TBase,
TWinTraits >, public CMapScrollImpl< T >
平面分割的滚动条:
template <class TBase = CWindow> class CFSBWindowT
:public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > >
typedef CFSBWindowT<CWindow> CFSBWindow;
分割条(splitters)(atlsplit.h)
水平和垂直的分割条可以用下面的三个模板实现:
template <class T, bool t_bVertical = true> class CSplitterImpl;
template <class T, bool t_bVertical = true, class TBase =
CWindow, class TWinTraits = CControlWinTraits>
class CSplitterWindowImpl : public CWindowImpl< T, TBase, TWinTraits
>, public CSplitterImpl<CSplitterWindowImpl< T , t_bVertical, TBase,
TWinTraits >, t_bVertical>
template <bool t_bVertical = true> class CSplitterWindowT
: public CSplitterWindowImpl<
CSplitterWindowT<t_bVertical>, t_bVertical>
typedef CSplitterWindowT<true> CSplitterWindow;
typedef CSplitterWindowT<false> CHorSplitterWindow;
菜单(atluser.h)
CMenuItemInfo类是Win32中MENUITEMINFO结果的包装,CMenuT可以用来管理菜单,它提供了对菜单所有属性的类型安全的访问。
class CMenuItemInfo : public MENUITEMINFO
template <bool t_bManaged> class CMenuT
WTL中没有什么?
(本节翻译内容并没有完全照搬原文,和原文相比有所删略。——译者注)
在看了WTL中的主要功能后,我们来看看WTL不支持的东西。
WTL的唯一目标是为开发人员提供用户界面,在这方面它已经做得非常好了。它并没有偏离该目标而设计其他领域。
没有Document支持
WTL提供了frame和view,但是没有document。WTL所关注的是用户界面,而document是不可见的,所以它不是WTL关心的范围。
没有Active Document支持
……
没有ISAPI支持
……
没有WinInet支持
……
没有对线程和同步进行包装
……
没有数据库支持
……
开发的问题
要开始使用WTL,还有下面几个问题需要理解。
最终产品
使用WTL建立的程序体积是很小的,AppWizard生成的默认SDI程序编译后的exe文件大小只有64K,TinyWTL例程由于去掉了多余的功能,编译后只有24K大小。一个真实的商业级程序应该不会超过250K。并且这些文件经过压缩后将会再减少2/3的体积,可以在Internet上快速下载。
在Build完成后,如果你没有使用CRT和其他的DirectX之类的库,那么WTL工程编译后的exe或dll就是你唯一需要发送给最终用户的文件了。WTL程序没有额外的依赖。文件少,出现问题的几率就少。
CRT
C-Runtime library上Win32 API之上的一组C函数,通常被称作CRT。CRT的源代码是VC++的一部分(在src目录),如果你仔细看一下的话,就会发现这些CRT的函数是用ANSI C实现的,一些直接调用了APIs,一些通过调用中间函数间接调用了APIs。CRT大部分是来自ANSI C标准库的一些函数(printf,strok等),但是也有一些Win32平台相关的函数(比如(beginthreadex在做了一些CRT初始化后调用了CreateThread API)
如果你的程序只使用ANSI C标准库,你的代码就是可移植的。有许多百万行代码级的工程在经过不到2%的更改后就可以在Windows和UNIX上顺利通过编译和正常运行。CRT确实在某些领域提供了Win32所没有的功能,比如string形式的浮点数、C++异常和为全局变量调用构造/析构函数。
如果你使用ATL和WTL进行编程,你的代码绝对不可能移植到UNIX/LINUX之上,这样有个问题就产生了,我到底有必要连接到CRT吗?CRT在很大程度上是Win32 APIs的重复,所以大部分情况下,大案是“No”。离开了C++异常处理和全局变量的构造/析构函数,也可以生存,而使用了CRT,你的程序体积将增大,并有了额外的外部依赖(MSVCRT.dll)而这个库有多个版本,这也可能成为麻烦的根源。
WTL AppWizard生成的工程的设置使得CRT在debug build是可用(为了调用ATLASSERT),而在release build时并不包含进来(预处理指令中的_ATL_MIN_CRT宏)。如果你没有注意到这个细节,可能会对“使用了CRT的WTL工程怎么也无法在release模式下编译通过”的问题束手无策。注意:CRT在Release模式下默认是不被包含的。
如果你真的打算使用CRT,只要去掉_ATL_MIN_CRT宏就可以了,(VC7中是把“项目”->“属性”对话框中的“在ATL中最小使用CRT”选项置“否”)。
如果使用了CRT,关于多线程的一个有趣的问题就产生了。CRT有多个版本,一些是静态连接的,一些的动态加载的,一些是用于单线程应用程序的,一些是用于多线程程序的。如果你在不止一个线程中使用CRT,你就必须使用多线程版本的CRT。同一个工程中的所有EXE和DLL也必须使用一致的设置(在DevStudio的 Project settings对话框的Generation类别里)。
错误处理
(本段翻译有删略——译者注)
在WTL程序中要使用C++异常处理,就必须依赖CRT(当然,如果你愿意可以使用)。另外对API可以使用GetLastError和ATLASSERT
WTL名称空间(namespace)
新的ISO C++标准引入了名称空间的概念,WTL为了避免和其他类库产生名称冲突,它的每一个头文件都是以下面的代码开始:
namespace WTL
{
并以:
}; //namespace WTL
结束
……
……
(省略关于名称空间的使用的说明——译者)
模板/类/方法名
WTL的命名管理沿用MFC的,由于它们两个都是基于Win32 API的,所以这么做是有意义的。并且多数的WTL程序员是来自MFC程序员。
WTL的类名是这样的,CEdit,CStatic和CDC。窗口消息的处理程序名称为OnInitDialog and OnOK。数据交换使用DDX,方法名为DoDataExchange。
WTL和MFC不同的地方是,在有些地方,WTL明智地遵循了Win32的名称,比如Win32的UpDown控件在WTL中为CUpDownCtrlT,而在MFC中为CSpinButtonCtrl。
Windows的版本
WTL全面支持Win2000和WinMe(以及Windows XP——译者)中的新UI特性,但也可以用于旧版本的Windows,这个可以通过#define一个WINVER来实现。
待续……