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,否则会造成内存泄漏。