MFC 实现图片的拖拽功能,代码很详细,贴过去就能用!
2014-04-14 00:17
561 查看
拖动是界面编程频繁使用的一个效果,在windows系统下可谓大行其道。纵观时下的应用软件几乎各个都支持各种各样拖动的效果,windows7更是把拖动做到了极致。其实说起来拖动的实现也很简单,对于有句柄的对象都可以通过MoveWindow或SetWindowPos实现位置变动,而没有句柄的对象实现拖动无非就是做些参数修改,说到底实现拖动就是在OnLButtonDown、OnMouseMove和OnLButtonUp中处理数据,当然你可以使用鼠标右键甚至中建消息来实现,基本原理是一样的。
基本原理是不难,不过要想做到效果二字就要动一番脑筋了。让我们来看看win7下的图标拖放,鼠标会拖起一个半透明的图标副本到你想要的位置,透过这个透明的图标你可以看到其下面的情况,这样的效果其实在windows的早期版本就已经实现了,它有着很好的用户体验。那么我们能不能轻松的实现类似的拖动效果呢?答案当然是肯定的!最近看到论坛里几个讨论拖动的帖子,正巧前一段时间自己也做了一些相关的工作,小研究了一下,于是就想把研究成果拿出来和大家分享,这样才有利于交流和进步嘛。以前我写博客没贴过效果图,以至于很多网友下载示例代码之后发现不是自己想要的东西,这个确实不好,在此我向大家表示歉意。这次把效果图贴上,如果觉得这个效果很一般或者不是你所需要的那就不要浪费你宝贵的时间阅读文章和下载代码了。
从图中可以看出,我的小猪头像是可以被拖动的,半透明的那个就是拖动的副本,截图的时候鼠标没有截到,呵呵。为了让半透明效果能够明显的看出来我特意为对话框贴了张背景图。被拖动的其实是一个picture ctrl,也就是一个静态控件,当然通过后面的介绍大家会发现这个方法的扩展性比较强,可以应用于很多场合,甚至可以应用于非控件的拖动对象的情况。好了,效果就是这样了,下面切入正题开始介绍实现方法。
对于熟悉拖动效果制作的朋友们都应该知道,实现拖动有一个很简单的方法就是通过CImageList。CImageList提供了BeginDrag、DragEnter、DragMove、DragLeave、EndDrag系列函数,分别在OnLButtonDown、OnMouseMove和OnLButtonUp等消息中合理调用这些函数就可以轻松实现对CImageList的元素的拖动效果。那么我们要做的就是构造一个CImageList,使它的元素是我们想要拖动的图片,这样就大功告成了。那怎样获取图像呢?答案也很简单,就是到被拖动的对象的DC中将所要拖动的区域拷贝到一个内存位图中即可。具体到我的这个例子,我是这样实现的:
在OnLButtonDown中判断鼠标是否在控件范围内,如果在就将控件范围内的DC内容拷贝到内存位图中,然后创建CImageList将包含有控件内容的位图添加进CImageList作为其元素,接着通过这个ImageList实现拖动。具体代码如下
1、加入一个Picture Control控件,并且将该控件属性中的Type设为Bitmap
2、定义CStatic m_pictureCtl;
并且与Picture Control控件关联起来 DDX_Control(pDX, IDC_STATIC_DEMO, m_pictureCtl);
3、OnInitDialog()中,将位图载入该控件中:
HBITMAP hBitMap2 = (HBITMAP)::LoadImage( NULL, _T("res\\Dog.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
m_pictureCtl.SetBitmap(hBitMap2);
4、此时Picture控件就可以将加入的位图显示出来。
再接下来:
头文件public中增加:
.CPP文件中:
下来就是响应函数:
PS:
上边的实例图片中有背景图片,关于如何添加背景图片,请参见上一篇文章 http://blog.csdn.net/max900428/article/details/23622945,但是一定要记住,先画背景图片,再m_pictureCtl.SetBitmap(hBitMap2);
否则背景图片会把此Picture控件盖住,具体位置在执行完BitBlt后m_pictureCtl.SetBitmap(hBitMap2);即可。
基本原理是不难,不过要想做到效果二字就要动一番脑筋了。让我们来看看win7下的图标拖放,鼠标会拖起一个半透明的图标副本到你想要的位置,透过这个透明的图标你可以看到其下面的情况,这样的效果其实在windows的早期版本就已经实现了,它有着很好的用户体验。那么我们能不能轻松的实现类似的拖动效果呢?答案当然是肯定的!最近看到论坛里几个讨论拖动的帖子,正巧前一段时间自己也做了一些相关的工作,小研究了一下,于是就想把研究成果拿出来和大家分享,这样才有利于交流和进步嘛。以前我写博客没贴过效果图,以至于很多网友下载示例代码之后发现不是自己想要的东西,这个确实不好,在此我向大家表示歉意。这次把效果图贴上,如果觉得这个效果很一般或者不是你所需要的那就不要浪费你宝贵的时间阅读文章和下载代码了。
从图中可以看出,我的小猪头像是可以被拖动的,半透明的那个就是拖动的副本,截图的时候鼠标没有截到,呵呵。为了让半透明效果能够明显的看出来我特意为对话框贴了张背景图。被拖动的其实是一个picture ctrl,也就是一个静态控件,当然通过后面的介绍大家会发现这个方法的扩展性比较强,可以应用于很多场合,甚至可以应用于非控件的拖动对象的情况。好了,效果就是这样了,下面切入正题开始介绍实现方法。
对于熟悉拖动效果制作的朋友们都应该知道,实现拖动有一个很简单的方法就是通过CImageList。CImageList提供了BeginDrag、DragEnter、DragMove、DragLeave、EndDrag系列函数,分别在OnLButtonDown、OnMouseMove和OnLButtonUp等消息中合理调用这些函数就可以轻松实现对CImageList的元素的拖动效果。那么我们要做的就是构造一个CImageList,使它的元素是我们想要拖动的图片,这样就大功告成了。那怎样获取图像呢?答案也很简单,就是到被拖动的对象的DC中将所要拖动的区域拷贝到一个内存位图中即可。具体到我的这个例子,我是这样实现的:
在OnLButtonDown中判断鼠标是否在控件范围内,如果在就将控件范围内的DC内容拷贝到内存位图中,然后创建CImageList将包含有控件内容的位图添加进CImageList作为其元素,接着通过这个ImageList实现拖动。具体代码如下
1、加入一个Picture Control控件,并且将该控件属性中的Type设为Bitmap
2、定义CStatic m_pictureCtl;
并且与Picture Control控件关联起来 DDX_Control(pDX, IDC_STATIC_DEMO, m_pictureCtl);
3、OnInitDialog()中,将位图载入该控件中:
HBITMAP hBitMap2 = (HBITMAP)::LoadImage( NULL, _T("res\\Dog.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
m_pictureCtl.SetBitmap(hBitMap2);
4、此时Picture控件就可以将加入的位图显示出来。
再接下来:
头文件public中增加:
//鼠标按下,抬起和移动的响应函数 afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); CPoint m_ptMove; CPoint m_ptOffset; BOOL m_bIsLButtonDown; CImageList m_imgDrag;
.CPP文件中:
BEGIN_MESSAGE_MAP(CMyDialogDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_SIZE() //鼠标左键按下,抬起,移动响应消息 ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() END_MESSAGE_MAP()
下来就是响应函数:
void CMyDialogDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rectPic; POINT ptPut = point; GetDlgItem(IDC_STATIC_DEMO)->GetWindowRect(rectPic); ClientToScreen(&ptPut); if(rectPic.PtInRect(ptPut)) { CBitmap bitmapTemp, *pOldBitmap; CDC *pDC = GetDlgItem(IDC_STATIC_DEMO)->GetDC(), *pMemDC = new CDC; //创建位图内存 bitmapTemp.CreateCompatibleBitmap(pDC, rectPic.Width(), rectPic.Height()); pMemDC->CreateCompatibleDC(pDC); pOldBitmap = pMemDC->SelectObject(&bitmapTemp); pMemDC->BitBlt(0, 0, rectPic.Width(), r 4000 ectPic.Height(), pDC, 0, 0, SRCCOPY); pMemDC->SelectObject(pOldBitmap); delete pMemDC; ReleaseDC(pDC); m_bIsLButtonDown = TRUE; m_ptOffset.x = ptPut.x-rectPic.left; m_ptOffset.y = ptPut.y-rectPic.top; m_imgDrag.DeleteImageList(); m_imgDrag.Create(rectPic.Width(), rectPic.Height(), ILC_COLOR32|ILC_MASK, 0, 1); m_imgDrag.Add(&bitmapTemp, RGB(0, 0, 0)); m_imgDrag.BeginDrag(0, m_ptOffset); m_imgDrag.DragEnter(NULL, ptPut); SetCapture( ); } CDialogEx::OnLButtonDown(nFlags, point); } void CMyDialogDlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rect; GetClientRect(&rect); if(m_bIsLButtonDown) { CRect rectPic; CWnd* pPic = GetDlgItem(IDC_STATIC_DEMO); ScreenToClient(&m_ptMove); pPic->GetWindowRect(rectPic); pPic->MoveWindow(m_ptMove.x-m_ptOffset.x, m_ptMove.y-m_ptOffset.y, rectPic.Width(), rectPic.Height()); m_bIsLButtonDown = FALSE; CImageList::DragLeave(this); CImageList::EndDrag(); ReleaseCapture(); pPic->Invalidate(); } CDialogEx::OnLButtonUp(nFlags, point); } void CMyDialogDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(m_bIsLButtonDown) { CRect rtClient, rtPicture; CPoint tempPoint; GetClientRect(rtClient); m_ptMove = point; GetDlgItem(IDC_STATIC_DEMO)->GetWindowRect(rtPicture); ClientToScreen(&rtClient); ClientToScreen(&m_ptMove); if(rtClient.left>m_ptMove.x-m_ptOffset.x) m_ptMove.x = rtClient.left+m_ptOffset.x; if(rtClient.top>m_ptMove.y-m_ptOffset.y) m_ptMove.y = rtClient.top+m_ptOffset.y; if( (rtClient.right-rtPicture.Width()) <(m_ptMove.x-m_ptOffset.x)) m_ptMove.x = rtClient.right-rtPicture.Width()+m_ptOffset.x; if(rtClient.bottom-rtPicture.Height() <(m_ptMove.y-m_ptOffset.y)) m_ptMove.y = rtClient.bottom-rtPicture.Height()+m_ptOffset.y; CImageList::DragMove(m_ptMove); } CDialogEx::OnMouseMove(nFlags, point); }
PS:
上边的实例图片中有背景图片,关于如何添加背景图片,请参见上一篇文章 http://blog.csdn.net/max900428/article/details/23622945,但是一定要记住,先画背景图片,再m_pictureCtl.SetBitmap(hBitMap2);
否则背景图片会把此Picture控件盖住,具体位置在执行完BitBlt后m_pictureCtl.SetBitmap(hBitMap2);即可。
相关文章推荐
- MFC实现全屏功能代码实例
- Javascript实现购物车功能的详细代码
- Draggable Elements 元素拖拽功能实现代码
- JavaScript中的FileReader图片预览上传功能实现代码
- ReactNative实现图片上传功能的示例代码
- (转)下面的代码实现从SQL Server数据库提取图片并显示在DataGrid的功能。
- MFC实现文件拖拽功能
- vue.js 图片上传并预览及图片更换功能的实现代码
- 利用jQuery简单实现产品展示图片左右滚动功能(示例代码)
- C#实现外部图片的拖拽到应用程序的简单功能,附全部源码,供有需要的参考
- php实现文件上传功能的详细代码实例
- MFC中实现单个控件接收拖拽文件的功能
- javascript 图片放大缩小功能实现代码
- Android使用GridView实现日历功能(详细代码)
- JS小功能(setInterval实现图片效果显示时间)实例代码
- 实现图片的拖拽缩放功能
- Vue.js实现实例搜索应用功能详细代码
- JS点击图片弹出文件选择框并覆盖原图功能的实现代码
- JS+CSS制作DIV层可(最小化/拖拽/排序)功能实现代码