• VC/MFC动态画线,画圆,画椭圆,画矩形 .


    转载自http://blog.csdn.net/zyq11223/article/details/8271006

    VC鼠标拖动动态画矩形框(http://blog.csdn.net/zhouxuguang236/article/details/7686163) 和 VC动态轨迹画线 (http://blog.csdn.net/akof1314/article/details/5547616),更感谢转载前一篇博文的作者(zhouxuguang236),是他给了我第二个博文的链接,使得我不用自己去搜索并尝试哪一篇的博文更便于我的学习。

    好了下面开始言归正传:

    所谓的动态画线,画矩形,画椭圆的本质就是在于消隐问题的解决以及对Windows消息循环机制的理解,消隐问题:因为MFC中有一个函数SetROP2,通过将该函数的参数设置为R2—NOT(当前绘制的像素值设为屏幕像素值的反色,这里面的“屏幕”二字是指你所绘制的图形所占据的那一部分屏幕区域,即直线所占的屏幕区域就是直线所在的那一段线的区域),利用这一点通过在同一区域重复画两次便可以将该区域的形状消隐。

    而Windows消息循环机制更好的体现于MouseMove消息响应中,因为要实现动态画线、画矩形这就体现在鼠标在绘图区的移动上,鼠标在绘图区移动时,产生动态的效果,也就是说在mouse 移动的过程中始终在画线、画矩形,这就要求在MouseMove消息响应中有画线、画矩形的相应函数的调用,但正是因为mouse移动的过程中画了很多的线、矩形,所以我们就要在mouse移动的过程中将之前画出的线、矩形消隐掉,才能保证实现了自己所要实现的功能——动态画线、画矩形,但又没有产生多余的线和矩形。

    消隐的问题和动态画图的问题关键在于MouseMove消息响应中的函数调用的顺序:

    1.首先将上次所画的图形消隐掉

    2.画出临时的图形

    3.消息循环的机制:循环执行上述代码(这是Windows循环的机制,不需要自己代码实现)

     

    在最后的LButtonUp消息响应中,需要将上面的MouseMove消息响应中循环的最后一次中最后所画的临时图形消隐掉,之后根据LButtonUp消息响应中point参数画出最终的图形。综上可知:MouseMove中的代码和LButtonUp中消隐临时图形的代码所要实现的功能就是动态这一过程,而图形的最终绘制还在与LButtonUp消息响应及其point参数。

    代码如下:

    private:

    //......
     HCURSOR m_HCross;
     UINT m_drawType;
     CPoint m_OldPoint;
     CPoint m_startPoint;
     BOOL m_startRect;

    CGISView::CGISView()
    {
     // TODO: add construction code here
     //....
     m_startRect=FALSE;
     m_startPoint=0;
     m_OldPoint=0;
     m_drawType=0;
     //初始化m_HCross为十字光标
     m_HCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);

    }

    void CGISView::OnLButtonDown(UINT nFlags, CPoint point)
    {
     // TODO: Add your message handler code here and/or call default
     m_startRect=TRUE; //鼠标左键单击,设置可以开始绘制矩形框
     m_startPoint=point; //记录起始点
     m_OldPoint=point;//设置老点也为起始点
     //设置光标为十字光标
     ::SetCursor(m_HCross);


     CView::OnLButtonDown(nFlags, point);
    }

    void CGISView::OnMouseMove(UINT nFlags, CPoint point)
    {
     // TODO: Add your message handler code here and/or call default
     
     CClientDC dc(this); //获取设备句柄
     dc.SetROP2(R2_NOT);//此为关键
     dc.SetROP2(R2_NOT);//所绘制的图形并没有消失,所以可以验证下面的连续两次颜色取反不是在一次相应中完成
     //SetRop2 Specifies the new drawing mode.(MSDN)
             //R2_NOT   Pixel is the inverse of the screen color.(MSDN)
             //即:该函数用来定义绘制的颜色,而该参数则将颜色设置为原屏幕颜色的反色
     //这样,如果连续绘制两次的话,就可以恢复原来屏幕的颜色了(如下)
     //但是,这里的连续两次绘制却不是在一次消息响应中完成的
     //而是在第一次拖动响应的绘制可以显示(也就是看到的),第二次拖动绘制实现擦出(也就看不到了)

     dc.SelectStockObject(NULL_BRUSH);//不使用画刷
     if(TRUE==m_startRect) //根据是否有单击判断是否可以画矩形
     {
      switch(m_drawType)
      {
                   case 1://Rectangle

        ::SetCursor(m_HCross);
                dc.Rectangle(CRect(m_startPoint,m_OldPoint));
                         dc.Rectangle(CRect(m_startPoint,point));
        m_OldPoint=point;
       
        break;

           case 2: //Line
        ::SetCursor(m_HCross);
        //擦去上一次绘制的临时线
        dc.MoveTo(m_startPoint);
                dc.LineTo(m_OldPoint);  
        
        //绘制这一次的临时线
                  dc.MoveTo(m_startPoint);
        dc.LineTo(point);

        //将临时线的终点复制给m_OldPoint,
        //使其在消息循环的过程中将该值传递到
        //擦去上一次画线的过程中,以便擦去上一次所画的线
        m_OldPoint=point;
        


        break;
           case 3:  //Circle
        ::SetCursor(m_HCross);
                                //擦去上一次绘制的临时圆
        //设定该圆的y坐标,因为要保证两点的x之差等于y之差
        m_OldPoint.y=m_OldPoint.x-m_startPoint.x+m_startPoint.y;
        dc.Ellipse(CRect(m_startPoint,m_OldPoint));

        //绘制临时圆

        point.y=point.x-m_startPoint.x+m_startPoint.y;
        dc.Ellipse(CRect(m_startPoint,point));

        m_OldPoint=point;
        break;
           case 4:  //Ellipse
        ::SetCursor(m_HCross);

        dc.Ellipse(CRect(m_startPoint,m_OldPoint));
        dc.Ellipse(CRect(m_startPoint,point));
        m_OldPoint=point;
        break;
           case 5:   //Dot

        break;

     }

    void CGISView::OnLButtonUp(UINT nFlags, CPoint point)
    {
     // TODO: Add your message handler code here and/or call default
     m_startRect=FALSE;//重置绘制矩形框标志
     ::ClipCursor(NULL);//解锁光标,即将光标恢复为默认光标
     //消隐最后的一个矩形
     CClientDC dc(this);//获取设备句柄
    // dc.SetROP2(R2_NOT); //在MouseMove消息响应中使用过该函数了,所以在这里再一次使用会使得其恢复为屏幕的颜色
     dc.SelectStockObject(NULL_BRUSH);  //设置画刷为空画刷
        switch(m_drawType)
     {
      case 1: //Retangle

      //利用当前画刷绘制矩形,内部由当前空画刷(NULL_BRUSH)填充。
      //擦去MouseMove消息响应中的临时矩形
      dc.Rectangle(CRect(m_startPoint,m_OldPoint));
      //绘制固定矩形
      dc.Rectangle(CRect(m_startPoint,point));

      //m_drawType=0;  //该行的可以使得每画一次都要选择所画的形状
                break;

              case 2:  //Line

      //擦去MouseMove消息响应中绘制的最后一次临时线
       dc.MoveTo(m_startPoint);
                       dc.LineTo(m_OldPoint);
      
       //绘制固定线
       dc.MoveTo(m_startPoint);
       dc.LineTo(point);
       break;
       case 3:  //Circle
     
      dc.Ellipse(CRect(m_startPoint,m_OldPoint));
      dc.Ellipse(CRect(m_startPoint,point));
       break;
       case 4:  //Ellipse

      dc.Ellipse(CRect(m_startPoint,m_OldPoint));
      dc.Ellipse(CRect(m_startPoint,point));
       break;
       case 5:  //Dot
                      dc.SetPixel(point,RGB(0,0,0));
       break;
     
     }
     CView::OnLButtonUp(nFlags, point);
    }

    void CGISView::OnRectangle()
    {
     // TODO: Add your command handler code here
      m_drawType=1;//设置所画的为矩形
     
    }

    void CGISView::OnLine()
    {
     // TODO: Add your command handler code here
     m_drawType=2;
    }

    void CGISView::OnEllipse()
    {
     // TODO: Add your command handler code here
     m_drawType=4;
    }

    void CGISView::OnDot()
    {
     // TODO: Add your command handler code here
     m_drawType=5;

    }

    void CGISView::OnCircle()
    {
     // TODO: Add your command handler code here
     m_drawType=3;
    }

  • 相关阅读:
    WCF寻址
    WCF之多个协定
    WCF之多个终结点
    WCF客户端和服务端配置
    VS2012新建项目出错:未找到与约束ContractName Microsoft.VisualStudio.Text.ITextDocumentFactoryService
    windows运行打开服务命令
    Android中 服务里的方法抽取成接口
    Android Studio 使用genymotion 模拟器运行app时 提示找不到任何设备
    SVN 首次用TortoiseSVN Checkout 提示Unexpected HTTP status 405
    jQuery EasyUI -onblu、onkeyup等事件
  • 原文地址:https://www.cnblogs.com/liuliu-NoGirl/p/3358758.html
Copyright © 2020-2023  润新知