为什么需要有Windows GDI
Windows GDI是Windows图形设备的简写。其中图形设备有各种显示器、打印机等等。由于应用程序不能直接访问硬件资源,所以当我们需要使用图形设备时,就需要用到GDI。GDI是Windows图形界面的基础。在编程语言上,就是通过Windows提供的一组函数进行GDI编程。
当然,想要实现类似的功能还可以使用其它库:GDI+、OpenGL、DirectX、Windows Image Acquisition 等可以实现类似或更高级的功能。Windows GDI是最基本的库。
Windows GDI可以实现以下的功能:
- 获取输出设备的输出,可以截获当前显示器显示的内容,包括整个屏幕、指定窗口或其他任意部分。
- 控制显示器的输出内容,在显示器的指定位置输出指定的内容。应用程序可以指定输出的位置、颜色、大小、区域。
- 可以以点、线条(直线、曲线)、图形、位图、文字等方式输出。
- 可指定输出内容的颜色、大小、位置。
- 可将输出内容进行变形、变色、字体的处理等。
设备上下文
在进行具体的GDI编程之前,有必要说说设备上下文这一关键概念。
*设备上下文(Device Context)*是一种对象(数据结构),设定了图形输出的特性与属性,包含了绘图所需的设备类型、绘图属性和状态信息。在Windows平台下,所有的图形操作都是通过DC来完成的。在系统中可以有多个DC,每DC都与一个特定的设备相关联。一个DC所关联的设备的驱动定义了过此 DC 进行的图形输出操作(文字输出、绘制、填充等)会被哪个设备(包括显示器、打印机、绘图仪)或设备的子区域(窗口客户端等)所接收。
这里所说的设备,不仅包括显示器、打印机等,一个窗口的客户区也算是设备;这里所说的绘图操作,不仅仅是绘制点、线以及简单多边形,还包括了文本绘制,图像绘制等等。不要误以为绘图操作只是简单地绘制线条。
设备上下文有四种类型:分别是“显示”、“打印机”、“内存”、“信息”。应用程序在进行图像输出时,只需要关心 DC 的类型,如果需要将图像输出到特定的设备只需创建相应类型的DC即可。而对不同类型的DC的操作方式都是统一的,应用程序不需要关注设备硬件的异同,无论哪种设备数据接口、哪种通信数据的格式等都是同样的处理,GDI的接口都是相同的。
说了这么多,DC一句话概括就是应用程序与硬件设备之间的桥梁。
创建DC
Windows编程中,要设备上下文,首先要定义设备上下文句柄HDC。
HDC hdc = GetDC(hwnd);//参数是一个窗口句柄
HDC hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);//第一个参数代表了这是一个显示设备上下文
如上代码所示,我们可以使用GetDC或CreateDC函数来获得或创建一个设备上下文句柄(类似的函数还有BeginPaint、GetWindowsDC)。有了设备上下文句柄之后,我们就可以把hdc当作参数传递给具有输出功能的函数,这样我们就可以在图形设备上进行输出操作了。
图形对象
一个DC中还包括一系列图形对象,通过修改图形对象,我们可以影响输出效果。
常用的图形对象包括字体、画笔、画刷、位图、区域、路径等等。除了路径和位图以外,当应用程序创建一个DC时,系统会为DC创建默认的图形对象。通过创建图形对象,我们可以控制绘图的效果。
HDC hdc = GetDC(hWnd);//定义设备上下文
HPEN hPen = CreatePen(PS_SOLID, 4, RGB(0, 0, 0));//定义画笔图形对象
SelectObject(hWnd, hPen);//为设备上下文选择图形对象
接下来更加详细地介绍图形对象。
选择图形对象
应用程序创建(Create)新的图形对象,通过选入操作(Select Into)替换DC中原来的图形对象。
对于同一种图形对象,DC中只会有一个当前对象。通常使用SelectObject函数为DC选择对象并替换原有对象。
HGDIOBJ SelectObject(
HDC hdc, //DC的句柄
HGDIOBJ hgdiobj //需要替换的图形对象的句柄
);
也可以通过特定的函数设置特定的图形对象,比如SetDCBrushColor、GetDCBrushColor、SetDCPenColor等。
获取图形对象及信息
我们可以使用GetCurrentObject函数获取DC中的指定图形对象信息。
HGDIOBJ GetCurrentObject(
HDC hdc,
UINT uObjectType
);
示例代码
接下来给出一份代码,这个程序的功能是直接在屏幕上绘制一条直线以及一个矩形。希望通过这个简单的小程序,帮助读者理解Windows GDI编程的有关概念
#include <Windows.h>
void GDIOut(HDC hdc)
{
HPEN hPen, hPenOld;//画笔图形对象
HBRUSH hbrush, hbrushOld;//画刷图形对象
BYTE bRed = 0;
BYTE hGreen = 0;
BYTE hBlue = 0;
COLORREF cPen = RGB(bRed, hGreen, hBlue);//定义画笔颜色
COLORREF cBrush = RGB(233, GetGValue(cPen), 255);//定义画刷颜色
hPen = CreatePen(PS_SOLID, 10, cPen);//创建画笔图形对象
hbrush = CreateSolidBrush(cBrush);//创建画刷图形对象
//选择对象
hPenOld = (HPEN)SelectObject(hdc, hPen);
hbrushOld = (HBRUSH)SelectObject(hdc, hbrush);
LineTo(hdc, 500, 500);
SelectObject(hdc, hPenOld);
Rectangle(hdc, 200, 200, 500, 500);
DeleteObject(hPen);
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush);
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
_In_ PSTR lpCmdLine, _In_ int nCmdShow)
{
HDC hdc = GetDC(NULL);//设定参数为NULL,获取整个屏幕的设备上下文句柄
GDIOut(hdc);
ReleaseDC(NULL, hdc);//释放DC,使其它程序可以使用
return 0;
}
写在最后
本文只给出了GDI编程中基本绘图的示例,希望读者在了解了Windows GDI的基本概念(尤其是设备上下文)之后,能够自行查阅Windows官方文档并写出其它功能的示例程序。后面我也会写文章介绍GDI的其它应用。
此外,MFC对Windows GDI进行了封装,之后会出一篇专门的文章说明MFC中的GDI编程。

752

被折叠的 条评论
为什么被折叠?



