VC/Wince 实现仿Win8 Metro风格界面2——页面滑动切换(附效果图)
前几天开始写仿Win8 Metro界面文章,部分网友觉得不错,感谢各位的意见。本来今天一直在折腾Android VLC播放器,没时间写。不过明天休息,所以今天就抽时间先写一下。
言归正传,我们都知道Win8的Metro界面只要手指一划,页面就跟着滑动(准确来说是按钮跟着滑动,背景其实没动),这个操作目前的Android和iPhone都是这种操作,个人感觉都是从iPhone借鉴来,滑动切换很早就有,不过按钮和壁纸分开滑动,这个还是iPhone时代开始。
(这效果图是截了几张图弄的,所以看上去不流畅)
类逻辑关系图
1、界面逻辑层次
开始说滑动前,先要解析一下屏幕显示的原理。我们都知道屏幕最后呈现出来的画面,其实都是显存的数据,这个只有一份。也就是说最后用户看到的都是只有一张画面。如果你只是单纯按钮滑动,而背景不滑动,给人感觉是一个二维动画。
没错,逻辑上的确是二维的,我们在显示逻辑上可以划分多个逻辑层,最后组合成一个显示画面。
例如下面的结构体:
我这里区分了三个逻辑层
1、背景层
2、按钮层
3、时间控件层
这三个层次在逻辑上是分开的,最后需要显示的时候,才需要把他们组合起来,把画面绘画到兼容DC上,兼容DC再拷贝到屏幕DC上。这样才完成一次画面输出。这个有点想PhotoShop的图层,一张图片,由多个图层叠加完成。用过PS的人,应该很容易理解。
为了实现两个页面滑动切换,我增加了一个Page类,(界面类之间关系,可以查看上一篇文章)用来管理每个页面的按钮,下面列出Page类的类声明。
//只支持2行
#define ROW_NUM 2 //识别操作
#define DEL_BTN 0x10
#define ADD_BTN 0x11
#define SWITCH_BTN 0x12 class CDUIPage:public CDUIBase
{
public:
CDUIPage(void);
~CDUIPage(void); public:
//保存界面按钮的二维容器
vector<vector<CDUIButton *> > m_pVUICtrlContent; //保存界面按钮位置二维容器
vector<vector<CPoint> > m_pVUICtrlPos; //标记是否按钮滑动
//BOOL m_slideBtn; //标记是否滑动页面
//BOOL m_enterMouseMove; //点击了按钮
BOOL m_ClickBtn; //按下点击点
CPoint m_ClickDownPoint; //内存DC,保存滑动时候背景
CDC m_BackDC;//记录有多少方块(目前只支持两行)
int m_BlockNum[]; //点击的是大按钮还是小按钮,大按钮为True
BOOL m_BigBlock; //点击第几行按钮
int m_BlockLine; //点击第几个按钮
int m_BlockClickNum; //删除区域
CRect m_rcMainInterfaceDel;
//...............
public:
//初始化一个页面
void InitPage(CDC * pDC, HWND MainWnd); //画图
void Draw(CDC * pDC); //响应窗口OnLButtonDown
BOOL OnLButtonDown(POINT point); //响应窗口OnLButtonUp
void OnLButtonUp(POINT point); //响应窗口OnMouseMove
int OnMouseMove(POINT point, CDC * pDC, CDC * pBackDC); //处理按钮移动交换
int OnLButtonUpDeal(int Page, POINT point); //添加新的按钮
void AddItem(CDUIButton * btn, int lineNum); //重新计算按钮位置
void ReloadBtnPos(); //设置偏移量
void SetOffsetPoint(int point);//插入项
void InsertItem(CDUIButton * btn, int lineNum, int Pos);//按钮排序//删除释放空按钮
void ReleaseBtn(int Line, int index); //...............
};
从上面定义可以看出,这个Page类,其实主要作用就是管理Button类的,定义了一个二维向量容易,对应界面的二维布局,因为我那里界面屏幕分辨率相对比较固定。所以最多只能放两排按钮,所以最上面我定义了多少行现在。不过二维向量理论上没有限制多少行多少列。也就是说创建的所有CDUIButton对象都会被添加到二维向量里面,下面是添加的操作:
void CDUIPage::AddItem(CDUIButton * btn, int lineNum)
{
ASSERT(btn != NULL);
m_pVUICtrlContent.at(lineNum).push_back(btn);
//重新计算按钮位置
ReloadBtnPos();
}
lineNum表示是第几行的按钮,添加傲二维向量容器后,会根据按钮大小,计算出这个按钮的位置。按钮的位置都是动态排布的,所以没有按钮滑动的时候显示区域是动态变化的。其实这个就是把屏幕划分为一个二维格子,有点像棋盘,每个按钮就是一个棋子,放到对应的格子上面。只是Metro界面棋子大小不一样,需要做些特殊处理,其中一种棋子占用了两个格子。其实这种设计思维在现在的Android界面上也同样如此,Android的Launcher就是按照一个个格子来放按钮和widget。至于iPhone,没看过源码,不敢确定。不敢按照它界面排布,多半也是类似的思想。 2、按钮绘画
按钮绘画的时候,是调用的Page的Draw函数,来绘画。我们看看Draw函数内容:
void CDUIPage::Draw(CDC * pDC)
{
//把原来的背景DC拷贝到控件内部DC
m_BackDC.BitBlt(,,ScreenWidth,ScreenHeight, pDC, , , SRCCOPY); for (int outer=; outer<ROW_NUM; outer++)
{
int vectorNum = m_pVUICtrlContent.at(outer).size();
for (int k=; k<vectorNum; k++)
{
m_pVUICtrlContent.at(outer).at(k)->Draw(pDC);
}
}
}
Draw的代码其实很简单,就是调用了Page里面每个DUIButton的Draw函数,也就是说Page本身并没有提供绘画的功能,真正绘画显示按钮,是DUIButton类的功能。
DUIButton类绘画的功能也很简单,就是显示一张按钮的PNG图片。Draw(CDC * pDC)里面的DC指针其实就是指向内存兼容DC的指针。。目前可以理解为把所有按钮绘画到内存兼容DC上,而这个内容兼容DC其实已经绘画好了背景(这是我在上一层Container实现的内,这个后面会讲)。
3、界面滑动实现
界面滑动,就是两个Page对象之间的切换。下面是onMouseMove的执行代码:
int CDUIPage::OnMouseMove(POINT point, CDC * pDC, CDC * pBackDC)
{
for (int outer=; outer<ROW_NUM; outer++)
{
int vectorNum = m_pVUICtrlContent.at(outer).size();
for (int k=; k<vectorNum; k++)
{
m_pVUICtrlContent.at(outer).at(k)->OnMouseMove(point, pDC, pBackDC);
}
}
return TRUE;
}
同上面onDraw函数一样,MouseMove也是调用了DUIButton自身的MouseMove函数。具体代码可以查看上一篇文章。
因此Page类的作用只是用来管理Button,统一所有界面的操作。为上层提供统一的处理接口。对于最上层的Dialog来说,
是不需要知道下面的按钮是如何工作的。
今天就讲到这里,下一次会把Container和上层对接说明。有问题的朋友可以留意!
新建的讨论群,有兴趣可以加入
VC/Wince群:87053214
Edited by mythou
原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3161754.html
系列文章链接:
VC/Wince 实现仿Win8 Metro风格界面1——设计概述和自绘Button(附效果图)
VC/Wince 实现仿Win8 Metro风格界面2——页面滑动切换(附效果图)的更多相关文章
- VC/Wince 实现仿Win8 Metro风格界面1——设计概述和自绘Button(附效果图)
去年用VC做了一个仿Win8 Metro风格的界面,感觉挺有意思,最近打算把实现过程和一些技术原理记录下来. 主要是风格上类似Win8,其实功能上很多借鉴了Android的操作方式.界面只支持两种大小 ...
- VC/Wince 实现仿Win8 Metro风格界面3——按钮移动交换、删除、添加快捷方式(附效果图)
上一篇文章写了如何进行页面滑动切换,今天我讲一下如何实现两个按钮拖动交换位置,包括同一个页面按钮交换或者两个页面之间的按钮交换.另外就是如何拖动删除界面上的快捷方式.按钮交换和拖动删除,这两个功能基本 ...
- Win8 Metro风格的Web桌面HteOS
前言 曾经天天折腾ExtJS,折腾累了.近期这段时间開始用jquery来做一些东西,发现还是蛮有意思的.可是做到最后才发现,原来做好设计真的很重要. 上图就是HteOS项目的截图,眼下正在开发 ...
- android仿win8 metro磁贴布局
代码下载 //更新代码, 这里是更新后的代码 //////////////////////// 1,含一个图片无限滚动的控件,自己实现的 2.可新增删除每个磁贴 3.来个图片吧 ////* ...
- windows8开发-关于wp7应用迁移到win8 metro风格
虽然微软说,wp7应用移植到win8上面是比较简单,只需要修改部分API和设计原则上的细节,同时它也提供了一份比较简洁的参考文档: 而实际上这种移植的工作量还是不小的,尤其当应用引用了较多底层的API ...
- 如何完美打造Win8 Metro版IE10浏览器页面(转)
Windows8 内置两种 Internet Explorer 10 (以下简称 IE10),一个是在桌面环境下使用的 IE10:视窗操作.可以支持各种插件(ActiveX):而另外一个则是在新的开始 ...
- Android 仿Win8的metro的UI界面(上)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23441455 昨晚没事手机下载了一些APP,发现现在仿win8的主界面越来越多, ...
- devexpress实现模仿Win8桌面metro风格
1.devexpress强大的控件库,可很容易的实现Win8桌面metro风格.使用的TileControl控件,拖动与Win效果相同.所有图片均来自网络资源.每个块也可实现如图所示的四种大小,如何实 ...
- 仿win8磁贴界面以及功能
做移动产品界面占很大的一部分,同时也是决定一款产品好的的重要因素,最近看见有人放win8的界面效果,搜了两款,一款是只是仿界面没有特效,另一款是自定义组件能够实现反转效果,今天分析一下这两类界面. 仿 ...
随机推荐
- MyBatis---使用MyBatis Generator生成Dto、Dao、Mapping
由于MyBatis属于一种半自动的ORM框架,所以主要的工作将是书写Mapping映射文件,但是由于手写映射文件很容易出错,所以查资料发现有现成的工具可以自动生成底层模型类.Dao接口类甚至Mappi ...
- ASP.NET MVC同时支持web与webapi模式
原文地址:https://blog.csdn.net/laymat/article/details/65444701 我们在创建 web mvc项目时是不支持web api的接口方式访问的,所以我们需 ...
- python学习笔记——爬虫学习中的重要库urllib
1 urllib概述 1.1 urllib库中的模块类型 urllib是python内置的http请求库 其提供了如下功能: (1)error 异常处理模块 (2)parse url解析模块 (3)r ...
- Android Logcat信息级别解读
Android Logcat信息级别解读 Logcat信息分为好几个级别,分别是:Assert(断言).Debug(调试).Error(错误).Info(信息).Verbose(详细).Warning ...
- JDK1.5新特性,基础类库篇,XML增强
Document Object Model (DOM) Level 3 文件对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口.DO ...
- 腾讯云服务器 离线安装最新稳定版MariaDB 10.2.6
数据库方面我们一般都是使用mysql,由于前段时间我们切换到了MariaDB后,当然生产环境也要更着变,谁叫oracle是个碧池呢! mariaDB主要有三种安装方式 源码安装,有点繁琐,不推荐 yu ...
- 菜鸟学SSH(十三)——Spring容器IOC解析及简单实现
最近一段时间,“容器”两个字一直萦绕在我的耳边,甚至是吃饭.睡觉的时候都在我脑子里蹦来蹦去的.随着这些天一次次的交流.讨论,对于容器的理解也逐渐加深.理论上的东西终归要落实到实践,今天就借助Sprin ...
- 菜鸟学SSH(五)——Struts2上传文件
上传文件在一个系统当中是一个很常用的功能,也是一个比较重要的功能.今天我们就一起来学习一下Struts2如何上传文件. 今天讲的上传文件的方式有三种: 1,以字节为单位传输文件: 2,Struts2封 ...
- Nexus 搭建maven 私有仓库
nexus如果没有私服,我们所需的所有构件都需要通过maven的中央仓库和第三方的Maven仓库下载到本地,而一个团队中的所有人都重复的从maven仓库下载构件无疑加大了仓库的负载和浪费了外网带宽,如 ...
- 不忘初心,回归本质 .net core
static void Main(string[] args) { ; object j = i;//装箱 就是把值类型转换成引用类型 int k = (int)j;//拆箱 就是把引用类型转换成值类 ...