现在的位置: 首页 > 综合 > 正文

深入剖析WTL

2013年08月14日 ⁄ 综合 ⁄ 共 2827字 ⁄ 字号 评论关闭

深入剖析WTL. 1

.      Win32模型... 1

二.如何封装Windows界面程序... 5

WTL框架窗口分析... 12

深入剖析WTL

一.   Win32模型

WTL Windows Template Library的缩写。最初,WTL是由微软的ATLActive Template Library)小组成员开发的一个SDK例子。主要是基于ATL的对Win32 API的封装。从2.0后,功能逐步完善,成为了一个完整的支持窗口的框架(windows framework)。

MFC相比较,功能并没有MFC完善。比如MFC支持doc/view架构,而WTL并不支持。同时,WTL也没有Microsoft的官方支持。但是,WTL是基于模版(template)的,其应用程序最小只有24KB,同时不象MFC,依赖DLLMFC需要MFC42.DLL)。

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;

   wcex.cbSize = sizeof(WNDCLASSEX);

   wcex.style = CS_HREDRAW | CS_VREDRAW;

   wcex.lpfnWndProc = (WNDPROC)WndProc;    //指定窗口函数

   wcex.cbClsExtra = 0;

   wcex.cbWndExtra = 0;

   wcex.hInstance = hInstance;

   wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_HELLOWORLD);

   wcex.hCursor = LoadCursor(NULL, IDC_ARROW);

   wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

   wcex.lpszMenuName = (LPCSTR)IDC_HELLOWORLD;

   wcex.lpszClassName = szWindowClass;

wcex.hIconSm = LoadIcon(wcex.hInstance,(LPCTSTR)IDI_SMALL);

   RegisterClassEx(&wcex);

   //2. 创建一个该类型的窗口

   HWND hWnd;

   hWnd = CreateWindow(szWindowClass,szTitle,

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0,

CW_USEDEFAULT, 0, NULL, NULL,

hInstance, NULL);

   if (!hWnd) return FALSE;

   //3. nCmdShow所指定的方式显示窗口

   ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

   //4. 启动消息循环,将消息发送给相应的窗口函数

   while (GetMessage(&msg, NULL, 0, 0))

   {

      TranslateMessage(&msg);

      DispatchMessage(&msg);

   }

   return msg.wParam;

}

//窗口函数

LRESULT CALLBACK WndProc(HWND hWnd,

UINT message,

WPARAM wParam,        

LPARAM lParam)

{

   PAINTSTRUCT ps;

   HDC hdc;

   char* szHello = "Hello, world!";

   switch (message)

   {

     case WM_PAINT:

      hdc = BeginPaint(hWnd, &ps);

      RECT rt;

      GetClientRect(hWnd, &rt);

      DrawText(hdc, szHello, strlen(szHello),&rt,DT_CENTER);

抱歉!评论已关闭.