1、 题 目 具有基本功能的矢量绘图软件 院、系(部) 专业及班级 学 号 姓 名 日 期 1 题目要求使用 VS 环境编写 MFC 类程序,制作一个具有基本功能的矢量绘图软件。2 需求分析1本实验的”矢量绘图” 软件是一个具有 Office 视觉样式的单文档应用程序,在应用程序的主框架窗口中包含一个 Ribbon 功能区,其中有两个标签选项卡: “主页”和“绘图” 。当选择“绘图”选项卡后,将列出一些简单的绘图工具。选择某个绘图工具后,既可以再客户区绘制相应的图形;单击面板上的“画笔颜色”或“填充颜色”按钮后,将淡出一个颜色对话框以分别设置绘图的颜色及填充图形的颜色,而当单击“文本”按钮后,可以
2、在客户区输入文本内容。3 总体设计3.1 业务逻辑设计2用户开始绘图是否更改颜色选择绘图工具 选择颜色NY绘制图形是否擦除绘制图形是否继续绘制图形Y是否输入文字描述N是否输入文字描述N输出显示YNY输入文字33.2 界面逻辑设计使用 VS 新建项目,选择 VC+项下的“MFC”项目类型,在弹出的“应用程序类型”界面中选择如图所示,然后进行一系列的设置后生成所需界面。所生成界面如图:43.3 数据库设计(如涉及数据库写这一部分)数据库设计这里只给出表结构。4 详细设计MyDraw111view.h#pragma once#include “Draw.h“#define SHAPE_NULL 0#
3、define SHAPE_PEN 1#define SHAPE_TEXT 2#define SHAPE_LINE 3#define SHAPE_RECT 4#define SHAPE_ELLIPSE 5#define SHAPE_CIRCLE 6#define SHAPE_ERASER 7class CMydraw111View : public CView protected: / 仅从序列化创建CMydraw111View();DECLARE_DYNCREATE(CMydraw111View)/ 特性public:CMydraw111Doc* GetDocument() const;/ 操
4、作public:BOOL m_bDrawShape;CPoint m_ptOrigin; /直线起始点CPoint m_ptPrv; / 直线终止点/ 重写public:virtual void OnDraw(CDC* pDC); / 重写以绘制该视图virtual BOOL PreCreateWindow(CREATESTRUCTpublic:virtual CMydraw111View();#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext#endif5protected:afx_msg
5、void OnFilePrintPreview();afx_msg void OnRButtonUp(UINT nFlags, CPoint point);afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);DECLARE_MESSAGE_MAP()public:int m_nDrawShape; /绘图类型COLORREF m_crDrawColor;COLORREF m_crFillColor;afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnDrawP
6、en();afx_msg void OnDrawLine();afx_msg void OnUpdateDrawPen(CCmdUI *pCmdUI);afx_msg void OnUpdateDrawLine(CCmdUI *pCmdUI);afx_msg void OnDrawColor();afx_msg void OnFillColor();afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnLBu
7、ttonUp(UINT nFlags, CPoint point);BOOL m_bShowCaret;BOOL m_bInputTEXT;POINT m_ptCaretPos;CString m_strTextBuf;LOGFONT m_lfTextFont;afx_msg void OnSetFocus(CWnd* pOldWnd);afx_msg void OnKillFocus(CWnd* pNewWnd);afx_msg void OnDrawText();afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);afx_m
8、sg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);afx_msg void OnDrawRect();afx_msg void OnUpdateDrawRect(CCmdUI *pCmdUI);afx_msg void OnDrawEllipse();afx_msg void OnUpdateDrawEllipse(CCmdUI *pCmdUI);afx_msg void OnDra
9、wCircle();afx_msg void OnUpdateDrawCircle(CCmdUI *pCmdUI);afx_msg void OnDrawEraser();afx_msg void OnUpdateDrawEraser(CCmdUI *pCmdUI);afx_msg void OnUpdateDrawText(CCmdUI *pCmdUI);#ifndef _DEBUG / Mydraw111View.cpp 中的调试版本inline CMydraw111Doc* CMydraw111View:GetDocument() const return reinterpret_cas
10、t(m_pDocument); #endif6MyDraw111view.cpp#include “stdafx.h“/ SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的/ ATL 项目中进行定义,并允许与该项目共享文档代码。#ifndef SHARED_HANDLERS#include “Mydraw111.h“#endif#include “Mydraw111Doc.h“#include “Mydraw111View.h“#include “Draw.h“#ifdef _DEBUG#define new DEBUG_NEW#endif/ CMydraw111View
11、IMPLEMENT_DYNCREATE(CMydraw111View, CView)BEGIN_MESSAGE_MAP(CMydraw111View, CView)ON_WM_CONTEXTMENU()ON_WM_RBUTTONUP()ON_WM_CREATE()ON_COMMAND(ID_DRAW_PEN, / CMydraw111View 绘制void CMydraw111View:OnDraw(CDC* pDC) CMydraw111Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;CDC MemDC;CBitma
12、p MemBitmap;CRect rect;GetClientRect(MemDC.CreateCompatibleDC(NULL);MemBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);CBitmap *pOldBit=MemDC.SelectObject(MemDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255);/直线绘制代码int nIndex=pDoc-GetNumLines();/取得线段数量TRACE(“nIndex1=%dn“,nIn
13、dex);/调试程序8/循环画出每一段线段while(nIndex-) TRACE(“nIndex2=%dn“,nIndex);pDoc-GetLine(nIndex)-Draw(/其余划线代码pDC-BitBlt(0,0,rect.right,rect.bottom,/ TODO: 在此处为本机数据添加绘制代码void CMydraw111View:OnRButtonUp(UINT /* nFlags */, CPoint point)ClientToScreen(OnContextMenu(this, point);void CMydraw111View:OnContextMenu(CWn
14、d* /* pWnd */, CPoint point)#ifndef SHARED_HANDLERStheApp.GetContextMenuManager()-ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);#endif/ CMydraw111View 诊断#ifdef _DEBUGvoid CMydraw111View:AssertValid() constCView:AssertValid();void CMydraw111View:Dump(CDumpContextCMydraw111Doc* CMydraw11
15、1View:GetDocument() const / 非调试版本是内联的9ASSERT(m_pDocument-IsKindOf(RUNTIME_CLASS(CMydraw111Doc);return (CMydraw111Doc*)m_pDocument;#endif /_DEBUG/ CMydraw111View 消息处理程序int CMydraw111View:OnCreate(LPCREATESTRUCT lpCreateStruct)if (CView:OnCreate(lpCreateStruct) = -1)return -1;m_nDrawShape=SHAPE_PEN;m_
16、crDrawColor=RGB(0,0,0); /黑色m_crFillColor=RGB(255,255,255); /白色m_bDrawShape=FALSE;m_strTextBuf=“;m_bInputTEXT=FALSE;m_bShowCaret=FALSE;m_ptCaretPos=CPoint(0,0);memset(m_lfTextFont.lfHeight=-13;m_lfTextFont.lfCharSet=GB2312_CHARSET;lstrcpy(m_lfTextFont.lfFaceName,_T(“宋体“);return 0;void CMydraw111View:
17、OnDrawPen()/ TODO: 在此添加命令处理程序代码m_nDrawShape=SHAPE_PEN;if(m_bShowCaret)HideCaret();m_bShowCaret=FALSE;void CMydraw111View:OnDrawLine()/ TODO: 在此添加命令处理程序代码m_nDrawShape=SHAPE_LINE;void CMydraw111View:OnDrawRect()m_nDrawShape=SHAPE_RECT;void CMydraw111View:OnDrawEllipse()10m_nDrawShape=SHAPE_ELLIPSE;voi
18、d CMydraw111View:OnDrawCircle()m_nDrawShape=SHAPE_CIRCLE;/ TODO: 在此添加命令处理程序代码void CMydraw111View:OnDrawEraser()m_nDrawShape=SHAPE_ERASER;/ TODO: 在此添加命令处理程序代码void CMydraw111View:OnUpdateDrawEraser(CCmdUI *pCmdUI)pCmdUI-SetCheck(m_nDrawShape=SHAPE_ERASER);/ TODO: 在此添加命令更新用户界面处理程序代码void CMydraw111View:
19、OnUpdateDrawCircle(CCmdUI *pCmdUI)pCmdUI-SetCheck(m_nDrawShape=SHAPE_CIRCLE);/ TODO: 在此添加命令更新用户界面处理程序代码void CMydraw111View:OnUpdateDrawEllipse(CCmdUI *pCmdUI)pCmdUI-SetCheck(m_nDrawShape=SHAPE_ELLIPSE);void CMydraw111View:OnUpdateDrawRect(CCmdUI *pCmdUI)pCmdUI-SetCheck(m_nDrawShape=SHAPE_RECT);void
20、CMydraw111View:OnUpdateDrawPen(CCmdUI *pCmdUI) pCmdUI-SetCheck(m_nDrawShape=SHAPE_PEN);/ TODO: 在此添加命令更新用户界面处理程序代码11void CMydraw111View:OnUpdateDrawLine(CCmdUI *pCmdUI)pCmdUI-SetCheck(m_nDrawShape=SHAPE_LINE);/ TODO: 在此添加命令更新用户界面处理程序代码void CMydraw111View:OnDrawColor()/ TODO: 在此添加命令处理程序代码CMFCColorDial
21、og dlg(m_crDrawColor);if(dlg.DoModal()!=IDOK) return;m_crDrawColor=dlg.GetColor();void CMydraw111View:OnFillColor()/ TODO: 在此添加命令处理程序代码CMFCColorDialog dlg(m_crFillColor);if(dlg.DoModal()!=IDOK) return;m_crFillColor=dlg.GetColor();void CMydraw111View:OnLButtonDown(UINT nFlags, CPoint point)/ TODO: 在此
22、添加消息处理程序代码和/或调用默认值if (m_nDrawShape!=SHAPE_TEXT)m_bDrawShape=TRUE; /开始绘图switch(m_nDrawShape)case SHAPE_LINE:m_ptOrigin=m_ptPrv=point;break;case SHAPE_PEN:m_ptOrigin=m_ptPrv=point;break;default:m_ptOrigin=m_ptPrv=point;12break;SetCapture();else /输出文本m_ptCaretPos=point;SetCaretPos(point);if(!m_bShowCar
23、et)ShowCaret();m_strTextBuf=“;m_bShowCaret=TRUE;m_bInputTEXT=TRUE;m_bDrawShape=FALSE;CView:OnLButtonDown(nFlags, point);void CMydraw111View:OnMouseMove(UINT nFlags, CPoint point) / TODO: 在此添加消息处理程序代码和/或调用默认值if(m_bDrawShape) CClientDC dc(this);CPen *pOldPen,pen;pen.CreatePen(PS_SOLID,1,m_crDrawColor)
24、;pOldPen=(CPen*)dc.SelectObject(CBrush *pOldBrush,brush;brush.CreateSolidBrush(m_crFillColor);pOldBrush=(CBrush*)dc.SelectObject(dc.SetROP2(R2_NOTXORPEN);switch(m_nDrawShape)case SHAPE_LINE:dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptPrv);dc.MoveTo(m_ptOrigin);dc.LineTo(point);m_ptPrv=point;break;case SHAPE
25、_PEN:13m_ptPrv.x=point.x;m_ptPrv.y=point.y;dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptPrv);m_ptOrigin.x=m_ptPrv.x;m_ptOrigin.y=m_ptPrv.y;m_ptPrv=point;break;case SHAPE_RECT:dc.Rectangle(CRect(m_ptOrigin,m_ptPrv);dc.Rectangle(CRect(m_ptOrigin,point);m_ptPrv=point;break;case SHAPE_CIRCLE:m_ptPrv.y=m_ptPrv.x-
26、m_ptOrigin.x+m_ptOrigin.y;dc.Ellipse(CRect(m_ptOrigin,m_ptPrv);point.y=point.x-m_ptOrigin.x+m_ptOrigin.y;dc.Ellipse(CRect(m_ptOrigin,point);m_ptPrv=point;case SHAPE_ELLIPSE:dc.Ellipse(CRect(m_ptOrigin,m_ptPrv);dc.Ellipse(CRect(m_ptOrigin,point);m_ptPrv=point;break;case SHAPE_ERASER:CBrush brush(RGB(
27、255,255,255);/创建一个白色画刷CClientDC dc(this);/创建并获得设备描述表CRect rect;rect.top=point.y-8;rect.left=point.x-8;rect.bottom=rect.top+8;rect.right=rect.left+8;dc.FillRect(rect,/利用白色画刷填充鼠标拖拽过程中形成的矩形区域break;dc.SelectObject(pOldPen);dc.SelectObject(pOldBrush);brush.DeleteObject();pen.DeleteObject();14CView:OnMous
28、eMove(nFlags, point);void CMydraw111View:OnLButtonUp(UINT nFlags, CPoint point)/ TODO: 在此添加消息处理程序代码和/或调用默认值if(m_bDrawShape) CMydraw111Doc *pDoc=GetDocument();ASSERT_VALID(pDoc);switch (m_nDrawShape)case SHAPE_LINE:pDoc-AddLine(m_crDrawColor,m_crFillColor,m_ptOrigin,point);break;ReleaseCapture();m_bD
29、rawShape=FALSE;CView:OnLButtonUp(nFlags, point);void CMydraw111View:OnSetFocus(CWnd* pOldWnd)CView:OnSetFocus(pOldWnd);CreateSolidCaret(2,-m_lfTextFont.lfHeight);SetCaretPos(m_ptCaretPos);if(m_bShowCaret)ShowCaret();/ TODO: 在此处添加消息处理程序代码void CMydraw111View:OnKillFocus(CWnd* pNewWnd)CView:OnKillFocus
30、(pNewWnd);m_ptCaretPos=GetCaretPos();if(m_bShowCaret)HideCaret();DestroyCaret();15/ TODO: 在此处添加消息处理程序代码void CMydraw111View:OnDrawText()/ TODO: 在此添加命令处理程序代码m_nDrawShape=SHAPE_TEXT;if(m_bShowCaret)HideCaret();m_bShowCaret=FALSE;m_strTextBuf=“;void CMydraw111View:OnUpdateDrawText(CCmdUI *pCmdUI)pCmdUI-
31、SetCheck(m_nDrawShape=SHAPE_TEXT);/ TODO: 在此添加命令更新用户界面处理程序代码void CMydraw111View:OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)/ TODO: 在此添加消息处理程序代码和/或调用默认值if(m_nDrawShape=SHAPE_TEXT) CSize sizeText;CFont ft,*pOld;CClientDC dc(this);CRect rect;GetClientRect(int nLength=m_strTextBuf.GetLength();ft.Creat
32、eFontIndirectW(pOld=(CFont*)dc.SelectObject(dc.SetTextColor(m_crDrawColor);HideCaret();switch(nChar) case 8:if(nLength0)m_strTextBuf.SetAt(nLength-1, );dc.TextOutW(m_ptCaretPos.x,m_ptCaretPos.y,m_strTextBuf);if(nLength0)m_strTextBuf.Delete(nLength-1);dc.TextOutW(m_ptCaretPos.x,m_ptCaretPos.y,m_strTe
33、xtBuf);sizeText=dc.GetTextExtent(m_strTextBuf);SetCaretPos(CPoint(m_ptCaretPos.x+sizeText.cx,m_ptCaretPos.y);break;case 13:16dc.TextOutW(m_ptCaretPos.x,m_ptCaretPos.y,m_strTextBuf);m_strTextBuf=“;sizeText=dc.GetTextExtent(m_strTextBuf);if(m_ptCaretPos.y+sizeText.cyLoadCursor(IDC_CURSOR1);else if (m_
34、nDrawShape=SHAPE_TEXT)SetCursor(AfxGetApp()-LoadCursor(IDC_CURSOR2);else if(m_nDrawShape=SHAPE_ERASER)SetCursor(AfxGetApp()-LoadCursor(IDC_CURSOR3);else SetCursor(AfxGetApp()-LoadCursor(IDC_CURSOR4);return TRUE;17void CMydraw111View:OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)CView:OnAc
35、tivate(nState, pWndOther, bMinimized);CLine();/ TODO: 在此处添加消息处理程序代码文档类:MyDraw111Doc.h#pragma once#include #include “Line.h“class CMydraw111Doc : public CDocumentpublic:CTypedPtrArray m_LineArray;CLine*GetLine(int nIndex);void AddLine(COLORREF ColorPen,COLORREF ColorBrush,CPoint pt1,CPoint pt2);int G
36、etNumLines();protected: / 仅从序列化创建CMydraw111Doc();DECLARE_DYNCREATE(CMydraw111Doc)/ 特性public:virtual void DeleteContents();/ 操作public:/ 重写public:virtual BOOL OnNewDocument();virtual void Serialize(CArchive#ifdef SHARED_HANDLERSvirtual void InitializeSearchContent();virtual void OnDrawThumbnail(CDC#en
37、dif / SHARED_HANDLERS/ 实现public:virtual CMydraw111Doc();#ifdef _DEBUGvirtual void AssertValid() const;18virtual void Dump(CDumpContext#endifprotected:/ 生成的消息映射函数protected:DECLARE_MESSAGE_MAP()#ifdef SHARED_HANDLERS/ 用于为搜索处理程序设置搜索内容的 Helper 函数void SetSearchContent(const CString#endif / SHARED_HANDLER
38、S;MyDraw111Doc.cpp#include “stdafx.h“/ SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的/ ATL 项目中进行定义,并允许与该项目共享文档代码。#ifndef SHARED_HANDLERS#include “Mydraw111.h“#endif#include “Mydraw111Doc.h“#include #ifdef _DEBUG#define new DEBUG_NEW#endif/ CMydraw111DocIMPLEMENT_DYNCREATE(CMydraw111Doc, CDocument)BEGIN_MESSAG
39、E_MAP(CMydraw111Doc, CDocument)END_MESSAGE_MAP()/ CMydraw111Doc 构造/析构CMydraw111Doc:CMydraw111Doc()/ TODO: 在此添加一次性构造代码19CMydraw111Doc:CMydraw111Doc()BOOL CMydraw111Doc:OnNewDocument()if (!CDocument:OnNewDocument()return FALSE;/ TODO: 在此添加重新初始化代码/ (SDI 文档将重用该文档)return TRUE;/ CMydraw111Doc 序列化void CMyd
40、raw111Doc:Serialize(CArchiveelsem_LineArray.Serialize(ar);#ifdef SHARED_HANDLERS/ 缩略图的支持void CMydraw111Doc:OnDrawThumbnail(CDCCString strText = _T(“TODO: implement thumbnail drawing here“);LOGFONT lf;CFont* pDefaultGUIFont = CFont:FromHandle(HFONT) GetStockObject(DEFAULT_GUI_FONT);pDefaultGUIFont-Ge
41、tLogFont(lf.lfHeight = 36;CFont fontDraw;20fontDraw.CreateFontIndirect(CFont* pOldFont = dc.SelectObject(dc.DrawText(strText, lprcBounds, DT_CENTER | DT_WORDBREAK);dc.SelectObject(pOldFont);/ 搜索处理程序的支持void CMydraw111Doc:InitializeSearchContent()CString strSearchContent;/ 从文档数据设置搜索内容。/ 内容部分应由“;”分隔/ 例
42、如: strSearchContent = _T(“point;rectangle;circle;ole object;“);SetSearchContent(strSearchContent);void CMydraw111Doc:SetSearchContent(const CStringelseCMFCFilterChunkValueImpl *pChunk = NULL;ATLTRY(pChunk = new CMFCFilterChunkValueImpl);if (pChunk != NULL)pChunk-SetTextValue(PKEY_Search_Contents, va
43、lue, CHUNK_TEXT);SetChunkValue(pChunk);#endif / SHARED_HANDLERS/ CMydraw111Doc 诊断#ifdef _DEBUGvoid CMydraw111Doc:AssertValid() constCDocument:AssertValid();21void CMydraw111Doc:Dump(CDumpContext#endif /_DEBUG/ CMydraw111Doc 命令void CMydraw111Doc:AddLine(COLORREF ColorPen,COLORREF ColorBrush,CPoint pt
44、1,CPoint pt2)CLine *pLine=new CLine(ColorPen,ColorBrush,pt1,pt2);m_LineArray.Add(pLine);SetModifiedFlag();CLine *CMydraw111Doc:GetLine(int nIndex) if(nIndexm_LineArray.GetUpperBound()return NULL;return m_LineArray.GetAt(nIndex);int CMydraw111Doc:GetNumLines() return m_LineArray.GetSize();void CMydraw111Doc:DeleteContents()int nIndex=GetNumLines();while(nIndex-)delete m_LineArray.GetAt(nIndex);m_LineArray.RemoveAll();CDocument:DeleteContents();5 测试与实现226 总结通过这次实验,我对 C+的 MFC 功能模块有了更深的理解,更加熟练的掌握了对此类软件的编写。软件的功能依然不是很完善,例如在 DC 面板被改变时,原本的绘制的图形会消失,我对图形进行了保存处理并在 OnDraw 函数中进行了重绘,但还是没有办法解决这个问题。