WTL简单介绍
关键词: WTL
WTL是一个好东东.它开发的程序都很短小精悍.对开发WIN32的应用有很好的优点.它不用MFC开发.但可以高速产生窗体和控件.
以文本方式查看主题 - 温馨小筑 (http://www.learnsky.com/bbs/index.asp) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WTL简单介绍vcmfc在ATL出现的时候,一些部分COM的编程人员開始认为开发COM运用是一种快乐,由于使用它非常方便地开发小规模的COM组件,但好景不长,现实的COM组件是包罗相当广泛的,特别当它们准备使用包装我窗体控件,发现ATL提供了相当的稀少。因此Microsoft推出了半成品与没有技术支持的WTL,这也是WTL诞生的原因。 非常多初次接触WTL都问“WTL这三个字母代表什么呢?”:WTL全称为Windows Template Library,构架于ATL之上,採用C++模板技术来包装大部窗体控制,并给出一个与MFC类似的应用框架。 他们紧跟着问“那我怎样得到它呢?”:因为WTL是Microsoft推出的,在Microsoft的PlatForm SDK中就有,下面是部分画面: 或者能过下面链接下载:http://msdn.microsoft.com/msdn-files/027/001/586/wtl31.exe 跟着问题又来了,“我该怎样使用它们呢?”:在你安装完了WTL SDK之后,在安装文件夹中有一个AtlApp60.Awx的向导文件,将它复制到你安装Visual C++的文件夹:Microsoft Visual Studio//common//mesdev98//bin//ide//文件夹下(实在不行使用Windows的搜索文件查找.awx),这是,在VC的应用程序向导里就有跟MFC类似的WTL应用程序向导。 假设你是MFC的使用者,你可能会再问“WTL与MFC在包装窗体控制有哪些不同呢?”:我仅仅能用下面表格回答你:
最后再说两句。因为WTL不是Microsoft的正式产品,因此得不到Microsoft的技术支持,尽管有不少民间技术团体的支持,但这还不够;关于WTL的技术文章相当的少,并且WTL使用C++的Template技术,这是一种相对较新的技术,无法与MFC混合使用,使用它须要又一次学习它,以致于相当少的人使用它。 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-- 作者:admin -- 公布时间:2005-1-11 2:11:00 -- 什么是WTL? 选择自 dairyman000 的 Blog 简单介绍 是不是让人失望? 不,由于ATL仅仅是对COM进行了简单的封装,这也是ATL的强大之处. 是的,写ATL您必须通晓COM. 您在ATL上额外花费的功夫跟您学习COM所作的努力比起来,简直微不足道.这跟那些须要把主要精力花费在学习类库本身,忽略COM的库是全然不同的. WTL与此相似.您须要懂得Win32窗体技术和GDI.仅仅要您懂得,学习WTL就似清风抚面,再简单只是了.假设您不懂 这些,那么您最好使用VB来写UI代码. WTL有什么? 它给各种类型的应用程序提供了一个主要的框架.注意,尽管您没有MFC那样的文档/视结构,可是您有视(views). 在WTL有大量的代码让您来管理视,并且增加您自己的代码也非常easy. WTL有AppWizard,能够让您生成SDI, MDI 和多线程SDI程序多线程SDI跟IE或Windows Explorer非常像.它看起来是打开了多个程序实例,实际上这些窗体都是属于一个进程的). 另外,您的程序能够是基于对话框的,也能够是基于视的.视能够是基于CWindowImpl的,也能够是基于控件,甚至是IE里的一个HTML页.您能够选择您的程序是否须要一个rebar, command bar (CE-like), toolbar 和/或status bar.另外,您的程序能够主持ActiveX控件,以及成为一个COMserver. 这里有几个关于视的选项. WTL提供splitter窗体类(这样在一个视里您能够有两个窗体)和scroll窗体类(这样您的窗体能够比它显示的"视"小). WTL也有个相似MFC的UpDateUI的东西,可是它们不是非常一样 - 基本的差别是您须要把须要更新的项用宏映射标注出来,然后您在您的类里增加运行UpdateUI的代码. DDX/DDV在WTL也支持,相同相似MFC,但有不同. 您必须加一个宏映射来实现DoDataExchange,然后增加调用它的代码. 如今WTL也有GDI类了.然而,HDC的封装类就像CWindow一样,仅仅进行了非常easy的封装 - 它差点儿没有增加不论什么新的功能.只是,在WTL,你能够得到播放meta文件和OpenGL支持. 最有价值的我猜应该是打印机DC的那些继承类 - WTL有打印机支持,甚至打印预览. 当然也有GDI对象的封装. 诸如画笔,画刷,区域等. WTL对全部的Win32 (和W2K) 通用对话框进行了封装.相同虽然简单,可是它的确使请求字体或者文件变的很的简单. WTL 终于把消息分离带入了ATL! 一些新的MSG映射宏将消息分离,调用您类里的消息处理函数.消息处理函数的參数的值是从消息分离得到的.唯一令人头痛的是,您须要查看头文件以确定函数參数的意义. 最后,WTL另一些有用类.最重要的是CString. 不错,它是从MFC克隆得到的(copy on write),具有(在我知道的范围内)MFC版本号的全部方法.还有查找文件的API的封装类,以及CRect, CSize and CPoint. 总结 假设您打算写一个Win32 界面程序,我建议您在考虑MFC之前,先试试WTL.使用WTL来写您的代码, 程序将变得小巧些,也更有效率些.使用WTL, 您还将得到ATL支持COM优点.而MFC没有对COM的支持. 作者Blog:http://blog.csdn.net/dairyman000/ |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-- 作者:admin -- 公布时间:2005-1-11 2:11:00 -- WTL体系结构 绪论 WTL终于来了,并且提供了我所希望的功能.我在WTL Bytesize(译文)的文章列出WTL主要特征.在本文中,我将描写叙述一下WTL的体系结构,同一时候我会给出一些简单的样例来演示怎样使用它的那些特征.希望可以对您有所帮助. WTL应用程序的类型 WTL有好几种应用程序类型,供您在AppWizard选取. 下表对这些应用程序进行了描写叙述. 这样的弹性构成了WTL体系结构的一部分.
你可能还是首次听说多线程SDI应用程序,可是不用操心,它的概念非常easy理解.一个多线程SDI程序启动后它会有一个窗体, 窗体显示了一个文档. 当你想要程序要再创建一个文档时,问题就出现了--SDI程序仅仅能显示一个文档.为了解决问题,多线程SDI创建了还有一个SDI窗体.看起来是一个新的实例在执行,实际上它只是是原来的进程创建了一个新的窗体,并把它依附到进程的一个新线程. IE的新建窗体就是这样做的. 除了多线程SDI,全部这些应用程序都能够作为COMserver, 而且应用程序向导(AppWizard)为此提供了一个选项.另外应用程序向导还能够让你指定该程序是否主持ActiveX控件.令人费解的是,不同的程序类型,选取"Host ActiveX Controls"的地方不同.除对话框应用程序外的其它类型在第一页上选取,而对话框类型却放到第二页. 第二页的其它选项,对对话框程序以外的类型都是可用的.它们让你指定程序是否须要工具条(toolbar),状态条(status bar)和视窗体(View Window). 假设选取了"Toolbar"选项,你能够通过"Rebar"选择是否将工具条放入IE Rebar控件中. 假设你选取了Rebar, 你就能够通过框架窗体(frame window)的成员m_hWndToolBar(后边会有具体的描写叙述)来訪问它.你能够依照你的意愿,在里边增加其它的工具条. 选取了"Rebar"后, 你能够决定是否选取"Command Bar". Command bar非常像CE的command bar控件.仅仅是WTL是用一个类来实现,而在CE, command bar是一个系统窗体类(system window class). Command bar非常实用,它能够把窗体也增加到工具条中去. 假设你选取了这个选项, 工具条和菜单都将被当做toolbar来实现.这使菜单项也能够有关联的图标,而且当你移动鼠标到一个菜单项上时,该菜单项会被置成高亮.从Office 97以来, Office软件的菜单都具有上述特征. 第二页还有指定程序是否使用视的选项(多半你想要使用), 同一时候你能够决定这些视怎样实现. 下表列出了全部可选的视.
本文的样例须要一个对话框模版,同一时候还须要菜单,因此Form view是个理想的选择. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-- 作者:admin -- 公布时间:2005-1-11 2:14:00 -- WTL体系结构程序线程 跟ATL一样,WTL程序也须要一个_Module全局变量来保存全局数据,方便应用级代码訪问.在WTL中,这个变量是CAppModule或CServerAppModule的实例,后者在程序同一时候作为一个COMserver时用到.每一个应用程序具有一个或者多个UI线程.WTL使用两种方式来管理这些线程. 假设应用程序仅仅有一个UI线程(除了多线程SDI以外,其它程序类型默认仅仅有一个UI线程),线程调用全局函数run(): int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT) 线程的消息循环包括在CMessageLoop内部.函数创建了一个CMessageLoop实例, 把它放入全局的消息循环映射(message loop map)数组. 以线程ID为索引,线程中执行的其它的代码能够訪问到这个实例. 消息循环对象包括了message filter和idle handler. 执行在这个UI线程的UI元件(UI element)能够有它自己的idle handler,在线程的消息队列为空时执行【译注:通过CMessageLoop::AddIdleHandler()把这个UI元件增加到CMessageLoop的idle handler 数组中】. CMessageLoop::Run()包括了UI线程的主消息映射(main message map).下边是它的伪代码: MSG m_msg; 能够看到,这个函数推动着消息队列. 没有消息时, 执行注冊到线程的idle hander. 假设在队列中检測到消息,把它取出来,传给每一个message filter. 假设消息没有被这些函数处理,它将依照通常的方式,发送到目标窗体. 假设程序有超过一个的UI线程,能够用WTL的线程管理器,多线程SDI就是这样做的. 主线程作为一个管理者线程,它会为每一个新窗体创建一个新的新线程. 主要流程例如以下: int nRet = m_dwCount; 那些线程句柄放在一个数组中. 线程通过AddThread()增加到数组(同一时候启动线程), RemoveThread()从数组移走. wait语句在两种情况下会被打断: 线程死亡(将线程从数组中移出) 或线程收到了WM_USER消息(一个线程在一个新线程里新建了一个窗体). 线程管理者为程序中的一个类,因此能够在循环中增加自己的message handler, 比方,当程序有不止一种窗体类型时. 创建一个新的窗体非常easy,仅仅需在随意一个窗体中调用: ::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L); 这个循环会一直执行下去,直到全部的UI线程都关闭了. UI线程具有一个thread procedure,它跟单UI线程的Run()方法一样.只是,因为线程管理者使用了MsgWaitForMultipleObjects(), 这意味者最多仅仅能有MAXIMUM_WAIT_OBJECTS-1个UI线程,这也意味着最多仅仅能创建63个窗体. 框架 WTL实际上是两类窗体: 框架窗体和视图窗体. 正如名字所暗示的那样, 框架窗体为窗体提供标题栏(caption bar)和边框,你的代码用它来处理工具条(tool bar)和菜单项命令.你看到的程序窗体实际上是视图窗体, 视图覆盖了框架窗体的客户区.客户区是指框架窗体没有被诸如状态条,工具条之类的修饰部件所遮挡的部分. 线程会创建主框架窗体的一个实例,创建视图的工作由主框架窗体的WM_CREATE消息处理函数完毕. 对于SDI程序来说,这个过程非常easy. 把视图类的一个实例作为主框架类的一个成员,调用视图类的Create()方法就可以.MDI程序略微有些不同, MDI主框架窗体通过CMDIFrameWindowImpl<>::CreateMDIClient()建立一个名为MDICLIENT的窗体. 这个客户窗体将CMDIChildWindowImpl<>窗体当做它的子窗体,子窗体有一个视图.这也反映了这么一个事实,MDI程序能够具有零个或者多个子窗体,每一个都有边框和标题栏. 框架窗体的OnCreate()非常有意思,让我看看: LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&) 接下来, 创建工具条并把它关联到commandbar, 然后创建状态条和视图.能够看到视图的HWND存放在框架窗体的m_hWndClient变量中. 这个窗体句柄在框架窗体的WM_SIZE handler中会用到.当框架窗体改变大小时,它告知视图改变自身,于此同一时候也要考虑状态条和command bar. 在下来的三行(从调用UIAddToolBar()開始) 用来显示在执行时会改变状态的UI项(UI item).文章后面还会重提这个话题. 最后,訪问消息循环(message loop), 你应该还记得该消息循环存放在一全局数组中. GetMessageLoop() 取得当前线程的消息循环,增加框架窗体的message filter和idle handler, 分别默认是PreTranslateMessage()和OnIdle(). 框架窗体继承于下面类: class CMainFrame : 后两个抽象类宣称了框架窗体类实现了PreTranslateMessage()和OnIdle(). 从CUpdateUI<>继承表示框架类支持UI update map. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-- 作者:admin -- 公布时间:2005-1-11 2:15:00 -- WTL体系结构 视图 视图窗体看起来显得非常easy: class CMyView : public CWindowImpl<CMyView> 上面是一个SDI程序的视图类. 多线程SDI和MDI的视图类在本质上也跟这个一样,但他们没有PreTranslateMessage()方法. SDI程序就是使用这个函数,赶在框架类处理消息之前把消息抓住. PreTranslateMessage()在SDI的框架类中的实现是,直接将消息转发给视图类. 这里显示的视图实际上没有做什么工作.你应该自己在OnPaint()函数中增加画出文档内容的代码.假设须要支持输入,如鼠标的点击和键盘的按键,你应该增加对应消息处理函数到类和映射中. 能够看到这个窗体是从CWindowImpl<>继承下来的,假设你想让它基于一个Win32控件的话,就应该从定义在AtlCtrls.h文件里某个WTL类继承. 假设想在基于CWindowImpl<>的类里加上滚动栏,那么你应该把基类换成CScrollWindowImpl<>,同一时候把消息链给它: class CMyView : public CScrollWindowImpl<CMyView> 基类保证窗体具备滚动栏,并提供滚动栏消息的默认处理.视图类不再有WM_PAINT的处理函数,由于它已被CScrollWindowImpl<>处理.依据滚动栏的位置,CScrollWindowImpl<>画出视图相相应的部分. 取而代之的是,在你的类里实现DoPaint(),在这里你须要画出整个视图.假设你想指定滚动的范围,大小或起点,你须要加上处理WM_CREATE消息的函数,把这些初始化代码放到里边. 正如我先前所提到的,框架窗体会改变视图窗体的大小,以使它客户区未被状态条和工具条覆盖的部分为视图所填充. 在大多数情况下,这样就够了.可是当你想要一个具有Windows Explorer样子的程序时,该怎么办呢? Windows Explorer的窗体包括了一个tree view 和一个list view,还有两者之间的切割条. WTL的解决方式非常easy:使用splitter窗体! 为此你须要改变一下框架窗体,让它创建splitter窗体的一个实例作为它的视图. 比如, 在你的框架类里有例如以下的数据成员: CSplitterWindow m_view; 你能够在OnCreate()创建一个splitter窗体: // get the frame client rect, so that we set the splitter initial size Splitter窗体如同一个视图,将框架窗体作为它的父窗体. 在这段代码里,我将框架窗体客户区的实际大小传给了splitter窗体. 我也能够在这里使用 rcDefault,由于一旦框架窗体创建完毕,框架窗体就会转发WM_SIZE消息给splitter. 这样splitter能够立即改变自身的大小来填充框架. 然而,当我准备使用不带參数的SetSplitterPos(),把切割条设置于窗体中线时,出现了问题.Splitter窗体使用它的大小来决定中线的位置,由于rcDefault告诉窗体它的大小是0(因此中线的位置也是0),从而意味着切割条将出如今z最左边,将左窗体隐藏了起来. 创建了splitter窗体后,你须要创建那些你想要切割的窗体了.它们将作为splitter窗体的子窗体被创建.最后你将这些子窗体通过SetSplitterPanes()加到splitter窗体中去,并确定切割条的位置所在. UI Update 菜单项能够被设置为有效或无效,能够带check记号或着像radiobutton一样,在一组菜单项中同一时候有且仅仅有一个能被check.此外,菜单项还能够带图标和文字. 全部的这些状态都能够在执行时依据程序中的某个值进行改变.工具条在某种程度上能够看做是菜单的易见形态,由于它们的button能够个别地,或者作为一组的一部分被置成有效或无效,推入推出. UI update机制同意你指定哪些UI元件(UI element)的状态能够在执行时改变. WTL使用例如以下的UI update映射来实现这一功能: BEGIN_UPDATE_UI_MAP(CMainFrame) 这个样例指出三个菜单项在执行时有一个状态须要显示,当中的一个, ID_FILE_SAVERESULTS,另一个工具条button跟它相关联. WTL通过建立一个数组来保存这些信息.为此你须要完毕双方面的工作: 首先是UI元件的状态. 假设是菜单项, 你能够使用UIEnable()使能该菜单项, UISetCheck()设置check记号, UISetText()改变菜单的文字.假设是工具条button,那么你使用UIEnable()使能该button, UISetCheck()或者UISetRadio()决定button是推入还是推出.下边的代码依据是否有文本被选中,来使能Cut菜单项和工具条button: BOOL bSelected = GetSelected(); 你能够把这种代码放入对应处理函数中(如一个菜单项的状态依赖于另一个菜单项的动作,将它放入后者的处理函数中),或者放入OnIdle()方法,通过检查某个类变量来决定元件的状态. 其次是确定各个UI元件是否都被更新了,为此你须要调用CUpdateUI<>的某个方法将UI元件增加到列表中.主菜单已被自己主动增加,可是其它的不论什么菜单和全部的工具条必须分别通过调用UIAddMenuBar()和UIAddToolBar()手动增加. 其它另一堆事情要注意. 首先,设置了工具条的状态后,使用UIUpdateToolBar()以使工具条状态更新. 对于菜单,你不需如此,由于子菜单是动态生成的.UIUpdateMenuBar()这种方法也存在,可是它的作用是把菜单恢复到初始状态,假设你改变过某些项的文字,调用UIUpdateMenuBar()的结果可能不是你所期望的(由于菜单项的文字会变成老的). 虽然另一个方法UISetRadio(),可是还没有一个把几个菜单项或者工具条button当做radiobutton组(也就是说,有一个并且仅仅有一个被选中)的机制.假设你希望得到这样效果,你必须自己编码,只是它并不难. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-- 作者:admin -- 公布时间:2005-1-11 2:16:00 -- WTL体系结构 对话框 class CMyFileDialog : public CFileDialogImpl<CMyFileDialog> 当目录的路径改变时,CFileDialogImpl<>调用OnFolderChange().该函数使用基类的GetFolderPath(),来取得新路径. 控件 WTL为全部的Win32和通用控件提供了封装类,包含Windows 2000新增加的. 尽管仅仅是简单的包装,可是它们使这些控件更加easy訪问.譬如,你能记清楚从List View读出当前选定项的文字的消息和须要传的參数吗?(实际上, 你须要发送两个消息, 一个是得到选定项的索引,还有一个是读出它的文字.) WTL的作者为你完毕了这些烦人的工作, 提供了一个简单的封装函数供你使用. 使用这些控件类有两种方法. 假设你的对话框里有一个控件, 你能够将控件的HWND依附到一个封装对象,使用封装类的方法来訪问控件.这样的方法简化了你读写控件数据和处理notification消息的代码. 另外的使用方法是把这些类加到你的视图类的继承层次中去: class CMyView : public CWindowImpl<CMyView, CListBox> 这表示CWindowImpl<>是从CListBox继承而来,因此创建的窗体将是一个list box (由于窗体类的名字是通过调用 在notification消息和子类化这个主题上,有一点非常值得指出,那就是当某事件发生时,绝大多数窗体控件都会发送notification消息给它们的父窗体.让你窗体来处理这些notification消息要比子类化一个已存在控件窗体(或子类化一个已存在的类,然后建立一个实例),从而在控件之前取得消息好得多. 譬如, 你想处理button的click事件,你所须要做的仅仅是处理BN_CLICKED notification.它将由button发送给你的窗体类.另外的一种方法是从CContainedWindow<>子类化BUTTON窗体来处理click消息. 我之所以说这个是由于一个知名的ATL鼓吹者给我一份代码里就是这么做的.他的代码取得一个简单的buttonclick事件所花的时间是别人的3到4倍,由于他子类化了button控件,而不是简单的处理BN_CLICKED notification. WTL还提供了一些新的控件,在win32中没有对等者. 你已经看到过一个 -- command bar, 实际上还有其它一些非常实用类:
|