[转]VC/MFC 基于对话框的图片拖动(利用内存DC防止图片闪烁)
2011-12-31 21:35
537 查看
在写一个基于对话框的MFC程序时,需要有鼠标拖动图片的功能,我在网上查了不少资料,发现大多数都是基于CView来实现的.基于CDialog的图片拖动例子很少,而且给出的例子还不太完整.在此,我把这几天参考网上的和自己编写的实现图片拖动的代码,完整贴出来,希望对大家有所帮助.
先说明下,我的是添加了一个图片控件IDC_STATIC,然后在此控件中来实现图片拖动.在整个绘制过程中,我利用了两个内存DC, 一个是选入BMP图片的内存DC, 另一个是绘制背景的内存DC(即与图片控件DC兼容的内存DC).
拖动与绘制图像的原理和过程简单介绍下,首先是靠鼠标按下,鼠标移动,鼠标抬起,这3个事件捕获鼠标的拖动,获取其拖动后的新坐标,然后调用InvalidateRect()局部更新函数使拖过的部分区域重绘, 此过程系统调用CDialog的OnPaint消息函数, 将绘制的所有代码放在这中,绘制时,先创建IDC_STATIC控件的背景位图,然后将位图选入绘制背景的内存DC中,接下来,就可以在此DC上绘图.然后再创建拖动图片的内存DC,并将图片选入此DC中,最后两步就是将拖动图片的内存DC bitblt到绘制背景的内存DC上, 然后将绘制背景的内存DC再bitblt到IDC_STATIC控件的DC上.
代码如下:
.h文件
class CMyDlg
{
//添加部分
private:
BOOL m_bCapture;
CRgn m_rgn;
SIZE m_off;//图片新位置与旧位置的偏移
CPoint m_pt;//图片的实时位置
SIZE m_pic;//图片的尺寸
CBitmap m_bitmap;
};
.cpp文件
BOOL CMyDlg::OnInitDialog()
{
//添加部分
m_pt.x = 0;
m_pt.y = 0;
m_bCapture = FALSE;
CWnd* pWnd = GetDlgItem(IDC_STATIC);
BITMAP bm;
m_bitmap.LoadBitmap(Monitor);
m_bitmap.GetObject(sizeof(bm), &bm);
m_pic.cx = bm.bmWidth;
m_pic.cy = bm.bmHeight;
}
void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd* pWnd = GetDlgItem(IDC_STATIC);
CRect rc;
pWnd->GetClientRect(&rc);
this->ClientToScreen(&point);//对话框坐标转屏幕坐标
pWnd->ScreenToClient(&point);//再转控件坐标
CRgn rgn;
rgn.CreateRectRgnIndirect(&rc);
if ( rgn.PtInRegion(point) )
{
SetCapture();
m_bCapture=TRUE;
m_off = point-m_pt;
SetCursor(LoadCursor(NULL,IDC_CROSS));
}
CDialog::OnLButtonDown(nFlags, point);
}
void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if ( m_bCapture )
{
this->ClientToScreen(&point);//对话框坐标转屏幕坐标
CWnd* pWnd = GetDlgItem(IDC_STATIC);
pWnd->ScreenToClient(&point);//再转控件坐标
CRect oldRc(m_pt, m_pic); //控件中坐标
pWnd->ClientToScreen(&oldRc);// 转换为屏幕坐标
this->ScreenToClient(&oldRc);
//计算新位置
m_pt.x = point.x - m_off.cx;
m_pt.y = point.y - m_off.cy;
this->InvalidateRect(oldRc, FALSE);
}
CDialog::OnMouseMove(nFlags, point);
}
void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
ReleaseCapture();
m_bCapture=FALSE;
CDialog::OnLButtonUp(nFlags, point);
}
void CMyDlg::OnPaint()
{
//添加部分
else
{
CWnd* pWnd = GetDlgItem(IDC_STATIC);
CRect rc;
pWnd->GetClientRect(&rc); //获得IDC_STATIC控件大小
//创建与IDC_STATIC控件大小相同的背景位图
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height());
//创建 绘制背景的内存DC
CPaintDC dc(pWnd); //控件DC
CDC memDC; //绘制背景的内存DC
memDC.CreateCompatibleDC(&dc);
memDC.SelectObject(&bitmap); //将背景位图选入
memDC.FillSolidRect(0,0,rc.Width(), rc.Height(), RGB(255,255,255)); //填充背景色
memDC.DrawEdge(&rc, EDGE_BUMP, BF_RECT); //四周有边框
//你可以这里用memDC绘制背景图案
//创建拖动图片的内存DC
CDC picDC;
picDC.CreateCompatibleDC(&memDC);
picDC.SelectObject(&m_bitmap);
memDC.BitBlt(m_pt.x, m_pt.y, m_pic.cx, m_pic.cy, &picDC, 0, 0, SRCCOPY); //bitblit到绘制背景的DC上
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &memDC, 0, 0, SRCCOPY); //最后bitblt到控件DC上
CDialog::OnPaint();
}
}
先说明下,我的是添加了一个图片控件IDC_STATIC,然后在此控件中来实现图片拖动.在整个绘制过程中,我利用了两个内存DC, 一个是选入BMP图片的内存DC, 另一个是绘制背景的内存DC(即与图片控件DC兼容的内存DC).
拖动与绘制图像的原理和过程简单介绍下,首先是靠鼠标按下,鼠标移动,鼠标抬起,这3个事件捕获鼠标的拖动,获取其拖动后的新坐标,然后调用InvalidateRect()局部更新函数使拖过的部分区域重绘, 此过程系统调用CDialog的OnPaint消息函数, 将绘制的所有代码放在这中,绘制时,先创建IDC_STATIC控件的背景位图,然后将位图选入绘制背景的内存DC中,接下来,就可以在此DC上绘图.然后再创建拖动图片的内存DC,并将图片选入此DC中,最后两步就是将拖动图片的内存DC bitblt到绘制背景的内存DC上, 然后将绘制背景的内存DC再bitblt到IDC_STATIC控件的DC上.
代码如下:
.h文件
class CMyDlg
{
//添加部分
private:
BOOL m_bCapture;
CRgn m_rgn;
SIZE m_off;//图片新位置与旧位置的偏移
CPoint m_pt;//图片的实时位置
SIZE m_pic;//图片的尺寸
CBitmap m_bitmap;
};
.cpp文件
BOOL CMyDlg::OnInitDialog()
{
//添加部分
m_pt.x = 0;
m_pt.y = 0;
m_bCapture = FALSE;
CWnd* pWnd = GetDlgItem(IDC_STATIC);
BITMAP bm;
m_bitmap.LoadBitmap(Monitor);
m_bitmap.GetObject(sizeof(bm), &bm);
m_pic.cx = bm.bmWidth;
m_pic.cy = bm.bmHeight;
}
void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd* pWnd = GetDlgItem(IDC_STATIC);
CRect rc;
pWnd->GetClientRect(&rc);
this->ClientToScreen(&point);//对话框坐标转屏幕坐标
pWnd->ScreenToClient(&point);//再转控件坐标
CRgn rgn;
rgn.CreateRectRgnIndirect(&rc);
if ( rgn.PtInRegion(point) )
{
SetCapture();
m_bCapture=TRUE;
m_off = point-m_pt;
SetCursor(LoadCursor(NULL,IDC_CROSS));
}
CDialog::OnLButtonDown(nFlags, point);
}
void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if ( m_bCapture )
{
this->ClientToScreen(&point);//对话框坐标转屏幕坐标
CWnd* pWnd = GetDlgItem(IDC_STATIC);
pWnd->ScreenToClient(&point);//再转控件坐标
CRect oldRc(m_pt, m_pic); //控件中坐标
pWnd->ClientToScreen(&oldRc);// 转换为屏幕坐标
this->ScreenToClient(&oldRc);
//计算新位置
m_pt.x = point.x - m_off.cx;
m_pt.y = point.y - m_off.cy;
this->InvalidateRect(oldRc, FALSE);
}
CDialog::OnMouseMove(nFlags, point);
}
void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
ReleaseCapture();
m_bCapture=FALSE;
CDialog::OnLButtonUp(nFlags, point);
}
void CMyDlg::OnPaint()
{
//添加部分
else
{
CWnd* pWnd = GetDlgItem(IDC_STATIC);
CRect rc;
pWnd->GetClientRect(&rc); //获得IDC_STATIC控件大小
//创建与IDC_STATIC控件大小相同的背景位图
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height());
//创建 绘制背景的内存DC
CPaintDC dc(pWnd); //控件DC
CDC memDC; //绘制背景的内存DC
memDC.CreateCompatibleDC(&dc);
memDC.SelectObject(&bitmap); //将背景位图选入
memDC.FillSolidRect(0,0,rc.Width(), rc.Height(), RGB(255,255,255)); //填充背景色
memDC.DrawEdge(&rc, EDGE_BUMP, BF_RECT); //四周有边框
//你可以这里用memDC绘制背景图案
//创建拖动图片的内存DC
CDC picDC;
picDC.CreateCompatibleDC(&memDC);
picDC.SelectObject(&m_bitmap);
memDC.BitBlt(m_pt.x, m_pt.y, m_pic.cx, m_pic.cy, &picDC, 0, 0, SRCCOPY); //bitblit到绘制背景的DC上
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &memDC, 0, 0, SRCCOPY); //最后bitblt到控件DC上
CDialog::OnPaint();
}
}
相关文章推荐
- 基于Dialog的MFC对话框上利用OpenCV 3.0显示图片
- VC++游戏开发1------利用图片拼接实现内存中构建游戏地图,许多游戏编辑器的原理。
- 关于内存DC绘图防止屏幕闪烁说明
- MFC三层模式标准版V1.5版演示源码(VC++代码生成,VC非托管代码,基于对话框程序)
- VC++游戏开发1------利用图片拼接实现内存中构建游戏地图,许多游戏编辑器的原理。
- 基于VS2010的MFC对话框编程之图片浏览器(附源代码)
- 关于内存DC绘图防止屏幕闪烁说明
- VC的内存绘图防止屏幕闪烁技术的实现
- 关于内存DC绘图防止屏幕闪烁
- VC++无标题窗口以及控件拖动的方法,MFC中的对话框怎么拖动不了
- VC的内存绘图防止屏幕闪烁技术的实现
- 接触VC之三:MFC基于对话框程序
- MFC的ADO实例(基于VC2012对话框实例)
- 关于内存DC绘图防止屏幕闪烁说明
- 使用内存DC防止窗口闪烁
- vs2012利用MFC开发基于对话框的小软件指南(连接Mysql数据库)
- 孙鑫VC学习笔记:第十五讲 编写一个基于MFC对话框的聊天程序
- MFC 基于对话框的图片控件(picture)动态加载.bmp图片并显示
- 孙鑫VC学习笔记:第十五讲 (四) 编写一个基于MFC对话框的聊天程序
- VC设置对话框背景图片 MFC显示背景图片方法