VC/Wince 實現仿Win8 Metro風格界面2——頁面滑動切換(附效果圖)

前幾天開始寫仿Win8 Metro界面文章,部分網友以爲不錯,感謝各位的意見。原本今天一直在折騰Android VLC播放器,沒時間寫。不過明天休息,因此今天就抽時間先寫一下。html

言歸正傳,咱們都知道Win8的Metro界面只要手指一劃,頁面就跟着滑動(準確來講是按鈕跟着滑動,背景其實沒動),這個操做目前的Android和iPhone都是這種操做,我的感受都是從iPhone借鑑來,滑動切換很早就有,不過按鈕和壁紙分開滑動,這個仍是iPhone時代開始。ide

(這效果圖是截了幾張圖弄的,因此看上去不流暢)函數

類邏輯關係圖佈局

一、界面邏輯層次post

開始說滑動前,先要解析一下屏幕顯示的原理。咱們都知道屏幕最後呈現出來的畫面,其實都是顯存的數據,這個只有一份。也就是說最後用戶看到的都是隻有一張畫面。若是你只是單純按鈕滑動,而背景不滑動,給人感受是一個二維動畫。動畫

沒錯,邏輯上的確是二維的,咱們在顯示邏輯上能夠劃分多個邏輯層,最後組合成一個顯示畫面。url

例以下面的結構體:spa

 

 

 

 

 

 

 

 

 

 

 

 

 

我這裏區分了三個邏輯層設計

一、背景層指針

二、按鈕層

三、時間控件層

這三個層次在邏輯上是分開的,最後須要顯示的時候,才須要把他們組合起來,把畫面繪畫到兼容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,沒看過源碼,不敢肯定。不敢按照它界面排布,多半也是相似的思想。

二、按鈕繪畫
按鈕繪畫的時候,是調用的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實現的內,這個後面會講)。

 

三、界面滑動實現

 界面滑動,就是兩個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(附效果圖)

相關文章
相關標籤/搜索