ATL的GUI程序设计(3)

xiaocui618

xiaocui618

2016-02-19 16:40

在这个颜值当道,屌丝闪边的时代,拼不过颜值拼内涵,只有知识丰富才能提升一个人的内在气质和修养,所谓人丑就要多学习,今天图老师给大家分享ATL的GUI程序设计(3),希望可以对大家能有小小的帮助。

  第二章 一个最简单窗口程序的转型

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  我知道,可能会有很多朋友对上一章的Hello, World!ATL版不以为然,因为它并不能算是什么ATL程序毕竟它只不过是有了个CComModule而已。不过不管怎样我还是要说,它几乎仍然拥有了一个ATL GUI程序的所有组成部分:入口、初始化、程序体、卸载

  等等!也许你会突然打断我,还有注册窗口类、消息循环呢?

  当然,对于一个完整的GUI程序来讲,这也是必要的。

  貌似废话

  不清楚你是否已经为本章的内容做好了准备,因为下面我们就要动真格的了。不过考虑到本书的读者群中可能会存在着相当一部分了解MFC却对Win32 GUI的基本原理和流程不甚熟悉的朋友,所以李马特别为你们准备了这一节的内容。SDK的粉丝们可以跳过这一节,如果你们觉得李马讲的有些拖沓冗长的话。

  那么,我还是先以一个标准的Win32 SDK程序开始:

  

//////////////////////////////////////////////////////////////////////////// ATL的GUI程序设计配套源代码// 第二章 一个最简单窗口程序的转型// 工程名称:HelloSDK// 作者:李马// http://www.titilima.cn//////////////////////////////////////////////////////////////////////////#include windows.h#include tchar.hLRESULT CALLBACK HelloWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ){  switch ( uMsg )  {  case WM_DESTROY:    {      PostQuitMessage( 0 );    }    break;  case WM_PAINT:    {      HDC hdc;      PAINTSTRUCT ps;      hdc = BeginPaint( hWnd, &ps );      DrawText( hdc, _T("Hello, SDK!"), -1, &ps.rcPaint, DT_CENTER | DT_VCENTER | DT_SINGLELINE );      EndPaint( hWnd, &ps );    }    break;  default:    return DefWindowProc( hWnd, uMsg, wParam, lParam );  }  return 0;}BOOL InitApplication( HINSTANCE hInstance ){  WNDCLASS wc;  wc.cbClsExtra  = 0;  wc.cbWndExtra  = 0;  wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );  wc.hCursor    = LoadCursor( NULL, IDC_ARROW );  wc.hIcon     = LoadIcon( NULL, IDI_APPLICATION );  wc.hInstance   = hInstance;  wc.lpfnWndProc  = HelloWndProc;  wc.lpszClassName = _T("HelloSDK");  wc.lpszMenuName = NULL;  wc.style     = CS_HREDRAW | CS_VREDRAW;  return RegisterClass( &wc );}int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd ){  // 注册窗口类  InitApplication( hInstance );  // 创建窗口  HWND hWnd = CreateWindow( _T("HelloSDK"), _T("Hello SDK"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,    CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );  ShowWindow( hWnd, nShowCmd );  UpdateWindow( hWnd );  // 消息循环  MSG msg;  while ( GetMessage( &msg, NULL, 0, 0 ) )  {    TranslateMessage( &msg );    DispatchMessage( &msg );  }  return msg.wParam;}

  不知道你是否会觉得这段代码有些冗长?事实上,这个程序已经体现了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等同品

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  在写作这本书的时候,我总是希望我每次都能够能使用让你不太陌生的代码来循序渐进地引导你。考虑再三,对于Hello, ATL!的这个程序,我决定先把它的WinMain展现给你:

  

int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd ){  _Module.Init( NULL, hInstance );  // 创建窗口  CHelloATLWnd wnd;  wnd.Create( NULL, CHelloATLWnd::rcDefault, _T("Hello ATL") );  wnd.ShowWindow( nShowCmd );  wnd.UpdateWindow();  // 消息循环  MSG msg;  while ( GetMessage( &msg, NULL, 0, 0 ) )  {    TranslateMessage( &msg );    DispatchMessage( &msg );  }  _Module.Term();  return msg.wParam;}

  OK,上一章介绍过的_Module又出现在你的眼前了不过还是没有什么特别的变化,仍然是那熟悉的Init和Term。而且,正如山哟还是那座山一样,消息循环哟也仍然是那个消息循环。当然,你肯定也发现了那寥寥的变化:CHelloATLWnd是什么?在我将它的代码展现给你之前,你可能会做出这样的猜想:

这是一个C++类,它对Win32窗口类进行了封装。 这个类封装了大多数窗口操作的API函数,诸如CreateWindow、ShowWindow、UpdateWindow。 窗口类的注册可能也是在这个C++类中完成的。

  好,打住,这就够了。让我们来撩开CHelloATLWnd那貌似神秘的面纱吧,赶紧着。

  

class CHelloATLWnd : public CWindowImpl CHelloATLWnd, CWindow, CWinTraits WS_OVERLAPPEDWINDOW  {public:  CHelloATLWnd()  {    CWndClassInfo& wci   = GetWndClassInfo();    wci.m_bSystemCursor  = TRUE;    wci.m_lpszCursorID   = IDC_ARROW;    wci.m_wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );    wci.m_wc.hIcon     = LoadIcon( NULL, IDI_APPLICATION );  }public:  DECLARE_WND_CLASS( _T("HelloATL") )public:  BEGIN_MSG_MAP( CHelloATLWnd )    MESSAGE_HANDLER( WM_DESTROY, OnDestroy )    MESSAGE_HANDLER( WM_PAINT, OnPaint )  END_MSG_MAP()public:  LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& hHandled )  {    ::PostQuitMessage( 0 );    return 0;  }  LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& hHandled )  {    HDC hdc;    PAINTSTRUCT ps;    hdc = BeginPaint( &ps );    DrawText( hdc, _T("Hello, ATL!"), -1, &ps.rcPaint, DT_CENTER | DT_VCENTER | DT_SINGLELINE );    EndPaint( &ps );    return 0;  }};

本文示例代码或素材下载

展开更多 50%)
分享

猜你喜欢

ATL的GUI程序设计(3)

编程语言 网络编程
ATL的GUI程序设计(3)

ATL的GUI程序设计(4)ATL的窗口类

编程语言 网络编程
ATL的GUI程序设计(4)ATL的窗口类

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

VisualBasic程序设计

编程语言 网络编程
VisualBasic程序设计

OOP程序设计实践

编程语言 网络编程
OOP程序设计实践

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

《PHP程序设计》序

PHP
《PHP程序设计》序

MySQL程序设计介绍

编程语言 网络编程
MySQL程序设计介绍

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

模拟简单猜扑克牌大小的 Win32 控制台游戏

模拟简单猜扑克牌大小的 Win32 控制台游戏

用PHP实现文件上传二法

用PHP实现文件上传二法
下拉加载更多内容 ↓