上一篇文章写了如何进行页面滑动切换,今天我讲一下如何实现两个按钮拖动交换位置,包括同一个页面按钮交换或者两个页面之间的按钮交换。另外就是如何拖动删除界面上的快捷方式。按钮交换和拖动删除,这两个功能基本上是现在智能手机的标准功能,不管是IOS或者Android都有类似功能。我实现的功能,主要是参考Android的功能实现。

下面这个就是动态交换按钮效果图:

还是先把逻辑关系图放出来:

1、按钮拖动

怎么样才能实现拖动一个按钮到另外一个按钮位置上,实现交换?这个首先一个需要做的就是拖动按钮的操作。按钮拖动我放到封装的DUIButton里面实现。下面我们看看DUIButton里面如何把按钮拖动出来。

  1.  
  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1. int CDUIButton::OnMouseMove(POINT point, CDC * pDC, CDC * backDC)
  2. {
      //printf("mythou------->enter the Page::omMouseMove");
      //判断拖动的条件,按下按钮并且移动的距离大于30像素的时候,认为是拖动按钮
  3. if( abs(point.x - m_iEndSlide) > || abs(m_clickY - point.y) > || m_mouseMove)//拖动快捷键
  4. {
  5. if(m_ClickState)
  6. {
  7. m_mouseMove = TRUE;
  8. CRect rect = CRect(, , ScreenWidth, ScreenHeight);
  9.        //恢复保存的背景,主要是提高绘画效率
  10. CDC destDC;
  11. destDC.CreateCompatibleDC(backDC);
  12. CBitmap CompatibleBmp;
  13. CompatibleBmp.CreateCompatibleBitmap(backDC,rect.Width(),rect.Height());
  14. CBitmap *pOlddestBmp = destDC.SelectObject(&CompatibleBmp);
  15. destDC.FillSolidRect(&rect,RGB(,,));
  16. CDC srcDC;
  17. srcDC.CreateCompatibleDC(backDC);
  18. HBITMAP hOldBmp;
  19. destDC.BitBlt(, , rect.Width(),rect.Height(), backDC, , , SRCCOPY);
  20.        //根据用户手指移动的位置,动态刷新按钮,形成按钮跟谁手指移动的效果
  21. hOldBmp = (HBITMAP)srcDC.SelectObject(m_btnHBitmap);
  22. m_pngCtrl.BiltPNG(&destDC,&srcDC,(point.x-(m_btnRc.Width()/) ),
  23. (point.y-(m_btnRc.Height()/)), m_btnRc.Width(),m_btnRc.Height(), m_AlphaSel);
  24. srcDC.SelectObject(hOldBmp);
  25.        //把按钮图片,绘画到屏幕
  26. pDC->BitBlt(,,rect.Width(),rect.Height(),&destDC,,,SRCCOPY);
  27.  
  28. srcDC.DeleteDC();
  29. destDC.SelectObject(pOlddestBmp);
  30. CompatibleBmp.DeleteObject();
  31. destDC.DeleteDC();
  32. return ;
  33. }
  34. }
  35. return ;
  36. }
    //http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  从这里可以发现,其实拖动一个按钮,就是把该按钮的图片,跟随手指的移动而动态贴图。需要注意的是如何才能保证拖动的流畅性。这个需要把你的背景图做成缓存,保留下来,拖动过程中,都是使用缓存中原始的背景图。这样每次拖动,只需要绘画一个按钮的图片,才能流畅得拖动按钮。

  另外你手指点击按钮还需要做一些条件判断,需要符合条件的情况下,才能拖动按钮。我这里把手指触摸按钮分为3种行为:

  • 点击按钮,打开某个程序
  • 触摸按钮,滑动切换页面
  • 把按钮拖动出来,执行交换、删除、添加操作

这几个也是目前智能机系统一般都支持的手势操作,上面我们按钮的拖动,就是属于第三种情况。

 2、按钮交换

把按钮拖动出来,然后拖动到需要交换的按钮的位置,释放按钮,执行交换操作。这个就是交换的流程,这里根据释放的位置来识别到底跟哪一个按钮进行交换。

  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1. //大按钮移动到大按钮位置 Edited by mythou
  2. if (UpBlockBig)
  3. {
           //printf("mythou-------->enter change the big block"); 
  4. CDUIButton * tempDUIBtn;
  5. tempDUIBtn = m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum);
  6. //保存IDS
  7. CString FirstBtnIDS = tempDUIBtn->GetBtnIDS();
  8. m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum)
  9. = m_pVUICtrlContent.at(Line).at(vectorBtnIndex);
  10. //保存IDS
  11. CString SecondBtnIDS = m_pVUICtrlContent.at(Line).at(vectorBtnIndex)->GetBtnIDS();
  12. m_pVUICtrlContent.at(Line).at(vectorBtnIndex) = tempDUIBtn;
  13.  
  14. //动画效果
  15. ChangeBtnPosAni(m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum),
  16. m_pVUICtrlContent.at(Line).at(vectorBtnIndex));
  17.  
  18. //修改配置文件
  19. int PosIndex1 = GetBtnPos(m_BlockLine,m_BlockClickNum);
  20. int PosIndex2 = GetBtnPos(Line,vectorBtnIndex);
  21. m_pSaveInterFace->SwitchSameButton(Page,m_BlockLine,PosIndex1,FirstBtnIDS,
  22. Page,Line,PosIndex2,SecondBtnIDS);
  23. }
  1. //http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  这是一个简单的交换逻辑,因为我们的按钮都是存放在Page类里面的二维Vector向量里面,按钮交换位置也就是交换Vector里面的值。因为Vector里面存放只是按钮对象的指针应用。因此,Vector交换两个指针也不会存在负责的数据交互。当然如果要做出比较好的交换效果,我们免不了使用动画,交换过程中。我们加入一个动画效果,我这里做的是一个淡入淡出的效果,主要控制按钮图片的Alpha值,形成一个较好的交换效果。最后还需要把交换的位置信息记录到文件里面,方便下次启动程序的时候,保存交换后的效果。需要注意的是交换按钮刷新和动画效果之间的操作。要做到流程,考虑使用一个线程运行动画。

 3、拖动删除按钮

  这个功能其实就是参照Android的删除快捷方式做的。当按钮被拉动出来后,界面上方会出现一个有垃圾桶图标的区域,把按钮拖动到该区域释放,就可以把相对的快捷方式删除。下面我们看看逻辑上如何实现。

  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1. //在删除区域释放,删除按钮
  2. if (m_rcMainInterfaceDel.PtInRect(point))
  3. {
  4. //printf("\n mythou------> Enter OnLButtonUpDeal() Delete the Btn ************** \n");
  5. //删除选中按钮
  6. CString DelBtnIDS = m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum)->GetBtnIDS();
  7. m_pVUICtrlContent.at(m_BlockLine).at(m_BlockClickNum)->ResetAllClickFlag();
  8. m_pVUICtrlContent.at(m_BlockLine).erase(m_pVUICtrlContent.at(m_BlockLine).begin()+m_BlockClickNum);
  9. //填充空按钮
  10. CDUIButton *pBtn = new CDUIButton();
  11. pBtn->SetNullBtn();
  12. m_pVUICtrlContent.at(m_BlockLine).insert((m_pVUICtrlContent.at(m_BlockLine).begin()+m_BlockClickNum),pBtn);
  13. //如果是大按钮,再填充一次
  14. if (m_BigBlock)
  15. {
  16. CDUIButton *pBtn = new CDUIButton();
  17. pBtn->SetNullBtn();
  18. m_pVUICtrlPos.at(m_BlockLine).push_back(CPoint(,));
  19. m_pVUICtrlContent.at(m_BlockLine).insert((m_pVUICtrlContent.at(m_BlockLine).begin()+m_BlockClickNum),pBtn);
  20. }
  21.  
  22. //修改配置文件
  23. int PosIndex1 = GetBtnPos(m_BlockLine,m_BlockClickNum);
  24. m_pSaveInterFace->DeleteButton(Page,m_BlockLine,PosIndex1,DelBtnIDS,m_BigBlock);
  25. //DeleteButton(Page,m_BlockLine,PosIndex1,DelBtnIDS,m_BigBlock);
  26.  
  27. m_BigBlock = FALSE;
  28. ReloadBtnPos();
  29. return DEL_BTN;
  30. }
  1. //http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  删除操作在逻辑上也很简单,就是删除我们记录的Vector里面的相对应的按钮指针。不过删除后,我们需要做一些额外的操作。第一需要填充一个空按钮指针到原来的位置。这个操作主要是用来记录界面上哪些位置是可以存放按钮和交换按钮。空按钮是一个空类,只有一个标记用来记录位置。删除后还需要针对按钮的类型做不同的添加操作,大按钮和小按钮。。最后还需要在配置文件做记录,记录哪个按钮删除了。如果需要一个好的效果,可以类似交换按钮一样,加入一个动画效果。

4、添加快捷方式栏

这是额外做的一个功能,主要是把常用的功能加入到一个导航栏上面,可以在任何界面使用相关常用功能。

  1.  
  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1. void CDUIPage::Send2TaskBar(CDUIButton *pBtn)
  2. {
  3. printf("\n mythou-------->Enter Send2TaskBar ********************************\n");
  4. DUIButtonData *pDuiData = new DUIButtonData();
  5.  
  6. //拷贝数据
  7. wcscpy(pDuiData->name, pBtn->m_btnName.GetBuffer(pBtn->m_btnName.GetLength()));
  8. pBtn->m_btnName.ReleaseBuffer();
  9. wcscpy(pDuiData->cmd, pBtn->m_BtnClickCMD.GetBuffer(pBtn->m_BtnClickCMD.GetLength()));
  10. pBtn->m_BtnClickCMD.ReleaseBuffer();
  11. wcscpy(pDuiData->animate, pBtn->m_AnimateType.GetBuffer(pBtn->m_AnimateType.GetLength()));
  12. pBtn->m_AnimateType.ReleaseBuffer();
  13. wcscpy(pDuiData->ids, pBtn->m_BtnNameIDS.GetBuffer(pBtn->m_BtnNameIDS.GetLength()));
  14. pBtn->m_BtnNameIDS.ReleaseBuffer();
  15. CString btnPicName = GetExeName(pBtn->m_btnPic);
  16. wcscpy(pDuiData->picName, btnPicName.GetBuffer(btnPicName.GetLength()));
  17. btnPicName.ReleaseBuffer();
  18.  
  19. COPYDATASTRUCT cpdata;
  20. cpdata.dwData=PROCESSID
  21. cpdata.cbData = sizeof(DUIButtonData);
  22. cpdata.lpData = (PVOID)pDuiData;
  23. HWND mainWnd = ::FindWindow(NULL,_T("APKTaskBar"));
  24.  
  25. if (!mainWnd)
  26. {
  27. return;
  28. }
  29.  
  30. printf("\n mythou------->Send the OnCopyData Send2TaskBar ********************************");
  31.  
  32. ::SendMessage(mainWnd, WM_COPYDATA, (WPARAM)m_MainWndH, (LPARAM)&cpdata);
  33.  
  34. delete pDuiData;
  35. }
  1. //http://www.cnblogs.com/mythou/p/3172707.html Edited by mythou

  因为我的快捷栏是另外一个独立程序,所以这里把需要添加的按钮拉动到界面底部,然后把按钮的相关数据转换为相关数据包,发送到快捷栏程序里面。这里也需要加入相关的动画效果,才能达到较好的界面交互效果。剩下的就是另外一个程序处理发送过来的数据包。解析然后显示出来就好了。

  今天主要是讲解界面上常用的交换按钮、删除按钮、添加快捷栏等操作。其中交换按钮这里只是把同页面的交换做了解说,除了同页面交换外,也需要做到不同页面之间交换,这个原理是一样,只是不同页面之间交换需要做到逻辑页面的切换。这个也是我做了Page类作为页面管理类的原因。不同类之间交换按钮,只要切换Page类就好了。。。

Edited by mythou

原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3172707.html

VC/Wince 实现仿Win8 Metro风格界面3——按钮移动交换、删除、添加快捷方式(附效果图)的更多相关文章

  1. VC/Wince 实现仿Win8 Metro风格界面1——设计概述和自绘Button(附效果图)

    去年用VC做了一个仿Win8 Metro风格的界面,感觉挺有意思,最近打算把实现过程和一些技术原理记录下来. 主要是风格上类似Win8,其实功能上很多借鉴了Android的操作方式.界面只支持两种大小 ...

  2. VC/Wince 实现仿Win8 Metro风格界面2——页面滑动切换(附效果图)

    前几天开始写仿Win8 Metro界面文章,部分网友觉得不错,感谢各位的意见.本来今天一直在折腾Android VLC播放器,没时间写.不过明天休息,所以今天就抽时间先写一下. 言归正传,我们都知道W ...

  3. Win8 Metro风格的Web桌面HteOS

    前言     曾经天天折腾ExtJS,折腾累了.近期这段时间開始用jquery来做一些东西,发现还是蛮有意思的.可是做到最后才发现,原来做好设计真的很重要. 上图就是HteOS项目的截图,眼下正在开发 ...

  4. cino伟斯 A770键盘界面快速设定记录后缀删除添加换行回车操作方法

    http://www.cinoscan.com/upload/2016063033256485.pdf cino A770键盘界面快速设定记录后缀删除添加换行回车操作方法

  5. android仿win8 metro磁贴布局

    代码下载     //更新代码,   这里是更新后的代码 //////////////////////// 1,含一个图片无限滚动的控件,自己实现的 2.可新增删除每个磁贴 3.来个图片吧 ////* ...

  6. windows8开发-关于wp7应用迁移到win8 metro风格

    虽然微软说,wp7应用移植到win8上面是比较简单,只需要修改部分API和设计原则上的细节,同时它也提供了一份比较简洁的参考文档: 而实际上这种移植的工作量还是不小的,尤其当应用引用了较多底层的API ...

  7. Android 仿Win8的metro的UI界面(上)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23441455 昨晚没事手机下载了一些APP,发现现在仿win8的主界面越来越多, ...

  8. devexpress实现模仿Win8桌面metro风格

    1.devexpress强大的控件库,可很容易的实现Win8桌面metro风格.使用的TileControl控件,拖动与Win效果相同.所有图片均来自网络资源.每个块也可实现如图所示的四种大小,如何实 ...

  9. 仿win8磁贴界面以及功能

    做移动产品界面占很大的一部分,同时也是决定一款产品好的的重要因素,最近看见有人放win8的界面效果,搜了两款,一款是只是仿界面没有特效,另一款是自定义组件能够实现反转效果,今天分析一下这两类界面. 仿 ...

随机推荐

  1. Android 首页图片轮播

    1.网络上的的一个框架,已经在github 上开源 github  : https://github.com/gcgongchao/flashview 相关博客 : http://www.eoeand ...

  2. 根据包名字符串跳转Activity

    /** * 跳转到对应activity */ public void toActivity(Context context,String fullName) { if (className != nu ...

  3. Xcode 编译运行报错: CpResource /user/xxxx/ xxx Directory not empty

    之前遇到过相同的问题,总是记吃不记打,踩过的坑后面还会踩进去... 仅以次标记加深一下印象 错误特征RT 确认该类型错误是library或frameWork的search路径问题 首先找到编译错误的路 ...

  4. IOS 杂笔-18 (let 与 var)

    var 是 variable的缩写形式,是变量的意思 ,是可改变的,并不是数据类型. let 是常量的意思,不可改变的.

  5. iOS 视频选择压缩

    //原理,还是调用UIImagePickerController控制器,设置Type为视频 #import "ViewController.h" #import <AVFou ...

  6. Android 启动过程简析

    首先我们先来看android构架图: android系统是构建在linux系统上面的. 所以android设备启动经历3个过程. Boot Loader,Linux Kernel & Andr ...

  7. office2010安装报错

    有没有童鞋,在第一次安装office 2010的时候,中途不管是何原因导致中断或者未安装成功的 然后从第二次开始就一直安装报错??? 哈哈,我最近就遇到了 其他很简单,网上有很多方法,也有很多步骤,包 ...

  8. 网络编程1--毕向东java基础教程视频学习笔记

    目录: 01 网络编程概述1 02 网络编程概述2 03网络编程 网络模型 04网络编程 IP地址 05网络编程 TCP和UDP 06网络编程 Socket 07网络编程 UDP发送端 01 网络编程 ...

  9. mysql ---复制表结构---创建新表

    1.复制表结构及数据到新表CREATE TABLE 新表SELECT * FROM 旧表这种方法会将oldtable中所有的内容都拷贝过来,当然我们可以用delete from newtable;来删 ...

  10. centOS 6.5下升级mysql,从5.1升级到5.7

    1.备份数据库,升级MySQL通常不会丢失数据,但保险起见,我们需要做这一步.输入命令: mysqldump -u xxx -h xxx -P 3306 -p --all-databases > ...