Windows中的GDI

原创
2022-12-07
4737
4

Windows 图形设备接口(Graphics Device Interface, GDI)使应用程序能够在视频显示器使用图形和格式化文本。


1. 设备环境

设备环境是Windows中内部使用的数据结构,它定义了GDI函数在显示设备特定区域的工作方式。要想在某个区域输出文字或绘制图形,必须先获取该区域的设备句柄。
首先看下面的部分代码:

case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = ::BeginPaint(hwnd, &ps);
    ::TextOut(hdc, 0, 0, TEXT("Hello GDI"), strlen("Hello GDI"));
    ::EndPaint(hwnd, &ps);
    return 0;
}

表示在客户区绘制文字,Hello GDI
如果不想在 WM_PAINT 消息中绘制,可以使用函数 GetDC 函数

case WM_LBUTTONDOWN:
{
    HDC hdc = ::GetDC(hwnd);
    ::SetTextColor(hdc, RGB(255, 0, 0));
    ::SetBkColor(hdc, RGB(0, 255, 255));
    ::TextOut(hdc, 0, 20, TEXT("Hello GDI"), strlen("Hello GDI"));
    ::ReleaseDC(hwnd, hdc);
    return 0;
}

表示按下鼠标时在坐标 (0,20)的位置绘制 Hello GDI,下面说一下 GetDCBeginPaint 函数的区别

  • BeginPaint 函数获取窗口客户区无效区域的设备句柄。
  • GetDC 函数获取客户区整个区域的设备句柄。不只是客户区的无效区域。当然, GetDCReleaseDC 不能使客户区中任何可能无效的区域有效。

当响应鼠标点击函数的时候,DC 结构成员的设置并没有被保存下来,下一次使用GDI函数的时候设备环境仍然使用Windows 的默认值,要想让Windows每次对DC的设置保存下来,只要在注册窗口时,向 WNDCLASSEX 的结构的 style 成员添加一个 CS_OWNDC 标志就可以了。

wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

颜色使用宏 RGB(r, g, b) 表示
GetRValueGetGValueGetBValue 可以从 COLORREF 获取各分量值

使用函数 SetPixel 函数设置一个像素值

COLORREF SetPixel (HDC hdc, int X, int Y, COLORREF crColor)

使用函数 GetPixel 获取获取一个像素值

COLORREF GetPixel(HDC hdc, int nXPos, int nYPos)

2. 绘制线条

绘制线条的函数有绘制单条直线 LineTo 、绘制多条直线 PolylinePolylineTo 、画贝塞尔曲线 PolyBezierPolyBezierTo 、绘制弧线 ArcArcTo

绘制直线只需要指定开始坐标,然后以直线的另一个坐标为参数调用 LineTo 函数,下面时绘制一条坐标从(0, 0)到(100,100)的直线

::MoveToEx(hdc, 0, 0, nullptr);
::LineTo(hdc, 100, 100);

DC的数据结构中有一个当前点,LineTo 函数就是从当前点绘制一条直线到参数指定点, 并把这个点设置为新的当前点。如果要设置当前点的位置可以使用函数 MoveToEx

BOOL MoveToEx(HDC hdc, int X, int Y, LPPOINT lpPoint)

DC 结构还有一个画笔句柄,每次绘画时,GDI 函数都会使用此句柄 设置画笔。画笔对象规定了线条的宽度、颜色和风格。
要想改变DC中默认的画笔,可以使用Windows中预定义的画笔对象,也可以创建新的画笔对象。预定义的画笔对象仅有三种 BLACK_PENWHITE_PENNULL_PEN 分别为黑色画笔、白色画笔和空画笔。

HPEN hPen = (HPEN)::GetStockObject(BLACK_PEN);
HPEN oldPen = (HPEN)::SelectObject(hdc, hPen);

使用函数 GetStockObject 函数选择好对象句柄后,就可以使用函数 SelectObject 将对象选入DC中。
使用函数 CreatePen 函数可以创建自定义画笔对象

HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor)
  • fnPenStyle: 画笔得风格,取值有PS_DOLID、PS_DASH、PS_DOT、PS_DASHDOT
  • nWdith: 画笔得宽度
  • color: 画笔得颜色

下面代码绘制一条直线:

case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = ::BeginPaint(hwnd, &ps);
    //::TextOut(hdc, 0, 0, TEXT("Hello GDI"), strlen("Hello GDI"));

    HPEN nPen = ::CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
    HPEN nOldPen = (HPEN)::SelectObject(hdc, nPen);
    ::MoveToEx(hdc, 10, 10, nullptr);
    ::LineTo(hdc, 100, 100);

    ::SelectObject(hdc, nOldPen);
    ::DeleteObject(nPen);
    ::EndPaint(hwnd, &ps);
    return 0;
}

3. 绘制区域

绘制直线得时候使用画笔,填充区域使用画刷。绘制时,使用当前画笔绘制边线,使用当前画刷填充区域。

  • Rectangle(hdc, x1, y1, x2, y2) 填充矩形
  • Ellipse(hdc, x1, y1, x2, y2) 矩形内切椭圆填充
  • Polyon(hdc, lpPoint, 5) 线轮廓

跟画笔一样可以使用系统默认得画刷,也可以使用自定义画刷

HBRUSH hBrush = ::CreateSolidBrush(RGB(255, 0, 0));
HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush);
::Rectangle(hdc, 10, 10, 200, 200);

::SelectObject(hdc, hOldBrush);
::DeleteObject(hBrush);

函数 CreateSolidBrush 输入唯一得参数就是画刷得颜色。函数 CreateHatchBrush 函数创建得画刷可以指定特定风格得线条:

HBRUSH CreateHatchBrush(
    int fnStyle,            // 线条的风格
    COLORREF clrref         // 图案线条的颜色
)
  • fnStyle 的风格可以为 HS_BDIAGLOBALHS_FDIAGLOBALHS_CROSSHS_HORIZONTALHS_DIAGCROSSHS_VERTICAL

可以使用 GetStockObject 函数获取一些常用的画刷对象,常用的预定义对象有 BLACK_BRUSH(黑色画刷)DKGRAY_BRUSH(深黑色画刷)GRAY_BRUSH(灰色画刷)LTGRAY_BRUSH(浅灰色画刷)WHITE_BRUSH(白色画刷)NULL_BRUSH(空画刷)

不会飞的纸飞机
扫一扫二维码,了解我的更多动态。

下一篇文章:Windows响应键盘鼠标事件