2024年3月19日发(作者:)

一、深入剖析

WTL——Win32

模型

WTL

Windows Template Library

的缩写。最初,

WTL

是由微软的

ATL

Active

Template Library

)小组成员开发的一个

SDK

例子。主要是基于

ATL

的对

Win32 API

封装。从

2.0

后,功能逐步完善,成为了一个完整的支持窗口的框架(

windows

framework

)。

MFC

相比较,功能并没有

MFC

完善。比如

MFC

支持

doc/view

架构,而

WTL

并不支

持。同时,

WTL

也没有

Microsoft

的官方支持。但是,

WTL

是基于模版

(template)

的,其

应用程序最小只有

24KB

,同时不象

MFC

,依赖

DLL

MFC

需要

)。

WTL

系列文章对

WTL

进行了深入剖析,希望能方便您对

WTL

有一个深入的理解,从

而能得心应手的开发出高质量的

Windows

应用程序。

Win32

的线程模型

为了便于以后的探讨,首先看一下

Win32

的线程模型。

一个

Win32

应用程序(或进程)是由一个或多个并发的线程组成的,其中第一个启动

的线程称为主线程。

Win32

定义了两种类型的线程,界面线程和工作线程。

Win32

的每个进程可以有一个或

多个界面线程和

/

或多个工作线程。界面线程拥有一个或多个窗口,拥有一个消息队列

和其它属于界面线程的元素。工作线程就是一般的线程,它没有窗口,没有消息队列。

界面线程通常有一个或几个窗口。当某一个窗口有消息时,界面线程会调用相应的窗口

函数

(Windows Process)

来处理该事件。由于某消息循环由它界面线程处理,同时不必在

乎是哪个线程发送消息的,因此,

Windows

会保证线程间的同步问题。

对于工作线程,线程间的同步必须由程序员来实现。尽可能避免死锁和竞争出现。

Win32

应用程序模型

Win32

应用程序可以分成两大类:控制台程序

(console application)

和窗口界面程序

(windows GUI application)

。控制台程序的入口函数是

main()

,窗口界面程序的入口函数

WinMain()

入口函数就是程序的主线程的运行起点。

这里讨论的开发框架

(Framework)

是针对窗口界面程序的。

窗口界面程序通常分成以下几类:

SDI, MDI, multi-SDI,

Dialog

应用程序。

SDI(Single Document Interface)

应用程序通常只有一个主窗口

(

通常是一个框架窗口,

Frame Window)

。框架窗口包含菜单、工具栏、状态栏和称为视

(View)

的客户工作区。

multi-SDI(Multiple Threads SDI)

应用程序有框架个主窗口。比如

IE

浏览器,使用

"

文件

/

新建

/

窗口

"

命令后,会出现另一个

IE

窗口。

MDI(Multiple Document Interface)

应用程序有一个主框架窗口,但有多个子框架窗口。

每个子窗口都有自己的视

(View)

Dialog

应用程序是基于对话框的。

通常一个简单的

SDI

应用程序由两个函数组成。一个是应用程序入口函数

WinMain()

另一个是该应用程序窗口的窗口函数。

程序(主线程)从入口函数开始运行。在该函数中,首先是注册并创建一个主窗口。然

后,启动消息循环。消息循环中,根据不同的消息,将消息发送到窗口函数中处理。当

消息是退出消息时,该入口函数会退出消息循环,然后结束程序。

下面是一个最简单的

Windows

界面应用程序。

//应用程序入口函数

int APIENTRY WinMain(HINSTANCE hInstance,

      HINSTANCE hPrevInstance,

      LPSTR lpCmdLine,

      int nCmdShow)

{

   MSG msg;

   //1. 注册窗口类

   WNDCLASSEX wcex;

    = sizeof(WNDCLASSEX);

    = CS_HREDRAW | CS_VREDRAW;

   dProc = (WNDPROC)WndProc; //指定窗口函数

   xtra = 0;

   xtra = 0;

   nce = hInstance;

    = LoadIcon(hInstance, (LPCTSTR)IDI_HELLOWORLD);

   r = LoadCursor(NULL, IDC_ARROW);