zoukankan      html  css  js  c++  java
  • 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[2];
    
        //点击的是大按钮还是小按钮,大按钮为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(0,0,ScreenWidth,ScreenHeight, pDC, 0, 0, SRCCOPY);
    
        for (int outer=0; outer<ROW_NUM; outer++)
        {
            int vectorNum = m_pVUICtrlContent.at(outer).size();
            for (int k=0; 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=0; outer<ROW_NUM; outer++)
        {
            int vectorNum = m_pVUICtrlContent.at(outer).size();
            for (int k=0; 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(附效果图)

  • 相关阅读:
    二进制安全(学习笔记)
    rsa
    bugku 隐写 笔记
    dvwa随学笔记
    实验吧 密码学 writeup
    实验吧 隐写 writeup
    实验吧 web题weiteup
    Java数据结构和算法 第二版 课后习题第三章
    自动化测试入门指南(3)-- 入门demo
    自动化测试入门指南(2)-- 环境搭建
  • 原文地址:https://www.cnblogs.com/mythou/p/3161754.html
Copyright © 2011-2022 走看看