windows编程之画刷

windows编程之画刷

涉及到的函数

  • GetStockObject (获取画刷句柄)
  • CreateSolidBrush (实心画刷)
  • CreateHatchBrush (阴影画刷)
  • CreateBrushIndirect

GetStockObject

GetStockObject 函数用于获得 Windows 预设的画笔、画刷、字体或者调色板的句柄。

  • API 函数原型:
HGDIOBJ GetStockObject(
  _In_  int fnObject
);

参数解析:

参数 含义
fnObject 指定待获取对象的类型,具体参考下边。

fnObject 可取如下值之一

含义
BLACK_BRUSH 黑色画刷
DKGRAY_BRUSH 暗灰色画刷
DC_BRUSH 1. 纯色画刷,默认颜色是白色的 2. 调用 SetDCBrushColor 函数可以修改该值的颜色
GRAY_BRUSH 灰色画刷
HOLLOW_BRUSH 空画刷(相当于 NULL_BRUSH)
LTGRAY_BRUSH 浅灰色画刷
NULL_BRUSH 空画刷(相当于 HOLLOW_BRUSH)
WHITE_BRUSH 白色画刷
BLACK_PEN 黑色画笔
DC_PEN 1. 纯色画笔,默认颜色是白色的 2. 调用 SetDCPenColor 函数可以修改该值的颜色
NULL_PEN 空画笔(空画笔不绘制任何东西)
WHITE_PEN 白色画笔
ANSI_FIXED_FONT Windows 中的固定间距(等宽)系统字体
ANSI_VAR_FONT Windows 中的可变间距(比例间距)系统字体
DEVICE_DEFAULT_FONT 设备相关字体
DEFAULT_GUI_FONT 1. 用户界面对象(如菜单、对话框)的默认字体 2. 不推荐使用 DEFAULT_GUI_FONT 或 SYSTEM_FONT 获得对话框或系统的字体 3. 该字体默认是 Tahoma
OEM_FIXED_FONT 原始设备制造商(OEM)相关固定间距(等宽)字体
SYSTEM_FONT 1. 系统字体 2. 默认情况下,Windows 使用系统字体绘制菜单,对话框和文本 3. 不推荐使用 DEFAULT_GUI_FONT 或 SYSTEM_FONT 获得对话框或系统的字体 4. 该字体默认是 Tahoma
SYSTEM_FIXED_FONT 1. 固定间距(等宽)系统字体 2. 该对象仅为兼容 16 位 Windows 版本提供
DEFAULT_PALETTE 默认调色板(该调色板由系统调色板中的静态色彩组成)

返回值:

  1. 如果函数调用成功,返回值是所申请的逻辑对象的句柄;

  2. 如果函数调用失败,返回值是 NULL。

备注:

  1. 不建议您使用该函数获得对话框和窗口的当前字体。应该使用 SystemParametersInfo 函数(SPI_GETNONCLIENTMETRICS 参数)来获得当前字体,因为 SystemParametersInfo 函数将考虑到当前主题,并提供了标题栏,菜单和消息对话框的字体信息。
  2. 仅在窗口风格为 CS_HREDRAWCS_VREDRAW 中,才能使用 DKGRAY_BRUSH、GRAY_BRUSH 和 LTGRAY_BRUSH 对象。如果在其他风格的窗口中使灰色画刷,可能导致在窗口移动或改变大小之后出现画刷模式错位现象,原始画刷不能被调整。
  3. HOLLOW_BRUSH 和 NULL_BRUSH 对象是一样的。
  4. 不必要通过调用[DeleteObject 函数来删除 Windows 预设的对象。
  5. DC_BRUSH 和 DC_PEN 都能与其他对象如 BLACK_BRUSH 和 BLACK_PEN 相互交换。具体请参考 GetDCBrushColor 函数、SetDCBrushColor 函数、GetDCPenColor 函数和 SetDCPenColor 函数。

CreateSolidBrush

CreateSolidBrush 函数用于创建一个指定颜色的逻辑画刷。

  • API 函数原型:
HBRUSH CreateSolidBrush(
  _In_  COLORREF crColor
);

参数解析:

参数 含义
crColor 1. 指定画刷的 RGB 颜色 2. RGB 颜色使用 RGB 宏生成 COLORREF 结构

返回值:

  1. 如果函数调用成功,返回值是新画刷的句柄;

    扫描二维码关注公众号,回复: 14784120 查看本文章
  2. 如果函数调用失败,返回值是 NULL。

备注:

  1. 如果你再也不需要该画刷,可以使用 DeleteObject 函数将其删除。

  2. 实心画刷实际上就是指系统用来绘制要填充图形的内部区域的位图。

  3. 调用该函数创建新画刷之后,可以使用 SelectObject 函数将新画刷选入设备环境中。

  4. 当要使用系统画刷的时候,应用程序应该使用 GetSysColorBrush(iIndex) 代替 CreateSolidBrush(GetSysColor(nIndex))。因为 GetSysColorBrush 函数会使用缓存好的画刷而不用重新创建一个新的。

ICM:在创建刷子时没有颜色操作。 然而,当把该刷子选入ICM许可的设备环境中时,将进行颜色管理。


CreateHatchBrush

CreateHatchBrush 函数用于创建一个具有指定阴影样式和颜色的逻辑刷子。

  • API 函数原型:
HBRUSH CreateHatchBrush(
  _In_  int fnStyle,
  _In_  COLORREF clrref
);

参数解析:

参数 含义
fnStyle 指定画刷的阴影样式(具体请看下方)
clrref 1. 指定用于画刷阴影的前景色 2. RGB 颜色使用 RGB 宏 生成 COLORREF 结构

fnStyle 参数指定画刷的阴影样式如下:

含义
HS_BDIAGONAL 45 度向上,从左至右的阴影
HS_CROSS 水平和垂直交叉阴影
HS_DIAGCROSS 45 度交叉阴影
HS_FDIAGONAL 45 度向下,自左至右阴影
HS_HORIZONTAL 水平阴影
HS_VERTICAL 垂直阴影

返回值:

  1. 如果函数调用成功,返回值是新画刷的句柄;

  2. 如果函数调用失败,返回值是 NULL。

备注:

  1. 阴影画刷实际上就是指系统用来绘制要填充图形的内部区域的位图。

  2. 调用该函数创建新画刷之后,可以使用 SelectObject 函数将新画刷选入设备环境中。

  3. 调用 SetBkColor 函数可以修改画刷图案的背景色。

  4. 调用 SetBkMode 函数可以影响搞该阴影画刷的渲染效果(如果是 OPAQUE 模式,背景颜色被用来填充线与线之间的空隙;如果是 TRANSPARENT 模式,Windows 就只画出阴影线,不填充它们之间的空隙)。

  5. 如果应用程序使用带阴影的刷子,用合适的颜色填充父窗口和子窗口的背景,那么在绘刷子窗口的背景之前,有可能需要设置刷子的起始点。要做到这一点,可以在应用程序中调用 SetBrushOrgEx 函数。

  6. 如果你再也不需要该画刷,可以使用 DeleteObject 函数将其删除。

ICM:在创建刷子时没有颜色,然而在把该刷子选入到ICM许可的设备环境中时,将会完成颜色管理。


CreateBrushIndirect

CreateBrushIndirect 函数根据指定的 LOGBRUSH 结构 创建一个画刷。

  • API 函数原型:

参数解析:

参数 含义
lplb 【1】 指向 LOGBRUSH 结构 的指针 【2】 LOGBRUSH 结构 指定了画刷的风格、颜色和模式

返回值:

  1. 如果函数调用成功,返回值是新画刷的句柄;

  2. 如果函数调用失败,返回值是 NULL。

备注:

  1. 画刷实际上就是指系统用来绘制要填充图形的内部区域的位图。

  2. 调用该函数创建新画刷之后,可以使用 SelectObject 函数将新画刷选入设备环境中。

  3. 使用单色位图(一个颜色平面,每个像素 1 位)创建的画刷,使用当前的文本和背景颜色绘制。

  4. 如果你再也不需要该画刷,可以使用 DeleteObject 函数将其删除。

ICM:在创建刷子时没有颜色操作。 然而,当把该刷子选入ICM许可的设备环境中时,将进行颜色管理。


LOGBRUSH 结构

LOGBRUSH 结构定义了逻辑画刷的样式,颜色和图案。

CreateBrushIndirect 函数和 ExtCreatePen 函数需要使用到该结构。

  • 结构原型:
typedef struct tagLOGBRUSH {
    
    
  UINT      lbStyle;
  COLORREF  lbColor;
  ULONG_PTR lbHatch;
} LOGBRUSH, *PLOGBRUSH;

成员解析:

成员 含义
lbStyle 指定画刷的样式,该成员决定着 Windows 如何解释另外的两个成员: 值含义BS_DIBPATTERN1. 带图案的刷子,由设备无关位图(DIB)来定义 2. lbHatch 成员应该是 DIB 的句柄BS_DIBPATTERN8X8同 BS_DIBPATTERNBS_DIBPATTERNPT1. 带图案的刷子,由设备无关位图(DIB)来定义 2. lbHatch 成员应该是指向 DIB 的指针BS_HATCHED阴影画刷BS_HOLLOW空画刷BS_NULL同 BS_HOLLOWBS_PATTERN由内存位图定义的画刷BS_PATTERN8X8同 BS_PATTERNBS_SOLID实心画刷
lbColor 1. 指定画刷的颜色 2. 如果 lbStyle 成员的值是 BS_HOLLOW 或 BS_PATTERN,该值被忽略 3. 如果 lbStyle 成员的值是 BS_DIBPATTERN 或 BS_DIBPATTERNPT,该值的低 8 位指定 BITMAPINFO 结构中的 bmiColors 成员,包含明确的 RGB 值或当前调色板的索引值: 含义DIB_PAL_COLORS包含了当前使用的逻辑调色板中的 16 位索引数组的颜色表DIB_RGB_COLORS包含了明确的 RGB 值的颜色表4. 如果 lbStyle 成员的值是 BS_HATCHED 或 BS_SOLID,该值是一个 COLORREF 类型的颜色值(使用 RGB 宏创建 COLORREF 类型)
lbHatch 1. 指定画刷的阴影样式 2. 如果 lbStyle 成员的值是 BS_DIBPATTERN,该值是一个 DIB 的句柄。为了获得这个句柄,应用程序需要调用 GlobalAlloc 函数(GMEM_MOVEABLE 标志)或调用 LocalAlloc 函数(LMEM_MOVEABLE 标志)分配内存块,然后填充 DIB。 3. 如果 lbStyle 成员的值是 BS_DIBPATTERNPT,该值是一个指向 DIB 的指针。该指针指向通过调用 LocalAlloc 函数(LMEM_FIXED 标志)或 GlobalAlloc 函数(GMEM_FIXED 标志)创建的内存块,或通过调用 LocalLock (handle_to_the_dib) 函数返回。 4. 如果 lbStyle 成员的值是 BS_HATCHED,该值指定阴影的样式: 值****含义HS_BDIAGONAL45 度向上,从左至右的阴影HS_CROSS水平和垂直交叉阴影HS_DIAGCROSS45 度交叉阴影HS_FDIAGONAL45 度向下,自左至右阴影HS_HORIZONTAL水平阴影HS_VERTICAL垂直阴影5. 如果 lbStyle 成员的值是 BS_PATTERN,该值是一个定义图案位图的句柄(该位图不能是 CreateDIBSection 函数创建的 DIB 位图) 6. 如果 lbStyle 成员的值是 BS_SOLID 或 BS_HOLLOW,该值被忽略

备注:

  1. DIB(设备无关位图文件格式)包含 BITMAPINFO 结构以及紧跟着的存储像素阵列的数组。

  2. 尽管 lbColor 成员指定了阴影画刷的前景色,但调用SetBkMode函数和 SetBkColor 函数可以控制背景颜色。


SetBkColor

SetBkColor 函数用于设置当前的背景颜色。

如果指定的颜色值超出了当前设备的表示范围,则设置为最近似的、设备可以表示的颜色。

  • API 函数原型:
COLORREF SetBkColor(
  _In_  HDC hdc,
  _In_  COLORREF crColor
);

参数解析:

参数 含义
hdc 指定设备环境句柄
crColor 新的背景颜色值(使用 RGB 宏 获得 COLORREF 类型)

返回值:

  1. 如果函数调用成功,返回值是先前背景的颜色值(COLORREF 类型);

  2. 如果函数调用失败,返回值是 CLR_INVALID。

备注:

  1. 该函数填充由 CreatePen 函数创建出来的非实线画笔之间的空隙(例如点线画笔,填充的是画笔间点和线的空隙,不是客户区的背景颜色哦)。

  2. 该函数不会填充由 ExtCreatePen 函数创建出来的画笔。

  3. 该函数也可以用于填充 TextOut 函数和 ExtTextOut 函数输出字符的背景颜色。

  4. 如果背景颜色设置为不透明(OPAQUE)时,背景颜色用来填充非实线画笔风格的间隙、阴影画刷和字符的背景颜色。


SetBkMode

SetBkMode 函数用于设置字符、阴影画刷和非实线画笔的背景模式。

  • API 函数档案:
int SetBkMode(
  _In_  HDC hdc,
  _In_  int iBkMode
);

参数解析:

参数 含义
hdc 指定设备环境句柄
iBkMode 背景模式: OPAQUE使用当前背景颜色来填充字符、阴影画刷和非实线画笔的空隙; TRANSPARENT背景模式为透明,Windows 不填充字符、阴影画刷和非实线画笔的空隙

返回值:

  1. 如果函数调用成功,返回值是先前的背景模式;

  2. 如果函数调用失败,返回值是 0。

备注:

  1. 该函数将影响到由 CreatePen 函数创建的非实线画笔。

  2. 该函数并不会影响到由 ExtCreatePen 函数创建的画笔。


代码示例

#pragma comment(lib, "User32.lib")
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "Gdi32.lib")
#include <windows.h>
#include <wingdi.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    
    
  static TCHAR szAppName[] = TEXT("NueXini");
  HWND hWnd;
  MSG msg;
  WNDCLASS wndclass;

  wndclass.style = CS_HREDRAW | CS_VREDRAW;
  wndclass.lpfnWndProc = WndProc;
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hInstance = hInstance;
  wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wndclass.lpszMenuName = NULL;
  wndclass.lpszClassName = szAppName;

  if (!RegisterClass(&wndclass))
  {
    
    
    MessageBox(NULL, TEXT("Error"), szAppName, MB_ICONERROR | MB_OK);
    return 0;
  }

  hWnd = CreateWindow(
      szAppName,
      TEXT("NueXini"),
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      NULL,
      NULL,
      hInstance,
      NULL);
  ShowWindow(hWnd, iCmdShow);
  UpdateWindow(hWnd);

  while (GetMessage(&msg, NULL, 0, 0))
  {
    
    
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
    
  HDC hdc;
  PAINTSTRUCT ps;
  RECT rect;
  static TCHAR szText[] = TEXT("NueXini: Hello World");

  HGDIOBJ hBrush, hOldBruch;

  switch (message)
  {
    
    

  case WM_SIZE:
    GetClientRect(hwnd, &rect);
    return 0;

  case WM_PAINT:
    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rect);

    SetTextAlign(hdc, TA_CENTER);
    SetTextColor(hdc, RGB(255, 0, 0));
    TextOut(hdc, (rect.right - rect.left) / 2, (rect.bottom - rect.top) / 2, szText, strlen(szText));

    // hBrush = GetStockObject(WHITE_BRUSH);
    // hBrush = CreateSolidBrush(RGB(255, 255, 0));
    hBrush = CreateHatchBrush(HS_HORIZONTAL, RGB(255, 0, 0));
    hOldBruch = SelectObject(hdc, hBrush);
    Rectangle(hdc, (rect.right - rect.left) / 7, (rect.bottom - rect.top) / 5, (rect.right - rect.left) * 2 / 7, (rect.bottom - rect.top) * 2 / 5);
    DeleteObject(SelectObject(hdc, hOldBruch));

    hBrush = CreateHatchBrush(HS_VERTICAL, RGB(0, 255, 0));
    hOldBruch = SelectObject(hdc, hBrush);
    Rectangle(hdc, (rect.right - rect.left) * 3 / 7, (rect.bottom - rect.top) / 5, (rect.right - rect.left) * 4 / 7, (rect.bottom - rect.top) * 2 / 5);
    DeleteObject(SelectObject(hdc, hOldBruch));

    hBrush = CreateHatchBrush(HS_FDIAGONAL, RGB(0, 0, 255));
    hOldBruch = SelectObject(hdc, hBrush);
    Rectangle(hdc, (rect.right - rect.left) * 5 / 7, (rect.bottom - rect.top) / 5, (rect.right - rect.left) * 6 / 7, (rect.bottom - rect.top) * 2 / 5);
    DeleteObject(SelectObject(hdc, hOldBruch));

    hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 255, 140));
    hOldBruch = SelectObject(hdc, hBrush);
    Rectangle(hdc, (rect.right - rect.left) / 7, (rect.bottom - rect.top) * 3 / 5, (rect.right - rect.left) * 2 / 7, (rect.bottom - rect.top) * 4 / 5);
    DeleteObject(SelectObject(hdc, hOldBruch));

    hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 145, 10));
    hOldBruch = SelectObject(hdc, hBrush);
    Rectangle(hdc, (rect.right - rect.left) * 3 / 7, (rect.bottom - rect.top) * 3 / 5, (rect.right - rect.left) * 4 / 7, (rect.bottom - rect.top) * 4 / 5);
    DeleteObject(SelectObject(hdc, hOldBruch));

    hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 255, 10));
    hOldBruch = SelectObject(hdc, hBrush);
    Rectangle(hdc, (rect.right - rect.left) * 5 / 7, (rect.bottom - rect.top) * 3 / 5, (rect.right - rect.left) * 6 / 7, (rect.bottom - rect.top) * 4 / 5);
    DeleteObject(SelectObject(hdc, hOldBruch));

    EndPaint(hwnd, &ps);
    return 0;

  case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
  }
  return DefWindowProc(hwnd, message, wParam, lParam);
}


enjoy it ~

猜你喜欢

转载自blog.csdn.net/a924282761/article/details/127522374