• 鼠标绘制简单图形


    功能:

    1、绘制的图形包括直线、椭圆和矩形,通过菜单对绘制的图形切换

    2、在视图中使用鼠标动态的绘制图形

    分析:

    当窗口尺寸发生变化时,引起窗口重绘,会发送WM_PAINT消息,这时首先会擦除窗口的背景,然后再进行重绘操作,这样就把窗口中先前绘制的图形擦除掉了;可以将绘制图形的三要素(起点、终点、绘制类型)保存下来,在窗口重绘调用程序视图类窗口的OnDraw函数中再将图形根据保存的三要素重新输出;

      1、数据

        在视图中添加两个点坐标

        CPoint m_ptOrigin;  //起点坐标

        CPoint m_ptEnd;  //终点坐标

        UINT m_nDrawType;  //图形的类型,0:不绘制;1:直线;2:椭圆;3:矩形;

        BOOL m_bFlag;  //是否绘制图形

      2、绘制过程

        2.1--LBUTTONDOWN

          1)保存图形的起点

          2)m_bFlag=TRUE;  //开始绘制

        2.2--MOUSEMOVE

          if(m_bFlag){

            //擦除旧线

            //画新线        

          }

        2.3--LBUTTONUP

          m_bFlag=FALSE;  //绘制结束

    实现:

    创建单文档类型的MFC工程:Graphic,在资源窗口中的菜单栏中添加顶层菜单项“绘图”,并添加下拉菜单项:IDM_DOT(点)、IDM_LINE(直线)、IDM_RECTANGLE(矩形)、IDM_ELLIPSE(椭圆);在工程的视图类CGraphicView类中添加私有成员变量:UINT m_nDrawType,并在视图类的构造函数中将其初始化为0,在不同的菜单项的消息响应函数中将m_nDrawType设为不同的值以标识不同的绘制图形:点--1、直线--2、矩形--3、椭圆--4;

    在视图类CGraphicView类中添加私有成员变量:CPoint m_ptOrigin,并在视图类的构造函数中将该变量初始化为0,在鼠标左键按下的消息响应函数中用以保存左键按下时的坐标;

      

      

    void CGraphicView::OnLButtonDown(UINT nFlags, CPoint point) 
    {
        // TODO: Add your message handler code here and/or call default
        m_ptOrigin=point;
        
        CView::OnLButtonDown(nFlags, point);
    }
    

    在鼠标左键松开消息响应函数中实现绘图功能:

      

    void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point) 
    {
        // TODO: Add your message handler code here and/or call default
        CClientDC dc(this);
    
        //创建画笔:PS_SOLID/PS_DASH/PS_DOT
        CPen pen(PS_SOLID,1,RGB(255,0,0));
        CPen* pOldPen=dc.SelectObject(&pen);
    
        //创建画刷,默认的画刷为白色填充,这里创建的是透明无填充的画刷
        //CBrush::FromHandle--将句柄转换为对象
        CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
        CBrush *pOldBrush=dc.SelectObject(pBrush);
    
        switch(m_nDrawType){
            case 1:
                //画点
                dc.SetPixel(point,RGB(255,0,0));
                break;
            case 2:
                //画线
                dc.MoveTo(m_ptOrigin);
                dc.LineTo(point);
                break;
            case 3:
                //画矩形线框,无填充
                dc.Rectangle(CRect(m_ptOrigin,point));
                break;
            case 4:
                //画椭圆线框,无填充
                dc.Ellipse(CRect(m_ptOrigin,point));
                break;
        }
    
        dc.SelectObject(pOldPen);
        dc.SelectObject(pOldBrush);
        
        CView::OnLButtonUp(nFlags, point);
    }
     

    右击工程名称增加一个新类:CGraph:

      

    为CGraph类添加3个成员变量:

      UINT    m_nDrawType  绘制类型

      CPoint  m_ptOrigin   起点

      CPoint  m_ptEnd      终点

      

      

      

    1、添加“设置”对话框

    在工程的菜单栏资源的顶层菜单栏“绘图”下添加下拉菜单项“设置”:

      

    为“设置”菜单项添加一个对应的对话框资源,在对话框中允许用户进行相关的绘图设置:

      

    双击对话框资源创建相应的对话框类:

      

      

    在对话框资源中添加一个静态文本框“线宽”和一个编辑框:

      

    利用MFC类向导为编辑框IDC_LINE_WIDTH关联一个成员变量,用来设置线宽:

      

    为“设置”菜单项添加命令响应,并选择视图类CGraphicView类对此消息进行响应:

      

      因为要在视图类中引用新建的对话框类,故需要在视图类的源文件中包含新建的对话框类的头文件:

      #include "SettingDlg.h" 

    void CGraphicView::OnSetting() 
    {
        // TODO: Add your command handler code here
        CSettingDlg dlg;
        dlg.DoModal();  //显示对话框
        
    }
    

    在视图类CGraphicView类中添加私有成员变量:UINT m_nLineWidth,并在视图类的构造函数中将其初始化为0,用来保存用户在对话框的线宽编辑框中设置的线宽;

      

    用户在线宽编辑框输入线宽后,若单击【确定】按钮则保存这个线宽值,若单击【取消】按钮则不保存线宽值:

    void CGraphicView::OnSetting() 
    {
        // TODO: Add your command handler code here
        CSettingDlg dlg;
        dlg.m_nLineWidth=m_nLineWidth;  //保存上次设置的线宽值
        if(IDOK==dlg.DoModal()){
            m_nLineWidth=dlg.m_nLineWidth;  //调用新填写的线宽值
        }
        
    }
    

    在创建画笔对象时,其宽度用m_nLineWidth变量来代替:

    void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)
    {
        // TODO: Add your message handler code here and/or call default
        CClientDC dc(this);
    
        CPen pen(PS_SOLID,m_nLineWidth,RGB(255,0,0));
        CPen* pOldPen=dc.SelectObject(&pen);
    
        CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
        CBrush *pOldBrush=dc.SelectObject(pBrush);
    
        switch(m_nDrawType){
            case 1:
                dc.SetPixel(point,RGB(255,0,0));
                break;
            case 2:
                dc.MoveTo(m_ptOrigin);
                dc.LineTo(point);
                break;
            case 3:
                dc.Rectangle(CRect(m_ptOrigin,point));
                break;
            case 4:
                dc.Ellipse(CRect(m_ptOrigin,point));
                break;
        }
    
        dc.SelectObject(pOldPen);
        dc.SelectObject(pOldBrush);
        
        CView::OnLButtonUp(nFlags, point);
    }
    

    在“设置”对话框中添加一个设置线型的组框IDC_LINE_STYLE,在组框中放置3个单选按钮,对应“实线”、“虚线”、“点线”,勾选第一个单选按钮的属性中的“组”,使其成为改组单选按钮组的组长;

      

    利用MFC类向导为这组单选按钮关联一个成员变量: int m_nLineStyle,以成员变量的值来区分选中哪个单选按钮:0--实线、1--虚线、2--点线、-1--未选中;

      

    在程序的视图类CGraphicView类中添加私有成员变量:int m_nLineStyle,并在视图类的构造函数中将其初始化为0:

       

    void CGraphicView::OnSetting() 
    {
        // TODO: Add your command handler code here
        CSettingDlg dlg;
        dlg.m_nLineWidth=m_nLineWidth;  //保存上次设置的线宽值
        dlg.m_nLineStyle=m_nLineStyle;  //保存上次设置的线型
        if(IDOK==dlg.DoModal()){
            m_nLineWidth=dlg.m_nLineWidth;  //调用新填写的线宽值
            m_nLineStyle=dlg.m_nLineStyle;  //调用新选择的线型
        }
        
    }
    

    PS_SOLID/PS_DASH/PS_DOT这些线型在WINGDI.h文件中定义时均对应有0/1/2的值关联,恰好与m_nLineStyle的取值相对应,故可以在创建画笔对象时直接将线型参数替换为m_nLineStyle

    void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)
    {
        // TODO: Add your message handler code here and/or call default
        CClientDC dc(this);
    
        CPen pen(m_nLineStyle,m_nLineWidth,RGB(255,0,0));
        CPen* pOldPen=dc.SelectObject(&pen);
    
        CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
        CBrush *pOldBrush=dc.SelectObject(pBrush);
    
        switch(m_nDrawType){
            case 1:
                dc.SetPixel(point,RGB(255,0,0));
                break;
            case 2:
                dc.MoveTo(m_ptOrigin);
                dc.LineTo(point);
                break;
            case 3:
                dc.Rectangle(CRect(m_ptOrigin,point));
                break;
            case 4:
                dc.Ellipse(CRect(m_ptOrigin,point));
                break;
        }
    
        dc.SelectObject(pOldPen);
        dc.SelectObject(pOldBrush);
        
        CView::OnLButtonUp(nFlags, point);
    }
    

    2、添加颜色对话框

      利用MFC提供的CColorDialog类可创建一个颜色对话框:

        CColorDialog(

          COLORREF clrInit = 0,  //指定默认的颜色选择,默认为黑色

          DWORD dwFlags = 0,  //指定一组标记,用来定制颜色对话框的功能和外观

          CWnd* pParentWnd = NULL  //指向颜色对话框父窗口或拥有者窗口的指针

        );

       在程序的菜单栏资源中的顶层菜单项“绘图”中增加“颜色”下拉菜单项:

        

      选择视图类CGraphicView类对此菜单项的命令做出相应:

        

      为视图类CGraphicView类添加一个私有成员变量:COLORREF m_clr,并在视图类的构造函数中将其初始化为黑色,用于保存用户选择的颜色;

        

        m_clr=RGB(0,0,0);  

    void CGraphicView::OnColor() 
    {
        // TODO: Add your command handler code here
        CColorDialog dlg;
        /*CColorDialog类有一个CHOOSECOLOR结构体类型的成员变量m_cc,
            m_cc.rgbResult中就保存了用户所选择的颜色*/
        dlg.m_cc.Flags |= CC_RGBINIT;  //设置颜色对话框选中已选颜色
        dlg.m_cc.rgbResult=m_clr;  //保存上次设置的颜色
        if(IDOK==dlg.DoModal()){
            m_clr=dlg.m_cc.rgbResult;  //调用新选择的颜色
        }
        
    }
    

      在创建画笔时,将颜色参数替换为变量m_clr   

    void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)
    {
        // TODO: Add your message handler code here and/or call default
        CClientDC dc(this);
    
        CPen pen(m_nLineStyle,m_nLineWidth,m_clr);
        CPen* pOldPen=dc.SelectObject(&pen);
    
        CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
        CBrush *pOldBrush=dc.SelectObject(pBrush);
    
        switch(m_nDrawType){
            case 1:
                dc.SetPixel(point,m_clr);
                break;
            case 2:
                dc.MoveTo(m_ptOrigin);
                dc.LineTo(point);
                break;
            case 3:
                dc.Rectangle(CRect(m_ptOrigin,point));
                break;
            case 4:
                dc.Ellipse(CRect(m_ptOrigin,point));
                break;
        }
    
        dc.SelectObject(pOldPen);
        dc.SelectObject(pOldBrush);
        
        CView::OnLButtonUp(nFlags, point);
    }
    

    3、添加字体对话框

      利用MFC提供的CFontDialog类创建字体对话框:

        CFontDialog(

          LPLOGFONT lplfInitial = NULL,  //指向LOGFONT结构体的指针,允许用户设置一些字体的特征

          DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,  //设置一个或多个与选择的字体相关的标记

          CDC* pdcPrinter = NULL,  //指向打印设备上下文的指针

          CWnd* pParentWnd = NULL  //指向字体对话框父窗口的指针

          );

       在程序菜单栏资源的顶层菜单项“绘图”中添加“字体”下拉选项:

        

      为“字体”菜单项添加命令响应,选择视图类CGraphicView类对此命令做出响应,在响应函数中创建并显示字体对话框:

        

      在工程的视图类CGraphicView类中添加一个私有成员变量:CFont m_font,用以保存用户选择的字体;再在视图类中添加另一个私有成员变量:CString m_strFontName,并在视图类的构造函数中将其初始化为空,用以保存所选字体的名称;

        

        

        m_strFontName="";   

    void CGraphicView::OnFont() 
    {
        // TODO: Add your command handler code here
        CFontDialog dlg;
        //CFontDialog类有一个CHOOSEFONT结构体类型的数据成员:m_cf
        //m_cf.lpLogFont--指向逻辑字体的指针
        //m_cf.lpLogFont->lfFaceName--存放字体的名称
        if(IDOK==dlg.DoModal()){
            //设置新字体前先判断是否已有指定的字体,如果有就先释放该字体资源
            if(m_font.m_hObject){  
                m_font.DeleteObject();
            }
            m_font.CreateFontIndirect(dlg.m_cf.lpLogFont);  //调用指定的逻辑字体
            m_strFontName=dlg.m_cf.lpLogFont->lfFaceName;  //保存所选字体的名称
            Invalidate(TRUE);  //窗口重绘,以在视图类的OnDraw函数中显示所选字体
        }
    
    }
    
    void CGraphicView::OnDraw(CDC* pDC)
    {
        CGraphicDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
        // TODO: add draw code for native data here
        CFont *pOldFont=pDC->SelectObject(&m_font);
        pDC->TextOut(0,0,m_strFontName);
        pDC->SelectObject(pOldFont);
    }
    

    4、示例对话框

      在程序的“设置”对话框中添加一个组框,当用户选择线宽和线型后能直接在组框中显示示例;

        

      当线宽的编辑框中的文本改变时,会向其父窗口(对话框)发送EN_CHANGE消息;当单选按钮被点击时,也会向其父窗口(对话框)发送BN_CLICKED消息;对话框的CSettingDlg类,需要捕获这两个通知消息,以反映出用户所做的改变;利用MFC类向导为CSettingDlg类添加编辑框(IDC_LINE_WIDTH)的EN_CHANGE消息的响应函数,和三个单选按钮的BN_CLICKED消息响应函数:

      

      

      不可能在编辑框及单选按钮的这4个消息响应函数中都绘制示例线条,可以在这4个响应函数中调用Invalidate函数进行窗口重绘,均会发送WM_PAINT消息,只需在该WM_PAINT消息的响应函数中绘制示例线条即可;为对话框类CSettingDlg类添加WM_PAINT消息的响应函数;

         

    void CSettingDlg::OnChangeLineWidth() 
    {
        // TODO: If this is a RICHEDIT control, the control will not
        // send this notification unless you override the CDialog::OnInitDialog()
        // function and call CRichEditCtrl().SetEventMask()
        // with the ENM_CHANGE flag ORed into the mask.
        
        // TODO: Add your control notification handler code here
        Invalidate(TRUE);
        
    }
    void CSettingDlg::OnRadio1() 
    {
        // TODO: Add your control notification handler code here
        Invalidate(TRUE);
        
    }
    
    void CSettingDlg::OnRadio2() 
    {
        // TODO: Add your control notification handler code here
        Invalidate(TRUE);
        
    }
    
    void CSettingDlg::OnRadio3() 
    {
        // TODO: Add your control notification handler code here
        Invalidate(TRUE);
        
    }
    void CSettingDlg::OnPaint() 
    {
        CPaintDC dc(this); // device context for painting
        
        // TODO: Add your message handler code here
        UpdateData();  //当对话框中的控件值发生改变时要先更新一下
        CPen pen(m_nLineStyle,m_nLineWidth,RGB(0,0,0));
        dc.SelectObject(&pen);
    
        CRect rect;
        GetDlgItem(IDC_SAMPLE)->GetWindowRect(&rect);  //获取“示例”组框的矩形区域大小
        ScreenToClient(&rect);  //由屏幕坐标转化为客户坐标
    
        dc.MoveTo(rect.left+20,rect.top+rect.Height()/2);
        dc.LineTo(rect.right-20,rect.top+rect.Height()/2);
        
        // Do not call CDialog::OnPaint() for painting messages
    }
    
  • 相关阅读:
    课后作业07--二分法查找算法代码
    检索03 -- 二分法查找
    课堂随笔05--冒泡排序
    课后作业 06 -- 小数后几位精确判断并输出
    课后作业 05 -- 输出一段带字母与数字的随机数
    课后作业 04 --DateTime应用,判断多久后生日之类
    检索02--随机数种子的一些概念和理解
    课堂随笔04--关于string类的一些基本操作
    P1174 互素
    P1001 第K极值
  • 原文地址:https://www.cnblogs.com/zhouwanqiu/p/6914749.html
Copyright © 2020-2023  润新知