VC/Wince 实现仿Win8 Metro风格界面1——设计概述和自绘Button(附效果图)
Posted on 2013-06-26 19:35 泡泡糖 阅读(13133) 评论(11) 编辑 收藏 举报去年用VC做了一个仿Win8 Metro风格的界面,感觉挺有意思,最近打算把实现过程和一些技术原理记录下来。
主要是风格上类似Win8,其实功能上很多借鉴了Android的操作方式。界面只支持两种大小的Metro磁铁。
原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3157205.html
1、主要实现了以下功能:
- 手指滑动切换页面。
- 图标位置交换。
- 从全部列表拖动添加到主页面。
- 主页面按钮拖动添加删除操作。
- 主页面按钮拖动添加到导航栏上。
- 背景更换
下面是一张最终桌面效果图:
程序是运行在Wince上,不过是使用MFC开发,所以对PC开发也是同用。
2、类图关系
要实现滑动操作和按钮拖动操作最基本的就是需要有一个支持滑动拖动的按钮。VC上微软的Button拖动效率太
低而且不好操作,所以很多重载Button类的控件都用不了。做嵌入式开发,需要一个绚丽点的界面,基本只有一条
路径,就是重绘。所以我们这里使用的按钮和其他控件都是基于重绘的。
做这个界面主要时为了兼顾程序健壮性,所以使用了MVC模式,所有界面元素都是独立于对话框,我把它们
都放在一个DUIInterface的目录下。还有一点这个界面逻辑是基于DirectUI的思想来做,基于一个窗体上绘
画不同的窗口和控件。不过这个并没有完整的使用DirectUI,消息分发方面还没有独立处理,仍然依赖窗口
的消息队列。
先把我界面结构类图画出来:
3、基类CDUIBase
CDUIBase是所有类的基类,是一个虚基类,提供了基本的点击接口、滑动接口、绘画控件接口
/*************************************************
2012. Co., Ltd.
Edited by OWL
Class name: CDUIBase
Description:
绘图控件基类,定义了绘画操作的动作
*************************************************/
#pragma once
class CDUIBase
{
public:
CDUIBase(void);
~CDUIBase(void);
public:
//画图
virtual void Draw(CDC * pDC);
//响应窗口OnLButtonDown
virtual BOOL OnLButtonDown(POINT point);
//响应窗口OnLButtonUp
virtual void OnLButtonUp(POINT point);
//响应窗口OnMouseMove
virtual int OnMouseMove(POINT point, CDC * pDC, CDC * pBackDC);
};
VC里面界面响应回调主要就是依靠OnLButtonDown、OnLButtonUp、OmMouseMove。这三个回调函数
基本构成了所以界面操作的基础。不仅仅是VC,其他的软件界面响应,其实底层都是基于这三个接口,然后根据
这三个接口数据就可以延伸出很多界面操作,例如手势操作。最近也在研究Android手势支持部分模块,Android
的手势支持很好,很多手势动作都可以识别出来。例如基本的滑动,按下拖动等等。不过这些操作都可以利用
OnLButtonDown、OnLButtonUp、OmMouseMove来混合实现。(多点触摸手势除外,这个需要底层屏幕驱动支持)。
例如判断手指向右拖动,可以根据OnLButtonUp的X坐标减去OnLButtonDown里面X坐标,得到结果如果是正数,
证明向右滑动,至于滑动距离也可以算出来。如果加上up和down之间的响应时间,就可以计算出这次滑动的速度是多少。
4、按钮类CDUIButton
这个Button类代码比较多,我就不贴出来了。主要就是继承实现CDUIBase里面的四个接口,另外因为Button点击
一般要处理事情,所以增加一个回调函数,在OnLbuttonUp的时候调用。
//定义点击按钮的响应回调函数
typedef void (CALLBACK* DUIBtnCallBack)(CWnd *pWnd, CString cmd, CString name, CString Animate);
pWnd是回调的窗口,cmd是按钮按下的识别命令,name是按钮名称,Animate是按钮按下需要执行的动画。
这几个可以根据需要调整,加入动画是为了操作看上去比较流畅。自从iPhone出来以后,做界面不加动画就是反人类 -_-!
class CDUIButton: public CDUIBase
{
public:
CDUIButton(void);
~CDUIButton(void);
private:
//按钮区域
CRect m_btnRc;
//标题的区域
CRect m_FontRc;
//按钮未选中状态图片路径
CString m_btnPic;
//按钮选中状态图片路径
CString m_btnPicSel;
//按钮动画效果图片路径
CString m_AnimatePic;
//按钮打开动画
CString m_AnimateType;
//点击按钮识别命令行
CString m_BtnClickCMD;
//按钮按下状态,TRUE为按下
BOOL m_ClickState;
//是否处于滑动
BOOL m_mouseMove;
//PNG图片正常状态透明度
BYTE m_Alpha;
//PNG图片按下透明度
BYTE m_AlphaSel;
//字体大小
int m_fontSize;
//..........
public:
//初始化按钮
void CreateBtn(CWnd * OwerWnd, HWND mainWnd, CString btnPic, CString btnPicSel, CRect rc);
//画图
void Draw(CDC * pDC);
//响应窗口OnLButtonDown
BOOL OnLButtonDown(POINT point);
//响应窗口OnLButtonUp
void OnLButtonUp(POINT point);
//响应窗口OnMouseMove
int OnMouseMove(POINT point, CDC * pDC, CDC * backDC);
//画按钮的名称
void DrawBtnText(CDC * pDC);
//..........
};
上面是定义的CDUIButton的一部分属性和方法,按钮一般都有按下、焦点、不可用、普通和点击5种状态。
不过我这里只需要用到普通和按下两种状态,所以只有两种属性,如果有需要可以把其他状态都加入进去。
这种只是一种虚拟的按钮,简单来说就是定义屏幕某个区域,然后在这个区域贴一张图片,如果你点击了这张图片,
把图片刷新成点击的状态,然后执行某个操作。就完成了一个按钮需要做的事情。至于按钮的数据是使XML配置,
然后读取XML配置的时候解析XML自动生成这个按钮对象,再放到管理容器里面。这方面的内容,后面会分开说明。
使用这种自绘的Button的好处就是,你要拖动这个按钮,其实只是拖动一张图片,整个系统消耗是很小的。
如果你要拖动重载的微软控件,还涉及闪烁、拖动慢、刷新慢等问题。例如下面的截图,我把电子词典这个按钮
拖动出来,其实只要绘画一张图片就可以。

按钮都是用PNG图片来显示,所以操作的时候都加入了半透明效果,至于PNG图片显示和使用,我已经写了两篇文章,
有兴趣的可以看看:
1、Wince PNG贴图类:
http://www.cnblogs.com/mythou/archive/2013/06/13/3133606.html
2、Wince/VC高效PNG贴图,自定义Alpha算法:
http://www.cnblogs.com/mythou/p/3150396.html
今天就先说到这里,其他逻辑实现,我会后面接着写。
PS:代码问题,这个项目因为是公司的项目,所以代码无法上传,我后面会自己写一个demo,然后上传上来。
发现那里写错的朋友,欢迎留言指出!
VC/Wince 实现仿Win8 Metro风格界面2——页面滑动切换(附效果图)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步