基本概念

何为GDI和DC

  1. GDI:(Graphics Device Interfase)图形设备接口,是一个应用程序与输出设备之间的中介。
  • 一方面,GDI向应用程序提供一个与设备无关的编程环境,另一方面,它又以设备相关的格式和具体的设备打交道。
  1. DC:(Device Context)设备描述表,是一种Windows数据结构。包括了与一个设备的绘制属性相关的信息。所有的绘制操作通过一个设备描述表进行,绘制线条、形状和文本的Windows API 函数都与DC有关。正因如此我们每次绘图都需要获取 DC 即 ++调用 CDC * pDC =GetDc();++之类的语句
    CDC 说明文档
  CDC *  GetDC(){
     CDC *objDC = new CDC;
     return objDC ;
  }

GetDC 函数:获取设备指针
函数功能描述:该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文的句柄.以后可以在GDI函数中用该句柄绘图.

MFC绘图的一般基本流程

  1. 获取设备指针
  2. 调用绘图相关的函数
    例如:
    我在这里鼠标左键单击时间里的写了如下代码,这样我每次点击一下,就会画出线来。
void CAboutDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (MK_LBUTTON & nFlags)
	{;
		CClientDC dc(this);
		dc.SetROP2(R2_NOT);
		dc.MoveTo(0,0);
		dc.LineTo(point);
	}

	CDialogEx::OnLButtonDown(nFlags, point);
}

效果

其他说明

当然 我们绘图一般都是写在 onPaint事件处理函数OnDraw(CDC* pDC)里面的

OnDraw(CDC* pDC)
{
	// TODO: 在此处为本机数据添加绘制代码
}

以后我们需要绘图的时候 发送onpaint消息就好了

扯一句闲话

MFC绘图帮忙封装了许多语句,调用API绘图还要获取窗口句柄之类的

坐标

  1. 屏幕坐标
    屏幕坐标描述物理设备(显示器、打印机等)的一种坐标体系,坐标原点在屏幕的左上角,X轴向右为正,Y轴向下为正。度量单位是象素。原点、坐标轴方向、度量单位都是不能够改变的。

  2. 设备坐标(又称物理坐标)
    设备坐标是描述在屏幕和打印机显示或打印的窗体的一种坐标体系。默认的坐标原点是在其客户区的左上角。X轴向右为正,Y轴向下为正。度量单位为象素。原点和坐标轴方向可以改变,但是度量单位不可以改变。

  3. 逻辑坐标
    逻辑坐标是在程序中控制显示,打印使用的坐标体系。该坐标系与定义的映射模式密切相关。默认的映射模式是MM_TEXT。我们可以通过设置不同的映射模式来改变该坐标体系的默认行为。

一些CDC常用函数

CDC 里面有许多自带的绘图函数,方便我们绘制圆形矩形哇之类的,太多了,我们可以查阅官方说明文档,我列举几个简单的

Arc(); //绘制圆弧
Ellipse(); //绘制圆形
TextOut();//输入字符串
/*等等*/

SelectObject()

作用:选择绘图对象 ,并且返回被这个对象替换的对象
我们在使用下面的要介绍的Cpen之类的对象的时候,务必要这样使用

void CNewView::OnDraw(CDC* pDC)
{
   CPen penBlack;  // Construct it, then initialize
    if(penBlack.CreatePen(PS_SOLID, 2, RGB(0,0,0)))
    {
        // Select it into the device context
        // Save the old pen at the same time
        CPen* pOldPen = pDC->SelectObject(&penBlack);
        // Draw with the pen
        pDC->MoveTo(20,20);
        pDC->LineTo(40,40);
        // Restore the old pen to the device context
        pDC->SelectObject(pOldPen);
    }
}

CPen* pOldPen = pDC->SelectObject(&penBlack);
绘图设备DC有默认的画笔和画刷,这样保存原来画笔用于还原,这样做是为了其它Windows程序,因为有的Windows程序直接使用默认的画笔和画刷进行绘图。并且!每个图形设备接口的对象都要占用一个HDC句柄,而且句柄是有限的 ,所以我们要做到有借有还

CPen 画笔类

说明文档
和我们正常画画一样 我们有了 用于绘图的纸——CDC,当然需要笔呀刷子这类的工具 CPen就是我们画画的笔.

构造函数

CPen();

CPen(
    int nPenStyle,
    int nWidth,
    COLORREF crColor);//常用!!!

CPen(
    int nPenStyle,
    int nWidth,
    const LOGBRUSH* pLogBrush,
    int nStyleCount = 0,
    const DWORD* lpStyle = NULL);

参数

nPenStyle

指定笔样式。 构造函数的第一版本中的此参数可以是以下值之一:

  • PS_SOLID 创建实心笔。
  • PS_DASH创建虚线笔。 仅当笔宽度为 1 或更少时(以设备单位为单位)才有效。
  • PS_DOT创建虚笔。 仅当笔宽度为 1 或更少时(以设备单位为单位)才有效。
  • PS_DASHDOT创建具有交替破折号和点的笔。 仅当笔宽度为 1 或更少时(以设备单位为单位)才有效。
  • PS_DASHDOTDOT创建具有交替破折号和双点的笔。 仅当笔宽度为 1 或更少时(以设备单位为单位)才有效。
  • PS_NULL创建空笔。
  • PS_INSIDEFRAME 创建一个笔,在 Windows GDI 输出函数Ellipse(例如, 、 Rectangle、RoundRect和Pie``Chord成员函数) 生成的封闭形状框架内绘制一条线。 当此样式与不指定边界矩形(例如LineTo成员函数)的 Windows GDI 输出函数一起使用时,笔的绘图区域不受框架的限制。

nWidth

笔的宽度

COLORREF crColor

笔的颜色

pLogBrush

指向结构LOGBRUSH。 如果nPenStyle是PS_COSMETIC,LOGBRUSH则结构的lbColor成员指定笔的颜色,并且必须将结构的LOGBRUSH lbStyle成员设置为BS_SOLID。 如果nPenStyle PS_GEOMETRIC,则必须使用所有成员指定笔的画笔属性。

nStyleCount

指定lpStyle数组的长度(以双字单位为单位)。 如果nPenStyle不是PS_USERSTYLE,则此值必须为零。

lpStyle

指向双字值数组。 第一个值指定用户定义样式中第一个虚线的长度,第二个值指定第一个空格的长度,等等。 如果未PS_USERSTYLE nPenStyle, 则此指针必须为 NULL。

调用方法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);

参数

和构造函数的一样

使用方法

  1. 创建一个CPen的对象,用于我们画笔,这里我们可以直接调用构造函数,或者CreatePen();函数都可以。
  2. SelectObject()
    选择使用画笔,保存原来的画笔
  3. 用完还原!
void CNewView::OnDraw(CDC* pDC)
{
   CPen penBlack;  // Construct it, then initialize
    if(penBlack.CreatePen(PS_SOLID, 2, RGB(0,0,0)))
    {
        // Select it into the device context
        // Save the old pen at the same time
        CPen* pOldPen = pDC->SelectObject(&penBlack);
        // Draw with the pen
        pDC->MoveTo(20,20);
        pDC->LineTo(40,40);
        // Restore the old pen to the device context
        pDC->SelectObject(pOldPen);
    }
}

补充

  1. 我们在调用话椭圆Ellipse()之类的函数的时候 CPen就是来画他的轮廓的边的,所以我们要改变轮廓就要设置Pen!
  2. 库存画笔 (堆画笔)
    微软还给我们存了几个库存的画笔,我们在调用SelectstockObject()来选择
  • 黑画笔 BLACK_PEN
  • 白色画笔 WHILE_PEN
  • 空画笔 NULL_PEN
  1. 我们可以这样创建库存画笔
CPen pen;
pen.CreateStockOject(BLACK_Pen); 

CBrush 画刷类

和Cpen 大同小异,不必重复介绍,重点说说一下不同

创建画刷

构造函数 成员函数

CBrush();
CBrush(COLORREF crColor);
CBrush(int nIndex, COLORREF crColor);

BOOL CreateBrush(int nIndex, COLORREF crColor);

参数

nIndex
指定画笔的填充样式。 它可以是以下任一值:

  • HS_BDIAGONAL 0
  • HS_CROSS 1
  • HS_DIAGCROSS 2
  • HS_FDIAGONAL 3
  • HS_HORIZONTAL 4
  • HS_VERTICAL 5
  • 大于5 就是实心的

使用和CPen一致

补充

位图?

位图(Bitmap),又称栅格图(英语:Raster graphics)或点阵图,是使用像素阵列(Pixel-array/Dot-matrix点阵)来表示的图像。

构造函数

在CBrush的的构造函数中,我们可以传入CBitmap指针参数,完成画刷的构造,其函数声明如下:
explicit CBrush(CBitmap* pBitmap); // CreatePatternBrush
该构造函数要求传入一个CBitmap指针,我们可以定义一个CBitmap对象,来完成CBrush的创建。然而,我们在创建一个CBitmap对象时,还需要完成位图的初始化,才能生成有效的CBitmap对象,CBitmap对象的初始化函数有CreateCompatibleBitmap、LoadBitmap、LoadMappedBitmap等。

字体CFont

我们其实可吧CFont 可以当成专门绘制图形的类和Cpen使用方法一样

构造

BOOL  CreateFont(
int nHeight,                          //字体高度(逻辑单位)
int nWidth,                           //字体平均宽度(逻辑单位)
int nEscapement,               //字体倾斜角度
int nOrientation,                  //字体倾斜角度
int nWeight,                         //字体磅数
BYTE bItalic,                       //是否斜体
BYTE bUnderline,              //是否带下划线
BYTE cStrikeOut,              //是否带删除线
BYTE nCharSet,                //字体的字符集
BYTE nOutPrecision,        //输出精度
BYTE nClipPrecision,       //裁剪精度
BYTE nQuality,                   //字体的输出质量
BYTE nPitchAndFamily,    //字体间距和字体族
LPCTSTR lpszFacename //字体的字样名
);

补充

pDC->SetTextColor()//设置文本颜色
pDC->SetBkColor()//设置文本颜色

结语

没有结语就是最好的结语
微信小程序

本文由 越行勤 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
原文链接:https://blog.yxqin.top/2020/11/28/mfc图形接口gdi
最后更新于:  316  天前,内容可能已经不具有时效性,请谨慎参考。

Q.E.D.


努力学习的小菜鸟