您无法捕获要在灰色背景上绘制的消息。系统会绘制WM_PRINTCLIENT 中的所有内容。然而,有一个不错的 hack!这个想法来自this post。
我这样做(在我的 WM_PAINT 处理程序中):
创建一个内存 DC 以供绘制
向选项卡控件发送 WM_PRINTCLIENT 消息,使其将选项卡绘制到内存 DC 中
创建一个反映选项卡形状的区域
用所需的背景画笔填充此区域 (RGN_DIFF) 之外的内存 DC 部分
将结果写入 BeginPaint 返回的 DC
调用 EndPaint 并返回,当然不调用选项卡控件自己的 WndProc :)
第 3 步有点繁琐,因为您必须知道标签的位置和形状,但其他
比这是一个非常干净的解决方案(请参见以下示例代码下方的图像)。你
或许可以使用 TransparentBlt 代替系统背景颜色。
我在这个解决方案中使用TransparentBlt:
创建hdcMemTab,第 1 步
HBITMAP hBitmap, hBitmapOld ; //keep them till the end of the program
HDC hdcMemTab; //keep it till the end of the program
HDC hdc;
Rect rt;
hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
hdcMemTab = CreateCompatibleDC(hdc);
GetWindowRect(hwnd_Tab, &rt);
rt.right = rt.right - rt.left;
rt.bottom = rt.bottom - rt.top;
rt.left = 0;
rt.top = 0;
hBitmap = CreateCompatibleBitmap(hdc, rt.right, rt.bottom);
hBitmapOld = SelectObject(hdcMemTab, hBitmap);
DeleteDC(hdc);
在子类标签控件的WM_PAINT中:
RECT rt, rtTab;
HDC hdc = BeginPaint(hwnd, &ps);
GetWindowRect(hwnd_Tab, &rt);
rt.right = rt.right - rt.left;
rt.bottom = rt.bottom - rt.top;
rt.left = 0;
rt.top = 0;
//step 2
SendMessage(hwnd_Tab, WM_PRINTCLIENT, (WPARAM)hdcMemTab, PRF_CLIENT);
FillRect(hdc, &rt, gBrushWhite); //gBrushWhite has the desired background color
HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
int n_items = TabCtrl_GetItemCount(hwnd_Tab);
//get tabs region, step 3
for(i = 0; i < n_items; i++){
TabCtrl_GetItemRect(hwnd_Tab, i, &rtTab);
HRGN hTabRgn = CreateRectRgn(rtTab.left, rtTab.top, rtTab.right, rt.bottom);
CombineRgn(hRgn, hRgn, hTabRgn, RGN_OR);
DeleteObject(hTabRgn);
}
GetRgnBox(hRgn, &rtTab);
DeleteObject(hRgn);
//step 5
TransparentBlt(hdc, 0, 0, rt.right, rt.bottom, hdcMemTab, 0, 0, rt.right, rt.bottom, RGB(240, 240, 240)); //(240, 240, 240) is the grey color
BitBlt(hdc, rtTab.left, rtTab.top, rtTab.right - 5, rtTab.bottom, hdcMemTab, rtTab.left, rtTab.top, SRCCOPY);
EndPaint(hwnd, &ps);
//step 6
return 0;