VC/Wince 實現仿Win8 Metro風格界面3——按鈕移動交換、刪除、添加快捷方式(附效果圖)


  上一篇文章寫了如何進行頁面滑動切換,今天我講一下如何實現兩個按鈕拖動交換位置,包括同一個頁面按鈕交換或者兩個頁面之間的按鈕交換。另外就是如何拖動刪除界面上的快捷方式。按鈕交換和拖動刪除,這兩個功能基本上是現在智能手機的標准功能,不管是IOS或者Android都有類似功能。我實現的功能,主要是參考Android的功能實現。

下面這個就是動態交換按鈕效果圖:

 

 

還是先把邏輯關系圖放出來:

 

1、按鈕拖動

怎么樣才能實現拖動一個按鈕到另外一個按鈕位置上,實現交換?這個首先一個需要做的就是拖動按鈕的操作。按鈕拖動我放到封裝的DUIButton里面實現。下面我們看看DUIButton里面如何把按鈕拖動出來。

 
         
//Edited by mythou
//http://www.cnblogs.com/mythou/
int CDUIButton::OnMouseMove(POINT point, CDC * pDC, CDC * backDC)
{
  //printf("mythou------->enter the Page::omMouseMove");
  //判斷拖動的條件,按下按鈕並且移動的距離大於30像素的時候,認為是拖動按鈕 if( abs(point.x - m_iEndSlide) > 30 || abs(m_clickY - point.y) > 30 || m_mouseMove)//拖動快捷鍵 { if(m_ClickState) { m_mouseMove = TRUE; CRect rect = CRect(0, 0, ScreenWidth, ScreenHeight);        //恢復保存的背景,主要是提高繪畫效率 CDC destDC; destDC.CreateCompatibleDC(backDC); CBitmap CompatibleBmp; CompatibleBmp.CreateCompatibleBitmap(backDC,rect.Width(),rect.Height()); CBitmap *pOlddestBmp = destDC.SelectObject(&CompatibleBmp); destDC.FillSolidRect(&rect,RGB(0,0,0)); CDC srcDC; srcDC.CreateCompatibleDC(backDC); HBITMAP hOldBmp; destDC.BitBlt(0, 0, rect.Width(),rect.Height(), backDC, 0, 0, SRCCOPY);        //根據用戶手指移動的位置,動態刷新按鈕,形成按鈕跟誰手指移動的效果 hOldBmp = (HBITMAP)srcDC.SelectObject(m_btnHBitmap); m_pngCtrl.BiltPNG(&destDC,&srcDC,(point.x-(m_btnRc.Width()/2) ), (point.y-(m_btnRc.Height()/2)), m_btnRc.Width(),m_btnRc.Height(), m_AlphaSel); srcDC.SelectObject(hOldBmp);        //把按鈕圖片,繪畫到屏幕 pDC->BitBlt(0,0,rect.Width(),rect.Height(),&destDC,0,0,SRCCOPY); srcDC.DeleteDC(); destDC.SelectObject(pOlddestBmp); CompatibleBmp.DeleteObject(); destDC.DeleteDC(); return 1; } } return 0; }
//http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  從這里可以發現,其實拖動一個按鈕,就是把該按鈕的圖片,跟隨手指的移動而動態貼圖。需要注意的是如何才能保證拖動的流暢性。這個需要把你的背景圖做成緩存,保留下來,拖動過程中,都是使用緩存中原始的背景圖。這樣每次拖動,只需要繪畫一個按鈕的圖片,才能流暢得拖動按鈕。

  另外你手指點擊按鈕還需要做一些條件判斷,需要符合條件的情況下,才能拖動按鈕。我這里把手指觸摸按鈕分為3種行為:

  • 點擊按鈕,打開某個程序
  • 觸摸按鈕,滑動切換頁面
  • 把按鈕拖動出來,執行交換、刪除、添加操作

這幾個也是目前智能機系統一般都支持的手勢操作,上面我們按鈕的拖動,就是屬於第三種情況。

 

 2、按鈕交換

把按鈕拖動出來,然后拖動到需要交換的按鈕的位置,釋放按鈕,執行交換操作。這個就是交換的流程,這里根據釋放的位置來識別到底跟哪一個按鈕進行交換。

//Edited by mythou
//http://www.cnblogs.com/mythou/
   //大按鈕移動到大按鈕位置 Edited by mythou
        if (UpBlockBig)
        {
       //printf("mythou-------->enter change the big block");  CDUIButton
* tempDUIBtn; tempDUIBtn = m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum); //保存IDS CString FirstBtnIDS = tempDUIBtn->GetBtnIDS(); m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum) = m_pVUICtrlContent.at(Line).at(vectorBtnIndex); //保存IDS CString SecondBtnIDS = m_pVUICtrlContent.at(Line).at(vectorBtnIndex)->GetBtnIDS(); m_pVUICtrlContent.at(Line).at(vectorBtnIndex) = tempDUIBtn; //動畫效果 ChangeBtnPosAni(m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum), m_pVUICtrlContent.at(Line).at(vectorBtnIndex)); //修改配置文件 int PosIndex1 = GetBtnPos(m_BlockLine,m_BlockClickNum); int PosIndex2 = GetBtnPos(Line,vectorBtnIndex); m_pSaveInterFace->SwitchSameButton(Page,m_BlockLine,PosIndex1,FirstBtnIDS, Page,Line,PosIndex2,SecondBtnIDS); }
//http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  這是一個簡單的交換邏輯,因為我們的按鈕都是存放在Page類里面的二維Vector向量里面,按鈕交換位置也就是交換Vector里面的值。因為Vector里面存放只是按鈕對象的指針應用。因此,Vector交換兩個指針也不會存在負責的數據交互。當然如果要做出比較好的交換效果,我們免不了使用動畫,交換過程中。我們加入一個動畫效果,我這里做的是一個淡入淡出的效果,主要控制按鈕圖片的Alpha值,形成一個較好的交換效果。最后還需要把交換的位置信息記錄到文件里面,方便下次啟動程序的時候,保存交換后的效果。需要注意的是交換按鈕刷新和動畫效果之間的操作。要做到流程,考慮使用一個線程運行動畫。

 

 3、拖動刪除按鈕

  這個功能其實就是參照Android的刪除快捷方式做的。當按鈕被拉動出來后,界面上方會出現一個有垃圾桶圖標的區域,把按鈕拖動到該區域釋放,就可以把相對的快捷方式刪除。下面我們看看邏輯上如何實現。

//Edited by mythou
//http://www.cnblogs.com/mythou/
 //在刪除區域釋放,刪除按鈕
    if (m_rcMainInterfaceDel.PtInRect(point))
    {
        //printf("\n mythou------> Enter OnLButtonUpDeal() Delete the Btn ************** \n"); //刪除選中按鈕
        CString DelBtnIDS = m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum)->GetBtnIDS();
        m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum)->ResetAllClickFlag();
        m_pVUICtrlContent.at(m_BlockLine).erase(m_pVUICtrlContent.at(m_BlockLine).begin()+m_BlockClickNum);
        //填充空按鈕
        CDUIButton *pBtn = new CDUIButton();
        pBtn->SetNullBtn();
        m_pVUICtrlContent.at(m_BlockLine).insert((m_pVUICtrlContent.at(m_BlockLine).begin()+m_BlockClickNum),pBtn);
        //如果是大按鈕,再填充一次
        if (m_BigBlock)
        {
            CDUIButton *pBtn = new CDUIButton();
            pBtn->SetNullBtn();
            m_pVUICtrlPos.at(m_BlockLine).push_back(CPoint(0,0));
            m_pVUICtrlContent.at(m_BlockLine).insert((m_pVUICtrlContent.at(m_BlockLine).begin()+m_BlockClickNum),pBtn);
        }

        //修改配置文件
        int PosIndex1 = GetBtnPos(m_BlockLine,m_BlockClickNum);
        m_pSaveInterFace->DeleteButton(Page,m_BlockLine,PosIndex1,DelBtnIDS,m_BigBlock);
        //DeleteButton(Page,m_BlockLine,PosIndex1,DelBtnIDS,m_BigBlock);

        m_BigBlock = FALSE;
        ReloadBtnPos();
        return DEL_BTN;
    }
//http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  刪除操作在邏輯上也很簡單,就是刪除我們記錄的Vector里面的相對應的按鈕指針。不過刪除后,我們需要做一些額外的操作。第一需要填充一個空按鈕指針到原來的位置。這個操作主要是用來記錄界面上哪些位置是可以存放按鈕和交換按鈕。空按鈕是一個空類,只有一個標記用來記錄位置。刪除后還需要針對按鈕的類型做不同的添加操作,大按鈕和小按鈕。。最后還需要在配置文件做記錄,記錄哪個按鈕刪除了。如果需要一個好的效果,可以類似交換按鈕一樣,加入一個動畫效果。

 

4、添加快捷方式欄

這是額外做的一個功能,主要是把常用的功能加入到一個導航欄上面,可以在任何界面使用相關常用功能。

 
         
//Edited by mythou
//http://www.cnblogs.com/mythou/
void CDUIPage::Send2TaskBar(CDUIButton *pBtn)
{
    printf("\n mythou-------->Enter Send2TaskBar ********************************\n");
    DUIButtonData *pDuiData = new DUIButtonData();

    //拷貝數據
    wcscpy(pDuiData->name, pBtn->m_btnName.GetBuffer(pBtn->m_btnName.GetLength()));
    pBtn->m_btnName.ReleaseBuffer();
    wcscpy(pDuiData->cmd, pBtn->m_BtnClickCMD.GetBuffer(pBtn->m_BtnClickCMD.GetLength()));
    pBtn->m_BtnClickCMD.ReleaseBuffer();
    wcscpy(pDuiData->animate, pBtn->m_AnimateType.GetBuffer(pBtn->m_AnimateType.GetLength()));
    pBtn->m_AnimateType.ReleaseBuffer();
    wcscpy(pDuiData->ids, pBtn->m_BtnNameIDS.GetBuffer(pBtn->m_BtnNameIDS.GetLength()));
    pBtn->m_BtnNameIDS.ReleaseBuffer();
    CString btnPicName = GetExeName(pBtn->m_btnPic);
    wcscpy(pDuiData->picName, btnPicName.GetBuffer(btnPicName.GetLength()));
    btnPicName.ReleaseBuffer();

    COPYDATASTRUCT cpdata;
    cpdata.dwData=PROCESSID
    cpdata.cbData = sizeof(DUIButtonData);
    cpdata.lpData = (PVOID)pDuiData;
    HWND mainWnd = ::FindWindow(NULL,_T("APKTaskBar"));

    if (!mainWnd)
    {
        return;
    }

    printf("\n mythou------->Send the OnCopyData Send2TaskBar ********************************");

    ::SendMessage(mainWnd, WM_COPYDATA, (WPARAM)m_MainWndH, (LPARAM)&cpdata);

    delete pDuiData;
}
//http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  因為我的快捷欄是另外一個獨立程序,所以這里把需要添加的按鈕拉動到界面底部,然后把按鈕的相關數據轉換為相關數據包,發送到快捷欄程序里面。這里也需要加入相關的動畫效果,才能達到較好的界面交互效果。剩下的就是另外一個程序處理發送過來的數據包。解析然后顯示出來就好了。

  今天主要是講解界面上常用的交換按鈕、刪除按鈕、添加快捷欄等操作。其中交換按鈕這里只是把同頁面的交換做了解說,除了同頁面交換外,也需要做到不同頁面之間交換,這個原理是一樣,只是不同頁面之間交換需要做到邏輯頁面的切換。這個也是我做了Page類作為頁面管理類的原因。不同類之間交換按鈕,只要切換Page類就好了。。。

 

Edited by mythou

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3172707.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM