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 | 默认调色板(该调色板由系统调色板中的静态色彩组成) |
返回值:
-
如果函数调用成功,返回值是所申请的逻辑对象的句柄;
-
如果函数调用失败,返回值是 NULL。
备注:
- 不建议您使用该函数获得对话框和窗口的当前字体。应该使用
SystemParametersInfo
函数(SPI_GETNONCLIENTMETRICS 参数)来获得当前字体,因为 SystemParametersInfo 函数将考虑到当前主题,并提供了标题栏,菜单和消息对话框的字体信息。 - 仅在窗口风格为
CS_HREDRAW
和CS_VREDRAW
中,才能使用 DKGRAY_BRUSH、GRAY_BRUSH 和 LTGRAY_BRUSH 对象。如果在其他风格的窗口中使灰色画刷,可能导致在窗口移动或改变大小之后出现画刷模式错位现象,原始画刷不能被调整。 - HOLLOW_BRUSH 和 NULL_BRUSH 对象是一样的。
- 不必要通过调用[DeleteObject 函数来删除 Windows 预设的对象。
- 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 结构 |
返回值:
-
如果函数调用成功,返回值是新画刷的句柄;
扫描二维码关注公众号,回复: 14784120 查看本文章 -
如果函数调用失败,返回值是 NULL。
备注:
-
如果你再也不需要该画刷,可以使用
DeleteObject
函数将其删除。 -
实心画刷实际上就是指系统用来绘制要填充图形的内部区域的位图。
-
调用该函数创建新画刷之后,可以使用
SelectObjec
t 函数将新画刷选入设备环境中。 -
当要使用系统画刷的时候,应用程序应该使用
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 | 垂直阴影 |
返回值:
-
如果函数调用成功,返回值是新画刷的句柄;
-
如果函数调用失败,返回值是 NULL。
备注:
-
阴影画刷实际上就是指系统用来绘制要填充图形的内部区域的位图。
-
调用该函数创建新画刷之后,可以使用 SelectObject 函数将新画刷选入设备环境中。
-
调用
SetBkColor
函数可以修改画刷图案的背景色。 -
调用
SetBkMode
函数可以影响搞该阴影画刷的渲染效果(如果是 OPAQUE 模式,背景颜色被用来填充线与线之间的空隙;如果是TRANSPARENT
模式,Windows 就只画出阴影线,不填充它们之间的空隙)。 -
如果应用程序使用带阴影的刷子,用合适的颜色填充父窗口和子窗口的背景,那么在绘刷子窗口的背景之前,有可能需要设置刷子的起始点。要做到这一点,可以在应用程序中调用
SetBrushOrgEx
函数。 -
如果你再也不需要该画刷,可以使用
DeleteObject
函数将其删除。
ICM:在创建刷子时没有颜色,然而在把该刷子选入到ICM许可的设备环境中时,将会完成颜色管理。
CreateBrushIndirect
CreateBrushIndirect 函数根据指定的 LOGBRUSH 结构
创建一个画刷。
- API 函数原型:
参数解析:
参数 | 含义 |
---|---|
lplb | 【1】 指向 LOGBRUSH 结构 的指针 【2】 LOGBRUSH 结构 指定了画刷的风格、颜色和模式 |
返回值:
-
如果函数调用成功,返回值是新画刷的句柄;
-
如果函数调用失败,返回值是 NULL。
备注:
-
画刷实际上就是指系统用来绘制要填充图形的内部区域的位图。
-
调用该函数创建新画刷之后,可以使用 SelectObject 函数将新画刷选入设备环境中。
-
使用单色位图(一个颜色平面,每个像素 1 位)创建的画刷,使用当前的文本和背景颜色绘制。
-
如果你再也不需要该画刷,可以使用 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,该值被忽略 |
备注:
-
DIB(设备无关位图文件格式)包含 BITMAPINFO 结构以及紧跟着的存储像素阵列的数组。
-
尽管 lbColor 成员指定了阴影画刷的前景色,但调用
SetBkMode
函数和SetBkColor
函数可以控制背景颜色。
SetBkColor
SetBkColor 函数用于设置当前的背景颜色。
如果指定的颜色值超出了当前设备的表示范围,则设置为最近似的、设备可以表示的颜色。
- API 函数原型:
COLORREF SetBkColor(
_In_ HDC hdc,
_In_ COLORREF crColor
);
参数解析:
参数 | 含义 |
---|---|
hdc | 指定设备环境句柄 |
crColor | 新的背景颜色值(使用 RGB 宏 获得 COLORREF 类型) |
返回值:
-
如果函数调用成功,返回值是先前背景的颜色值(COLORREF 类型);
-
如果函数调用失败,返回值是 CLR_INVALID。
备注:
-
该函数填充由 CreatePen 函数创建出来的非实线画笔之间的空隙(例如点线画笔,填充的是画笔间点和线的空隙,不是客户区的背景颜色哦)。
-
该函数不会填充由 ExtCreatePen 函数创建出来的画笔。
-
该函数也可以用于填充 TextOut 函数和 ExtTextOut 函数输出字符的背景颜色。
-
如果背景颜色设置为不透明(OPAQUE)时,背景颜色用来填充非实线画笔风格的间隙、阴影画刷和字符的背景颜色。
SetBkMode
SetBkMode 函数用于设置字符、阴影画刷和非实线画笔的背景模式。
- API 函数档案:
int SetBkMode(
_In_ HDC hdc,
_In_ int iBkMode
);
参数解析:
参数 | 含义 |
---|---|
hdc | 指定设备环境句柄 |
iBkMode | 背景模式: OPAQUE 使用当前背景颜色来填充字符、阴影画刷和非实线画笔的空隙; TRANSPARENT 背景模式为透明,Windows 不填充字符、阴影画刷和非实线画笔的空隙 |
返回值:
-
如果函数调用成功,返回值是先前的背景模式;
-
如果函数调用失败,返回值是 0。
备注:
-
该函数将影响到由
CreatePen
函数创建的非实线画笔。 -
该函数并不会影响到由
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 ~