本篇学习自:孔令德老师的《三维计算机图形学》
文章目录
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_ANISOTROPIC
和
8
是等价的。
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
版权归原作者 ^ V ^ 所有, 如有侵权,请联系我们删除。