WTL开发者指南 第1章 WTL概述
WTL开发者指南
注:本文是袁晓辉根据Eamon O’ Tuathail的WTL Developer’s Guide(www.clipcode.biz ) 翻译而来,发布在www.farproc.com 和 blog.csdn.net。作者翻译本文仅仅是为自己和其他WTL爱好者学习之用,请勿用于商业用途。你可以转载本文,但必须保证本文的完整性,并保留该声明!
第1章 WTL概述
目标
该章的目标为:
Ÿ WTL在整个VC++开发中所处的位置
Ÿ WTL的目标
Ÿ WTL和其他用户界面(UI)开发技术的对比
Ÿ 介绍WTL的安装
Ÿ 介绍WTL安装了什么
Ÿ 列举可用的开发资源
Ÿ 对后面各章的介绍
概述
以前Visual C++开发者往往选择MFC,因为它提供的功能涵盖了非常广的编程技术领域而模板库所涉及的领域相对狭窄。
最近模板库涉足的领域和质量都有很大发展,因而越来越多的人选择了模板库。
ATL设计的目标是提供快速紧凑的COM组件,ISO C++的STL提供集合(collections),VC++ OLE DB Data Consumer and Provider模板提供数据库支持。与之相对应,MFC提供了一个C++类库,这个类库包含对COM创建、集合类(collection class)、数据库和用户界面的普遍支持。
大部分的高级开发人员更喜欢较新的模板开发方式。MFC很庞大、臃肿、对线程不友好,并且,基本上已经过时了!模板的方法既快速(当正确设计时)、有弹性而且涵盖了所有最新的技术,拿来应对新的开发需要是再好不过的了。
到目前为止,让模板狂热分子头疼的主要问题在于如何创建图形用户界面(GUI)。ATL确实提供了一个轻量级的Win32/64 windowing 包装类,但是它并没有涵盖所有的UI需求。ATL开发者为了琐碎的用户界面处理不得不重操MFC UI编程或者用VB给自己的ATL COM做前端,这两种方法都不能完全令人满意。
进入正题,开始说窗口模板库(Windows Template Library)。WTL是一个居于Win32/64 API之上的一个包装类和方便易用的增强模板的高级集合,它对图形用户界面提供了广泛的支持。WTL不但保持着模板库的真正血统,小巧,快速,不具侵入性而且包括了最新的UI理念,非常好地支持多线程。你可以单独使用WTL或和ATL、STL、VC++ Data Templates、第三方类库,以及你自己的类库一起使用以便利用他们各自的优点。WTL通常不依赖外部的DLLs,如果你用WTL开发程序的话,你提供给最终用户的可以只有一个EXE文件。
WTL的目标
WTL之于用户界面就像ATL之于COM、STL之于collection。和它的堂兄一样,WTL需要一段时间来学习,但是一旦掌握了,就没有比它更好的开发高级程序的途径了。从本质上说,WTL完成了三个重大任务:
提供了一个应用程序框架(framwork)
集合了UI功能
包装了windows控件、系统对话框和GDI对象
让我们逐个来看。
提供了一个应用程序框架
WTL提供了一个轻量级的广泛的应用程序框架,这个框架为基于它的程序提供了非常有价值的工具。它的目标既不是像MFC框架那样难以理解也不像手工写WinMain那样原始。
WTL包含了一系列的C++模板和一个WTL AppWizard,AppWizard向程序开发者提出几个问题,然后据此生产VC++工程和程序源代码,源代码里多数是WTL模板类的实例或继承类。一般来说,开发者仅仅需要改变AppWizard生产的代码,而那些很少需要改动的“样板”式的代码都被WTL模板封装了。
WTL中有一个管理整个模块(一个DLL或EXE)的类,这个类在AppWizard生成的代码中实例化,在自动生成的WinMain中被初始化和终结。一个WTL程序也可以作为COM server,支持可编程的应用程序。WTL提供了消息处理机制,支持消息过滤和空闲(on-idle)功能,WM_SETTINGCHANGE引发的改变通知也可以被截获。
MFC提供了一个“文档-框架-视图”结构,WTL也提供框架(比如一个包括菜单条、工具条和状态条的顶层窗口)和视图,但是根本不支持文档。MFC的那套方法往往妨碍高级的开发者,它的文档是基于二进制数据的序列化(serialize),在当今互联网的世界里,基于XML/XSL的文档格式越来越流行,对于弹性化存储机制的需求也越来越多(可能根本就不是存储在本地磁盘上的),文档可能需要运用大量的远程机制,比如WebDAV,FTP等,进行存储。WTL没有提供任何关于数据或存储格式的功能和机制,程序开发者可以自己编写代码,比如利用高效的Win32 API WriteFileGather/ReadFileScatter或XML解析器来根据需要做这些工作。
WTL支持基于对话框的程序,单文档界面(SDI)和多文档界面(MDI)。对于SDI它同样支持多线程SDI,每个SDI窗口一个线程,多数高级的应用程序很有可能用到这种构架(比如,模仿Word2000的方法)。WTL不支持多线程MDI构架,即不支持一个MID子窗口一个线程,但这是可以理解的,比如这样可以避免线程和MDI父子窗口之间交互的许多问题。
集合了UI功能
WTL提供了一组实现现代的用户界面所必不可少的特性。
WTL提供了一个框架窗口用于管理一个包含了命令条(增强的菜单条)、工具条的rebar,一个状态条,一个或多个视图(views)。视图可以基于一个普通的空窗口RechEidt,ListView,TreeView之类的控件。如果使用了多个视图,WTL的分割功能就派上用场了,视图也支持滚动,状态条可以是一个pane或多个panes。
WTL也支持传统的菜单条和工具条,但是它的主菜单表现概念是基于命令条的。一个命令条可以容纳菜单和工具条图标,可以放在一个rebar里显示并四处移动。如果一个菜单项目和一个工具条按钮拥有同样的命令ID的话,菜单项目旁边会自动显示对应的图标。WTL支持可停泊或浮动的命令条,WTL的命令条和Internet Explorer中的很像但和Word2000或Visual Studio的(更令人向往)不一样,WTL不支持可以隐藏不常用的项目的菜单(比如Word2000的)。动态数据交换的概念允许数据在可见的UI控件和C++数据成员之间双向传递,和MFC的DDX很相近。可以用ATL生成对话框,包括那些支持ActiveX控件和窗口容器,利用Visual C++的Resource View可以用来在对话框资源上布局标准控件、通用控件和ActiveX控件,利用ATL Window Message Handler Wizard来映射这些控件的消息。
WTL提供了用来管理属性薄、属性页创建和向导创建的模板创建。
打印机设备场景、打印预览、devmode处理和打印作业管理功能可以用来实现文档打印。
使用特殊的设备场景、文件管理器和增强metafile信息类可以支持增强的metafile。
包装了windows控件、系统对话框和GDI对象
ATL提供了对普通窗口的控制但是没有提供对基于不同窗口类的窗口的特殊支持,开发者不得不根据需要手工编写SnedMessage调用。对于和Edit或TreeView的通讯他们不得不使用ATL的CWindow并且调用Win32的SendMessage以EM_LIMITTEXT或VM_SETITEM还得担心消息的参数是否正确(SendMessage没有类型检查,全部为WPARAM,LPARAM)。当程序接收到它们时也是“裸数据”- wParam和lParam被送到了消息队列,必须通过代码来转换数据为合适的类型,这时还得保证转换对于每个消息是正确的
一些ATL开发者都使用从ATLCON例程中提取出的代码,这些代码提供了对Windows UI 元素的一些封装封装。WTL现在以及进化出了一整套的广泛的封装类,这些类实现了对所有标准和通用窗口控件、系统对话框和所有GDI对象以及其他的封装。WTL中无论是对edit,button,listbox,treeview,listview等还是对通用文件对话框、颜色对话框、字体对话框等还是对DC,pen,brush,region,font等都有对应的包装类。
另外,WTL还提供了一整套的message crackers,进入窗口的消息被映射到指定的处理函数。使用ATL时,消息处理函数收到的是lParam和wParam,而使用WTL的message cracker,消息处理函数的参数都是具体消息的具体类型。比如:WM_LBUTTONDOWN消息有一个CPoint类型的参数(CPoint是WTL对Win32 POINT结构的包装-WTL包装了每一个通用的结构)。注意,ATL Windows Message Handler Wizard 使用ATL的原始消息映射,非WTL的message crackers,VC++下一版可能对向导支持会好一些。
许多的开发者选择MFC仅仅是为了使用CString,WTL自己也提供了对CString的实现,并且是几乎和MFC一样的实现。WTL的CString支持ASCII,MBCS,UNICODE和自动化的BSTR,支持这些类型间的相互转换,支持字符串连接、截断、和比较,支持printf一样的格式化处理,支持弹性的内存管理。
WTL,ATL和Win32/64 API之间的关系
WTL是基于ATL和Win32、64API的,ATL是基于Win32/64 API的,当谈到它们之间的关系时,我们应该从源代码和二进制两个视角来讨论。
源代码
Win32/64 API是成千上百的C函数的集合,涵盖了相当大的范围,包括我们感兴趣的COM和windowing。
ATL是C++模板的集合,几乎就是为COM编程量身定做的,但是也包括广泛的底层windowing功能的支持。
WTL是C++模板的集合,它的关注点在高层的windowing功能,WTL不依赖于COM,但是可以和COM一起使用。只要你不在WTL中选择支持“Com Server”,CoInitialize就不会被调用。
WTL使用ATL的windowing服务,所以要使用WTL,你必须访问ATL模板。
ATL调用Win32/64 API,WTL调用ATL模板和Win32/64 API,你的程序代码调用WTL,ATL和Win32/64 API。
当你运行了WTL AppWizard,他给你生成一些源文件,这些源文件将成为你程序代码的一部分,这些生成的代码调用WTL,构建程序框架。
WTL支持Windows 2000,Windows Me,Windows NT4,Windows 98,Windows95, OSR 2和“经典”windows 95,WTL并不是只支持它们 “最小公分母”,而是提供#define(比如 _RICHEDIT_VER, _WIN32_IE, _WIN32_WINNT and WINVER)来决定使用那些Win32/64的特性。WTL不会自动判别被安装到的操作系统的版本或IE的版本(比如,它不使用LoadLibrary /GetProceAddress 或GetVersionEx APIs来判别)。程序开发者必须指定#define宏,而且在编译期间已经假定程序在正确版本的客户机上可以正常运行,否则不能。
举个例子,菜单中的“>>”符号(v型符号),当一个命令条因为窗口大小改变而被截短时如果不使用v型符号,超出窗口边界的那部分命令条就别直接“剪掉”了。
V型符号是一个包含两个大于号的标志,当被按下时,就弹出一个菜单菜单上包含由于窗口大小改变而被从命令条尾部截去的那些项目。如果包含了IE5,v型符号就被支持,反之不支持。
在WTL程序中,如果_WIN32_IE 别定义为0x0500或更高(比如,在stdafxh里)那么v型符号在必要时就会显示。
二进制
ATL和WTL是作为一组包含C++模板的头文件的形式发布的。ATL中有少数的类可以作为一个独立的DLL来使用,但是多数的程序员也把它们的源代码包含到自己的工程里面去,对于WTL程序来说,这也是被推荐的。WTL没有可以作为独立的DLL的东西,所以WTL的C++类(并非全部)将被包含进每个程序。当你编译WTL程序,你最终会得到一个EXE或DLL,这就是你唯一需要交付最终用户的程序,不依赖外部库,当然除去操作系统自带的DLL,比如kernel32.dll,但是这些库基本上都存在(如果不存在,windows本身也许就无法正常工作了)。一个例外:如果你需要使用浮点数,你不得不使用C语言运行库(CRT)。
WTL-ATL,MFC,VB,Java,DHTML等的抉择
……(省略废话数百字)
为什么选择WTL?
WTL不像MFC那样笨重,最终的应用程序也比较小巧。对于高级程序,WTL给你使用API的机会,但是比纯粹的API编程节省时间。
Win32 API可以直接使用,但是有时候它们看起来相当独立,很难决定如何将它们结合起来使用。
WTL提供了更多的可以完成同样操作的功能。
由于被调用的方法是在编译期而不是运行期决定的,这就是它在效率和代码规模方面占有优势,模板库正在变得越来越流行。
安装WTL
WTL的发展很快,它的发行机制也在时常变化。
未来的发行模式
很可能下一版VC++发布时将会整合进WTL,因此,它可能会和ATL,STL,Data Templates一起自动安装。
现在的安装机制
当前,WTL是作为Microsoft Platform SDK (January 2000 或更高)的一部分发布的,需要手动分三步安装,未来可能会自动完成。
第一步-取得文件
可以从MSDN光盘的第三张或http://msdn.microsoft.com得到安装文件。你可以选择全部安装这个SDK或仅仅安装包含Windows Template Library的部分。(译者注:你也以在www.farproc.com下载WTL7.1安装包)
注意:WTL7.1安装的后面步骤与作者原文有出入,所以下面关于安装的就没有安装原文翻译
第二步-WTL Appwizard
安装后打开WTL的安装目录(比如c:/Program Files/Microsoft Platform SDK)进入对应的AppWizXX目录,其中XX为你的VC的版本号,比如你用的是VC6.0的话就进入AppWiz60,你会看到一个setup.js文件,点击运行它就可以为你自动安装WTL的AppWizard了。如果你无法运行这个文件或想手工安装,就复制这个目录下的AtlApp60.awx到“……/Microsoft Visual Studio/Common/MSDev98/Template”目录下也可以的。
然后打开vc,在new对话框中就可以看到“ATL/WTL AppWizard”选项了。
第三步-更新路径
第三步是设置路径以便让编译器找到WTL头文件。WTL是一个包含C++头文件(没有.cpp文件)的模板库,当编译时,编译器需要找到这些文件,这些文件在WTL安装目录/Src/WTL/include下,你可以在你的源文件里包含这个全路径(不推荐,但也可以),或把这个路径添加到VC的“Include Files”里,如下图
WTL安装了什么
WTL安装后,会有一个或若干个AppWizXX目录,这是WTL AppWizard文件的所在地;一个Include目录为WTL的头文件(也就是源文件)所在;还有一个samples,一些WTL程序的例子。
<待续>