实验八 MFC鼠标作图编程实验
电气1002班 李震 学号10053212
一、 实验目的
(1) 熟悉Visual C++6.0开发环境;
(2) 掌握应用MFC类库编写鼠标绘图程序的方法;
(3) 掌握MFC环境中绘图函数的使用方法。
二、 实验内容
创建一个单文档应用程序,实现鼠标的绘图功能。要求:
(1) 创建一个工具栏,有线段、矩形、椭圆三个按钮;
(2) 绘图前,选择工具栏上的按钮,确定图形的形状。按下鼠标左键,开始绘图,结合鼠标光标的坐标值,来确定图形的形状和大小,并随着鼠标的移动在屏幕上实时绘制图形,放开鼠标左键,确定最后的图形,绘制在屏幕上。
三、 程序清单
// DemoView.cpp : implementation of the CDemoView class
#include "stdafx.h"
#include "Demo.h"
#include "DemoDoc.h"
#include "DemoView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDemoView
IMPLEMENT_DYNCREATE(CDemoView, CView)
BEGIN_MESSAGE_MAP(CDemoView, CView)
//{{AFX_MSG_MAP(CDemoView)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_COMMAND(ID_FILEOP_OPEN, OnFileopOpen)
ON_UPDATE_COMMAND_UI(ID_FILEOP_OPEN, OnUpdateFileopOpen)
ON_COMMAND(ID_FILEOP_SAVE, OnFileopSave)
ON_UPDATE_COMMAND_UI(ID_FILEOP_SAVE, OnUpdateFileopSave)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND_RANGE(ID_DRAW_LINE,ID_DRAW_ELLIPSE,OnDrawType)
ON_UPDATE_COMMAND_UI_RANGE(ID_DRAW_LINE,ID_DRAW_ELLIPSE,OnDrawTypeUI)
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDemoView construction/destruction
CDemoView::CDemoView()
{
// TODO: add construction code here
m_nPicNum = 0;
m_nDrawType = 0;
}
CDemoView::~CDemoView()
{
}
BOOL CDemoView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CDemoView drawing
void CDemoView::OnDraw(CDC* pDC)
{
CDemoDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CPen BluePen,*pOldPen;
BluePen.CreatePen(PS_SOLID,3,RGB(0,0,255));
pOldPen = pDC->SelectObject(&BluePen);
for(int i=0; i<m_nPicNum; i++)
{
switch(m_Pic[i].m_nDrawType)
{
case 0:
pDC->MoveTo(m_Pic[i].m_nX0,m_Pic[i].m_nY0);
pDC->LineTo(m_Pic[i].m_nX1,m_Pic[i].m_nY1);
break;
case 1:
pDC->Rectangle(m_Pic[i].m_nX0,m_Pic[i].m_nY0,
m_Pic[i].m_nX1,m_Pic[i].m_nY1);
break;
case 2:
pDC->Ellipse(m_Pic[i].m_nX0,m_Pic[i].m_nY0,
m_Pic[i].m_nX1,m_Pic[i].m_nY1);
break;
}
}
pDC->SelectObject(pOldPen);
}
/////////////////////////////////////////////////////////////////////////////
// CDemoView printing
BOOL CDemoView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CDemoView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CDemoView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CDemoView diagnostics
#ifdef _DEBUG
void CDemoView::AssertValid() const
{
CView::AssertValid();
}
void CDemoView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CDemoDoc* CDemoView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDemoDoc)));
return (CDemoDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDemoView message handlers
void CDemoView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_nX0 = m_nX1 = point.x;
m_nY0 = m_nY1 = point.y;
CView::OnLButtonDown(nFlags, point);
}
void CDemoView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
CPen WhitePen,RedPen,*pOldPen;
WhitePen.CreatePen(PS_SOLID,1,RGB(255,255,255));
RedPen.CreatePen(PS_DASH,1,RGB(255,0,0));
if(nFlags & MK_LBUTTON)
{
switch(m_nDrawType)
{
case 0:
pOldPen = dc.SelectObject(&WhitePen);
dc.MoveTo(m_nX0,m_nY0);
dc.LineTo(m_nX1,m_nY1);
m_nX1 = point.x;
m_nY1 = point.y;
dc.SelectObject(&RedPen);
dc.MoveTo(m_nX0,m_nY0);
dc.LineTo(m_nX1,m_nY1);
dc.SelectObject(pOldPen);
break;
case 1:
pOldPen = dc.SelectObject(&WhitePen);
dc.Rectangle(m_nX0,m_nY0,m_nX1,m_nY1);
m_nX1 = point.x;
m_nY1 = point.y;
dc.SelectObject(&RedPen);
dc.Rectangle(m_nX0,m_nY0,m_nX1,m_nY1);
dc.SelectObject(pOldPen);
break;
case 2:
pOldPen = dc.SelectObject(&WhitePen);
dc.Ellipse(m_nX0,m_nY0,m_nX1,m_nY1);
m_nX1 = point.x;
m_nY1 = point.y;
dc.SelectObject(&RedPen);
dc.Ellipse(m_nX0,m_nY0,m_nX1,m_nY1);
dc.SelectObject(pOldPen);
break;
}
}
CView::OnMouseMove(nFlags, point);
}
void CDemoView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
CPen WhitePen,BluePen,*pOldPen;
WhitePen.CreatePen(PS_SOLID,1,RGB(255,255,255));
BluePen.CreatePen(PS_SOLID,3,RGB(0,0,255));
switch(m_nDrawType)
{
case 0:
pOldPen = dc.SelectObject(&WhitePen);
dc.MoveTo(m_nX0,m_nY0);
dc.LineTo(m_nX1,m_nY1);
m_nX1 = point.x;
m_nY1 = point.y;
dc.SelectObject(&BluePen);
dc.MoveTo(m_nX0,m_nY0);
dc.LineTo(m_nX1,m_nY1);
dc.SelectObject(pOldPen);
break;
case 1:
pOldPen = dc.SelectObject(&WhitePen);
dc.Rectangle(m_nX0,m_nY0,m_nX1,m_nY1);
m_nX1 = point.x;
m_nY1 = point.y;
dc.SelectObject(&BluePen);
dc.Rectangle(m_nX0,m_nY0,m_nX1,m_nY1);
dc.SelectObject(pOldPen);
break;
case 2:
pOldPen = dc.SelectObject(&WhitePen);
dc.Ellipse(m_nX0,m_nY0,m_nX1,m_nY1);
m_nX1 = point.x;
m_nY1 = point.y;
dc.SelectObject(&BluePen);
dc.Ellipse(m_nX0,m_nY0,m_nX1,m_nY1);
dc.SelectObject(pOldPen);
break;
}
m_Pic[m_nPicNum].m_nDrawType = m_nDrawType;
m_Pic[m_nPicNum].m_nX0 = m_nX0;
m_Pic[m_nPicNum].m_nY0 = m_nY0;
m_Pic[m_nPicNum].m_nX1 = m_nX1;
m_Pic[m_nPicNum].m_nY1 = m_nY1;
m_nPicNum++;
CView::OnLButtonUp(nFlags, point);
}
void CDemoView::OnFileopOpen()
{
// TODO: Add your command handler code here
CFileDialog dlg(TRUE);
if(dlg.DoModal() == IDOK)
{
CString szPathName;
szPathName = dlg.GetPathName();
CFile file(szPathName,CFile::modeRead);
file.Read(&m_nPicNum,sizeof(int));
for(int i=0; i<m_nPicNum; i++)
{
file.Read(&m_Pic[i],sizeof(CPic));
}
file.Close();
Invalidate();
}
}
void CDemoView::OnUpdateFileopOpen(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
void CDemoView::OnFileopSave()
{
// TODO: Add your command handler code here
CFileDialog dlg(FALSE);
if(dlg.DoModal() == IDOK)
{
CString szPathName;
szPathName = dlg.GetPathName();
CFile file(szPathName,CFile::modeCreate|CFile::modeWrite);
file.Write(&m_nPicNum,sizeof(int));
for(int i=0; i<m_nPicNum; i++)
{
file.Write(&m_Pic[i],sizeof(CPic));
}
file.Close();
}
}
void CDemoView::OnUpdateFileopSave(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
void CDemoView::OnDrawType(WORD id)
{
m_nDrawType = id - ID_DRAW_LINE;
}
void CDemoView::OnDrawTypeUI(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(pCmdUI->m_nID-ID_DRAW_LINE == m_nDrawType);
}
四、 运行结果
五、 心得体会
本次实验中,我学会了用MFC类库编辑工具栏,并在MFC程序中编写绘图文件。通过这次实验我加深了对MFC类库的理解,熟练掌握了MFC的编程方法。在实验中我遇到过一些问题,比如怎么编写工具栏、怎么在MFC中调用绘图函数、怎么用光标位置随机确定顶点坐标值等。通过查阅书籍、上网搜索等方法解决了这些问题。