计算机图形学MFC基础(基于Visual Studio2019)入门教学

本篇学习自:孔令德老师的《三维计算机图形学》

1. MFC新建一个工程

1.1 创建一个新项目

创建一个新项目

1.2 选择MFC应用

选好后,进行下一步。
在这里插入图片描述

1.3 定义项目名称,项目文件存放路径

这里定义的项目名称应当为英文,且工程会自动创建对应名称的头文件(.h)以及源文件(.cpp)。
项目文件会创建在自己定义的路径位置下。
单击创建。
在这里插入图片描述

1.4 完成创建

这里选择单文档,是因为我们只需要一个交互式窗口,完成对应的绘图任务,不必使用复杂项目工程的多文档窗口。
使用MFC标准,点击完成。
在这里插入图片描述

2. 初始工程文件的结构

完成创建后,来到如下界面,首先看看左侧的部分:
在这里插入图片描述

2.1 解决方案资源管理器

在解决方案中,包含了新建工程的所有文件,单击可查看对应文件的代码。
在这里插入图片描述

其中,各类的功能简述如下:

CAboutDlg类:帮助类,用于说明这个工程的开发信息

CMainFrame类:主框架类

CnameApp类:应用程序入口
其中“C”代表class,“类别”的意思。
“name”是在1.3中我们自定义的项目工程名。
“App”代表application应用程序。

CnameDoc类:文档类,用来管理,存放数据
“Doc”代表document文档。

CnameView类:将文档中的数据可视化,绘制图形就是通过该类实现。

2.2 类视图

在这里插入图片描述

上方窗口显示我们已经定义的类。

选中某个类别后,会在下方窗口显示该类的成员函数。

2.3 各类之间的继承关系

其中Text其实就是我们的项目工程名,例如刚刚创建的工程name。
在这里插入图片描述

2.4 OnDraw函数

我们进行绘图的代码需要写在CnameView类中的OnDraw函数里。
第一步都是将/*pDC*/替换成pDC(被注释的指针要放开),便于后文绘图使用。
在这里插入图片描述
这里对指针pDC举一个简单的例子,画一条直线。
// TODO: 在此处为本机数据添加绘制代码之后添加代码:

pDC->MoveTo(100,100); // 起点
pDC->LineTo(400,400); // 与上一个点连线连线
pDC->LineTo(200,400); 
pDC->LineTo(100,100); 

点击运行即可看到一个简单三角形。
在这里插入图片描述

3. 自定义坐标系的设置

3.1 原因

默认坐标系仅有一个象限(图左),但是平时生活中使用的都是具备四个象限的坐标系(图右),这样横纵坐标可以是负值。
在这里插入图片描述

3.2 映射模式的宏定义表

在这里插入图片描述
自定义的坐标系选择最后一个,由于是宏定义,参数写成MM_ANISOTROPIC8是等价的。

3.3 实现

自定义坐标系,将原定选定在客户区中心,x轴水平向右,y轴竖直向上。
清除之前添加的代码。
在CnameView类中的OnDraw函数里添加代码:

   CRect rect; // 矩形对象(含有宽高等)
   GetClientRect(rect); // 初始化为视区大小
   pDC->SetMapMode(8); // 选择映射模式为自定义
   pDC->SetWindowExt(rect.Width(), rect.Height()); // 设置窗口大小
   pDC->SetViewportExt(rect.Width(), -rect.Height()); // 设置视区大小
   pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2); // 设置视区原点位置
   rect.OffsetRect(-rect.Width()/2, -rect.Height()/2); //设置偏移函数,对正客户区

讲解:

  • 首先设置映射模式函数,函数原型是virtual int SetMapMode(int nMapMode);形参用于指定新的映射模式,这里自定义取值为8。
  • 然后设置窗口范围函数,函数原型是virtual CSize SetWindowExt(int cx, int cy);
  • 接着设置视区范围函数,函数原型是virtual CSize SetViewportExt(int cx, int cy);
  • 之后设置视区原点函数,函数原型是virtual CPoint SetViewportOrg(int x, int y);
  • 最后需要将rect平移到客户视区。
    在这里插入图片描述
    这是一个基本的架构代码,以后在绘图前可以直接使用。
    其实除了我们改变映射模式的方法之外,还可以将原本的坐标点进行坐标变换,从一个坐标系转换到另一个坐标系,这样也能达到同样的效果。

可以简单画出坐标轴(当时运行试了一下,然后我就删了这段代码):

	pDC->MoveTo(-rect.Width() / 2, 0); // 起点
	pDC->LineTo(rect.Width() / 2, 0); // 与上一个点连线连线
	pDC->MoveTo(0, -rect.Height() / 2);
	pDC->LineTo(0, rect.Height() / 2);

在自定义坐标系之后添加测试代码:

	CPoint p0(-200,-100), p1(200,-100), p2 (0,200); // 三个顶点坐标
	// 一个简单的三角形
	pDC->MoveTo(p0); // 从p0出发
	pDC->LineTo(p1);
	pDC->LineTo(p2);
	pDC->LineTo(p0); // 到p0终止

在这里插入图片描述

4. 画笔画刷的使用

4.1 CDC类 , 绘图工具类

CDC类

  • 第一个C代表class类,DC代表设备上下文,定义了设备上下文对象的基类,封装了绘图所需的成员函数。

  • GDI是应用程序的图形设备接口,抽象之后得到CDC类。

  • 我们在绘图时,经常使用到该类型的指针pDC,但是有一个限制,不能同时使用超过五个设备上下文CDC对象。


绘图工具类

  • CGdiObject属于Windows GDI绘图工具的基类,其派生类包含位图CBitmap, 画刷CBrush, 字体CFont, 调色板CPalette, 画笔CPen

小知识
如何快速得到随机数
使用如下的语句

srand((unsigned)time(NULL)); //时间函数得到真随机
rand() % 255  //随机数的范围为 0~254

RGB宏红色的两种表示方式的差异是?

  • RGB(255,0,0), 从左往右,分别对应红 绿 蓝
  • 0x0000FF, 从左往右(高位到低位),分别对应蓝 绿 红

4.2 绘制像素点

  • 下面的绘制像素点函数SetPixel,这个函数会返回RGB值,或者使用仅仅返回bool值的更加快捷的SetPixelV函数。

    CDC::SetPixel //类属
    COLORREF SetPixel(int x, int y, COLORREF crColor);
    COLORREF SetPixel(POINT point, COLORREF crColor);   
    COLORREF SetPixelV(int x, int y, COLORREF crColor);
    COLORREF SetPixelV(POINT point, COLORREF crColor);   
    

清除之前添加的代码,保留3.3中 坐标系的变换代码。

在CnameView类中的OnDraw函数里添加代码:

	srand((unsigned)time(NULL)); // 真随机
	COLORREF crColor; // 颜色
	//第一四象限随机色像素点构成的正方形
	for(int x = 50; x < 350; x++)
		for(int y = -50; y < 250; y++)
			pDC->SetPixelV(x, y, RGB(rand() % 255,rand() % 255, rand() % 255 ));
	//第二三象限随机色像素点构成的正方形
	for(int x = 50; x < 350; x++)
		for(int y = -50; y < 250; y++)
		{
			crColor = pDC->GetPixel(x, y); // 这个比较费时
			pDC->SetPixelV(-x, y,crColor );
		}

结果如图:
对称随机色像素点

4.3 绘图标准步骤

使用GDI图形设备接口的步骤一般为:

  • 创建新的GDI对象,并选入当前设备上下文中
  • 同时保存指向原GDI对象的指针
  • 再用新的GDI对象绘图
  • 最后将已经保存的GDI对象指针将设备上下文恢复原状。

4.4 画笔的使用(直线段为例)

清除之前手动添加的所有代码。

在CnameView类中的OnDraw函数里添加代码:
注释很详细,力求弄懂设备上下文绘图:
代码

	// 定义三个点
	CPoint p0(100, 100),p1(300, 200), p2(500, 150);
	
	//定义两个颜色画笔,以及一个保存指针
	CPen greenPen, bluePen, *pOldPen;

	//创建绿画笔,这里第一个参数见下文“CPen画笔样式”。
	greenPen.CreatePen(0, 3,RGB(0,255,0)); //(实线,宽度为1,颜色为RGB(0,255,0))
	
	//CDC类型的指针pDC,就是一个指向GDI对象的工具
	//创建新的GDI对象:pDC->SelectObject(&greenPen)
	//SelectObject(&greenPen) 会返回 【原GDI对象的指针】
	//使用pOldPen 保存 【原GDI对象的指针】
	pOldPen = pDC->SelectObject(&greenPen);

	//绘制直线(用新的GDI对象绘图)
	pDC->MoveTo(p0);
	pDC->LineTo(p1);

	//恢复设备上下文,到此为止,绿色直线段完成绘制
	pDC->SelectObject(pOldPen);


	//同理,红色直线段绘制
	bluePen.CreatePen(0, 3,RGB(0,0,255)); //(实线,宽度为1,颜色为RGB(0,255,0))
	pOldPen = pDC->SelectObject(&bluePen);
	pDC->LineTo(p2);
	pDC->SelectObject(pOldPen);
	
	

结果
直线段

CPen画笔样式 参数
(CreatePen的第一个参数)
在这里插入图片描述

5. 未完待续

5.1

5.2

  • 23
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值