QWinClass:(一)創建基於CWnd類的自定義窗體

QWinClass是本人開發的一套適用於CE5.0的觸摸屏UI類,其主要內容是對CWnd的繼承,對CDC的操作,以及窗體消息的過濾組合,從技術上而言這並不算複雜,只是對MFC的簡單操作,但的確是需要耗費時間的,主要是爲了備忘,在我的BLOG上寫點相關的技術難點(可能只是對我而言)。

此UI系統總的構建思路有多種,在我寫好並已應用的類裏,我是基於一個CDialog的DC來創建全部的窗體(大概十來個吧),我一開始的思路是以內存來換顯示速度,但使用到後面,內存開銷過大,因爲主類基本成型,想在內存吃緊的情況下動態delete一些DC資源相當有難度,於是我回想起我的QWinClass1.0時的辦法——在資源裏創建一個CDialog類,然後在類裏作其他操作,其方便的地方是,你可以很隨意地創建跟關閉一個Dialog,這在內存有限的情況下很有用,畢竟如果程序都沒辦法使用,談何刷圖速度呢?基於此想法,我再擴展一下我的UI類。

創建一個窗口,當然不想在資源面板裏手動添加,那實在不方便工程的協作,我是越來越喜歡純代碼的東西了,如果懂得繼承,搭建好父類,子類的代碼量可以足夠的少。好吧,接下來說實際操作。

可以使用VS的類嚮導創建一個基於CWnd的類CQBaseWnd,生成的CPP及H文件裏有一些原生代碼,主要是用於映射的,可以不管,照留着就好,然後重載OnCreate、PostNcDestroy、OnPaint函數,稍作添加,如下所示:

  1. //2013-1-12 重新修改代碼,添加關閉窗體函數 
  2. /////////////////////////////////////////////////// 
  3. //QBaseWnd.h 
  4. /////////////////////////////////////////////////// 
  5. #pragma once 
  6. #include "afxwin.h" 
  7.  
  8. class CQBaseWnd : public CWnd 
  9.     DECLARE_DYNAMIC(CQBaseWnd) 
  10. private
  11.     //父窗體指針 
  12.     CWnd * _pParentWnd; 
  13.     //背景顏色 
  14.     COLORREF _crBackup; 
  15.     //窗體尺寸 
  16.     CRect _rcWnd; 
  17.  
  18. public
  19.     //默認構造函數 
  20.     CQBaseWnd(void); 
  21.     //析構函數 
  22.     virtual ~CQBaseWnd(void); 
  23.     //顯示窗體 
  24.     BOOL ShowWnd(); 
  25.     //窗體創建函數 
  26.     BOOL Create(CWnd * pParentWnd, COLORREF crBackup, CRect rcWnd); 
  27.     //關閉窗體 
  28.     BOOL Close(); 
  29.  
  30. private
  31.     //響應創建消息 
  32.     afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 
  33.     //響應重繪消息 
  34.     afx_msg void OnPaint(); 
  35.     //創建窗體 
  36.     BOOL CreateWnd(CWnd * pParentWnd = NULL); 
  37.  
  38. protected
  39.     DECLARE_MESSAGE_MAP() 
  40.     //註銷窗體 
  41.     virtual void PostNcDestroy(); 
  42. }; 
  43.  
  44.  
  45. ////////////////////////////////////////////////////   
  46. //QBaseWnd.cpp   
  47. ////////////////////////////////////////////////////   
  48. #include "stdafx.h"   
  49. #include "QBaseWnd.h"    
  50.  
  51. // CQBaseWnd   
  52.  
  53. //動態聲明類 
  54. IMPLEMENT_DYNAMIC(CQBaseWnd, CWnd)   
  55.  
  56. //默認構造函數 
  57. CQBaseWnd::CQBaseWnd()   
  58. {   
  59.  
  60. }   
  61.  
  62. //析構函數 
  63. CQBaseWnd::~CQBaseWnd()   
  64. {   
  65. }   
  66.  
  67.  
  68. BEGIN_MESSAGE_MAP(CQBaseWnd, CWnd)   
  69.     ON_WM_CREATE()   
  70.     ON_WM_PAINT()   
  71. END_MESSAGE_MAP()   
  72.  
  73.  
  74. // CQBaseWnd 消息處理程序   
  75.  
  76. //響應創建消息 
  77. int CQBaseWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)   
  78. {   
  79.     if (CWnd::OnCreate(lpCreateStruct) == -1)   
  80.         return -1;   
  81.  
  82.     // TODO:  在此添加您專用的創建代碼   
  83.     CenterWindow();   
  84.     return 0;   
  85. }   
  86.  
  87. //註銷窗體時必須調用Destroy()函數 
  88. void CQBaseWnd::PostNcDestroy()   
  89. {   
  90.     // TODO: 在此添加專用代碼和/或調用基類   
  91.  
  92.     CWnd::PostNcDestroy();   
  93. }   
  94.  
  95. //自建窗體的函數 
  96. BOOL CQBaseWnd::CreateWnd(CWnd* pParentWnd)   
  97. {   
  98.     LPCTSTR strSplashWndClass;   
  99.     strSplashWndClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, 0, 0, 0);   
  100.     return CreateEx(0,strSplashWndClass,NULL, WS_POPUP|WS_VISIBLE, 0, 0, this->_rcWnd.Width(), this->_rcWnd.Height(), pParentWnd->GetSafeHwnd(), NULL);   
  101.  
  102. //自定義的窗體創建函數 
  103. BOOL CQBaseWnd::Create(CWnd * pParentWnd, COLORREF crBackup, CRect rcWnd) 
  104.     this->_pParentWnd = pParentWnd; 
  105.     this->_rcWnd = rcWnd; 
  106.     this->_crBackup = crBackup; 
  107.  
  108.     if (!CreateWnd(pParentWnd)) 
  109.     { 
  110.         delete this
  111.         return FALSE; 
  112.     }else
  113.         return TRUE; 
  114.     } 
  115.  
  116. //關閉窗體,必須調用DestroyWindows() 
  117. BOOL CQBaseWnd::Close() 
  118.     this->DestroyWindow(); 
  119.     return TRUE; 
  120.  
  121. //顯示窗體 
  122. BOOL CQBaseWnd::ShowWnd()   
  123. {   
  124.     // 顯示啓動畫面   
  125.     if (!CreateWnd(AfxGetMainWnd())) {   
  126.         delete this;   
  127.         return FALSE; }   
  128.  
  129.     UpdateWindow();   
  130.  
  131.     return TRUE;   
  132.  
  133. void CQBaseWnd::OnPaint()   
  134. {   
  135.     CPaintDC dc(this); // device context for painting   
  136.     // TODO: 在此處添加消息處理程序代碼   
  137.     // 不爲繪圖消息調用 CWnd::OnPaint()   
  138.  
  139.     CBrush br = CBrush(this->_crBackup);   
  140.     dc.FillRect(CRect(0, 0, this->_rcWnd.Width(), this->_rcWnd.Height()), &br);   
  141. }  

要顯示此窗體時,這樣用法:

  1. CTestDlg * pWnd = new CTestDlg();  
  2. pWnd->ShowWnd(); 

顯示的窗體長怎麼樣,就看你在OnPaint()作了什麼操作了,我這裏只是刷了一片純色而已,大家可以詳細研究一下AfxRegisterWndClass與CWnd::CreateEx的用法。窗口生成後可以自行調用ShowWindows()來顯示或隱藏窗體。

需要提醒一下,我這沒寫關閉窗體的代碼,如果需要關閉,一定要使用DestroyWindow,否則會造成內存泄漏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章