在画图过程中比如说要删除一条直线
一般采用反色来处理,即SetROP2
但是,如果直线下面还有其它图形,就会把直线与其它图形相交的部分也擦拭掉了。
大家有什么好的处理方法,谢谢!

解决方案 »

  1.   

    画在客户区上而不是画在底图上,当结束当前画图指令时,才彻底画在底图上并刷新.
    例如画橡皮筋直线,根据onmousemove直接:
    CClientDC dc( this );
    dc.setrop2(notxorpen);
    //刷除上次
    dc.moveto..
    dc.lineto..
    //重绘新线
    dc.moveto..
    dc.lineto..
    dc.setrop2(oldrop).
    当结束绘图时(onlbuttonup)才直接绘到底图上刷新.
      

  2.   

    lambochan,你好,你所说的底图和客户区有什么区别?CClientDC dc( this ); 客户区底图也是在CDC上画的呀,
    CClientDC dc( this ); 
    dc.setrop2(notxorpen); 
    //刷除上次 
    dc.moveto.. 
    dc.lineto..这也会影响到底图的可能我没有明白你的意思,能不能再给些提示,谢谢!
      

  3.   


    汗,我知道了,你并没有画在一幅内存BMP上,而是直接在客户区作图.
    那么,当你重绘时,你就需要重绘所有画过的DD,因此非常耗时,而且有可能在刷除时受影响。那么为何不画在BMP上呢?画在bmp上就没那么多烦恼了。
      

  4.   

    在内存画布上画完图形后,最终还需要拷贝到客户区
    如果要动态移动这条直线,我就不知道怎么处理,我知道橡它类似橡皮筋的原理,可是不知道怎么处理。
    CRect rect;
            GetClientRect(&rect);
            CDC memDC;
            memDC.CreateCompatibleDC(pDC);
            CBitmap memBmp;
            memBmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
            memDC.SelectObject(&memBmp);
            memDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255));        memDC.Rectangle(CRect(50,50,200,200));//矩形        memDC.MoveTo(70,40);
            memDC.LineTo(70,250); //直线
            pDC->BitBlt(50,50,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);//拷贝到客户区
      

  5.   

    其实画橡皮筋很容易的,以直线来举例吧:
    首先要有变量记录开始点(CPoint ptStart),然后还有个变量记录当前点(CPoint ptCur),最终点就是鼠标抬起时的那点了(CPoint ptEnd),当然还需要有个变量来控制开始画橡皮筋(BOOL bStartDraw)...最后,要有个BOOL变量来控制画还是不画(DrawXiangPi)。
    整个过程就是要得到开始和最终点来画一条直线。那么当鼠标按下时:void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
    {
        if( DrawXiangPi ){   // 如果要画橡皮就开始,否则啥都不做(这个BOOL变量当然是菜单或者命令更改)
            ptStart = ptCur = point; // 记录开始点
            bStartDraw = TRUE;// 开始画
            SetCapture();     // 捕捉鼠标
        }
        CScrollView::OnLButtonDown(nFlags, point);
    }当鼠标按下移动时就画橡皮:void CMyView::OnMouseMove(UINT nFlags, CPoint point)
    {
        if( bStartDraw ){ // 如果开始了
            // 直接画在客户区
            CClientDC dc(this);
            int nROP = dc.SetROP2(R2_NOTXORPEN);      
            dc.MoveTo( ptStart );  
            dc.LineTo( ptCur );               // 画旧的,等于刷除上一条
            ptCur = point;                     // re
            dc.MoveTo( ptStart );  
            dc.LineTo( ptCur );               // 画新的。
            dc.SetROP2( nROP );
        }
        CScrollView::OnMouseMove(nFlags, point);
    }最后,当鼠标抬起时,就得到连个点,可以画在底图上了:void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
    {
        if( bStartDraw ){
            CClientDC dc( this );
            int nROP = dc.SetROP2(R2_NOTXORPEN);      
            dc.MoveTo( ptStart );  
            dc.LineTo( ptCur );               // 画旧的,等于刷除上一条
            dc.SetROP2(nROP);        bStartDraw = FALSE;              // 画完
            ::ReleaseCapture();              // 释放鼠标
            ptEnd = point;        // 现在,你已经得到两个点了:起始点和最终点来画一条直线了。
            // 可以调用你那堆东西:memdc.MoveTo(ptStart);memdc.LineTo(ptEnd);
           dosomethink(here); // 可以把你上面那堆搞成个函数: dosomethink( CPoint ptStart, CPoint ptEnd );        // Invalidate(); // 刷新or not..看你的代码而定了.
        }
        CScrollView::OnLButtonUp(nFlags, point); 
    }以上大概就是画橡皮筋直线的办法.画矩形也是差不多的.
    当然,那不是摘录下来的代码,是偶随手写的,有错不出奇..hoho.
    gl.
      

  6.   

    void CMyView::OnMouseMove(UINT nFlags, CPoint point)
    {
        if( bStartDraw ){ // 如果开始了
            // 直接画在客户区
            CClientDC dc(this);
            int nROP = dc.SetROP2(R2_NOTXORPEN);      
            dc.MoveTo( ptStart );  
            dc.LineTo( ptCur );               // 画旧的,等于刷除上一条//这里就会把底层的图形破坏了
            ptCur = point;                     // re
            dc.MoveTo( ptStart );  
            dc.LineTo( ptCur );               // 画新的。
            dc.SetROP2( nROP );
        }
        CScrollView::OnMouseMove(nFlags, point);
    }
    void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
    {
        if( bStartDraw ){
            CClientDC dc( this );
            int nROP = dc.SetROP2(R2_NOTXORPEN);      
            dc.MoveTo( ptStart );  
            dc.LineTo( ptCur );               // 画旧的,等于刷除上一条
            dc.SetROP2(nROP);        bStartDraw = FALSE;              // 画完
            ::ReleaseCapture();              // 释放鼠标
            ptEnd = point;        // 现在,你已经得到两个点了:起始点和最终点来画一条直线了。
            // 可以调用你那堆东西:
            
    Draw(); //其实在这里又重新把以前有的图形重新画了
            
        }
        CScrollView::OnLButtonUp(nFlags, point); 
    }
    CScrollView::Draw()
    {
            CDC* pDC=GetDC();
    CRect rect; 
            GetClientRect(&rect); 
            CDC memDC; 
            memDC.CreateCompatibleDC(pDC); 
            CBitmap memBmp; 
            memBmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height()); 
            memDC.SelectObject(&memBmp); 
            memDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255));         memDC.Rectangle(CRect(50,50,200,200));//矩形         memDC.MoveTo(ptStart); 
            memDC.LineTo(ptEnd); //直线 
            pDC->BitBlt(50,50,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);//拷贝到客户区
    }
    我对您思路的理解是:
    在动态画出跟随鼠标移动的直线后,重新刷新了底层图形,不然按照以上的代码应该实现不了我要的功能
    橡皮筋应该可以画出来,我的苦恼是,在画出橡皮筋的同时,由于使用了SetROP2(R2_NOTXORPEN),使得直线移动过的区域有些点被擦拭掉了。呵呵!谢谢您的耐心指教!
      

  7.   

    额..怎么说呢?..你应该把那幅内存BMP置为类内变量(或者干脆连memdc都内置)..
    当画一个图形例如点时,那么就画在这个BMP上..
    当画了一百个图形时,根本就不需要重绘那已经画了的100个图形,因为已经都画在了那幅BMP上了,只需刷新帖图,那么实际上OnDraw()就只需要一句:
    void CMyView::OnDraw( CDC *pDC )
    {
        if( m_pMemDC != NULL ){
            pDC->BitBlt(xxxxxxxxx, m_pMemDC,XXXXXX);
        }
    }
    ok,然后回到上面的画直线..由于直接画在客户区,根本不接触到BMP上,所以不会对已画的有任何影响,当结束时,才直接画在内存BMP上..然后Invalidate()..或许偶的表达能力有限,这里有个连接:http://d.download.csdn.net/down/181825/zhaobei1986
    里面有周长发的ImageBoard的代码,绝对可以满足你的要求了..