当 static 控件或具有 ES_READONLY 风格的 edit 控件被绘制时,会向父窗口发送 WM_CTLCOLORSTATIC 消息。如果我们在窗口过程中处理该消息,就必须返回一个画刷句柄,Windows 会使用该画刷来绘制控件背景(子窗口背景)。
也就是说,改变 static 控件的背景颜色只有这一种方式,就是处理 WM_CTLCOLORSTATIC 消息。WM_CTLCOLORSTATIC 消息就是用来设置背景画刷的。
改变 static 控件的背景颜色
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;//定义设备环境句柄
static TCHAR szBuffer[128];
//TEXTMETRIC tm;
// SCROLLINFO si;
PAINTSTRUCT ps;
size_t iStrLength;
static int cxChar, cyChar, cxClient, cyClient;
static HWND hStatic;//静态文本框
static HFONT hFont[6]; //声明一个逻辑字体句柄为静态变量
static HBRUSH hBrush; //画刷
int i,n;
//size_t iLength;
static int iClick = 0;
static TCHAR szFont[10][6] = { TEXT("微软雅黑"), TEXT("宋体"), TEXT("黑体"), TEXT("楷体"), TEXT("幼圆"), TEXT("隶书") };
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_CREATE:
//创建画刷
hBrush = CreateSolidBrush(RGB(0x41, 0x96, 0x4F)); //翠绿色
//创建6个字体
for (i = 0; i < 6; i++)
{
hFont[i] = CreateFont(
-20/*高度*/, -10/*宽度*/, 0/*不用管*/, 0/*不用管*/, 400,//设置字体粗细程度一般这个值设为400,
FALSE/*不带斜体*/, FALSE/*不带下划线*/, FALSE/*不带删除线*/,
DEFAULT_CHARSET, //这里我们使用默认字符集,还有其他以 _CHARSET 结尾的常量可用
OUT_CHARACTER_PRECIS, //输出精度
CLIP_CHARACTER_PRECIS, //剪裁精度
DEFAULT_QUALITY, //默认输出质量
FF_DONTCARE, //不指定字体族*/
szFont[i] //字体名
);
}
hStatic = CreateWindow(
TEXT("static"), //静态文本框的类名
TEXT("我其实是一个静态文本框"), //控件的文本
WS_CHILD /*子窗口*/ | WS_VISIBLE /*创建时显示*/ | WS_BORDER /*带边框*/ | SS_CENTER /*水平居中*/ | SS_CENTERIMAGE /*垂直居中*/,
20 /*X坐标*/, 20 /*Y坐标*/, 400 /*宽度*/, 300 /*高度*/,
hWnd, //父窗口句柄
(HMENU)1, //为控件指定一个唯一标识符
hInst, //当前程序实例句柄
NULL
);
break;
case WM_CTLCOLORSTATIC:
return (INT_PTR)hBrush; //这里必须返回画刷句柄
case WM_PAINT://窗口绘画:点
{
//int x, xLast;
HDC hdc = BeginPaint(hWnd, &ps);//函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。
EndPaint(hWnd, &ps);
return 0;
}
case WM_LBUTTONDOWN: //鼠标左键单击消息
iClick++;//鼠标点击次数
//设置控件字体
n = (iClick) % 6-1;//取余减一,
//更改静态文本框 字体
SendMessage(
hStatic, //欲设置字体的控件句柄
WM_SETFONT, //消息名(消息类型)
(WPARAM)hFont[n], //取得字体句柄
NULL //传空值即可
);
StringCchPrintf(szBuffer, 128, TEXT("鼠标左键被单击%d次"), iClick);
SetWindowText(hStatic, szBuffer);
break;
case WM_DESTROY:
DeleteObject(hBrush);
DeleteObject(hFont);//删除创建的字体
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
效果
修改文字颜色和文字背景颜色
上图中,我们的代码只是改变了控件的背景颜色(整个子窗口的背景颜色),却忽略了文字的背景颜色。
修改文字背景颜色使用 SetBkColor 函数,它的原型为:
COLORREF SetBkColor(
HDC hdc, //设备环境句柄
COLORREF crColor //背景颜色
);
修改文字前景色(文字颜色)使用 SetTextColor 函数,它的原型为:
COLORREF SetTextColor(
HDC hdc, //设备环境句柄
COLORREF crColor //背景颜色
);
这里我们修改的是 static 控件中的文本颜色,所以需要获取 static 控件的设备环境句柄。非常巧妙的是,发送 WM_CTLCOLORSTATIC 消息时,wParam 参数表示的就是 static 控件的设备环境句柄(lParam 表示控件句柄)。
下面的代码会修改文本的背景色和前景色:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;//定义设备环境句柄
HDC hdcStatic;
static TCHAR szBuffer[128];
//TEXTMETRIC tm;
// SCROLLINFO si;
PAINTSTRUCT ps;
size_t iStrLength;
static int cxChar, cyChar, cxClient, cyClient;
static HWND hStatic;//静态文本框
static HFONT hFont[6]; //声明一个逻辑字体句柄为静态变量
static HBRUSH hBrush; //画刷
int i, n;
//size_t iLength;
static int iClick = 0;
static TCHAR szFont[10][6] = { TEXT("微软雅黑"), TEXT("宋体"), TEXT("黑体"), TEXT("楷体"), TEXT("幼圆"), TEXT("隶书") };
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_CREATE:
//创建画刷
hBrush = CreateSolidBrush(RGB(0x41, 0x96, 0x4F)); //翠绿色
//创建6个字体
for (i = 0; i < 6; i++)
{
hFont[i] = CreateFont(
-20/*高度*/, -10/*宽度*/, 0/*不用管*/, 0/*不用管*/, 400,//设置字体粗细程度一般这个值设为400,
FALSE/*不带斜体*/, FALSE/*不带下划线*/, FALSE/*不带删除线*/,
DEFAULT_CHARSET, //这里我们使用默认字符集,还有其他以 _CHARSET 结尾的常量可用
OUT_CHARACTER_PRECIS, //输出精度
CLIP_CHARACTER_PRECIS, //剪裁精度
DEFAULT_QUALITY, //默认输出质量
FF_DONTCARE, //不指定字体族*/
szFont[i] //字体名
);
}
hStatic = CreateWindow(
TEXT("static"), //静态文本框的类名
TEXT("我其实是一个静态文本框"), //控件的文本
WS_CHILD /*子窗口*/ | WS_VISIBLE /*创建时显示*/ | WS_BORDER /*带边框*/ | SS_CENTER /*水平居中*/ | SS_CENTERIMAGE /*垂直居中*/,
20 /*X坐标*/, 20 /*Y坐标*/, 400 /*宽度*/, 300 /*高度*/,
hWnd, //父窗口句柄
(HMENU)1, //为控件指定一个唯一标识符
hInst, //当前程序实例句柄
NULL
);
break;
case WM_CTLCOLORSTATIC:
hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(255, 255, 255)); //白色
SetBkColor(hdcStatic, RGB(0x41, 0x96, 0x4F)); //设置字体背景为翠绿色
return (INT_PTR)hBrush; //这里必须返回画刷句柄
case WM_PAINT://窗口绘画:点
{
//int x, xLast;
HDC hdc = BeginPaint(hWnd, &ps);//函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。
EndPaint(hWnd, &ps);
return 0;
}
case WM_LBUTTONDOWN: //鼠标左键单击消息
iClick++;//鼠标点击次数
//设置控件字体
n = (iClick) % 6 - 1;//取余减一,
//更改静态文本框 字体
SendMessage(
hStatic, //欲设置字体的控件句柄
WM_SETFONT, //消息名(消息类型)
(WPARAM)hFont[n], //取得字体句柄
NULL //传空值即可
);
StringCchPrintf(szBuffer, 128, TEXT("鼠标左键被单击%d次"), iClick);
SetWindowText(hStatic, szBuffer);
break;
case WM_DESTROY:
DeleteObject(hBrush);
DeleteObject(hFont);//删除创建的字体
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
运行结果:
所以要想达到修改背景颜色的目的,除了修改static 控件的背景颜色,还要修改文本的背景颜色。
透明背景
实现透明背景需要设置文本背景颜色透明,同时返回没有颜色的画刷。
- SetBkMode 函数可以用来设置文本的背景模式,它的原型为:
int SetBkMode(
HDC hdc, //设备环境句柄
int iBkMode //背景模式
);
iBkMode 有下面两种取值:
取值 说明
OPAQUE 使用当前背景颜色来填充背景。
TRANSPARENT 背景透明。
- GetStockObject (NULL_BRUSH); 语句可以返回没有颜色的画刷。
示例代码:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;//定义设备环境句柄
HDC hdcStatic;
static TCHAR szBuffer[128];
//TEXTMETRIC tm;
// SCROLLINFO si;
PAINTSTRUCT ps;
size_t iStrLength;
static int cxChar, cyChar, cxClient, cyClient;
static HWND hStatic;//静态文本框
static HFONT hFont[6]; //声明一个逻辑字体句柄为静态变量
static HBRUSH hBrush; //画刷
int i, n;
//size_t iLength;
static int iClick = 0;
static TCHAR szFont[10][6] = { TEXT("微软雅黑"), TEXT("宋体"), TEXT("黑体"), TEXT("楷体"), TEXT("幼圆"), TEXT("隶书") };
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_CREATE:
//创建画刷
hBrush = CreateSolidBrush(RGB(0x41, 0x96, 0x4F)); //翠绿色
//创建6个字体
for (i = 0; i < 6; i++)
{
hFont[i] = CreateFont(
-20/*高度*/, -10/*宽度*/, 0/*不用管*/, 0/*不用管*/, 400,//设置字体粗细程度一般这个值设为400,
FALSE/*不带斜体*/, FALSE/*不带下划线*/, FALSE/*不带删除线*/,
DEFAULT_CHARSET, //这里我们使用默认字符集,还有其他以 _CHARSET 结尾的常量可用
OUT_CHARACTER_PRECIS, //输出精度
CLIP_CHARACTER_PRECIS, //剪裁精度
DEFAULT_QUALITY, //默认输出质量
FF_DONTCARE, //不指定字体族*/
szFont[i] //字体名
);
}
hStatic = CreateWindow(
TEXT("static"), //静态文本框的类名
TEXT("我其实是一个静态文本框"), //控件的文本
WS_CHILD /*子窗口*/ | WS_VISIBLE /*创建时显示*/ | WS_BORDER /*带边框*/ | SS_CENTER /*水平居中*/ | SS_CENTERIMAGE /*垂直居中*/,
20 /*X坐标*/, 20 /*Y坐标*/, 400 /*宽度*/, 300 /*高度*/,
hWnd, //父窗口句柄
(HMENU)1, //为控件指定一个唯一标识符
hInst, //当前程序实例句柄
NULL
);
break;
case WM_CTLCOLORSTATIC:
hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(0, 0, 255)); //蓝色
//SetBkColor(hdcStatic, RGB(0x41, 0x96, 0x4F)); //设置字体背景为翠绿色
SetBkMode(hdcStatic, TRANSPARENT); //透明背景
//return (INT_PTR)hBrush; //这里必须返回画刷句柄
return (INT_PTR)GetStockObject(NULL_BRUSH); //无颜色画刷
case WM_PAINT://窗口绘画:点
{
//int x, xLast;
HDC hdc = BeginPaint(hWnd, &ps);//函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。
EndPaint(hWnd, &ps);
return 0;
}
case WM_LBUTTONDOWN: //鼠标左键单击消息
iClick++;//鼠标点击次数
//设置控件字体
n = (iClick) % 6 - 1;//取余减一,
//更改静态文本框 字体
SendMessage(
hStatic, //欲设置字体的控件句柄
WM_SETFONT, //消息名(消息类型)
(WPARAM)hFont[n], //取得字体句柄
NULL //传空值即可
);
StringCchPrintf(szBuffer, 128, TEXT("鼠标左键被单击%d次"), iClick);
SetWindowText(hStatic, szBuffer);
break;
case WM_DESTROY:
DeleteObject(hBrush);
DeleteObject(hFont);//删除创建的字体
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
运行效果: