【计算机图形学基础教程】MFC基本绘图函数2

news2024/11/15 18:27:10

MFC基本绘图函数

绘图工具类

  • CGdiObject类:GDI绘图工具的基类
  • CBitmap类:封装了GDI画刷,可以选作设备上下文的当前画刷,用于填充图形的内部
  • CFont类:封装了GDI字体,可以选作设备上下文的当前字体
  • CPalette类:封装了GDI调色板,提供应用程序和显示器之间的颜色接口
  • CPen类:封装了GDI画笔,可以选作设备上下文的当前画笔,用于绘制图形的边界线
  • CRgn类:封装了一个Windows的GDI区域,这一区域是某一个窗口的一个椭圆或多边形区域

选择GDI对象进行绘图,应遵循的步骤:

  1. 绘图开始前,创建一个新的GDI对象,并选入当前设备上下文,同时保存原GDI对象指针
  2. 使用新GDI对象绘图
  3. 绘图结束后,使用已保存的原GDI对象指针设备上下文恢复原状

映射模式

映射:将图形显示在屏幕坐标系的过程。
映射模式:逻辑坐标和设备坐标
逻辑坐标:单位是米制尺度或英制尺度
设备坐标:单位是像素

1. 设置映射模式函数

CDC::SetMapMode

// Mapping Functions
	virtual int SetMapMode(int nMapMode);

nMapMode为映射代码
设置映射模式,定义了将逻辑坐标转换为设备坐标的度量单位,并定义了设备坐标系的x轴和y轴方向

2. 设置窗口范围函数

CDC::SetWindowExt

	// Window extent
	virtual CSize SetWindowExt(int cx, int cy);
			CSize SetWindowExt(SIZE size);

cx, cy窗口x, y范围的逻辑坐标,size是窗口的SIZE结构或CSize对象

3. 设置视区范围函数

CDC::SetViewportExt

	// Viewport Extent
	virtual CSize SetViewportExt(int cx, int cy);
			CSize SetViewportExt(SIZE size);

cx, cy窗口x, y范围的逻辑坐标,size是窗口的SIZE结构或CSize对象

4. 设置窗口原点函数

CDC::SetWindowOrg

	// Window Origin
	CPoint SetWindowOrg(int x, int y);
	CPoint SetWindowOrg(POINT point);

x, y窗口新原点坐标,point是窗口新原点的POINT结构或CPoint对象

5. 设置视区原点函数

CDC::SetViewportOrg

	// Viewport Origin
	virtual CPoint SetViewportOrg(int x, int y);
			CPoint SetViewportOrg(POINT point);

x, y窗口新原点坐标,point是窗口新原点的POINT结构或CPoint对象

映射代码

各向同性MM_ISOTROPIC和各向异性MM_ANISOTROPIC,需调用SetWindowExt()和SetViewportExt()来改变窗口和视区的设置

MM_ISOTROPIC: 要求x轴和y轴比例相等,以保持图形形状不发生变化
MM_ANISOTROPIC: 可以改变坐标系的单位、方向和比例

窗口与视区

窗口:可以理解为一种逻辑坐标系下的矩形区域
视区:是设备坐标系下的矩形区域

x方向比例因子 = 视区cx / 窗口cx
y方向比例因子 = 视区cy / 窗口cy

例子1:

SetWindowExt(100, 100);
SetViewportExt(200, 200);

x,y方向的比例因子为2, 说明窗口的一个逻辑坐标映射为视区的两个像素。
绘制100×100逻辑坐标的正方形,结果为200×200像素的正方形

例子2:

SetWindowExt(100, 200);
SetViewportExt(200, 200);

x方向的比例因子为2, y方向的比例因子为1,说明窗口x方向的一个逻辑坐标映射为视区的两个像素,窗口y方向的一个逻辑坐标映射为视区的一个像素
绘制100×100逻辑坐标的正方形,结果为200×100像素的正方形

例子3:
使用用户自定义映射模式,设置窗口大小和视区大小相等的二维坐标系。视区中x轴水平向右为正,y轴垂直向上为正,原点位于屏幕客户区中心。

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	pDC->TextOutW(600, 100, _T("Hello there!"));
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正
	pDC->TextOutW(600, 100, _T("Hello there!"));

在这里插入图片描述
可以看到变换了坐标系之后,在输入相同的坐标位置的文字时,文字会在屏幕不同的位置打印出来,这是因为对坐标系进行了变换(原点从左上角平移到中+上下翻转)。

使用GDI对象

1. 创建画笔函数

画笔属性:线型、宽度和颜色
画笔的线型:实线、虚线、点线、点划线、双点划线、不可见线和内框架线,PS_为前缀
画笔的宽度:用像素表示
画笔的颜色:RGB宏表示

CPen::CreatePen

BOOL CreatePen(int nPenStyle, int nWidth, COLORREF crColor);
BOOL CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush,
		int nStyleCount = 0, const DWORD* lpStyle = NULL);

nPenStyle是画笔样式,nWidth是画笔宽度,crColor是画笔颜色

typedef DWORD   COLORREF;

2. 创建画刷函数

仅对绘制的闭合图形有效

CBrush::CreateSolidBrush:

BOOL CreateSolidBrush(COLORREF crColor);

实体画刷,用指定的颜色填充图形内部

CBrush::CreateHatchBrush:

BOOL CreateHatchBrush(int nIndex, COLORREF crColor);

使用指定的阴影样式和颜色填充图形内部, HS前缀

CBrush::CreatePatternBrush:

BOOL CreatePatternBrush(CBitmap* pBitmap);

使用位图创建一个逻辑画刷

3. 选入GDI对象

CDC::SelectObject

	CPen* SelectObject(CPen* pPen);
	CBrush* SelectObject(CBrush* pBrush);
	virtual CFont* SelectObject(CFont* pFont);
	CBitmap* SelectObject(CBitmap* pBitmap);
	int SelectObject(CRgn* pRgn);       // special return for regions
	CGdiObject* SelectObject(CGdiObject* pObject);

pPen是将要选择的画笔对象指针
pBrush是将要选择的画刷对象指针
pBitmap是将要选择的位图对象指针

4. 删除GDI对象

CGdiObject::DeleteObject

BOOL DeleteObject();

5. 选入库对象

使用完库画笔和画刷不需要调用DeleteObject()函数从内存中删除

CDC::SelectStockObject

virtual CGdiObject* SelectStockObject(int nIndex);

CDC类绘图成员函数

1. 绘制像素点函数

CDC::SetPixel和CDC::SetPixelV

	COLORREF SetPixel(int x, int y, COLORREF crColor);
	COLORREF SetPixel(POINT point, COLORREF crColor);
	BOOL SetPixelV(int x, int y, COLORREF crColor);
	BOOL SetPixelV(POINT point, COLORREF crColor);

SetPixel()返回绘制像素点的RGB值,SetPixelV不需要返回所绘制像素点的RGB值

2. 获取像素点颜色函数

CDC::GetPixel

	COLORREF GetPixel(int x, int y) const;
	COLORREF GetPixel(POINT point) const;

返回指定像素的RGB值

例子4:

在屏幕上使用SetPixelV()函数将crColor参数设置为随机颜色,用像素点在x轴负向画出对角点为(-150, -50)和(-50, 50)的正方形。然后使用GetPixel()函数依次读出该正方形内各像素点的颜色,在x轴正向的对称位置上重新绘制该正方形

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正
	srand((unsigned)time(NULL));   // 使用系统时间初始化随机种子,使得每次产生不同的随机数
	COLORREF crColor;              // 用于存放像素点的颜色值
	int x, y;                      // 像素点的位置坐标
	for (y = -50; y < 50; y++)
	{
		for (x = -150; x < -50; x++)
		{
			// 用随机颜色在x轴负向绘制对角点(-150, -50)和(-50, 50)的正方形
			pDC->SetPixelV(x, y, RGB(rand() % 255, rand() % 255, rand() % 255));  
		}
	}
	for (y = -50; y < 50; y++)
	{
		for (x = -150; x < -50; x++)
		{
			crColor = pDC->GetPixel(x, y);   // 先读取对角点(-150, -50)和(-50, 50)的正方形的像素点的颜色
			pDC->SetPixelV(-x, y, crColor);  // 关于y轴对称位置绘制
		}
	}

	
}

在这里插入图片描述

3. 绘制直线段函数

配合使用MoveTo()和LineTo()函数
每次绘制直线以当前位置为起点,绘制结束后,终点成为当前位置。

CDC::MoveTo

	CPoint MoveTo(int x, int y);
	CPoint MoveTo(POINT point);

设置当前位置函数,只将画笔的当前位置移动到坐标x和y处,不画线

CDC::LineTo

	BOOL LineTo(int x, int y);
	BOOL LineTo(POINT point);

绘制直线段函数,从当前位置绘制直线段,但不包括(x,y)点

例5:

从起点p0(-100, -50)到终点p1(100, 50)绘制一段1像素宽的蓝色直线。

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正

	CPoint p0(-100, -50), p1(100, 50);               // 定义直线段的起点和终点
	CPen NewPen, *pOldPen;                      
	NewPen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));    // 创建蓝色实线画笔, RGB:0xff0000
	pOldPen = pDC->SelectObject(&NewPen);             // 将新画笔选入设备上下文,同时用pOldPen指针保存原画笔指针
	pDC->MoveTo(p0);                                 // 将当前位置移动到直线段起点
	pDC->LineTo(p1);                                // 从起点绘制直线段直到终点
	pDC->SelectObject(pOldPen);                     // 新画笔使用完毕后,用pOldPen指针保存的原画笔将设备上下文恢复原状
}

在这里插入图片描述

4. 绘制矩形函数

CDC::Rectangle

	BOOL Rectangle(int x1, int y1, int x2, int y2);
	BOOL Rectangle(LPCRECT lpRect);

绘制直角矩形,使用当前画刷填充直角矩形内部,并使用当前画笔绘制直角矩形边界线

CDC::RoundRect

	BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3);
	BOOL RoundRect(LPCRECT lpRect, POINT point);

绘制圆角矩形,使用当前画刷填充圆角矩形内部,并使用当前画笔绘制圆角矩形边界线

CDC::SetPolyFillMode

	int SetPolyFillMode(int nPolyFillMode);

设置填充模式函数,有ALTERNATE和WINDING模式

  • ALTERNATE:按照扫描线填充相邻的奇偶边内的区域,五角星只填充五角星的五个角,不填充五角星内部的五边形
  • WINDING:根据边的绘制方向(顺时针或逆时针)来决定是否填充多边形内部,从图形内部向外引一条假想直线,遇到顺时针绘制的边计数器加1,遇到逆时针绘制的边计数器减1,计数器不为0时,填充该区域。内部五边形引出假想直线,遇到两条逆时针绘制的边,计数器为-2; 五角星的角内引出假想的边,遇到一条逆时针的边,计数器为-1。两种情况计数器均不为0, 所以WINDING模式填充整个五角星

例6:

将客户区矩形上下左右边界各收缩100个像素绘制重叠的方角矩形和圆角矩形。矩形边框为1的像素宽的蓝色边界线。方角矩形内部使用默认画刷填充,圆角矩形内部填充红色,圆角取为(200, 200)

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正

	rect.DeflateRect(100, 100);                      // 将矩形两个方向都缩小100个像素
	CPen NewPen, *pOldPen;
	NewPen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));  // 创建蓝色实线画笔, RGB:0xff0000
	pOldPen = pDC->SelectObject(&NewPen);           // 将新画笔选入设备上下文,同时用pOldPen指针保存原画笔指针
	pDC->Rectangle(rect);                           // 绘制方角矩形
	CBrush NewBrush, *pOldBrush;
	NewBrush.CreateSolidBrush(RGB(255, 0, 0));      // 创建红色画刷
	pOldBrush = pDC->SelectObject(&NewBrush);       // 将新画刷选入设备上下文,同时用pOldBrush指针保存原画刷指针
	pDC->RoundRect(rect, CPoint(200, 200));         // 绘制圆角矩形
	pDC->SelectObject(pOldPen);
	pDC->SelectObject(pOldBrush);
}

在这里插入图片描述

CDC::FillRect

	void FillRect(LPCRECT lpRect, CBrush* pBrush);

画刷填充矩形函数,使用当前话术填充整个矩形,包括左边界和上边界,但不包括右边界和下边界

CDC::FillSolidRect

	void FillSolidRect(LPCRECT lpRect, COLORREF clr);
	void FillSolidRect(int x, int y, int cx, int cy, COLORREF clr);

FillSolidRect()函数颜色填充矩形函数,仅使用颜色填充矩形;FillRect()函数则可以使用阴影图案填充矩形

例7:

以(-250, 50)为左下角点,以(250, 150)为右上角点绘制矩形,使用红色HS_BDIANGONAL阴影模式填充。以(-250, -150)为左下角点,以(250, -50)为右上角点绘制矩形,使用红色填充

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正

	CRect rect1(CPoint(-250, 50), CPoint(250, 150));
	CRect rect2(CPoint(-250, -150), CPoint(250, -50));
	CBrush Brush(HS_BDIAGONAL, RGB(255, 0, 0));     // 定义红色阴影画刷
	pDC->FillRect(&rect1, &Brush);                  // 阴影填充矩形
	pDC->FillSolidRect(&rect2, RGB(255, 0, 0));     // 红色填充矩形
}

在这里插入图片描述

5. 绘制椭圆函数

CDC::Ellipse

	BOOL Ellipse(int x1, int y1, int x2, int y2);
	BOOL Ellipse(LPCRECT lpRect);

使用当前画刷填充椭圆内部,并使用当前画笔绘制椭圆边界线;圆= 长半轴和短半轴相等椭圆,lpRect是确定椭圆范围的外接矩形

例8

将客户区矩形上下左右边界各收缩100像素,分别绘制矩形、矩形内切圆和矩形内切椭圆。绘制过程按圆、椭圆和矩形顺序完成。设定圆、椭圆和矩形的边界线为1像素宽黑色实现,内部全部使用透明画刷填充

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正

	rect.DeflateRect(100, 100);                      // 将矩形两个方向都缩小100个像素,返回的类型是CGdiObject*, 需要强制转换为CBrush*
	CBrush *pOldBrush;
	pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);   // 选择透明画刷
	int r = rect.Height() / 2;            // 定义圆的半径
	CRect rect1(CPoint(-r, -r), CPoint(r, r));    // 定义圆的外接矩形
	pDC->Ellipse(rect1);            // 绘制圆
	pDC->Ellipse(rect);             // 绘制椭圆
	pDC->Rectangle(rect);           // 绘制外接矩形
	pDC->SelectObject(pOldBrush);    
}

在这里插入图片描述

6. 绘制椭圆弧函数

CDC::Arc

	BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
	BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd);

椭圆弧的真实起点是外接矩形中心点与(x3,y3)(或ptStart)点所构成的射线与椭圆的交点;椭圆弧的真实终点是外接矩形中心与(x1,y1)(或ptEnd)点所构成的射线与椭圆的交点。

例9

在客户区内从12点到3点位置逆时针绘制黑色点划线椭圆弧,从12点到3点位置顺时针绘制蓝色实现椭圆弧

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正


	CPoint Twelve(0, rect.Height() / 2), Three(rect.Width() / 2,  0);  // 定义12点和3点的位置
	CPen penBlack, penBlue, *pOldPen;
	penBlue.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));    // 蓝色实线画笔
	penBlack.CreatePen(PS_DASHDOT, 1, RGB(0, 0, 0));    // 黑色点划线画笔
	pDC->SetArcDirection(AD_CLOCKWISE);      // 顺时针绘制12点到3点的椭圆形
	pOldPen = pDC->SelectObject(&penBlue);    
	pDC->Arc(rect, Twelve, Three);            // 绘制椭圆形
	pDC->SetArcDirection(AD_COUNTERCLOCKWISE);     // 逆时针绘制12点到3点的椭圆形
	pOldPen = pDC->SelectObject(&penBlack);
	pDC->Arc(rect, Twelve, Three);     
	pDC->SelectObject(pOldPen);
}

在这里插入图片描述

7. 绘制扇形函数

CDC::Pie

	BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
	BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd);

扇形中心位置坐标是外接矩形的中心,扇形从起点到终点逆时针方向绘制,扇形直接用直线段连接扇形中心与扇形的起点和终点

例10

绘制两个扇形构成扇子形状,使用位图画刷填充扇子内部

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正

	CBitmap NewBitmap;
	NewBitmap.LoadBitmap(IDB_BITMAP1);            // 导入位图
	CBrush NewBrush, *pOldBrush;
	NewBrush.CreatePatternBrush(&NewBitmap);     // 创建位图画刷
	pOldBrush = pDC->SelectObject(&NewBrush);
	CPen * pOldPen;
	pOldPen = (CPen*)pDC->SelectStockObject(NULL_PEN);   // 选入透明库画笔,不绘制扇形的边界线
	CPoint ld, rt, sp, ep;
	ld = CPoint(-400, -600), rt = CPoint(400, 200);  // 外接矩形的左下角ld,右上角rt, 椭圆弧的起点sp和终点ep

	sp = CPoint(400, 0), ep = CPoint(-400, 0);
	pDC->Pie(CRect(ld, rt), sp, ep);    
	pDC->SelectObject(pOldBrush);                       // 更换位图画刷
	NewBitmap.DeleteObject();                           // 删除位图

	ld = CPoint(-80, -280), rt = CPoint(80, -120);      //绘制扇子的内扇形
	sp = CPoint(400, 0), ep = CPoint(-400, 0);
	pDC->Pie(CRect(ld, rt), sp, ep);                 // 使用白色的默认画刷填充
	pDC->SelectObject(pOldPen);                      // 恢复原画笔
}

在这里插入图片描述

其中,导入位图步骤如下:

  1. 在解决方案资源管理图找到MFCTest.rc, 双击:
    在这里插入图片描述
  2. 进入资源视图,右击MFCTest.rc,选择添加资源:
    在这里插入图片描述
  3. 选中Bitmap, 点击导入:
    在这里插入图片描述
  4. 选择bmp文件:
    在这里插入图片描述
  5. 即可看到IDB_BITMAP1被加载到Bitmap里:
    在这里插入图片描述

8. 绘制多边形函数

CDC::Polygon

	BOOL Polygon(const POINT* lpPoints, int nCount);	

使用当前画刷填充多边形内部,并使用当前画笔绘制多边形边界线

例11

以正五边形的5个顶点为基础,隔点存储构成五角星,p0p4为五边形的5个顶点,v0v4为五角星的5个顶点。填充模式采用WINDING。五角星边界线为5个像素宽的蓝色实线,内部使用红色填充。

void CMFCTestView::OnDraw(CDC* pDC)
{
	CMFCTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
	CRect rect;    // 定义矩形
	GetClientRect(&rect);    // 获得客户区矩形
	pDC->SetMapMode(MM_ANISOTROPIC);    // 设置映射模式
	pDC->SetWindowExt(rect.Width(), rect.Height());     // 设置窗口
	pDC->SetViewportExt(rect.Width(), -rect.Height());   // 设置视区:x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);   // 设置客户区中心点为坐标系原点
	rect.OffsetRect(-rect.Width()/2, -rect.Height()/2);    // 客户区矩形校正


	CPen penBlue(PS_SOLID, 5, RGB(0, 0, 0255));     // 定义5个像素宽的蓝色画笔
	CPen *pOldPen = pDC->SelectObject(&penBlue); 
	CBrush brushRed(RGB(255, 0, 0));    // 定义红色画刷
	CBrush * pOldBrush = pDC->SelectObject(&brushRed);  
	pDC->SetPolyFillMode(WINDING);   // 设置填充模式
	int r = 200;            // 设置五边形外接圆半径
	CPoint p[5];            // 设置正五边形顶点数据
	double Beta = 2 * PI / 5;  // 定义每个顶点的圆心角
	double Alpha = PI / 10;   // 定义起始角, 18°起始角正好将五角星放正

	for (int i = 0; i < 5; i++)
	{
		p[i].x = Round(r*cos(i*Beta + Alpha));    // 计算正五边形顶点坐标
		p[i].y = Round(r*sin(i*Beta + Alpha));
	}
	CPoint v[5];   // 定义五角星顶点数组
	v[0] = p[0];    // 将正五边形的顶点数组转储为五角星的顶点数组
	v[1] = p[2];
	v[2] = p[4];
	v[3] = p[1];
	v[4] = p[3];    // 转储顶点
	pDC->Polygon(v, 5);    //绘制五角星
	pDC->SelectObject(pOldPen);   // 恢复画笔
	pDC->SelectObject(pOldBrush);  // 恢复画刷
}

在这里插入图片描述
采用ALTERNATE模式:
在这里插入图片描述
参考:
孔令德, 计算机图形学基础教程(Visual C++版)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/494287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一图看懂 aiohttp 模块:基于 asyncio 的异步HTTP网络库, 资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 aiohttp 模块&#xff1a;基于 asyncio 的异步HTTP网络库, 资料整理笔记&#xff08;大全&#xff09; 摘要模块图类关系图模块全展开【aiohttp】统计常量模块1 aiohttp.hd…

Redis超详细入门手册教程!还不快来看看?

地址&#xff1a; RedisRedis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures …https://redis.io/ 1&#xff1a;NoSQL简介 1.1&#xff1a;数据库应用的演变历程 单…

【Matlab】基于改进的 Hausdorf 距离的DBSCAN船舶航迹聚类

【Matlab】基于改进的 Hausdorff 距离的DBSCAN船舶航迹聚类 一、模型简介1.1问题背景1.2具体内容AIS数据的预处理船舶轨迹分割船舶轨迹相似度度量船舶轨迹表达方式船舶轨迹相似度量方法改进的 Hausdorff 距离船舶轨迹聚类及轨迹提取基于改进DBSCAN算法轨迹聚类船舶典型轨迹的提…

PHP+vue基于web的小区物业管理管理系统1995a

小区物业管理系统主要是对小区物业以及居民信息进行管理&#xff0c;方便用户使用该资源的一种有效手段。能有效地对物业以及用户信息进行管理并为广大用户服务是该管理系统的基本要求&#xff0c;同时用户也可以及时了解最新的物业信息&#xff0c;方便地查询相关物业情况。基…

Django配置WebSocket:django3配置websocket步骤

一、websocket概述 简单可以认为是在web上实现socket功能&#xff0c;在服务器上与浏览器保持socket长连接。 实现websocket是通过magic string 二、环境概述 解释器&#xff1a;python3.9 django3.2 channels3.0.4 #有些时候是channels版本有问题&#xff0c;导致配置不…

linux和window下svn版本控制可视化工具

之前一直用命令行来拉取代码建立分支&#xff0c;推送代码等等 也不是不行&#xff0c;但是用久了&#xff0c;感觉很麻烦&#xff0c;后面就用了svn的版本可视化工具 linux和window下svn版本控制可视化工具 Linux环境下使用图形化界面的SVN客户端软件&#xff0c;那么RabbitVC…

触控笔和电容笔哪个好用?ipad第三方电容笔了解下

和最早出现的那一些触控笔相比&#xff0c;现在电容笔最大的不同之处在于&#xff0c;这些电容笔具备了防误触、倾斜可以随意调整笔迹粗细的特性。苹果的Pencil&#xff0c;现在的价格&#xff0c;也是非常高的。所以&#xff0c;对于预算不足的人群来说&#xff0c;平替电容笔…

SDMTSP:斑马优化算法ZOA求解单仓库多旅行商问题(提供MATLAB代码,可更改起点及旅行商个数)

一、单仓库多旅行商问题 单仓库多旅行商问题&#xff08;Single-Depot Multiple Travelling Salesman Problem, SD-MTSP&#xff09;&#xff1a;&#x1d45a;个推销员从同一座中心城市出发&#xff0c;访问其中一定数量的城市并且每座城市只能被某一个推销员访问一次&#x…

安装java配置

目录 安装JDK ​编辑 环境变量配置 3、检验环境变量配置 二、安装tomcat 验证Tomcat配置是否成功 三、安装Mysql 一、安装 二、卸载 安装JDK 点击更改将C直接给为F即可。 点击确定后进行安装&#xff0c;安装完以后会提示安装JRE; 检测是否已经安装JDK的方法 java命令通…

尚硅谷-宋红康-JVM上中下篇完整笔记-JVM上篇_内存与垃圾回收篇

前言 一.jvm及java体系结构 1. Java及JVM简介 TIOBE语言热度排行榜 https://www.tiobe.com/tiobe-index/ 世界上没有最好的编程语言&#xff0c;只有最适用于具体应用场景的编程语言。 java: 跨平台的语言JVM: 跨语言的平台 随着Java7的正式发布,Java虚拟机的设计者们通过JS…

【周末闲谈】什么是云计算?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 ✨第一周 二进制VS三进制 ✨第二周 文心一言&#xff0c;模仿还是超越&#xff1f; ✨第二周 畅想AR 文章目录 前言什么是云计算&#xff1f;&#x1f914;&#x1f914;&#x1f914;大数…

【Linux】进程信号(中)

在上一个文章中&#xff0c;关于信号的产生&#xff0c;还有没补充完的&#xff0c;所以在这篇文章补充一下 文章目录 1.信号的产生硬件异常产生信号a/0问题验证为8号信号 野指针问题验证为11号信号 核心转储设置核心转储大小Core与Term的区别核心转储的作用 2.信号保存1. 概念…

Windows搭建C++开发环境(visual studio 2022)

开发环境的搭建 开发工具&#xff1a;vscode、visual studio 2022、visual studio 2019、2015、2010 .. 安装步骤&#xff08;以Windows下visual studio2022为例&#xff09;&#xff1a; 打开官网地址 Visual Studio 2022 IDE - 适用于软件开发人员的编程工具 (microsoft.com…

Playwright-python 自动化测试【Anaconda】环境配置

第一步&#xff1a;Anaconda的安装 安装Anaconda的好处&#xff0c;比prenv网速快&#xff0c;并且拥有独立的python环境&#xff0c;再也不用烦恼用哪个python好了。 Anaconda的下载页参见官网下载&#xff0c;Linux、Mac、Windows均支持。 https://mirrors.tuna.tsinghua.ed…

传奇人物《周兴和》书连载之68 创意改变了世界

2008年11月3日。 上海。 这一天对周兴和来说&#xff0c;是一个非常值得记忆的日子。 这一天&#xff0c;联合国“南南全球技术产权交易所” 揭牌仪式在上海举行。这个交易所是由联合国开发计划署、中国商务部和上海市三方共同组建设立的。其主要任务是帮助发展中国家&#…

.NET 发布和支持计划介绍

对于 .NET 的发布&#xff0c;大多数童鞋都知道现在每年发布一个版本&#xff0c;针对 .NET 的发布&#xff0c;最近有些更新&#xff0c;Current 版本将改为 STS 版本&#xff0c;所以写一篇文章介绍一下 每年 11 月都会发布新的 .NET 主要版本&#xff0c;使开发人员、社区和…

回归预测 | MATLAB实现MLR多元线性回归预测(多指标评价)

回归预测 | MATLAB实现MLR多元线性回归预测(多指标评价) 目录 回归预测 | MATLAB实现MLR多元线性回归预测(多指标评价)预测效果基本介绍模型描述程序设计参考资料预测效果 基本介绍 回归预测 | MATLAB实现MLR多元线性回归预测(多指标评价) 模型描述 多元线性回归(Multip…

【Docker】命令大全

文章目录 基本命令镜像相关docker imagesdocker pulldocker rmidocker rundocker build镜像发布镜像常用命令 容器相关docker psdocker logs容器常用命令 数据卷相关网络相关compose相关swarm相关 基本命令 命令说明docker version显示版本信息docker info显示系统信息&#x…

SOFA Weekly|开源之夏 MOSN 与 Layotto 项目简介、社区会议预告、社区本周贡献

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展 欢迎留言互动&#xff5e; SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&am…

作为精益敏捷根基的科学管理与福特、大野耐一、戴明、德鲁克

果总这个文&#xff0c;对中外管理的基因做了解析&#xff1a; 数字化和管理哲学 &#xff5c; 中国企业为啥用不好ERP却信中台和阿米巴 《科学管理》是一本被低估的书&#xff0c;国内的管理很多还停留在“你有科学&#xff0c;我有神功”的阶段。重新学习科学管理很有必要。 …