1 实验目的和要求
- 熟悉开发环境,使用MFC封装函数绘制简单图形;
- 在OnDraw中,使用MFC封装函数(MoveTo,LineTo,Rectangle,Ellipse等)绘制点、线、矩形、椭圆/圆。
- 最终完成鼠标绘制图形
2 基本原理
MFC是微软基础类库
3 主要仪器与设备
Window10,Visual Studio 2019
4 实验步骤/数据处理与结果
4.1点击自动生成图案版本
-
(1)设计窗口
-
(2)使用类向导快速建立消息映射
-
(3)点击跳转编写处理函数
①点函数
void CEXP1View::OnDrawPoint()
{
// TODO: 在此添加命令处理程序代码
CDC* pDC = GetDC();
pDC->SetPixel(200, 200, RGB(255, 0, 0));
}
②直线函数
void CEXP1View::OnDrawLinear()
{
// TODO: 在此添加命令处理程序代码
CClientDC dc(this);
dc.MoveTo(20, 20);
dc.LineTo(100, 100);
}
③折线函数
void CEXP1View::OnDrawLine()
{
// TODO: 在此添加命令处理程序代码
CClientDC dc(this);
POINT p[4];
p[0].x = 400;
p[0].y = 300;
p[1].x = 500;
p[1].y = 500;
p[2].x = 300;
p[2].y = 200;
p[3].x = 200;
p[3].y = 500;
dc.Polyline(p, 4);
}}
④矩形函数
void CEXP1View::OnDrawRectangular()
{
// TODO: 在此添加命令处理程序代码
CClientDC dc(this);
dc.Rectangle(500, 500, 800, 700);
⑤椭圆函数
void CEXP1View::OnDrawElliptic()
{
// TODO: 在此添加命令处理程序代码
CClientDC dc(this);
dc.Ellipse(400, 300, 500,500);
}
- (4)运行结果:
4.2鼠标绘制生成
- (1)修改CEXP1View.h,声明绘图函数需要的参数变量
#pragma once
#include<afxtempl.h>
class CEXP1View : public CView
{
protected: // 仅从序列化创建
CEXP1View() noexcept;
DECLARE_DYNCREATE(CEXP1View)
// 特性
public:
CEXP1Doc* GetDocument() const;
//起始点与终点
CPoint m_ptStart, m_ptEnd;
//制图类型
UINT m_Type;
//数组
CArray<CPoint, CPoint> m_ptArray;
// 操作
public:
……
}
- (2)修改4.1中(3)中的绘图函数:
void CEXP1View::OnDrawPoint()
{
// TODO: 在此添加命令处理程序代码
//CDC* pDC = GetDC();
//pDC->SetPixel(200, 200, RGB(0, 0, 255));
m_Type = 0;
}
void CEXP1View::OnDrawLinear()
{
// TODO: 在此添加命令处理程序代码
//CClientDC dc(this);
//dc.MoveTo(20, 20);
//dc.LineTo(100, 100);
m_Type = 1;
}
void CEXP1View::OnDrawLine()
{
// TODO: 在此添加命令处理程序代码
//CClientDC dc(this);
//POINT p[4];
//p[0].x = 200;
//p[0].y = 300;
//p[1].x = 300;
//p[1].y = 400;
//p[2].x = 300;
//p[2].y = 450;
//p[3].x = 200;
//p[3].y = 500;
//dc.Polyline(p, 4);
m_Type = 4;
}
void CEXP1View::OnDrawRectangular()
{
// TODO: 在此添加命令处理程序代码
/*CClientDC dc(this);
dc.Rectangle(400, 400, 500, 500);*/
m_Type = 2;
}
void CEXP1View::OnDrawRound()
{
// TODO: 在此添加命令处理程序代码
//CClientDC dc(this);
//dc.Ellipse(200, 200, 300, 300);
m_Type = 3;
}
- (3)编写鼠标左键按下与抬起,以及左键双击的处理函数(这个函数是用来取消折线的绘制)
左键抬起
void CEXP1View::OnLButtonUp(UINT nFlags, CPoint point){
// TODO: 在此添加消息处理程序代码和/或调用默认值
CView::OnLButtonUp(nFlags, point);
ReleaseCapture();
//记鼠标录抬起位置
m_ptEnd = point;
m_ptArray[1] = point;
/*m_ptArray.Add(point);*/
//设备环境对象
CClientDC dc(this);
CDC* pDC = GetDC();
//使用case流程语句实现跳转
switch (m_Type){
case 0: //点
pDC->SetPixel(m_ptStart.x,m_ptStart.y, RGB(0, 0, 255));
break;
case 1: //直线
dc.MoveTo(m_ptStart);
dc.LineTo(m_ptEnd);
break;
case 2: //矩形
dc.Rectangle(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y);
break;
case 3: //椭圆和圆
dc.Ellipse(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y);
break;
case 4: //折线
if (mask == 1) {
dc.Polyline(m_ptArray, 2);
}
else{
m_ptArray[0].x = 0;
m_ptArray[1].x = 0;
}
m_ptArray[0] = m_ptArray[1];
break;
default:
break;
}
//释放
ReleaseDC(pDC);
}
左键按下
void CEXP1View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
SetCapture();
//记录按下位置的坐标
m_ptStart = point;
//添加按下位置到数组中
//注意起始点的位置是x与y一样!!!
mask = 1;
if ((m_ptArray[0].x != 0 )& (m_ptArray[0].y != 0) &(m_ptArray[1].x != 0) &(m_ptArray[1].y != 0))
{
m_ptArray[1] = point;
}
else
{
m_ptArray[0] = point;
}
//m_ptArray.Add(point);
CView::OnLButtonDown(nFlags, point);
}
左键双击
void CEXP1View::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//用于清空数组,结束折线绘制
mask = 0;
m_ptArray[0].x = 0;
m_ptArray[1].x = 0;
CView::OnLButtonDblClk(nFlags, point);
}
- 结果