汗,一个平移图像的问题,始终得不到想要的效果,在论坛里都问了好多次了,惭愧啊!
先把问题讲清楚,我是在一个CMyStatic类里面画图,然后画好的曲线图像能够在鼠标拖动的情况下移动,现在情况是可以移动,但效果很不理想,一拖动整个图像跟个漏水的袋子似的,弄得整个区域都是它移动的痕迹,而且,把窗口一缩小再还原,图像又跑回到出发点了。问题介绍完了,下面讲一下我的思路(在另一个帖子里我已经讲过了),当鼠标单击时记下m_downpoint,拖动时记下m_movepoint,算出移动的距离: x=m_movepoint.x-m_downpoint.x;
y=m_movepoint.y-m_downpoint.y;然后得到绘制的图像的原来的位置m_oldrect,计算出移动后的新的位置m_newrect: m_newrect.left=m_oldrect.left+x;
m_newrect.top=m_oldrect.top+y;
m_newrect.right=m_oldrect.right+x;
m_newrect.bottom=m_oldrect.bottom+y;然后把波形图重新贴到新的位置 dc.BitBlt(0  ,0,m_newrect.Width(),m_newrect.Height() ,&MemDC,0,0,SRCCOPY);下面是我的部分代码

解决方案 »

  1.   

    然后得到绘制的图像的原来的位置m_oldrect,计算出移动后的新的位置m_newrect: OffsetRect(&m_oldrect, x, y);然后把波形图重新贴到新的位置 
    dc.BitBlt(m_oldrect.left, m_oldrect.top, m_oldrect.Width(), m_oldrect.Height() ,&MemDC,0,0,SRCCOPY);
      

  2.   

    需要在onpaint里面也画上......而且更新的话只需要invalidaterect来更新
      

  3.   

    我又修改了部分代码,但是不能平移图像了,但是这是我按上面那个的思路写的,跟上面叙述有出入的地方我后面指出来:
    void CMyStatic::OnPaint()
    {
       CPaintDC dc(this);//这里定义的是一个CPaintDC
       DrawCurve(dc);//调用DrawCurve(CPaintDC &dc)}
    void CMyStatic::DrawCurve(CPaintDC &dc)
    {

         CRect   rect; 
        GetWindowRect(&rect); 
        m_oldrect=rect;//没有拖动的时候把原位置赋值给m_oldrect
        -------绘图部分略-----------
        dc.BitBlt(0  ,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);//从内存中贴到显示设备
    }void CMyStatic::OnLButtonDown(UINT nFlags, CPoint point) //单击
    {
     m_downpoint=point;
    }void CMyStatic::OnMouseMove(UINT nFlags, CPoint point) //拖动
    {
    CClientDC dc(this);
    m_movepoint=point;
            int x = point.x-m_downpoint.x  ;
            int y = point.y-m_downpoint.y  ;
               
    //位图新的位置
    m_newrect.left=m_oldrect.left+x;
            m_newrect.top=m_oldrect.top+y;
            m_newrect.right=m_oldrect.right+x;
            m_newrect.bottom=m_oldrect.bottom+y;
    DrawCurve(dc);//这里调用的是后面那个DrawCurve(CClientDC &dc),不是前面那个,说来惭愧,这个地方不知道该怎么弄了,因为前面那个的参数是CPaintDC类型的,而这里只能定义成CClientDC型的,所以我就只改了个参数,其实函数跟原来那个差别不大,都是绘制图像

    }void CMyStatic::DrawCurve(CClientDC &dc)
    {
            CRect   rect; 
            //////////////////////把新的位图位置赋值给rect
    rect.left=m_newrect.left;
    rect.top=m_newrect.top;
    rect.right=m_newrect.right;
    rect.bottom =m_newrect.bottom;
    m_oldrect=m_oldrect;
    MemBitmap.CreateCompatibleBitmap(&dc,rect.Width() ,rect.Height() );
    -------------绘图部分略----------------------
            dc.BitBlt(0  ,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY); //能拖动的那个只是这里改动了一下//dc.BitBlt(0  ,0,rect.Width(),rect.Height() ,&MemDC,-x,-y,SRCCOPY);

    }
      

  4.   

    从Static类派生新类CMyStatic
    此类中 DrawItem
    响应鼠标消息 
    使用橡皮筋类 移动或改变大小
      

  5.   

    m_oldrect=m_oldrect; 应改为m_oldrect=m_newrect;
    在此之前应该先在m_oldrect中刷新背景。
    另外,应另外定义一个标志变量,在OnMouseMove中判断该变量,决定是否移动图象。
      

  6.   

    需要在onpaint里面也画上......而且更新的话只需要invalidaterect来更新
      

  7.   

    现在需要解决的问题是为什么拖动没有反应了呢?
    dc.BitBlt(0, 0, m_newrect.Width(), m_newrect.Height() ,&MemDC,0 ,0 ,SRCCOPY);
    如果改成
    dc.BitBlt(m_oldrect.left, m_oldrect.top, m_oldrect.Width(), m_oldrect.Height() ,&MemDC,0,0,SRCCOPY);
    图像拖动可以超出控件的范围,而我想让它在控件范围内拖动
      

  8.   

    随手写的不知道行不
    CRect rect;控件大小dc.BitBlt(m_oldrect.left,
    m_oldrect.top, 
    (m_oldrect.left+m_oldrect.Width())>rect.Width()?(rect.Width()-m_oldrect.left):m_oldrect.Width(),
    (m_oldrect.top+m_oldrect.Height())>rect.Height()?(rect.Height()-m_oldrect.top):m_oldrect.Height() ,
    &MemDC,0,0,SRCCOPY);
      

  9.   

    呵呵,不可以,一拖图像就跑出去了,况且我要把图像贴到这个静态文本控件上,我认为既然静态文本框生成的这个控件已经是固定的了,那
    dc.BitBlt(目标区域,)
    这个目标区域就不要变了,只要改成后面的那个原区域就可以了。可能前面的思路有问题,所以,我把它改成了
    dc.BitBlt(0, 0, m_newrect.Width(),m_newrect.Height(),&MemDC,-x ,-y ,SRCCOPY);
    其中x,y就是鼠标移动的距离,所以也就没有必要计算新的位图的位置了。
    x = m_movepoint.x-m_downpoint.x  ;
    y = m_movepoint.y-m_downpoint.y  ;
    但是这样的问题就是我开头说的:
    可以移动,但效果很不理想,一拖动整个图像跟个漏水的袋子似的,弄得整个区域都是它移动的痕迹,而且,把窗口一缩小再还原,图像又跑回到出发点了。(这一点我想应该是有DrawCurve(CPaintDC &dc)的原因,但是我不知该怎么解决。 )
    不知道自己的思路是不是正确,恳请大家指教,谢谢
      

  10.   

    我设了一个BOOL型变量,当鼠标拖动时m_mouseState2=TRUE;
    然后在OnPaint() 里面加了一个判断
              if(m_mouseState2==FALSE)
    {
           DrawCurve(dc);//如果鼠标拖动,关闭DrawCurve(CPaintDC &dc)的运行
             }
    但是运行之后发现,窗口一动,图像就都没有了!我没有关闭DrawCurve(CClientDC &dc)a啊?
      

  11.   

    dc.BitBlt(0  ,0,m_newrect.Width(),m_newrect.Height() ,&MemDC,0,0,SRCCOPY);
    倒数第三个参数就是X轴偏移值正数向右 负数向左;
    用双缓冲来做你的例子 否则会很闪  调用invalidaterect刷新即可去掉痕迹
      

  12.   

    我以前做的图形编辑器比较多:
    给你提供一个思路:
    1.标要移动图形前,将屏幕重画,但不要画你要移动的图形(当然重画最好按照图形最后修改时间的先后顺序),将此时的屏幕图象保存到内存中,且将你要画的图形也在内存中保存起来,在图形移动的时候,不断Bitblt原来的屏幕和你保存的图形就可以了
      

  13.   

    我这样不是双缓冲吗?明明是啊
    void CMyStatic::DrawCurve(CPaintDC &dc)
    {
    CBitmap MemBitmap;
    MemDC.CreateCompatibleDC(&dc);
    //建立一个与屏幕显示兼容的位图
             CRect   rect; 
            GetWindowRect(&rect);  m_oldrect=rect;
    //this->GetParent() ->GetDocument();
    //MemBitmap.CreateCompatibleBitmap(&dc,300,300);
    MemBitmap.CreateCompatibleBitmap(&dc,rect.Width (),rect.Height ());
    //将位图选入到内存显示设备中
    CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);

    MemDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(230,230,230));
    dc.BitBlt(0  ,0,m_newrect.Width(),m_newrect.Height() ,&MemDC,-x,-y,SRCCOPY); //这一句为什么要改成dc.BitBlt(0  ,0,m_newrect.Width(),m_newrect.Height() ,&MemDC,0,0,SRCCOPY); ?

    //InvalidateRect(m_newrect);添加这一句刷新效果还不如不刷新的呢
    MemDC.SelectObject(pOldPen);
    MemBitmap.DeleteObject();
    MemDC.DeleteDC();
    }
      

  14.   

    都是高手啊我做过一个,不知你是否适用,有一个东西叫异或笔,CDC dc;
    dc.SetROP2(R2_XORPEN);   
    CPen   pen(PS_SOLID,0,RGB(255,255,255)); //开始画曲线...先在原始位置画,当你有新的位置的时候,先在原来的位置再画一遍,这样原来位置的图像就不见了,然后在新位置画一遍,再有新位置时,在刚才的位置画一遍,再在新位置画一遍。这样拖动就不会闪屏,因为不用invalidate不知你用不用的上,这是个简单的方法  
     
      

  15.   

    晕,没什么例子啊,这也是我项目的一小部分,只有几行代码给你看看吧void CMyView::OnMouseMove(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    CMyDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    CClientDC dc(this);
    OnPrepareDC(&dc);
                   if(point.x>=50)
     {  
     if(LMouseDrag)
      {
    if(point.x<pDoc->CursorPt3.x)//光标1不能在光标2右面
    {
    if(point.x!=pDoc->m_ptLast.x)
    {
    pDoc->CursorPt1.x=point.x;
                        int nSave=dc.SaveDC();   
                        dc.SetROP2(R2_XORPEN);   
                        CPen   pen(PS_SOLID,0,RGB(255,255,255));   
                        dc.SelectObject(pen); 
                        dc.MoveTo(pDoc->m_ptLast.x,429);   先在上次的位置画
                        dc.LineTo(pDoc->m_ptLast.x,25);        
        
                        dc.MoveTo(point.x,429);   在新位置画
                        dc.LineTo(point.x,25);   
                        pDoc->m_ptLast=point;
    }
    }
    这是在鼠标拖动时的代码。我拖动的是两根直线。