ATL的GUI程序设计(2)
from:http://blog.titilima.com/atlgui-2.html
第二章 一个最简单窗口程序的转型
我知道,可能会有很多朋友对上一章的“Hello, World!”ATL版不以为然,因为它并不能算是什么ATL程序——毕竟它只不过是有了个CComModule而已。不过不管怎样我还是要说,它几乎仍然拥有了一个ATL GUI程序的所有组成部分:入口、初始化、程序体、卸载……
“等等!”也许你会突然打断我,“——还有注册窗口类、消息循环呢?”
当然,对于一个完整的GUI程序来讲,这也是必要的。
貌似废话
不清楚你是否已经为本章的内容做好了准备,因为下面我们就要动真格的了。不过考虑到本书的读者群中可能会存在着相当一部分了解MFC却对Win32 GUI的基本原理和流程不甚熟悉的朋友,所以李马特别为你们准备了这一节的内容。SDK的粉丝们可以跳过这一节,如果你们觉得李马讲的有些拖沓冗长的话。
那么,我还是先以一个标准的Win32 SDK程序开始:
1 |
////////////////////////////////////////////////////////////////////////// |
不知道你是否会觉得这段代码有些冗长?事实上,这个程序已经体现了Win32 GUI程序运行的所有流程(请注意,我并不会对这些代码进行详细的解释,因为我已经假设你已经了解了这些代码具体行为的必要细节。如果不是这样的话,请参考相关的书籍或者MSDN):
- 注册窗口类的部分。在这个程序中,InitApplication函数完成了这一工作。窗口类的概念类似于OO(面向对象)中的类,所有你在Windows中能看到的窗口都是某个特定窗口类的一份实例。但是,窗口类并非任何一种OOP语言中的类——它所包括的并不是通称的属性和方法(在C++中称作成员变量和成员函数),而是属性和响应。这个区别可能会使你感到费解,我会在下一章中为你详细介绍——因为ATL中对窗口的封装类将这一点体现得十分淋漓尽致。
- 创建窗口的部分。在通常的SDK代码里,这些代码被封装在一个名为InitInstance的函数中。这段代码所做的工作一般是创建窗口并将其显示出来。
- 消息循环。Windows是一个基于消息机制的操作系统,各个窗口之间的通信也主要是靠Windows消息来完成的。而程序中的消息循环也就是将本程序UI线程中的消息队列中提取各种消息,进行处理(如果有必要的话)之后分发给各个消息的属主窗口(或者说是目标窗口)。
在这里需要指出的是,HelloWndProc是我们自己定义的一个函数,我们需要用它来控制我们对特定窗口消息的特定响应。我们只需要在注册窗口类之前,将这个函数的地址(也就是函数名)赋值给WNDCLASS::lpfnWndProc成员就可以了。这个函数我们自己不需要进行调用,它的调用是当我们的窗口收到窗口消息后,由Windows完成的。在这个回调函数中,我们的处理是这样的:
- WM_DESTROY。在窗口被销毁的时候,窗口会收到此消息。在这里,我们会调用PostQuitMessage,用以向当前UI线程的消息队列之中发送一条WM_QUIT消息,GetMessage在收到这条消息后,会返回FALSE,也就结束了消息循环,WinMain也就结束了。
- WM_PAINT。在窗口需要绘制的时候,窗口会收到此消息。在这里我们只是简单的在窗口的中间绘制了一行文字“Hello, SDK!”。
- 其它消息。这些消息都是我们不关心的,所以我们将其交由系统默认的窗口过程DefWindowProc来处理。
这段代码貌似冗长,但实际上还是很有条理的,你可以根据它以及我以上的解说来对照这个程序的ATL版本。
ATL等同品
在写作这本书的时候,我总是希望我每次都能够能使用让你不太陌生的代码来循序渐进地引导你。考虑再三,对于“Hello, ATL!”的这个程序,我决定先把它的WinMain展现给你:
1 |
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd ) |
OK,上一章介绍过的_Module又出现在你的眼前了——不过还是没有什么特别的变化,仍然是那熟悉的Init和Term。而且,正如“山哟还是那座山”一样,消息循环哟也仍然是那个消息循环。当然,你肯定也发现了那寥寥的变化:CHelloATLWnd是什么?在我将它的代码展现给你之前,你可能会做出这样的猜想:
- 这是一个C++类,它对Win32窗口类进行了封装。
- 这个类封装了大多数窗口操作的API函数,诸如CreateWindow、ShowWindow、UpdateWindow。
- 窗口类的注册可能也是在这个C++类中完成的。
好,打住,这就够了。让我们来撩开CHelloATLWnd那貌似神秘的面纱吧,赶紧着。
1 |
class CHelloATLWnd : public CWindowImpl< CHelloATLWnd, CWindow, CWinTraits< WS_OVERLAPPEDWINDOW > > |
猜想,还是猜想!
请允许我在本章中不为你解释这个类的任何具体细节,取而代之的是继续的猜想。因为,这个类中需要解释的东西太多了,以至于我必须为它单独开辟一章。
- 窗口类的注册是由这个C++类的构造函数与DECLARE_WND_CLASS宏一起完成的。
- 对于BEGIN_MSG_MAP与END_MSG_MAP这一部分,想必使用过MFC的朋友们应该更容易理解。是的,这一对宏可以算作ATL的消息映射,在其中由MESSAGE_HANDLER作为消息分流器,将各种窗口消息分配给各个处理函数。
- 创建窗口时指定的样式貌似和模板参数CWinTraits有关。
当然,除了这些猜想之外,你可能还会同时存在以下疑问:
- CWindowImpl、CWindow、CWinTraits究竟是什么?
- 窗口类是在何时注册的?
- 消息分流器是如何实现的?
也许你还会有更多的疑问,那么就让我一并将它们留到下一章再解决吧。如果你实在等不及的话,atlwin.h的代码也会告诉你一切的。
补叙CComModule
由于这本书主要针对的是ATL 3.0/Visual C++ 6.0,所以我疏忽了对CComModule的研究。在此感谢老李老刀兄提出的一点,就是CComModule在ATL 7.0中已经不建议使用了。于是我将MSDN中的相关章节摘抄下来,权作借花献佛之用。
不过,出于代码的兼容性以及WTL的内容考虑,本系列后续文章仍然将使用ATL 3.0中的CComModule。
CComModule 替换类
ATL 的早期版本使用 CComModule。在 ATL 7.0 中,CComModule 功能被若干个类所取代:
- CAtlBaseModule 包含大多数使用 ATL 的应用程序所需的信息。包含模块和资源实例的 HINSTANCE。
- CAtlComModule 包含 ATL 中的 COM 类所需的信息。
- CAtlWinModule 包含 ATL 中的窗口化类所需的信息。
- CAtlDebugInterfacesModule 包含接口调试支持。
- CAtlModule 下列 CAtlModule 派生的类被自定义为包含特定应用程序类型中所需的信息。这些类中的大部分成员都可以被重写:
CAtlDllModuleT 在 DLL 应用程序中使用。为标准导出提供代码。
CAtlExeModuleT 在 EXE 应用程序中使用。提供 EXE 中所需的代码。
CAtlServiceModuleT 为创建 Windows NT 和 Windows 2000 服务提供支持。
CComModule 仍然可用以便向后兼容。
分布 CComModule 功能的原因
由于以下原因,CComModule 的功能分布到了几个新类中:
- 使 CComModule 中的功能呈粒状分割。
对 COM、窗口化、接口调试和应用程序特定的(DLL 或 EXE)功能的支持现在在不同的类中。 - 自动为这些模块的每一个声明全局实例。
所需模块类的全局实例链接到项目中。 - 消除了调用 Init 和 Term 方法的必要性。
Init 和 Term 方法已移动到模块类的构造函数和析构函数中;不再需要调用 Init 和 Term。
附件:atlgui02.zip
ATL的GUI程序设计(2)的更多相关文章
- ATL的GUI程序设计(4)
第四章 对话框和控件 对于Win32 GUI的程序设计来说,其实大部分的情况下我们都不需要自己进行窗口类的设计,而是可以使用Win32中与用户交互的标准方式--对话框(Dialog Box).我们可以 ...
- ATL的GUI程序设计(3)
第三章 ATL的窗口类 CWindowImpl.CWindow.CWinTraits,ATL窗口类的奥秘尽在此三者之中.在本章里,李马将为你详细解说它们的使用方法.另外,本章的内容也可以算是本书的核心 ...
- ATL的GUI程序设计(前言)
前言 也许,你是一个顽固的SDK簇拥者: 也许,你对MFC抱着无比排斥的态度,甚至像我一样对它几乎一无所知: 也许,你符合上面两条,而且正在寻求着一种出路: 也许,你找到了一条出路--WTL,但是仍然 ...
- ATL的GUI程序设计(1)
from:http://blog.titilima.com/atlgui-1.html 第一章 不能免俗的"Hello, World!" 在这一章里,就像所有的入门级教程一样,我也 ...
- Java GUI程序设计
在实际应用中,我们见到的许多应用界面都属于GUI图形型用户界面.如:我们点击QQ图标,就会弹出一个QQ登陆界面的对话框.这个QQ图标就可以被称作图形化的用户界面. 其实,用户界面的类型分为两类:Com ...
- GUI程序设计2
8. 按钮(JButton)使用示例 例14. 按钮使用示例. package GUI; import java.awt.BorderLayout; import java.awt.Container ...
- GUI程序设计
1. 对话框(JDialog)使用示例 例1. JDialog简单使用示例. import javax.swing.JLabel; public class demoJDialog { JFrame ...
- Matlab GUI程序设计入门——信号发生器+时域分析
背景:学习matlab gui编程入门,完成一个基于GUIDE的图形化界面程序,结合信号生成及分析等. 操作步骤: 1.新建程序 新建一个GUIDE程序 这里选择第一个选项,即创建一个空白的GUIDE ...
- MATLAB GUI程序设计中ListBox控件在运行期间消失的原因及解决方法
在运行期间,ListBox控件突然消失,同时给出如下错误提示: Warning: single-selection listbox control requires that Value be an ...
随机推荐
- Go网络文件传输
流程分析 借助TCP完成文件的传输,基本思路如下: 发送方(客户端)向服务端发送文件名,服务端保存该文件名. 接收方(服务端)向客户端返回一个消息ok,确认文件名保存成功. 发送方(客户端)收到消息后 ...
- 2019 年 stackoverflow 网站最受欢迎的 20 个 Python 问题
在最新一期的"Python开发者周刊"(Pycoder's weekly)里,我看到一则有意思的分享,故转出来分享给大家. 该分享来自是一份"python weekly ...
- 低副瓣阵列天线综合1 matlab HFSS
车载雷达天线多采用微带贴片天线,贴片振子的形状多种多样,较常用的是矩形: 组阵时多采用先串馈再把串馈好的行或列单元采取并馈的方式组阵,无论是串馈或并馈,想要获得较低的副瓣效果,都需要采取电流幅度加权的 ...
- 数据库的SQL基本用法 创建 删除 查询 修改
1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname 3.说明:备份sql server--- 创建 备份数据的 ...
- HTTP图解笔记(一)—— 第1章 了解Web及网络基础
TCP/IP协议族 网络是在TCP/IP协议族的基础上运作的,HTTP是一个子集 OSI四层: 应用层:通用的应用服务协议,FTP.DNS.HTTP ↓ 传输层:提供计算机之间的数据传输,TCP.UD ...
- Scrapy定制起始请求
Scrapy引擎来爬虫中取起始的URL 1.调用start_requests方法(父类),并获取返回值 2.将放回值变成迭代器,通过iter() 3.执行__next__()方法取值 4.把返回值全部 ...
- Elastcisearch.Nest 7.x 系列`伪`官方翻译:通过 NEST 来快捷试用 Elasticsearch
本系列已经已经全部完成,完整版可见:https://blog.zhuliang.ltd/categories/Elasticsearch/ 本系列博文是"伪"官方文档翻译(更加本土 ...
- 【Flink】Flink作业调度流程分析
1. 概述 当向Flink集群提交用户作业时,从用户角度看,只需要作业处理逻辑正确,输出正确的结果即可:而不用关心作业何时被调度的,作业申请的资源又是如何被分配的以及作业何时会结束:但是了解作业在运行 ...
- 第二阶段冲刺个人任务——three
今日任务: 优化统计个人博客结果页面的显示. 昨日成果: 优化作业查询结果,按学号排列.
- 关于Xen
尝试了各种方法搭建xen,尝试过从xenserver入手,但似乎最近时间端不允许访问,感谢我的老师,叫我从kvm入手,暂时记下xen中种种的坑,以后有缘再战.欢迎交流