从零开始的WTL入门教程(2)创建第一个窗口

在开始创建窗口前 有一些必须了解的C/C++特性,即使看不太懂也没有关系先记下

一.C++中的变量。

如果你没有C++基础 那么你需要重新理清C++中的变量和对象关系。
对于变量 它在创建的时候在栈中分配内存。C++中的对象可与基本类型一样直接创建,创建时即分配内存,离开作用域时出栈释放。也可以在堆中创建即创建指针指向new的对象

void founction(){
yourClass obj1;
yourClass *obj2 = new class;
}//obj1释放,obj2指针释放 ,*obj2对象内存溢出
二.模板。

WTL是基于模板开发,模板是实现泛型编程的基础。可以将模板看成一种描述方式,用于描述一个类型的对象遵循模板类型对象的类型声明。
举个例子

//一个单纯的类A
class A {
void functionA(){
}
}

//一个单纯的类B
class B {
void functionB(){
}
}
//一个单纯的类P
class P {
void functionP(){
}
}

//准备一个遵循T模板的类C
template<class T>//声明模板
class C:public T{
void functionC(){

}
}
//自己定义Class D
class D :public C<A>{
}
//D就是一个包含 functionC,functionA的类这样的描述指明了D继承于C 而C继承于A同样
//自己定义Class E
class E :public C<B>{
}
//E则是包含 functionC,functionB的类

模板可以用于描述一种继承关系,也就可以在使用的时候再去定义一个对象继承于谁

//自定义一个class F
template<class T /* = P */>//声明模板同时注释其类型 
class F :public T{
void functionF(){
//调用自己继承而来的functionP 继承于F的类必须指定其模板参数为P及P的子类
functionP()
}
//或用于方法
//创建一个R类型的对象并调用其founctionP方法
template <class R /* = P */>
void founctionF2(){
R objR;
objR.founctionP();
}

void functionF3(){
//调用时必须使用P或P的子类
founctionF2<P>();
}
}

这么做则相当于我们创建一个F类并且指定其继承于T类,并且T必须是一个P的子类因为我们在F中直接使用了P的方法。
模板主要是为了多态服务。极大的增强了代码的可复用性。而且模板的替换是静态的,在编译时就可以发现错误。
但是会造成继承关系不清晰,调试错误难以定位的问题,使用错误会导致问题定位到模板中,因此,不要设计业务十分复杂的模板类。
WTL中模板主要用于声明自定义控件的继承类型 。

三. 虚函数

对于一个类中的函数使用virtual关键字 则这个函数是一个虚函数

virtual void founction(){};//虚函数
virtual void founction() = 0;//纯虚函数

虚函数可以视作是一种接口声明。
纯虚函数更多是一种描述性用途,它规定了包含纯虚函数的类为基类 ,不可直接使用只能使用其子类。

回到WTL

在理解以上三点后 就可以开始了解WTL界面搭建的基本工具了。
在Win程序中 一切界面元素皆是CWindow。在WTL中最基本的界面类是CWindowImpl
在正式开始使用前先简单了解一下CWindowImpl
CWindowImpl

它有三个模板参数 其中 T自定义的类 TBase 是WinAPI中的窗口类 TWinTraits 是设置模板,可以不使用 先无视它。
从它的定义可以看出来两个泛型参数 TBase用于类型传递,T则用于本地调用,让CWindowImpl能够调用到你自定义的类的一些类方法,如果你重写了这些方法。防止子类重写这些方法后调用的仍然是父类的这些方法。
接着向上看
TWindowImplBaseT
这里给与了Tbase以及TWinTraits 初始值因此如果你不写这两个参数,才不会报错。这个类主要是设置窗口的一些默认属性。可以不用关心他。接下来它又将TBase传递给了CWindowImplRoot。接着向上看。
CWindowImplRoot
这样我们就找到了最终的目的地 传递到这里的TBase指定了自定义控件的实际基类。
并且它同时继承于CMessageMap马上就会用到。我们先看一看它。
CMessageMap
CMessageMap 中 定义了一个纯虚函数ProcessWindowMessage。也就是这里让我们必须使用CWindowImpl的子类并且必须实现ProcessWindowMessage方法。CMessageMap贴心的提供了一整套宏命令用来实现消息和消息转发。后面用到时会讲。
整理一下:
继承于CWindowImpl的类需要至少传三个参数 <T,TBase,TWinTraits > 其中 T 用于 CWindowImpl 调用。TBase 必须是 CWindow 及它的子类,有默认值CWinodw,实际用途为传递到最后给CWindowImplRoot并被它继承为该自定义类的基类。TWinTraits用于设置样式有默认值。

定义第一个自定义的窗口

第一个自定义窗口
此时创建了一个FirstWindow 类,它是一个基本的WTL对象。继承于CWindow
由于CMessageMap中的纯虚函数存在,因此必须添加
宏命令对其做出实现。

BEGIN_MSG_MAP(FirstWindow)
END_MSG_MAP()

这些是自动创建的构造函数和析构函数。如无需要,可以删掉。

	FirstWindow();
	~FirstWindow();
FirstWindow::FirstWindow()
{
}

FirstWindow::~FirstWindow()
{
}

练习项目中可以将代码全部写在.h文件。

然后使用它

WinMain函数中,Moudle创建后,消息循环开始执行前创建并显示这个窗口
使用FirstWindowImpl

其中CRect是描述位置大小的对象,可以设置上下左右边相对于父控件的位置。
创建了Window对象后需要调用Create方法创建窗口
该方法有以下几个参数

         In_opt_ HWND hWndParent, //父控件的句柄
		_In_ _U_RECT rect = NULL,//指定位置大小
		_In_opt_z_ LPCTSTR szWindowName = NULL,//窗口名称,会显示在左上角系统栏。默认样式可见
		_In_ DWORD dwStyle = 0,//窗口风格类型,属性设置 
		_In_ DWORD dwExStyle = 0,//窗口扩展风格
		_In_ _U_MENUorID MenuOrID = 0U,//资源ID,可以理解为该对象的数字标记,后面使用资源文件的时候会再次用到
		_In_opt_ LPVOID lpCreateParam = NULL//16位机遗留参数。现在用不着

这里我简单解释一下句柄
句柄是是一个结构体表示一个Window资源,也就相当于它的索引,通过句柄可以找到这个资源。也就可以通过句柄发收消息。CWindow对运算符进行了重载。使得CWindow的赋值操作实际只是让另一个CWindow对象的句柄指针指向目标对象的句柄。暂时了解一下就行了。
句柄

在Create方法中指定句柄通常用于设置控件位置,也就是说 rect参数设置的控件位置是相对于 hWndParent 的。而指定hWndParent为空的时候,窗口的位置是相对于屏幕的,左上角为0.0点,向右/向下为正轴
此时我们添加的代码创建了一个从屏幕左上角X/Y轴均为以10为起点到500为终点的FirstWindow类型的窗口。执行一下看看
在这里插入图片描述
看起来左侧边距似乎是要比顶部多一些,这是因为系统窗口的样式是有边框的,分布在左右下侧,在Win10中为透明样式,大约8像素
窗口缺了一个关闭按钮
可以在创建时dwStyle属性中设置该参数。可以使用 | 按位操作同时设置多个 。然后可以可以使用X按钮关闭窗口。

Window.Create(NULL, rc, "HELLO WORLD",WS_VISIBLE | WS_SYSMENU,NULL,0U,NULL );

拥有关闭按钮

但是这并不能关闭程序!
点击X只是隐藏了窗口,程序仍然在主方法中循环,没有任何变量被释放。
关闭窗口
我们要在关闭窗口的时候关闭程序,就要用到消息机制。
在WTL窗口中的生命周期方法,界面交互都有对应的消息分发到对应的类中。这些消息的接收转发,都被封装为一系列的宏命令,将其插入到BEGIN_MSG_MAPEND_MSG_MAP之间并实现对应的方法即可接收消息
添加消息
PostQuitMessage(0) 是WinApi方法,可以结束程序。
MSG_WM_CLOSE(OnClose) 声明了由OnClose方法接收关闭窗口的消息。
可以更改方法名,但是一般使用原头文件中的方法名以便阅读
同理可以推得,如窗口创建,移动,绘制鼠标时间等大量的生命周期/操作相应等系统管理的事件都可以通过这个机制来操作
MSG的定义
可以直接去对应的头文件中找到消息和消息参数定义。
但是要注意 调用该方法结束应用前必须删除掉所有你创建的窗口
WTL中对于关闭程序时还有残留窗口的断言
DestroyWindow() 可以删除当前窗口,也可以填入一个窗口的句柄用于删除指定窗口。
删除指定窗口
删除前
删除后

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WTL 具有两面性,确实是这样的。它没有MFC的界面(GUI)类库那样功能强大,但是能够生成很小的可执行文件。如果你象我一样使用MFC进行界面编程,你会觉得MFC提供的界面控件封装使用起来非常舒服,更不用说MFC内置的消息处理机制。当然,如果你也象我一样不希望自己的程序仅仅因为使用了MFC的框架就增加几百K的大小的话,WTL就是你的选择。当然,我们还要克服一些障碍: ATL样式的模板类初看起来有点怪异 没有类向导的支持,所以要手工处理所有的消息映射。 MSDN没有正式的文档支持,你需要到处去收集有关的文档,甚至是查看WTL的源代码。 买不到参考书籍 没有微软的官方支持 ATL/WTL窗口与MFC的窗口有很大的不同,你所了解的有关MFC的知识并不全部适用与WTL。 从另一方面讲,WTL也有它自身的优势: 不需要学习或掌握复杂的文档/视图框架。 具有MFC的基本的界面特色,比如DDX/DDV和命令状态的自动更新功能(译者加:比如菜单的Check标记和Enable标记)。 增强了一些MFC的特性(比如更加易用的分隔窗口)。 可生成比静态链接的MFC程序更小的可执行文件(译者加:WTL的所有源代码都是静态链接到你的程序中的)。 你可以修正自己使用的WTL中的错误(BUG)而不会影响其他的应用程序(相比之下,如果你修正了有BUG的MFC/CRT动态库就可能会引起其它应用程序的崩溃。 如果你仍然需要使用MFC,MFC的窗口和ATL/WTL窗口可以“和平共处”。(例如我工作中的一个原型就使用了了MFC的 CFrameWnd,并在其内包含了WTL的CSplitterWindow,在CSplitterWindow中又使用了MFC的CDialogs -- 我并不是为了炫耀什么,只是修改了MFC的代码使之能够使用WTL的分割窗口,它比MFC的分割窗口好的多)。 在这一系列文章中,我将首先介绍ATL的窗口类,毕竟WTL是构建与ATL之上的一系列附加类,所以需要很好的了解ATL的窗口类。介绍完ATL之后我将介绍WTL的特性以并展示它是如何使界面编程变得轻而易举。 对第一章的简单介绍
目录 WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue ................................ ........................... 6 WTL for MFC Programmers, Part I - ATL GUI Classes ................................ ........................... 8 README.TXTREADME.TXT README.TXTREADME.TXT README.TXTREADME.TXT ................................ ................................ ................................ ......................... 8 对本系列文章的总体介绍 对本系列文章的总体介绍 对本系列文章的总体介绍 ................................ ................................ ................................ ....... 9 对第一章的简单介绍 对第一章的简单介绍 ................................ ................................ ................................ ............. 11 ATL ATL ATL 背景知识 ................................ ................................ ................................ ....................... 11 ATL 和 WTL 的发展历史 ................................ ................................ ......................... 12 ATL-style 模板 ................................ ................................ ................................ ............. 12 ATL ATL ATL 窗口类 ................................ ................................ ................................ ........................... 15 定义一个窗口的实现 定义一个窗口的实现 ................................ ................................ ................................ ............. 17 填写消息映射链 ................................ ................................ ................................ ............. 19 高级消息映射链和嵌 高级消息映射链和嵌 入类 ................................ ................................ ................................ ..... 21 ATLATL 程序的结构 ................................ ................................ ................................ .................... 24 ATLATL 中的对话框 ................................ ................................ ................................ .................... 27 WTL for MFC Programmers, Part II - WTL GUI Base Classes ................................ ............. 32 对第二部分的介绍 对第二部分的介绍 ................................ ................................ ................................ ................. 32 WTL WTL WTL WTL 总体印象 ................................ ................................ ................................ ...................... 32 开始写 WTLWTLWTL程序 ................................ ................................ ................................ .................. 33 WTL WTL WTL WTL 对消息映射的增强 ................................ ................................ ................................ ...... 36 从 WTLWTLWTL的应用程序生成向导能得到什么 的应用程序生成向导能得到什么 的应用程序生成向导能得到什么 ................................ ................................ .......... 42 使用向导的整个过程 ................................ ................................ ................................ ..... 42 查看生成的代码 ................................ ................................ ................................ ............. 44 CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop 的内部实现 ................................ ................................ ................................ .. 47 CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl 的内部实现 ................................ ................................ ......................... 48 回到前面的时钟程序 回到前面的时钟程序 ................................ ................................ ................................ ............. 50 界面元素的自动更新 界面元素的自动更新 (UI Updating)(UI Updating)(UI Updating)(UI Updating) (UI Updating) (UI Updating)(UI Updating)(UI Updating)(UI Updating) (UI Updating) ................................ ................................ ...................... 51 添加控制时钟的新菜单项 ................................ ................................ ............................. 52 调用 UIEnable()................................ ................................ ................................ ............ 53 消息映射链中最后需要注意的地方 消息映射链中最后需要注意的地方 消息映射链中最后需要注意的地方 消息映射链中最后需要注意的地方 ................................ ................................
WTL 具有两面性,确实是这样的。它没有MFC的界面(GUI)类库那样功能强大,但是能够生成很小的可执行文件。如果你象我一样使用MFC进行界面编程,你会觉得MFC提供的界面控件封装使用起来非常舒服,更不用说MFC内置的消息处理机制。当然,如果你也象我一样不希望自己的程序仅仅因为使用了MFC的框架就增加几百K的大小的话,WTL就是你的选择。当然,我们还要克服一些障碍: ATL样式的模板类初看起来有点怪异 没有类向导的支持,所以要手工处理所有的消息映射。 MSDN没有正式的文档支持,你需要到处去收集有关的文档,甚至是查看WTL的源代码。 买不到参考书籍 没有微软的官方支持 ATL/WTL窗口与MFC的窗口有很大的不同,你所了解的有关MFC的知识并不全部适用与WTL。 从另一方面讲,WTL也有它自身的优势: 不需要学习或掌握复杂的文档/视图框架。 具有MFC的基本的界面特色,比如DDX/DDV和命令状态的自动更新功能(译者加:比如菜单的Check标记和Enable标记)。 增强了一些MFC的特性(比如更加易用的分隔窗口)。 可生成比静态链接的MFC程序更小的可执行文件(译者加:WTL的所有源代码都是静态链接到你的程序中的)。 你可以修正自己使用的WTL中的错误(BUG)而不会影响其他的应用程序(相比之下,如果你修正了有BUG的MFC/CRT动态库就可能会引起其它应用程序的崩溃。 如果你仍然需要使用MFC,MFC的窗口和ATL/WTL窗口可以“和平共处”。(例如我工作中的一个原型就使用了了MFC的CFrameWnd,并在其内包含了WTL的CSplitterWindow,在CSplitterWindow中又使用了MFC的CDialogs -- 我并不是为了炫耀什么,只是修改了MFC的代码使之能够使用WTL的分割窗口,它比MFC的分割窗口好的多)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值