关于WTL学习的一些心得

最近学习使用WTL作Windows编程,网上找资料----->少,仅仅有个叫www.imyaker.com的网站上有个牛X老外的一本书,而且是针对MFC编程人员的,像我这种初学者简直----->难。

对于一个标准的windows应用,虽然╮(╯_╰)╭但是我们必需牢记在心,因为所有的什么messge map等等最终还是在switch case或者在if else。她包括一下几个部分:

1:-TWinMain,函数入口点

2:注册窗口类

3:创建主窗口

4:showWindow,UpdateWindow

5:消息循环,消息处理。

6:退出

然后WTL,ATL,MFC都是对这一过程的封装。

 

WTL继承自ATL,ATL是为COM而作的,她对windows组件进行了一定的包装。如:Cwindow,CDilog==,后来微软的一帮技术牛X人,觉得用模板库来做窗体的封装不错,然后就对ATL的这些东西做了扩展就是WTL。

以下我们就来看看他的CWindowImpl。

首先,CWindowImpl最终是从Cwindow派生的。

 

  1. template <class T, class TBase /* = CWindow */class TWinTraits /* = CControlWinTraits */>
  2. class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits >
  3. {
  4. public:
  5.     DECLARE_WND_CLASS(NULL)
  6.     static LPCTSTR GetWndCaption()
  7.     {
  8.         return NULL;
  9.     }
  10.     HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  11.             DWORD dwStyle = 0, DWORD dwExStyle = 0,
  12.             _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  13.     {
  14.         if (T::GetWndClassInfo().m_lpszOrigName == NULL)
  15.             T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
  16.         ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  17.         dwStyle = T::GetWndStyle(dwStyle);
  18.         dwExStyle = T::GetWndExStyle(dwExStyle);
  19.         // set caption
  20.         if (szWindowName == NULL)
  21.             szWindowName = T::GetWndCaption();
  22.         return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName,
  23.             dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam);
  24.     }
  25. };

Cwindow仅仅是做了一个类来存放一个HWND,几乎所有API中第一个参数是HWND的方法这个类都有。看它的源代码就可以得出,它仅仅是调用了API。此时它并没有消息循环,与窗口处理函数。

然后,再看看WTL给的.h文件就可以知道,它貌似是有一个叫:Cmessage的类里面拥有消息循环。如下:

 

  1. class ATL_NO_VTABLE CMessageMap
  2. public:
  3.  virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,LRESULT& lResult, DWORD dwMsgMapID) = 0;
  4. };

当然了,CWindowImpl 多半是继承了这个类。如下:

  1. template <class TBase /* = CWindow */>
  2. class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap

从此,CWindowImpl 就有了消息循环。

那么,注册窗口,与创建窗口在哪里喃?

看到源码中第一句就是一宏,展开看一下:

  1. #define DECLARE_WND_CLASS(WndClassName) /
  2. static ATL::CWndClassInfo& GetWndClassInfo() /
  3. { /
  4.     static ATL::CWndClassInfo wc = /
  5.     { /
  6.         { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, /
  7.           0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, /
  8.         NULL, NULL, IDC_ARROW, TRUE, 0, _T("") /
  9.     }; /
  10.     return wc; /
  11. }

....这个就是窗口的注册了,其中StartWindowProc很诡异,如下:

  1. static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg,
  2.         WPARAM wParam, LPARAM lParam)
  3.     {
  4.         CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)_AtlWinModule.ExtractCreateWndData();
  5.         ATLASSERT(pThis != NULL);
  6.         if(!pThis)
  7.         {
  8.             return 0;
  9.         }
  10.         pThis->m_hWnd = hWnd;
  11.         // Initialize the thunk.  This was allocated in CContainedWindowT::Create,
  12.         // so failure is unexpected here.
  13.         pThis->m_thunk.Init(WindowProc, pThis);
  14.         WNDPROC pProc = pThis->m_thunk.GetWNDPROC();
  15.         WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  16. #ifdef _DEBUG
  17.         // check if somebody has subclassed us already since we discard it
  18.         if(pOldProc != StartWindowProc)
  19.             ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded./n"));
  20. #else
  21.         pOldProc;   // avoid unused warning
  22. #endif
  23.         return pProc(hWnd, uMsg, wParam, lParam);
  24.     }

最终,以上的东西实现一个功能:将与窗口相联系的窗口过程变成了一个类与其方法的联系。

注:m_thunk 是一个ASM结构。作用:在调用CWindowImpl的静态成员方法WindowProc更进一步地进行消息处理 之前将HWND替换成为CWindowImpl 对象的this指针。

后面就是像这样的东西了:

  1.     BEGIN_MSG_MAP(CWtl_SDIView)
  2.         MESSAGE_HANDLER(WM_PAINT, OnPaint)
  3.         MSG_WM_SETCURSOR(OnSetCursor)
  4.         MESSAGE_HANDLER(WM_CREATE,OnCreate)
  5.         MESSAGE_HANDLER(WM_LBUTTONDOWN,OnLbdown)
  6.         MESSAGE_HANDLER(WM_DESTROY,OnDestroy) 
  7.     
  8.     END_MSG_MAP()

什么也不说,这个就是一系列case,if等等的语句,展开就OK。


  1.     BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) /
  2.     { /
  3.         BOOL bHandled = TRUE; /
  4.         (hWnd); /
  5.         (uMsg); /
  6.         (wParam); /
  7.         (lParam); /
  8.         (lResult); /
  9.         (bHandled); /
  10.         switch(dwMsgMapID) /
  11.         { /
  12.         case 0:

 然后就没有了。下面是一个列子:

  1. #pragma once
  2. #include "stdafx.h"
  3. class CWtl_SDIView : public CWindowImpl<CWtl_SDIView>
  4. {
  5. public:
  6.     DECLARE_WND_CLASS(NULL)
  7.     //BOOL PreTranslateMessage(MSG* pMsg);
  8.     BEGIN_MSG_MAP(CWtl_SDIView)
  9.         MESSAGE_HANDLER(WM_PAINT, OnPaint)
  10.         MSG_WM_SETCURSOR(OnSetCursor)
  11.         MESSAGE_HANDLER(WM_LBUTTONDOWN,OnLbdown)
  12.         
  13.     END_MSG_MAP()
  14.     // Handler prototypes (uncomment arguments if needed):
  15.     //  LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  16.     //  LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  17.     //  LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
  18. // void OnNcLButtonDown(UINT nHitTest, CPoint point)
  19.     LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
  20.     LRESULT OnLbdown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  21.     LRESULT OnSetCursor(HWND hwndCtrl, UINT uHitTest, UINT uMouseMsg)
  22.     {
  23.         static HCURSOR hcur = LoadCursor ( NULL, IDC_SIZEALL );
  24.         if ( NULL != hcur )
  25.         {
  26.             SetCursor ( hcur );
  27.             return TRUE;
  28.         }
  29.         else
  30.         {
  31.             SetMsgHandled(false);
  32.             return FALSE;
  33.         }
  34.     }
  35. };
  36. LRESULT CWtl_SDIView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  37. {
  38.     CPaintDC dc(m_hWnd);
  39.     //TODO: Add your drawing code here
  40.     dc.TextOut(0,0,_T("hello world"));
  41.     return 0;
  42. }
  43. LRESULT CWtl_SDIView::OnLbdown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) //向父窗口发送消息
  44. {
  45.     if (wParam == (MK_CONTROL|MK_LBUTTON))
  46.     {
  47.         ::MessageBox(this->m_hWnd,_T("you press key"),_T("test0"),0);
  48.         WPARAM wParam=MAKEWPARAM(ID_APP_ABOUT,0);
  49.         ::SendMessage(this->GetParent(),WM_COMMAND,wParam,0);
  50.         ::MessageBox(this->m_hWnd,_T("after SendMessage ID_APP_ABOUT"),_T("test1"),0);
  51.         return 1;
  52.     }
  53.     else if (wParam == MK_LBUTTON)
  54.     {
  55.         ::MessageBox(this->m_hWnd,_T("you just press left button "),_T("test2"),0);
  56.         WPARAM wParam=MAKEWPARAM(IDOK,0);
  57.         ::SendMessage(this->GetParent(),WM_COMMAND,wParam,0);
  58.         ::MessageBox(this->m_hWnd,_T("after SendMessage IDOK"),_T("test1"),0);
  59.         return 1;
  60.     }
  61.     return 0;
  62. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值