中年人学C语言Windows程序设计,13窗口绘画:画笔
GetStockObject
函数功能:
GetStockObject 函数用于获得 Windows 预设的画笔、画刷、字体或者调色板的句柄。
API 函数原型:
注释:_In_ 说明该参数是输入的。
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 函数。
SelectObject
函数功能:
SelectObject 函数用于选择一对象到指定的设备环境中,该新对象将替换先前的相同类型的对象。
API 函数原型:
注释:In 说明该参数是输入的。
HGDIOBJ SelectObject(
_In_ HDC hdc,
_In_ HGDIOBJ hgdiobj
);
参数解析:
参数 含义
hdc 指定设备环境句柄
hgdiobj 1. 被选择的对象的句柄
2. 该指定对象必须由以下的函数创建
hgdiobj 参数的对象必需由以下的函数创建:
对象 函数
位图 CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection
(只有内存设备环境可选择位图,并且在同一时刻只能一个设备环境选择位图)
画刷 CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush
字体 CreateFont, CreateFontIndirect
画笔 CreatePen, CreatePenIndirect
区域 CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect
返回值:
-
如果选择对象不是区域并且函数调用成功,那么返回值是被取代的对象的句柄;
-
如果选择对象是区域并且函数执行成功,返回以下值之一:
值 含义
SIMPLEREGION 区域由单个矩形组成
COMPLEXREGION 区域由多个矩形组成
NULLREGION 区域为空
- 如果发生错误并且选择对象不是一个区域,那么返回值为 NULL,否则返回 HGDI_ERROR。
备注:
-
该函数返回先前指定类型的选择对象。
-
一个应用程序在它使用新对象进行绘制完成之后,应该用原始的默认对象替换新对象。
-
应用程序不能同时选择一个位图到多个设备环境中。
-
ICM:如果被选择的对象是画笔或笔,那么就执行颜色管理。
CreatePen
函数功能:
CreatePen 函数用指定的样式、宽度和颜色创建一个逻辑画笔。
创建的画笔随后可以被选择到设备环境中,并用于绘制直线和曲线。
API 函数原型:
注释:In 说明该参数是输入的。
HPEN CreatePen(
_In_ int fnPenStyle,
_In_ int nWidth,
_In_ COLORREF crColor
);
参数解析:
参数 含义
fnPenStyle 指定画笔样式,详细内容请看下边
nWidth 1. 指定画笔的宽度
2. 如果该值为 0,则画笔为一个像素宽度,不管当前的映射模式
crColor 1. 指定画笔的 RGB 颜色
2. RGB 颜色使用 RGB 宏生成 COLORREF 结构
fnPenStyle 参数指定画笔样式为如下值之一:
值 含义
PS_SOLID 实线
PS_DASH 虚线(nWidth 参数的值必须 <= 1)
PS_DOT 点线(nWidth 参数的值必须 <= 1)
PS_DASHDOT 点划线(nWidth 参数的值必须 <= 1)
PS_DASHDOTDOT 点点划线(nWidth 参数的值必须 <= 1)
PS_NULL 该画笔看不见
PS_INSIDEFRAME 该画笔用于在 GDI 函数绘图中实现,绘制椭圆、矩形、圆角矩形、饼图以及弦等生成的封闭对象框时,画笔宽度向内扩展。
返回值:
-
如果函数调用成功,返回值是新画笔的句柄;
-
如果函数调用失败,返回值是 NULL。
备注:
-
调用该函数创建新画笔之后,可以使用 SelectObject 函数将新画笔选入设备环境中。只有当画笔被选入设备环境,才能使用该画笔绘制线段或曲线。
-
如果 nWidth 参数的值是 0,则画笔为一个像素宽度,不管当前的映射模式。
-
如果 nWidth 参数的值大于 1,则 fnPenStyle 参数的值必须为 PS_NULL, PS_SOLID 或 PS_INSIDEFRAME 的其中一个。
-
如果 nWidth 参数的值大于 1,且 fnPenStyle 参数的值为 PS_INSIDEFRAME,所有与该画笔相关联(除了折线和多边形)的封闭图形绘制,画笔宽度向内扩展。
-
如果 nWidth 参数的值大于 1,且 fnPenStyle 参数的值为 PS_INSIDEFRAME,如果指定的 RGB 颜色不存在,就进行抖动处理。
-
如果你再也不需要该画笔,可以使用 DeleteObject 函数将其删除。
SetBkColor
函数功能:
SetBkColor 函数用于设置当前的背景颜色。
如果指定的颜色值超出了当前设备的表示范围,则设置为最近似的、设备可以表示的颜色。
API 函数原型:
注释:In 说明该参数是输入的。
COLORREF SetBkColor(
_In_ HDC hdc,
_In_ COLORREF crColor
);
参数解析:
参数 含义
hdc 指定设备环境句柄
crColor 新的背景颜色值(使用 RGB 宏获得 COLORREF 类型)
返回值:
-
如果函数调用成功,返回值是先前背景的颜色值(COLORREF 类型);
-
如果函数调用失败,返回值是 CLR_INVALID。
备注:
-
该函数填充由 CreatePen 函数创建出来的非实线画笔之间的空隙(例如点线画笔,填充的是画笔间点和线的空隙,不是客户区的背景颜色哦)。
-
该函数不会填充由 ExtCreatePen 函数创建出来的画笔。
-
该函数也可以用于填充 TextOut 函数和 ExtTextOut 函数输出字符的背景颜色。
-
如果背景颜色设置为不透明(OPAQUE)时,背景颜色用来填充非实线画笔风格的间隙、阴影画刷和字符的背景颜色。
SetBkMode
Windows 也允许我们设置画笔对象的背景模式,总共有两种模式:透明(TRANSPARENT)和不透明(OPAQUE),刚才我们说了,默认是不透明的,所以我们看得到画笔对象的背景颜色,我们可以调用 SetBkMode 函数将背景模式设置为透明。
函数功能:
SetBkMode 函数用于设置字符、阴影画刷和非实线画笔的背景模式。
API 函数档案:
注释:In 说明该参数是输入的。
int SetBkMode(
_In_ HDC hdc,
_In_ int iBkMode
);
参数解析:
参数 含义
hdc 指定设备环境句柄
iBkMode 背景模式:
OPAQUE 使用当前背景颜色来填充字符、阴影画刷和非实线画笔的空隙
TRANSPARENT 背景模式为透明,Windows 不填充字符、阴影画刷和非实线画笔的空隙
返回值:
-
如果函数调用成功,返回值是先前的背景模式;
-
如果函数调用失败,返回值是 0。
备注:
-
该函数将影响到由 CreatePen 函数创建的非实线画笔。
-
该函数并不会影响到由 ExtCreatePen 函数创建的画笔。
SetROP2
函数功能:
SetROP2 函数用于设置当前的前景色混合模式(绘图模式)。
GDI 使用前景色混合模式,将画笔的颜色和画线显示区域的颜色混合后显示出来。
API 函数原型:
注释:In 说明该参数是输入的。
int SetROP2(
_In_ HDC hdc,
_In_ int fnDrawMode
);
参数解析:
参数 含义
hdc 指定设备环境句柄
fnDrawMode 绘图模式,即混合模式,具体请看下边。
fnDrawMode 参数指定的混合模式可以是以下值之一:
混合模式 含义
R2_BLACK 显示的颜色总是黑色
R2_COPYPEN 显示当前画笔的颜色
R2_MASKNOTPEN 显示的颜色是画笔颜色的取反值和屏幕颜色的交集,即:R2_NOTCOPYPEN & 屏幕颜色
R2_MASKPEN 显示的颜色是画笔颜色和屏幕颜色的交集,即:R2_COPYPEN & 屏幕颜色
R2_MASKPENNOT 显示的颜色是画笔颜色和屏幕颜色的取反值的交集,即:R2_COPYPEN & R2_NOT
R2_MERGENOTPEN 显示的颜色是画笔颜色的取反值和屏幕颜色的并集,即:R2_NOTCOPYPEN | 屏幕颜色
R2_MERGEPEN 显示的颜色是画笔颜色和屏幕颜色的并集,即:R2_COPYPEN | 屏幕颜色
R2_MERGEPENNOT 显示的颜色是画笔颜色和屏幕颜色的取反值的并集,即:R2_COPYPEN | R2_NOT
R2_NOP 不操作,颜色保持不变
R2_NOT 显示的颜色是屏幕颜色的取反值
R2_NOTCOPYPEN 显示的颜色是当前画笔颜色的取反值
R2_NOTMASKPEN 显示的颜色是画笔颜色和屏幕颜色的交集的取反值,即:~R2_MASKPEN
R2_NOTMERGEPEN 显示的颜色是画笔颜色和屏幕颜色的并集的取反值,即:~R2_MERGEPEN
R2_NOTXORPEN 显示的颜色是画笔颜色和屏幕颜色的异或结果的取反值,即:~R2_XORPEN
R2_WHITE 显示的颜色总是白色
R2_XORPEN 显示的颜色是画笔颜色和屏幕颜色的异或结果,即:R2_COPYPEN ^ 屏幕颜色
返回值:
-
如果函数调用成功,返回值是先前的混合模式(绘图模式);
-
如果函数调用失败,返回值是 0。
备注:
-
当使用一个画笔进行绘制时,实际上是在将画笔的像素颜色和目标显示表面的像素颜色按位进行布尔运算。
-
对像素颜色执行一个按位布尔运算称为“光栅操作”(Raster Operation, ROP),简称“ROP”,因为只涉及两种像素颜色(即画笔和屏幕),所以这里的布尔运算就被称为“二元光栅操作”,或者“ROP2”。
-
混合模式(绘图模式)仅支持光栅设备,并不支持矢量设备
代码实例
用画笔画各种图形
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
回调函数
参数:
hwnd : 窗口句柄
message : 消息ID
wParam和lParam:消息参数
//int i;
//size_t j;
HDC hdc;//定义设备环境句柄
static TCHAR szBuffer[128];
//TEXTMETRIC tm;
// SCROLLINFO si;
PAINTSTRUCT ps;
RECT rect;
size_t iStrLength;
static int cxChar, cyChar, cxClient, cyClient;
HPEN hNewPen, hOldPen;
switch (message)
{
case WM_SIZE://窗体大小改变
hdc = GetDC(hWnd);
//GetClientRect(hwnd, &rect);
cxClient = LOWORD(lParam);//当前x像素
cyClient = HIWORD(lParam);//当前y像素
StringCchPrintf(szBuffer, 128, TEXT("当前客户区的分辨率:%d * %d px"), cxClient, cyClient);
StringCchLength(szBuffer, 128, &iStrLength);
SetTextAlign(hdc, TA_CENTER | TA_TOP);
TextOut(hdc, cxClient / 2, 0, szBuffer, iStrLength);
ReleaseDC(hWnd, hdc);
return 0;
case WM_PAINT://窗口绘画:点
{
//int x, xLast;
HDC hdc = BeginPaint(hWnd, &ps);//函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。
GetClientRect(hWnd, &rect);
//系统预设样式
hNewPen = GetStockObject(BLACK_PEN);//函数用于获得 Windows 预设的画笔、画刷、字体或者调色板的句柄。
hOldPen = SelectObject(hdc, hNewPen);//函数用于选择一对象到指定的设备环境中,该新对象将替换先前的相同类型的对象。
MoveToEx(hdc, 0, rect.bottom / 8, NULL);
LineTo(hdc, rect.right, rect.bottom/8);
SelectObject(hdc, hOldPen);
/*PS_SOLID 实线
PS_DASH 虚线(nWidth 参数的值必须 <= 1)
PS_DOT 点线(nWidth 参数的值必须 <= 1)
PS_DASHDOT 点划线(nWidth 参数的值必须 <= 1)
PS_DASHDOTDOT 点点划线(nWidth 参数的值必须 <= 1)
PS_NULL 该画笔看不见
PS_INSIDEFRAME*/
//自定义画笔
//实线
hNewPen = CreatePen(PS_SOLID, 10, RGB(255, 0, 0));//函数用指定的样式、宽度和颜色创建一个逻辑画笔。
hOldPen = SelectObject(hdc, hNewPen);
MoveToEx(hdc, 0, rect.bottom / 4, NULL);
LineTo(hdc, rect.right, rect.bottom / 4);
SelectObject(hdc, hOldPen);
//PS_DASH 虚线(nWidth 参数的值必须 <= 1
hNewPen = CreatePen(PS_DASH, 1, RGB(0, 255, 0));
hOldPen = SelectObject(hdc, hNewPen);
MoveToEx(hdc, 0, rect.bottom *3/ 8, NULL);
LineTo(hdc, rect.right, rect.bottom *3/ 8);
SelectObject(hdc, hOldPen);
//PS_DOT 点线(nWidth 参数的值必须 <= 1)
hNewPen = CreatePen(PS_DOT, 1, RGB(0, 0, 255));
hOldPen = SelectObject(hdc, hNewPen);
MoveToEx(hdc, 0, rect.bottom / 2, NULL);
LineTo(hdc, rect.right, rect.bottom / 2);
SelectObject(hdc, hOldPen);
//PS_DASHDOT 点划线(nWidth 参数的值必须 <= 1)
hNewPen = CreatePen(PS_DASHDOT, 1, RGB(0, 255, 255));
hOldPen = SelectObject(hdc, hNewPen);
MoveToEx(hdc, 0, rect.bottom*6 / 10, NULL);
LineTo(hdc, rect.right, rect.bottom * 6 / 10);
SelectObject(hdc, hOldPen);
//PS_DASHDOTDOT 点点划线(nWidth 参数的值必须 <= 1)
hNewPen = CreatePen(PS_DASHDOTDOT, 1, RGB(255, 0, 255));
hOldPen = SelectObject(hdc, hNewPen);
MoveToEx(hdc, 0, rect.bottom * 6 / 8, NULL);
LineTo(hdc, rect.right, rect.bottom * 6 / 8);
SelectObject(hdc, hOldPen);
//PS_INSIDEFRAME
//该画笔用于在 GDI 函数绘图中实现,绘制椭圆、矩形、圆角矩形、饼图以及弦等生成的封闭对象框时,画笔宽度向内扩展。
hNewPen = CreatePen(PS_SOLID, 10, RGB(255, 255, 0));
hOldPen = SelectObject(hdc, hNewPen);
Ellipse(hdc, 250, rect.bottom * 8 / 10, 400, rect.bottom * 9 / 10);
SelectObject(hdc, hOldPen);
hNewPen = CreatePen(PS_INSIDEFRAME, 10, RGB(255, 255, 0));
hOldPen = SelectObject(hdc, hNewPen);
Ellipse(hdc, 50, rect.bottom * 8 / 10, 200, rect.bottom * 9 / 10);
SelectObject(hdc, hOldPen);
MoveToEx(hdc, 0, rect.bottom * 8 / 10, NULL);
LineTo(hdc, rect.right, rect.bottom * 8 / 10);
MoveToEx(hdc, 0, rect.bottom * 9/ 10, NULL);
LineTo(hdc, rect.right, rect.bottom * 9 / 10);
// 设置背景颜色
hNewPen = CreatePen(PS_DASHDOT, 1, RGB(255, 255,0));
hOldPen = SelectObject(hdc, hNewPen);
SetBkColor(hdc, RGB(0, 255, 0));// 设置背景颜色
MoveToEx(hdc, 0, rect.bottom * 7 / 10, NULL);
LineTo(hdc, rect.right, rect.bottom * 7 / 10);
SelectObject(hdc, hOldPen);
// 设置背景为透明色
hNewPen = CreatePen(PS_DASHDOT, 1, RGB(255, 255, 0));
hOldPen = SelectObject(hdc, hNewPen);
SetBkMode(hdc, TRANSPARENT); // 设置背景为透明色
MoveToEx(hdc, 0, rect.bottom * 6.5 / 10, NULL);
LineTo(hdc, rect.right, rect.bottom * 6.5 / 10);
SelectObject(hdc, hOldPen);
DeleteObject(hNewPen);
EndPaint(hWnd, &ps);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}