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函数,稍作添加,如下所示:
- //2013-1-12 重新修改代码,添加关闭窗体函数
- ///
- //QBaseWnd.h
- ///
- #pragma once
- #include "afxwin.h"
- class CQBaseWnd : public CWnd
- {
- DECLARE_DYNAMIC(CQBaseWnd)
- private:
- //父窗体指针
- CWnd * _pParentWnd;
- //背景颜色
- COLORREF _crBackup;
- //窗体尺寸
- CRect _rcWnd;
- public:
- //默认构造函数
- CQBaseWnd(void);
- //析构函数
- virtual ~CQBaseWnd(void);
- //显示窗体
- BOOL ShowWnd();
- //窗体创建函数
- BOOL Create(CWnd * pParentWnd, COLORREF crBackup, CRect rcWnd);
- //关闭窗体
- BOOL Close();
- private:
- //响应创建消息
- afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
- //响应重绘消息
- afx_msg void OnPaint();
- //创建窗体
- BOOL CreateWnd(CWnd * pParentWnd = NULL);
- protected:
- DECLARE_MESSAGE_MAP()
- //注销窗体
- virtual void PostNcDestroy();
- };
- //QBaseWnd.cpp
- #include "stdafx.h"
- #include "QBaseWnd.h"
- // CQBaseWnd
- //动态声明类
- IMPLEMENT_DYNAMIC(CQBaseWnd, CWnd)
- //默认构造函数
- CQBaseWnd::CQBaseWnd()
- {
- }
- //析构函数
- CQBaseWnd::~CQBaseWnd()
- {
- }
- BEGIN_MESSAGE_MAP(CQBaseWnd, CWnd)
- ON_WM_CREATE()
- ON_WM_PAINT()
- END_MESSAGE_MAP()
- // CQBaseWnd 消息处理程序
- //响应创建消息
- int CQBaseWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CWnd::OnCreate(lpCreateStruct) == -1)
- return -1;
- // TODO: 在此添加您专用的创建代码
- CenterWindow();
- return 0;
- }
- //注销窗体时必须调用Destroy()函数
- void CQBaseWnd::PostNcDestroy()
- {
- // TODO: 在此添加专用代码和/或调用基类
- CWnd::PostNcDestroy();
- }
- //自建窗体的函数
- BOOL CQBaseWnd::CreateWnd(CWnd* pParentWnd)
- {
- LPCTSTR strSplashWndClass;
- strSplashWndClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, 0, 0, 0);
- return CreateEx(0,strSplashWndClass,NULL, WS_POPUP|WS_VISIBLE, 0, 0, this->_rcWnd.Width(), this->_rcWnd.Height(), pParentWnd->GetSafeHwnd(), NULL);
- }
- //自定义的窗体创建函数
- BOOL CQBaseWnd::Create(CWnd * pParentWnd, COLORREF crBackup, CRect rcWnd)
- {
- this->_pParentWnd = pParentWnd;
- this->_rcWnd = rcWnd;
- this->_crBackup = crBackup;
- if (!CreateWnd(pParentWnd))
- {
- delete this;
- return FALSE;
- }else{
- return TRUE;
- }
- }
- //关闭窗体,必须调用DestroyWindows()
- BOOL CQBaseWnd::Close()
- {
- this->DestroyWindow();
- return TRUE;
- }
- //显示窗体
- BOOL CQBaseWnd::ShowWnd()
- {
- // 显示启动画面
- if (!CreateWnd(AfxGetMainWnd())) {
- delete this;
- return FALSE; }
- UpdateWindow();
- return TRUE;
- }
- void CQBaseWnd::OnPaint()
- {
- CPaintDC dc(this); // device context for painting
- // TODO: 在此处添加消息处理程序代码
- // 不为绘图消息调用 CWnd::OnPaint()
- CBrush br = CBrush(this->_crBackup);
- dc.FillRect(CRect(0, 0, this->_rcWnd.Width(), this->_rcWnd.Height()), &br);
- }
要显示此窗体时,这样用法:
- CTestDlg * pWnd = new CTestDlg();
- pWnd->ShowWnd();
显示的窗体长怎么样,就看你在OnPaint()作了什么操作了,我这里只是刷了一片纯色而已,大家可以详细研究一下AfxRegisterWndClass与CWnd::CreateEx的用法。窗口生成后可以自行调用ShowWindows()来显示或隐藏窗体。
需要提醒一下,我这没写关闭窗体的代码,如果需要关闭,一定要使用DestroyWindow,否则会造成内存泄漏。
转载于:https://blog.51cto.com/joeyliu/1076123