zoukankan      html  css  js  c++  java
  • [转]VC/MFC 基于对话框的图片拖动(利用内存DC防止图片闪烁)

         在写一个基于对话框的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();

       }

    }

  • 相关阅读:
    vue 学习
    vue如何新建一个项目
    Java入门之流程控制语句
    Java 入门之数据类型转换、运算符、方法
    Java 入门 常量,变量
    Java 开发工具IntelliJ IDEA
    Java 前言&开发环境搭建
    Java 学习
    装饰器模式
    springcloud 的学习(五) 路由网关
  • 原文地址:https://www.cnblogs.com/vic_lu/p/2309130.html
Copyright © 2011-2022 走看看