0

首先,对不起,如果我在这里听起来傲慢/粗鲁。

好的,所以现在每个人都遇到了这个(我希望);我只是在任何地方都没有找到任何适当的答案。我们从 Common Controls 6 清单开始,然后

case WM_CTLCOLORSTATIC:
    if (/* window has WS_EX_TRANSPARENT */) {
        SetBkMode((HDC) wParam, TRANSPARENT);
        return (LRESULT) GetStockObject(HOLLOW_BRUSH);
    }

并给出我们的标签WS_EX_TRANSPARENT。它们变得透明;到目前为止,一切都很好。现在我们必须将该样式添加到我们的复选框中(因为复选框响应该样式而不是WM_CTLCOLORBTN出于某种原因)。而且...复选框变黑了!

有没有办法让它们完全透明而不诉诸所有者绘制?我宁愿自己不画复选框;我宁愿不必猜测它看起来是否正确,或者如果主题 API 在我身上失败,我将不得不自己绘制复选框(当我将自定义复选框添加到我的列表视图时,我将不得不自己绘制复选框)而且我已经对所涉及的猜测数量不满意)。

这些复选框被绘制在主题选项卡控件上。到目前为止,我在 Windows XP 中发现了五个对话框,主题选项卡上带有透明复选框:快捷方式属性的常规选项卡、任务栏和开始菜单属性的任务栏选项卡、系统属性的系统还原选项卡、文件夹选项的常规选项卡(单选按钮)和辅助功能选项的键盘选项卡。所以这肯定是可能的!我确信 Windows UI 作者不必在整个操作系统中使用自定义绘图...我们都缺少什么?

如果我需要子类,那很好(无论如何我已经有一个子类用于事件处理目的),但我仍然不想自己画。

作为奖励,按钮呢?覆盖WM_CTLCOLORBTN给按钮一个黑色边框,但我注意到上面提到的标准对话框都没有让按钮的角透明,所以嗯:/

谢谢!

4

3 回答 3

1

您必须返回已 hbrBackground注册的窗口类的元素,如下所示:

case WM_CTLCOLORBTN:
case WM_CTLCOLORSTATIC: {
    wchar_t  class_Name[100];
    GetClassName(hWnd, class_Name, 100);
    WNDCLASS lpcls{};
    GetClassInfo(g_hInstance, class_Name, &lpcls);

    return  (LRESULT)lpcls.hbrBackground;
}
于 2016-06-11T15:42:19.040 回答
0

主要是这样:

void paintControlBackground(HWND hwnd, HDC dc)
{
    HWND parent;
    RECT r;
    POINT p;
    int saved;

    parent = GetParent(hwnd);
    if (parent == NULL)
        xpanic("error getting parent container of control in paintControlBackground()", GetLastError());
    if (GetWindowRect(hwnd, &r) == 0)
        xpanic("error getting control's window rect in paintControlBackground()", GetLastError());
    // the above is a window rect; convert to client rect
    p.x = r.left;
    p.y = r.top;
    if (ScreenToClient(parent, &p) == 0)
        xpanic("error getting client origin of control in paintControlBackground()", GetLastError());
    saved = SaveDC(dc);
    if (saved == 0)
        xpanic("error saving DC info in paintControlBackground()", GetLastError());
    if (SetWindowOrgEx(dc, p.x, p.y, NULL) == 0)
        xpanic("error moving window origin in paintControlBackground()", GetLastError());
    SendMessageW(parent, WM_PRINTCLIENT, (WPARAM) dc, PRF_CLIENT);
    if (RestoreDC(dc, saved) == 0)
        xpanic("error restoring DC info in paintControlBackground()", GetLastError());
}

    case WM_CTLCOLORSTATIC:
    case WM_CTLCOLORBTN:
        if (SetBkMode((HDC) wParam, TRANSPARENT) == 0)
            xpanic("error setting transparent background mode to Labels", GetLastError());
        paintControlBackground((HWND) lParam, (HDC) wParam);
        *lResult = (LRESULT) hollowBrush;
        return TRUE;

有一些松散的结局:

如果给定控件的直接父级是组框,这将不起作用;在这种情况下,您需要检查类名并沿着父链向上走。

您还需要WM_PRINTCLIENT在任何自定义容器和窗口类中实现。

这还不适用于组框标签;您将看到正确绘制的纹理,但组框线将绘制在其顶部。当我弄清楚并使用该信息更新此帖子时,我会将其标记为已解决。

(我看到的闪烁似乎是由程序的另一部分使用的停止世界垃圾收集器引起的,因此暂时不受我的控制。希望这很快就会改变。)

同时感谢!

于 2014-08-28T14:41:08.930 回答
0

这个答案很晚,但提供了一种更简单的方法。

要使 GroupBox 的子项透明,请在 GroupBox 的子类 proc 中处理 WM_CTLCOLORBTN 消息。

要使 GroupBox 的标题透明,请在 GroupBox 的 wndproc 过程的父级中处理 WM_CTLCOLORBTN 消息。

是显示我学习方法的链接。

我的代码(在 groupbox 的父级和 groupbox 的子类 proc 中都需要这个):

case WM_CTLCOLORSTATIC:
 case WM_CTLCOLORBTN:{
    SetBkMode((HDC) wParam, TRANSPARENT);

//if you need to get the classname
//char class_name[100];
  // GetClassName(hwnd, class_Name, 100);  
//end if you need to get the classname

    WNDCLASS lpcls{};
    GetClassInfo(hInstance,  _T("MainWindow"),&lpcls);//or use class_name
    return  (LRESULT)lpcls.hbrBackground;//works everywhere bs_groupbox
//below works in the groupbox's subclass proc but not in parent (strikes through the title)
 // return (LRESULT)GetStockObject(NULL_BRUSH);
       }

于 2021-04-18T20:10:54.233 回答