用VS2008的MFC写的CAD画图程序2017.12.15

一、实现的功能

1、程序可以画点、直线、矩形、椭圆

2、可以设置线宽、颜色、字体,可以看到线型示例

3、可以显示鼠标点的坐标,可以显示系统时间

4、在IDR_MAINFRAME字符串里面直接更改程序标题

5、画图文件的重绘。

6、程序用VS2008编写,个人觉得,VC6.0就像windowsXP

VS2008就像Win10,习惯了就好

二、实现的功能图片

用VS2008的MFC写的CAD画图程序2017.12.15_第1张图片


用VS2008的MFC写的CAD画图程序2017.12.15_第2张图片

三、实现的过程与代码

3.1、添加的菜单项

1、IDM_DOT 点 IDM_LINE 线 IDM_RECTANGLE 矩形 IDM_ELLIPSE 椭圆

IDM_COLOR颜色 IDM_FONT 字体 IDM_SETTING

3.2、添加的对话框资源

1、IDD_DLG_SETTING 设置 IDC_LINE_WIDTH 线宽(线型默认设置)IDC_SAMPLE 示例

3.3、添加的成员变量

1、CGraphicview

UNITm_nDrawType;//保存绘图选择,分别为1、2、3、4、初始化为0

CPointm_ptOrigin;//保存鼠标当前按下的点,初始化为0

COLORREFm_clr;//将当前所绘画的颜色保存下来,初始化为RGB(255,0,0)

 

UNITm_nLineWidth;//保存线宽值,然后在画图程序中使用,初始化为0

intm_nLineStyle;//保存线型,画图时使用,初始化为0

 

CFontm_font;//选择一种字体
CString m_strFontName;//保存所选字体的名称


CPtrArray m_ptrArray;//集合类的变量保存对象值

 

2、设置对话框增加了一个新类CSettingDlg

UNITm_nLineWidth;//保存对话框选择的线宽
int m_nLineStyle;//保存对话框选择的线型


3、图形保存与重绘

UINT m_nDrawType;//保存绘图选择

CPoint m_ptOrigin;//保存起点

CPoint m_ptEnd;//保存终点

COLORREFm_clr;//保存颜色

 

3.3代码的实现过程

1、所有变量在构造函数中初始化

CGraphicView::CGraphicView()

{

     m_nDrawType=0;

     m_ptOrigin=0;

     m_nLineWidth=0;

     m_nLineStyle=0;

     m_clr=RGB(255,0,0);

     m_strFontName="";

}

2、在CGraphicView类添加命令响应(添加事件处理程序)

同时设置变量UNIT m_nDrawType;//保存绘图选择,分别为1、2、3、4、表示

点、直线、矩形、椭圆

用VS2008的MFC写的CAD画图程序2017.12.15_第3张图片

用VS2008的MFC写的CAD画图程序2017.12.15_第4张图片

程序实现代码:

void CGraphicView::OnDot()

{

 m_nDrawType=1;

}

void CGraphicView::OnLine()

{

 m_nDrawType=2;

}

void CGraphicView::OnRectangle()

{

 m_nDrawType=3;

}

void CGraphicView::OnEllipse()

{

 m_nDrawType=4;

}

3、在CGraphicView类增加鼠标左键按下和鼠标左键松开两个消息响应函数

用VS2008的MFC写的CAD画图程序2017.12.15_第5张图片

在左键按下的时候保存起点

在左键松开的时候,实现画图功能

程序代码实现如下:

void CGraphicView::OnLButtonDown(UINTnFlags, CPoint point)

{

    m_ptOrigin=point;

    CView::OnLButtonDown(nFlags, point);

}

 

void CGraphicView::OnLButtonUp(UINTnFlags, CPoint point)

{

CClientDCdc(this);

//选择画笔

CPen pen(m_nLineStyle,m_nLineWidth,m_clr);

dc.SelectObject(&pen);

 

// 透明画刷

CBrush*pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

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;

}

 

//为了使得图形保存和重绘,每次绘图操作结束后,就构造一个相应的CGraph对象,并将该对象的地址保//存到 m_ptrArray对象中,如果想要增加一个成员,可以用Add方法,来增加一个void指针所指向的对象

   CGraph*pGraph=new CGraph(m_nDrawType,m_ptOrigin,point,m_clr);

   m_ptrArray.Add(pGraph);

 

    CView::OnLButtonUp(nFlags, point);

}

4、状态栏直接修改标题,程序改为CAD

IDR_MAINFRAME字符串资源直接修改,字符串2,没有指定就是无标题

本例中指定了CAD,可以直接修改

用VS2008的MFC写的CAD画图程序2017.12.15_第6张图片

5、显示鼠标坐标,显示系统时间


用VS2008的MFC写的CAD画图程序2017.12.15_第7张图片

程序左下角显示鼠标当前坐标

程序右下角显示系统当前时间

程序代码如下:

首先实现显示鼠标当前坐标,添加WM_MOUSEMOVE消息响应函数

void CGraphicView::OnMouseMove(UINTnFlags, CPoint point)

{

//添加坐标显示

  //VC2005及更高版本默认使用Unicode字符集,CString里存的是宽字符,也就是wchar_t,而不再是//char。你可以这么写:

//*strDate.Format(_T("%4d-%2d-%2d"),st.wYear,st.wMonth,st.wDay);

//strTime.Format(_T("%4d:%2d:%2d"),st.wHour,st.wMinute,st.wSecond);

//以后写程序的时候,定义字符串变量,不要用char*,而用TCHAR*。所有字符串常量,不要直接用//"",而要用_T("")。举个例子:

//TCHAR*str = _T( "Hello, World" );

//  MessageBox( _T( "Hello" )); */

//所以VC6.0和VS2008还是有一点区别,没有_T还是会报错

 

//实现的过程中,首先调用GetParent()得到视类窗口的指针,即框架窗口

//因为其返回值是CWnd指针,再强制转换为(CMainFrame*)

//在视类cpp增加框架类的头文件MainFrm.h

//修改成员变量m_wndStatusBar保护类型改为公有类型

    CString str;

    str.Format(_T("x=%d,y=%d"),point.x,point.y);

((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);

    CView::OnMouseMove(nFlags, point);

}

接着再显示系统当前时间

先在资源String Table中增加IDS_TIMER,,然后再将字符串资源ID加入到indicator数组中,在框架类cpp

static UINTindicators[] =

{

    ID_SEPARATOR,          

    IDS_TIMER,//增加时间

    ID_INDICATOR_CAPS,

    ID_INDICATOR_NUM,

    ID_INDICATOR_SCRL,

};

在OnCreate函数里面实现时间显示

int CMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct)

{

    //系统自带程序代码,省略显示

    //状态栏显示系统时间,让时间动起来,设置定时器,同时在ontimer消息响应函数中实现

    SetTimer(1,1000,NULL);//设置定时器

 

    CTime t=CTime::GetCurrentTime();

    CString str=t.Format("%H:%M:%S");

    CClientDC dc(this);

    CSize sz=dc.GetTextExtent(str);

    int index=0;

    index=m_wndStatusBar.CommandToIndex(IDS_TIMER);

m_wndStatusBar.SetPaneInfo(index,IDS_TIMER,SBPS_NORMAL,sz.cx);

    m_wndStatusBar.SetPaneText(index,str);

 

    return 0;

}

在框架类增加消息响应函数WM_TIMER

void CMainFrame::OnTimer(UINT_PTRnIDEvent)

{

//让状态栏时间动起来

    CTime t=CTime::GetCurrentTime();

    CString str=t.Format("%H:%M:%S");

    CClientDC dc(this);

    CSize sz=dc.GetTextExtent(str);

m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);

    m_wndStatusBar.SetPaneText(1,str);

 

    CFrameWnd::OnTimer(nIDEvent);

}

6选择颜色

增加颜色的消息响应函数,实现代码如下

void CGraphicView::OnColor()

{

    //颜色实现与保存

    CColorDialog dlg;

    //默认与颜色打开CC_RGBINIT,颜色初始保存,CC_FULLOPEN对话框全部打开

    dlg.m_cc.Flags |=CC_RGBINIT | CC_FULLOPEN;

    dlg.m_cc.rgbResult=m_clr;

    if (IDOK==dlg.DoModal())

    {

       m_clr=dlg.m_cc.rgbResult;

    }

}

8、选择字体,先增加两个成员变量

CFont m_font CString m_strFontName再增加消息响应函数

void CGraphicView::OnFont()

{

    //实现字体打开

    CFontDialog dlg;

    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();

    }

}

然后在OnDraw函数中将所选的字体输出到屏幕

void CGraphicView::OnDraw(CDC*pDC)

{

    CGraphicDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

   

 

//把所选择的字体显示在屏幕

    CFont *pOldFont=pDC->SelectObject(&m_font);

    pDC->TextOut(0,0,m_strFontName);

    pDC->SelectObject(pOldFont);

 

 if (!pDoc)

       return;

}

9、设置线宽、线型、显示示例

设置IDD_DLG_SETING,增加一个新类CSettingDlg,然后为编辑框关联添加两个成员变量,保存当前选择的线宽、线型,三个复选框要选择Group选项

UINT m_nLineWidth

int  m_nLineStyle

COLORREF m_clr

只是关联值,选择的时候要选value

用VS2008的MFC写的CAD画图程序2017.12.15_第8张图片

在设置菜单处增加命令响应函数

设置IDM_SETTING,程序代码为:

void CGraphicView::OnSetting()

{

    //线宽,线型实现与保存,还有颜色

    CSettingDlg dlg;

    dlg.m_nLineWidth=m_nLineWidth;

    dlg.m_nLineStyle=m_nLineStyle;

    dlg.m_clr=m_clr;

    if(IDOK==dlg.DoModal())

    {

       m_nLineWidth=dlg.m_nLineWidth;

       m_nLineStyle=dlg.m_nLineStyle;

       m_clr=dlg.m_clr;

    }

}同时,在CGraphicView中加上SettingDlg.h头文件

最后,将所选的线宽、线型的数据作为示例显示出来,示例IDC_SAMPLE

实现的代码为:

实现的原理为:对编辑框控件来说,当用户在其上面对文本进行改变时,它会向对话框发送EN_CHANGE的消息,当用户单击单选按钮时,该按钮会向对话框发送BN_CLICKED的消息。所以对这四个控件添加消息响应函数。

首先添加Invalidate()函数让窗口无效,当下一次发生WM_PAINT消息时,重绘窗口,在OnPaint函数中实现。

void CSettingDlg::OnEnChangeLineWidth()

{

Invalidate();

}

void CSettingDlg::OnBnClickedRadio1()

{

    Invalidate();

}

void CSettingDlg::OnBnClickedRadio2()

{

    Invalidate();

}

void CSettingDlg::OnBnClickedRadio3()

{

    Invalidate();

}

void CSettingDlg::OnPaint()

{

    CPaintDC dc(this); // device context forpainting

 

    UpdateData();//必须用的

    CPen pen(m_nLineStyle,m_nLineWidth,m_clr);

    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);

}

10、图形的保存与重绘

需要建立一个新类,来保存绘制线型、起点、终点、颜色,类名CGraph,直接添加,无基类!

增加变量:

public:

    CGraph(void);

    CGraph::CGraph(UINT m_nDrawType,CPoint m_ptOrigin,CPointm_ptEnd,COLORREF m_clr);

    ~CGraph(void);

    UINT m_nDrawType;

    CPoint m_ptOrigin;

    CPoint m_ptEnd;

    COLORREF m_clr;

提供带参数的构造函数

CGraph::CGraph(UINTm_nDrawType,CPoint m_ptOrigin,CPoint m_ptEnd,COLORREF m_clr)

{

    this->m_nDrawType=m_nDrawType;

    this->m_ptOrigin=m_ptOrigin;

    this->m_ptEnd=m_ptEnd;

    this->m_clr=m_clr;

}

在CGraphicView中增加一个集合类的变量CPtrArraym_ptrArray,每次操作结束后,就构造一个CGraph的对象,并将该对象的地址保存在m_ptrArray对象中,见上面OnLButtonUp消息函数中代码

CGraph*pGraph=new CGraph(m_nDrawType,m_ptOrigin,point,m_clr);

   m_ptrArray.Add(pGraph);

 

同时增加Graph.h头文件

最后在CGraphicView的OnDraw函数中,重绘出来

void CGraphicView::OnDraw(CDC*pDC)

{

    CGraphicDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    //把图形全部重新绘制一遍

    CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

    pDC->SelectObject(pBrush);

    int j=m_ptrArray.GetSize();

    for (int i=0;i

    {

       CGraph * pGraph = (CGraph *)m_ptrArray.GetAt(i);

       CPen pen(m_nLineStyle,m_nLineWidth,pGraph->m_clr);

        CPen*pOldPen =  pDC->SelectObject(&pen);

       switch(pGraph->m_nDrawType)

       {

       case 1:

           pDC->SetPixel(pGraph->m_ptEnd,m_clr);

           pDC->SelectObject(pOldPen);

           break;

       case 2:

           pDC->MoveTo(pGraph->m_ptOrigin);

           pDC->LineTo(pGraph->m_ptEnd);

           pDC->SelectObject(pOldPen);

           break;

       case 3:

           pDC->Rectangle(CRect(pGraph->m_ptOrigin,pGraph->m_ptEnd));

              pDC->SelectObject(pOldPen);

           break;

       case 4:

          pDC->Ellipse(CRect(pGraph->m_ptOrigin,pGraph->m_ptEnd));

           pDC->SelectObject(pOldPen);

           break;

       }

    }

    if (!pDoc)

       return;

}

全部完成!


你可能感兴趣的:(自学)