【计算机图形学课程】一.MFC基本绘图函数使用方法

【计算机图形学课程】一.MFC基本绘图函数使用方法

2023年7月17日发(作者:)

【计算机图形学课程】⼀.MFC基本绘图函数使⽤⽅法 这是最近我《计算机图形学》课程实践编程课介绍的相关知识,主要是想通过MFC C++绘图,让学⽣体会下图形学相关的编程及简单的图形绘制,同时⾮常佩服学⽣的想象⼒,他们做得真的不错。希望这篇基础⽂章对你有所帮助吧!尤其是有这门课程的学⽣或编程爱好者,如果⽂章存在错误或不⾜之处,还请海涵。 参考书籍:孔令德·《计算机图形学基础教程(Visual C++版)》 学⽣绘制的图形还是⾮常有创新的,表⽰很满意,哈哈哈~

⼀. MFC绘图基础知识 CDC类 PS:这部分主要引⼊孔令德⽼师的知识,这篇⽂章以后⾯的编程为主。 VC++具有强⼤的绘图功能,虽然基于对话框的应⽤我推荐⼤家使⽤C# Winform程序,但是计算机图形和图像的基础知识,还是强烈推荐使⽤VC++ MFC实现。这有助于让你深⼊的理解图形变换、图像处理等知识。 在Windows平台下,GDI(Graphics DeviceInterface)图形设备接⼝被抽象为上下⽂CDC类(Device Context,DC)。Windows平台直接接收图形数据信息的不是显⽰器和打印机等硬件设备,⽽是CDC对象。MFC中,CDC类定义设备上下⽂对象的基类,封装了所需的成员函数,调⽤CDC类的成员函数,绘制和打印图形及⽂字。 CDC类派⽣出CClientDC类、CMetaFileDC类、CPaintDC类和CWindowDC类,请读者⾃⾏学习,同时推荐阅读原书。 MFC常⽤CPoint、CRect、CSize等数据类型。 (1) CPoint类:存放点坐标(x,y); (2) CRect类:存放矩形左上顶点和右下⾓顶点的坐标(top、left、right、bottom),其中(top,left)为矩形的左上⾓点,(right,bottom)为矩形的右下⾓点; (3) CSzie类:存放矩形的宽度和⾼度的坐标(cx,cy),其中cx为矩形的宽度,cy为矩形的⾼度。

MFC绘图⼯具类包括CGdiObject、CBitmap、CBrush、CFont、CPallette、CPen和CRgn等。常⽤的包括: (1) CBitmap:封装了⼀个GDI位图,提供位图操作的接⼝; (2) CFont:封装了GDI字体,可以选作设备上下⽂中的当前字体; (3) CBrush:封装了GDI画刷,选作设备上下⽂的当前画刷,画刷⽤于填充图形内部; (4) CPen:封装了GDI画笔,选作设备上下⽂的当前画笔,画笔⽤于绘制图形边界线; (5) CPallette:封装了GDI调⾊板,提供应⽤程序和显⽰器之间的颜⾊接⼝; (6) CGdiObject:GDI绘图⼯具的基类,⼀般不能直接使⽤。 ⼆. MFC单⽂档编程介绍 ⾸先创建MFC项⽬,选择"MFC AppWizard"⼯程,命名为"test01"。 然后选择"单⽂档"格式,其中"基于对话框"是Dialog对话框⼯程。 创建完⼯程,在⼯作区间主要包括:ClassView(类视图)、ResourceView(资源视图)和FileView(⽂件视图)。其中类视图主要包含各个类,⽂件视图包括源⽂件.cpp和头⽂件.h。 打开资源ResourceView视图如下所⽰: MFC写代码通常在⽂件下,在""中找到OnDraw()函数,⽤于绘图:/// CTest01View drawingvoid CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here} 下⾯将详细介绍MFC基础绘图函数

三. MFC绘图函数及扩展绘图函数 (1)绘制直线 CDC::MoveTo(int x, int y) 将画笔移动到当前位置,即坐标(x, y)处,并没有画线。 CDC::LineTo(int x, int y) 画笔从当前位置绘制⼀条⼦线到(x, y)点,但不包含(x, y)点。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->MoveTo(100,150); pDC->LineTo(300,400); // TODO: add draw code for native data here} 绘制图形如下所⽰,坐标(100, 150)表⽰距离左边100,距离顶部150。 注意:绘制图形主要调⽤CDC* pDC⽅法实现,MFC可以补充提⽰函数。 (2) 设置画笔 通常可以设置绘制图形的颜⾊及线条属性,函数为: CPen::CreatePen(int nPenStyle, int nWidth, COLORREF color) 其中第⼀个参数为画笔的风格,实现、虚线等,第⼆个参数为画笔粗细,第三个参数使画笔的颜⾊,采⽤RGB(255, 255, 255)赋值。 CPen::SelectObject(Cpen *pen) 调⽤CPen选中画笔对象指针,即将画笔指向新画笔,同时指向指针。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //绘制直线 pDC->MoveTo(100,150); pDC->LineTo(300,400); //定义画笔绘制直线 CPen pen(PS_DASH, 4, RGB(255,0,0)); //虚线 粗4 红⾊ pDC->SelectObject(&pen); pDC->MoveTo(100,150); pDC->LineTo(400,300); //⽅法⼆ CreatePen定义画笔 CPen pen2;

Pen(PS_DASHDOTDOT, 1, RGB(0,255,0)); //双点画线 粗2 绿⾊ pDC->SelectObject(&pen2); pDC->MoveTo(100,150); pDC->LineTo(500,200);} 运⾏结果如下图所⽰,注意定义画笔后需要选择画笔SelectObject(),才能使⽤。 (3) 绘制矩形 CDC::Rectangle(int x1, int y1, int x2, int y2) 参数x1、y1表⽰矩形左上⾓坐标,参数x2、y2表⽰矩形右下⾓坐标。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //定义画笔绘制矩形 CPen pen(PS_DASH, 2, RGB(0,0,255)); //虚线 粗2 蓝⾊ pDC->SelectObject(&pen); //定义坐标点 CPoint point1(100,150); CPoint point2(400,300);

//绘制矩形 pDC->Rectangle(point1.x, point1.y, point2.x, point2.y);} 运⾏结果如下图所⽰,同时定义点是CPoint,可以调⽤point.x和point.y获取坐标。 (4) 设置画刷填颜⾊ CBrush::CreateSolidBrush(COLORREF crColor)

参数为画刷颜⾊,主要⽤于填充图形。 CBrush::SelectObject(CBrush* pBrush) 选择画刷,填充颜⾊,参数pBrush为选中CBrush对象的指针。 CGdiObject::DelectObject() 把已成⾃由状态的画刷从系统内存中清除,此函数同删除画笔函数。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //定义画笔绘制矩形 CPen pen(PS_DASH, 2, RGB(0,0,255)); //虚线 粗2 蓝⾊ pDC->SelectObject(&pen); CBrush bush; SolidBrush(RGB(255,0,0)); pDC->SelectObject(bush); //定义坐标点 CPoint point1(100,150); CPoint point2(400,300);

//绘制矩形 pDC->Rectangle(point1.x, point1.y, point2.x, point2.y);} 选择画刷填充如下图所⽰: (5) 清除画笔及画刷 真实操作中,通常会在画笔和画刷使⽤完毕时,把已成为⾃由状态的画笔和画刷从系统内存中删除。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //定义画笔绘制矩形 CPen MyPen, *OldPen;

Pen(PS_DASH, 2, RGB(0,0,255)); //虚线 粗2 蓝⾊ OldPen = pDC->SelectObject(&MyPen); //旧画笔赋值 //画刷 CBrush MyBrush, *OldBrush; SolidBrush(RGB(255,0,0)); OldBrush = pDC->SelectObject(&MyBrush); //定义坐标点 CPoint point1(100,150); CPoint point2(400,300);

//绘制矩形 pDC->Rectangle(point1.x, point1.y, point2.x, point2.y); //清除 pDC->SelectObject(OldPen); Object(); pDC->SelectObject(OldBrush); Object();} (6) 绘制椭圆函数 CDC::Ellipse(int x1, int y1, int x2, int y2) 参数x1、y1是绘制椭圆外接矩形左上⾓的坐标,x2、y2是外接矩形的右下⾓坐标。当绘制的外接矩形长和宽相同,即绘制的是圆。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //定义画笔 CPen MyPen, *OldPen;

Pen(PS_DASH, 2, RGB(0,0,255)); //虚线 粗2 蓝⾊ OldPen = pDC->SelectObject(&MyPen); //旧画笔赋值 //画刷 CBrush MyBrush, *OldBrush; SolidBrush(RGB(255,0,0)); OldBrush = pDC->SelectObject(&MyBrush); //定义坐标点 CPoint point1(100,150); CPoint point2(400,300);

//绘制椭圆 pDC->Ellipse(point1.x, point1.y, point2.x, point2.y); //绘制圆 pDC->Ellipse(0, 0, 100, 100); //清除 pDC->SelectObject(OldPen); Object(); pDC->SelectObject(OldBrush); Object();} 输出如下图所⽰: 注意:还有些⽅法,包括绘制圆弧、绘制多边形,⽅法类似,只是注意下参数即可。 (7) 绘制⽂字 CDC::TextOut(int x, int y, const CString & str) 参数x、y是⽂本的起点坐标,参数str是CString对象,⽂字内容。同时可以结合Format格式控制字符串输出变量。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //定义画笔 CPen MyPen, *OldPen;

Pen(PS_DASH, 2, RGB(0,0,255)); //虚线 粗2 蓝⾊ OldPen = pDC->SelectObject(&MyPen); //旧画笔赋值 //画刷 CBrush MyBrush, *OldBrush; SolidBrush(RGB(255,0,0)); OldBrush = pDC->SelectObject(&MyBrush); //定义坐标点 CPoint point1(100,150); CPoint point2(400,300);

//绘制椭圆 pDC->Ellipse(point1.x, point1.y, point2.x, point2.y); pDC->TextOut(405,305,_T("绘制椭圆")); //绘制圆 pDC->Ellipse(0, 0, 100, 100); //使⽤Format写⽂字 CString str1 = "绘制圆 半径="; int r = 50; CString data; ("%s %d", str1,r); pDC->TextOut(105,105,data); //清除 pDC->SelectObject(OldPen); Object(); pDC->SelectObject(OldBrush); Object();} 输出如下图所⽰:

2.扩展知识 第⼀个扩展是,绘制直线过程中,如果围绕⼀个圆⼼进⾏循环绘制,可以得到很好看的圆形直线。#include void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //定义画笔并选择 CPen pen(PS_SOLID,4,RGB(120,32,240)); pDC->SelectObject(&pen); //定义点绘制⼀条竖直直线 CPoint p0(300,300); CPoint p1(300,550); pDC->MoveTo(p0); pDC->LineTo(p1); //半径和PI int R = 250; float pi = 3.14f; //定义150个点 循环按照圆形绘制 CPoint p[100]; for(int i=0;i<100;i++) { p[i].x = int(p0.x+R*sin((pi+i+1)/20)); //x坐标 sin涉及数学知识 p[i].y = int(p0.y+R*cos((pi+i+1)/20)); //y坐标 //先移动到圆形p0(300,300) 再绘制直线 pDC->MoveTo(p0); pDC->LineTo(p[i]); }}输出如下图所⽰: 该内容就是常见的图形旋转知识,核⼼内容:计算新坐标,通过sin和cos数学知识,同时圆形不变,每次循环先MoveTo(p0)即可。 第⼆段代码涉及图形平移,就是绘制矩形图形平移操作。void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //定义画笔并选择 CPen pen(PS_SOLID,4,RGB(120,32,240)); pDC->SelectObject(&pen); CBrush brush(RGB(250,12,30)); pDC->SelectObject(&brush); //循环绘制矩形 int x1=100,y1=100,x2=300,y2=400; for(int j=0; j<100; j=j+3) { pDC->Rectangle(x1+j, y1+j, x2+j, y2+j); }} 输出如下所⽰:

四. 学⽣成果及创新 下⾯的代码是做得⽐较好的同学的,感觉还是不错的。 夏KH同学:#include void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here int d,k,x1,x2,y1,y2; float pi,a,e; CPen pen; Pen(PS_SOLID,1,RGB(155,0,0)); CPen *pOldPen = pDC->SelectObject(&pen); pi = 3.1415926f; d = 80; for (a = 0; a<=2 * pi; a+= pi/360) { e = d * (1+0.25*sin(4*a)); e = e * (1 + sin(8*a)); x1 = int(320+e*cos(a)); x2 = int(320+e*cos(a + pi/8)); y1 = int(200+e*sin(a)); y2 = int(200+e*sin(a + pi/8)); pDC->MoveTo(x1,y1); pDC->LineTo(x2,y2); }} 输出如下所⽰: 李N同学:void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here //定义画笔 CPen pen(PS_SOLID,2,RGB(0,255,0)); pDC->SelectObject(&pen); CPoint p0(400,200); int R=200; CPoint p1(400,600); pDC->MoveTo(p0); pDC->LineTo(p1); float pi=3.14f; CPoint p[126]; for(int i=0;i<126;i++) { p[i].x=int(p0.x + R*sin((pi+i+1)/20)); p[i].y=int(p0.y + R*cos((pi+i+1)/20)); pDC->MoveTo(p0); pDC->LineTo(p[i]); } CBrush bush(RGB(255,255,0)); pDC->SelectObject(&bush); int x1=700,y1=100,x2=900,y2=400; for(int j=0;j<50;j++) { pDC->Rectangle(x1+j,y1+j, x2+j, y2+j); }} 输出如下所⽰: 杨J同学:void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPen pen(PS_SOLID,1,RGB(255,0,0)); pDC->SelectObject(&pen);

CPoint p0(400,300); int R=200; CPoint p1; p1.x=p0.x; p1.y=p0.y+R;

pDC->MoveTo(p0); pDC->LineTo(p1); CPoint p2; float pi=3.14f; p2.x=int(p0.x+R*sin(pi/20)); p2.y=int(p0.y+R*cos(pi/20)); pDC->MoveTo(p0); pDC->LineTo(p2); CPoint p[1000]; for(int i=0;i<1000;i++){ p[i].x=int(p0.x+R*sin((pi+i+1)/20)); p[i].y=int(p0.y+R*cos((pi+i+1)/20)); pDC->MoveTo(p0); pDC->LineTo(p[i]); } CBrush bush(RGB(0,255,255)); pDC->SelectObject(&bush); for(int j=0;j<200;j=j+3) { pDC->Rectangle(600+j,100+j,800+j,400+j); }} 输出如下图所⽰: 张J同学:#include void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPen pen(PS_SOLID,1,RGB(255,80,0)); pDC->SelectObject(&pen); CPoint p0(200,200); CPoint p1; int R=200,P=100; p1.x=p0.x; p1.y=p0.y+R; pDC->MoveTo(p0); pDC->LineTo(p1); float pi=3.14; CPoint p[200]; for(int i=0,h=1;i<200,i<200;i=i+2,h=h+2) { p[i].x=int(R*sin((pi+i)/20)+p0.x); p[i].y=int(R*cos((pi+i)/20)+p0.y); p[h].x=int(P*sin((pi+h)/20)+p0.x); p[h].y=int(P*cos((pi+h)/20)+p0.y); pDC->MoveTo(p0); pDC->LineTo(p[i]); pDC->MoveTo(p0); pDC->LineTo(p[h]); } CBrush bush(RGB(255,190,0)); pDC->SelectObject(&bush); int x1=500,y1=100,x2=600,y2=300; for(int j=0;j<100;j++) { pDC->Rectangle(500-j,100+j,600+j,300-j); } int x3=700,y3=100,x4=800,y4=300; for(int k=0;k<100;k++) { pDC->Ellipse(700-k,100+k,800+k,300-k); } int x5=900,y5=100,x6=1000,y6=300; for(int l=0;l<100;l++) { pDC->Rectangle(900+l,100+l,1000+l,300+l); }} 输出如下图所⽰: 郑DD同学:#include void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPen pen(PS_SOLID,1,RGB(0,255,0,)); pDC->SelectObject(&pen); CPoint p1,p2; int R=200; p1.x=200; p1.y=300; p2.x=100; p2.y=p1.y+R; pDC->MoveTo(p1); pDC->MoveTo(p2); float pi=3.14f; CPoint p[400]; for(int i=0;i<400;i++) { p[i].x = int(R*sin((pi+i+1)/3)+p1.x); p[i].y = int(R*cos((pi+i+1)/6)+p1.y); pDC->MoveTo(p1); pDC->LineTo(p[i]); } pDC->TextOut(190,280,_T("wow")),RGB(255,0,0); float ph=3.14f; for(int h=0;h<400;h++) { p[h].x = int(R*sin((ph+h+1)/6)+p1.x); p[h].y = int(R*cos((ph+h+1)/3)+p1.y); pDC->MoveTo(p1); pDC->LineTo(p[i]); }} 输出如下图所⽰: 赵BL同学:#include void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here //定义画笔 CPen pen(PS_SOLID,2,RGB(255,32,150)); pDC->SelectObject(&pen); //定义点 CPoint p0(300,400); CPoint p1(300,600); pDC->MoveTo(p0); pDC->LineTo(p1); float pi=3.14f; int R=200; CPoint p[249]; for(int i=0; i<249; i++){ p[i].x = int(p0.x + R*cos((pi+i+1)/20)); p[i].y = int(p0.y + R*tan((pi+i+1)/20)); pDC->MoveTo(p0); pDC->LineTo(p[i]); } CBrush bush(RGB(255,166,123)); pDC->SelectObject(bush); int x=600,y=100; int x2=900,y2=300; pDC->Rectangle(x,y,x2,y2); for(int j=0;j<100;j=j+4){

pDC->Rectangle(x+j,y+j,x2+j,y2+j); }} 输出如下图所⽰: 陈Y同学:void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPen pen(PS_SOLID,8,RGB(132,255,255)); pDC->SelectObject(&pen); CPoint p0(220,300); int R=200; CPoint p1; p1.x=p0.x; p1.y=p0.y+R; pDC->MoveTo(p0); pDC->LineTo(p1); CPoint p2; float pie=3.14f; CPoint p[45]; for(int i=0;i<60;i++) {

p2.x=int(p0.x+R*sin((pie-i)/10)); p2.y=int(p0.y+R*tan((pie-i)/10));

pDC->MoveTo(p0); pDC->LineTo(p2); }} 输出如下图所⽰: ⽂FB同学代码:#include void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPen pen(PS_SOLID, 3, RGB(0, 0, 255)); pDC->SelectObject(&pen); CPoint p0(350, 200); int r = 200; CPoint p1(350, 300 + r); pDC->MoveTo(p0); pDC->LineTo(p1); CPoint p2; float PI = 3.14f; p2.x = int(p0.x + r*sin(PI / 10)); p2.y = int(p0.y + r*cos(PI / 10)); pDC->MoveTo(p0); pDC->LineTo(p2); CPoint p[1000]; for (int i = 0; i <300; i++) {

p[i].x = int(p0.x + r*sin((PI + i + 1) / 10)); p[i].y = int(p0.y + r*cos((PI + i + 1) / 10)); r--; pDC->MoveTo(p0); pDC->LineTo(p[i]); }} 输出如下图所⽰: 刘JL同学代码如下:void CTest01View::OnDraw(CDC* pDC){ CTest01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPen pen(PS_SOLID,2,RGB(255,0,0)); pDC->SelectObject(&pen); CPoint p0(300,200); int R=170; CPoint p1(350,400); pDC->MoveTo(p0); pDC->LineTo(p1);

float pi=3.14f; CPoint p[45]; for(int i=0;i<45;i++) { p[i].x=int(p0.x*sin((pi+i)/20)); p[i].y=int(p0.y*cos((pi+i)/20)+R); pDC->MoveTo(p0); pDC->LineTo(p[i]); }} 输出如下图所⽰:

发布者:admin,转转请注明出处:http://www.yc00.com/news/1689605339a269953.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信