Learning WTL8.0 Part-1 Win32 vs. ATL Windows Programming(3)

原创 2007年09月21日 19:41:00
4. ATL Windows编程模型
参照3.1.1 Win32基础构造块和主要流程,来初步的了解ATL Windows编程模型(有关ATL Windows编程的文档极为“罕见“, 甚至与WTL相比 : -)) ;ATL Windows编程是WTL的基石,当然有必要在此费一番力气。  
4.1 RegisterClass在哪?
在 1.2.1 Register windows class 中,MyRegisterClass函数要完成的工作:1. 初始化WNDCLASSEX;2. RegisterClassEx 。 而在ATL中,由CWellcomeWindow之由宏定义的成员函数(member function by macro defined)DECLARE_WND_CLASS(NULL)完成,其由wnd.Create(NULL, 0, appTitle) 调用(例如,在win32.cpp中)。
 
4.1.1 DECLARE_WND_CLASS(NULL)宏定义 
/////////////////////////////////////////////////////////////////////////////
// CWndClassInfo - Manages Windows class information
 
#define DECLARE_WND_CLASS(WndClassName) /
static ATL::CWndClassInfo& GetWndClassInfo() /
{ /
      static ATL::CWndClassInfo wc = /
      { /
            { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, /
             0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, /
            NULL, NULL, IDC_ARROW, TRUE, 0, _T("") /
      }; /
      return wc; /
}
CWndClassInfo为ATL内使用WNDCLASSEX结构的结构(C++),看看代码就应该有所了解了,关键在于 4.1.2 CWndClassInfo结构(_ATL_WNDCLASSINFOW)定义 的黑体部分(Bold)。 
 
4.1.2 CWndClassInfo结构(_ATL_WNDCLASSINFOW)定义
struct _ATL_WNDCLASSINFOW
{
      WNDCLASSEXW m_wc;
      LPCWSTR m_lpszOrigName;
      WNDPROC pWndProc;
      LPCWSTR m_lpszCursorID;
      BOOL m_bSystemCursor;
      ATOM m_atom;
      WCHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT];
      ATOM Register(WNDPROC* p)
      {
            return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, this, p);
      }
};
 
4.1.3 ATL::CWindowImpl::Create定义
HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
                  DWORD dwStyle = 0, DWORD dwExStyle = 0,
                  _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
      {
            if (T::GetWndClassInfo().m_lpszOrigName == NULL)
                  T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
            ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
 
            dwStyle = T::GetWndStyle(dwStyle);
            dwExStyle = T::GetWndExStyle(dwExStyle);
 
            // set caption
            if (szWindowName == NULL)
                  szWindowName = T::GetWndCaption();
 
            return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName,
                  dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam);
      }
真正完成CreateWindow。
4.2 WndProc在哪?
Main message loop在ATL予以了保留(例如,在win32.cpp中)。
 
WndProc由宏定义成员函数完成,参看 2.2 添加CWellcomeWindow.h可以看到如下代码:
      BEGIN_MSG_MAP(CWellcomeWindow)
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
            MESSAGE_HANDLER(WM_PAINT, OnPaint)
            MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
      END_MSG_MAP()
 
4.2.1 Message-Map
#define BEGIN_MSG_MAP(theClass) /
public: /
      BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) /
      { /
            BOOL bHandled = TRUE; /
            (hWnd); /
            (uMsg); /
            (wParam); /
            (lParam); /
            (lResult); /
            (bHandled); /
            switch(dwMsgMapID) /
            { /
            case 0:
                 
#define END_MSG_MAP() /
                  break; /
            default: /
                  ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)/n"), dwMsgMapID); /
                  ATLASSERT(FALSE); /
                  break; /
            } /
            return FALSE; /
      }
 
你所定义的特定的消息处理将会置于case 0defaul之间,例如 2.2 添加CWellcomeWindow.h将会产生如下代码:
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0)
      {
            BOOL bHandled = TRUE;
            (hWnd);
            (uMsg);
            (wParam);
            (lParam);
            (lResult);
            (bHandled);
            switch(dwMsgMapID)
            {
            case 0:
                  if(uMsg == msg)
                  {
                        bHandled = TRUE;
                        lResult = OnCreate(uMsg, wParam, lParam, bHandled);
                        if(bHandled)
                              return TRUE;
                  }
            ……
                  break;
            default:
                  break;
            }
            return FALSE;
      }
 
5. Tips
对于一些技术点和平台作一定的介绍,以便于后续的学习。
5.1 UNREFERENCED_PARAMETER Macro
主要为消除M$ C++编译器在Level 4 (/W4)产生的C4100 :unreferenced formal parameter警告,但在/TC编译器选项下不可用。
 
消除C4100警告的还有另外一种常见的Unamed object的写法,如在 2.2 添加CWellcomeWindow.hOnPaint(UINT /*uMsg*/...) ;这两种为消除C4100警告的写法,并无明显的优劣之分,且都是平台可移植的;但,从标准C++的编码规范来说,笔者更倾向于后者。
在M$ C++ Specification下还有其它的写法,但因其是M$ C++所特有,不便于学习标准C++,故在此不予考虑。
5.2 CXxx : public CYyy<CXxx>
此种声明在C++中是合法的,主要为实现编译时多态(Compile-time Polymophism)。
 
可参看如下代码:
//CXxxx declarations
#pragma once
#include "stdafx.h"
 
template <typename T>
class CYyy {
public:
 
      void Wellcome(const char* s)
      {
            T* pT = static_cast<T*>(this);
            pT->sayHello(s);
      }
 
      void sayHello(const char* s)
      {
            std::cout<<"Hi, "<<s<<std::endl;
      }
};
 
class CXxx1 : public CYyy<CXxx1> {
 
};
 
class CXxx2 : public CYyy<CXxx2> {
public:
      void sayHello(const char* s)
      {
            std::cout<<"Wellcome, "<<s<<std::endl;
      }
};
 
// main entry point
int _tmain(int argc, _TCHAR* argv[])
{
      CXxx1 x1;
      CXxx2 x2;
 
      x1.Wellcome("Joe");
      x2.Wellcome("JoeM");
 
      return 0;
}
以上代码中Cyyy ::Wellcome相当于一个多态函数的一个包装器(wrapper),而所有的秘密就在T* pT = static_cast<T*>(this) 语句;编译时多态在空间开销上至少比运行时多态节省一个vtable指针的空间开销,且因其在编译时就已决定了函数入口点,故具有更高的执行效率。
5.3 throw()
C++ 异常规范(Exception Specifications),用于函数声明之后,通知编译器此函数不会抛出异常;但在ATL中主要目的是使M$ C 的SEH (Structured Exception Handling)在ATL中具有可移植性。
 
在ATL中经常可以看到这样的代码,如在atlwin.h中Cwindow的声明中:
class CWindow
{
public:
      static RECT rcDefault;
      HWND m_hWnd;
 
      CWindow(HWND hWnd = NULL) throw() :
            m_hWnd(hWnd)
      {
      }
...
}
 

李宏毅机器学习笔记

转自:http://blog.csdn.net/soulmeetliang/article/details/73251790 [机器学习入门] 李宏毅机器学习笔记-13 (Semi-...
  • hhsh49
  • hhsh49
  • 2017年11月02日 19:40
  • 90

如何用ATL编写Windows服务

有时候,我们需要自己写的程序在没有用户登陆的情况下,只要Windows系统启动就运行,那我们可以把我们的程序写成一个Windows服务。   服务是能够为各种用户(包括本地用户和远程用户)所用的,拥...
  • lsrwan
  • lsrwan
  • 2014年11月15日 22:17
  • 372

STL,ATL,WTL之间的联系和区别

一、STL即 Standard Template Library (标准模板库)       STL是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Le...
  • wangwenjing90
  • wangwenjing90
  • 2013年05月14日 14:44
  • 3967

faster-rcnn(matlab版)在windows平台上的配置

VS2013+cuda8.0+matlab编译faster-rcnn
  • ChuQiDeCha
  • ChuQiDeCha
  • 2017年02月21日 19:18
  • 2978

《Programming in Lua 3》读书笔记(十五)

日期:2014.7.22 PartⅢ     The Standard Libraries 19 The Bitwise Library 位运算库 lua中的位运算由于数值类型...
  • u011894560
  • u011894560
  • 2014年08月10日 21:31
  • 4049

VS2010 ATL服务程序编写全攻略(一) - 建立ATL服务

网上有很多关于编写ATL服务程序的代码和文章,但多数仍使用Visual C++ 6.0的ATL服务程序框架。对于XP系统,Visual C++ 6.0提供的框架能够正常工作,但对于Vista、Wind...
  • sonsie007
  • sonsie007
  • 2013年04月22日 15:06
  • 7269

用 VC 2008 编写 Windows Service(系统服务) atl 编写系统服务

http://hi.baidu.com/lewutian/item/9019396a05d517166995e6a5 http://hi.baidu.com/cntrump/item/2bf6b43...
  • smallnew198705
  • smallnew198705
  • 2014年03月30日 16:27
  • 1472

ROS系列一之Robot发展史

一.前言 二.概念 1920年,捷克作家卡尔·恰彼克写了一个剧本《罗素姆万能机器人》,剧本描写了一个依赖机器人的社会,戏剧中有一个长得像人,动作也像人的机器人——罗伯特(Robot,捷克语意为“强迫...
  • ad3600
  • ad3600
  • 2017年01月19日 16:30
  • 612

WinCE7.0 Win32智能设备项目使用 CString 的问题

建 了一个 WinCE 7.0 的 Win32 智能设备项目,在项目中增加了一些 .cpp 和 .h 文件。先是编译时出现 CString 未定义的错误,于是 #include "atlstr.h"。...
  • 91program
  • 91program
  • 2015年03月09日 07:41
  • 1591

Learning OpenCV第一版和第三版对比

于2017.06.15
  • JasonSunJian
  • JasonSunJian
  • 2017年06月15日 12:59
  • 1229
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Learning WTL8.0 Part-1 Win32 vs. ATL Windows Programming(3)
举报原因:
原因补充:

(最多只允许输入30个字)