设置Win32静态文本颜色

5

我正在制作一个控制对话框的dll。我想让某个区域显示为红色文本。这段代码确实可以编译,但效果并未出现。以下是dialogProc执行的区域:

LRESULT CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_INITDIALOG:     
        CheckDlgButton(hDlg, IDC_CHECK, FALSE);
        EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
        return TRUE;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDC_CHECK:
            if (IsDlgButtonChecked(hDlg, IDC_CHECK))
            {
                EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
                EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
            }
            else
            {
                EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
                EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
            }
            break;
        case IDOK:
            {           
                EndDialog(hDlg, TRUE);
                return FALSE;
            }
        case IDCANCEL:
            {               
                EndDialog(hDlg, FALSE);
                return FALSE;
            }
        case WM_CTLCOLORSTATIC:
            // Set the colour of the text for our URL
            if ((HWND)lParam == GetDlgItem(hDlg,IDC_WARNING)) 
            {
                // we're about to draw the static
                // set the text colour in (HDC)lParam
                SetBkMode((HDC)wParam,TRANSPARENT);
                SetTextColor((HDC)wParam, RGB(255,0,0));
                return (BOOL)CreateSolidBrush (GetSysColor(COLOR_MENU));
            }
    return TRUE;
        }
    }
    return FALSE;
}

你确定你的代码块被执行了吗? - Nick Dandoulakis
选择语句是根据用户交互,例如点击按钮等操作来执行的。我不太确定如何在Win32 API中静态设置颜色。我更习惯于使用C++,其中对象有一个颜色属性。 - Jon Weinraub
好的,蓝色现在可以使用了,其他地方现在都是白色背景! - Jon Weinraub
除了图标控件,所有背景都没问题。它也被标记为透明的。不太确定为什么该控件现在有白色背景! - Jon Weinraub
是的,我后来意识到了,这就是我现在让它工作的方式,我将它移出了那个块,只是因为我不小心把它放错了位置!但是,我现在无法使我的图标具有透明背景。我将透明部分移到了if之外,所以现在一切都是透明的,因为在此之前,黑色文本具有白色背景,但我现在无法使图标具有透明背景。在此之前,它是可以工作的。 - Jon Weinraub
显示剩余2条评论
1个回答

12

WM_CTLCOLORSTATIC是与WM_COMMAND分开的一条消息。您对该消息的处理似乎是正确的,只是您将消息检查放在了WM_COMMAND特定项的检查内部。尝试重新组织您的外部switch语句。也许像下面这样:

LRESULT CALLBACK DialogProc(HWND hDlg, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_INITDIALOG:         
        // ...
        break;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDC_CHECK:
            // ...
            break;
        case IDOK:
            // ...
            break;
        case IDCANCEL:
            // ...
            break;
        }
        break;
    case WM_CTLCOLORSTATIC:
        // Set the colour of the text for our URL
        if ((HWND)lParam == GetDlgItem(hDlg, IDC_WARNING)) 
        {
                // we're about to draw the static
                // set the text colour in (HDC)lParam
                SetBkMode((HDC)wParam,TRANSPARENT);
                SetTextColor((HDC)wParam, RGB(255,0,0));
                // NOTE: per documentation as pointed out by selbie, GetSolidBrush would leak a GDI handle.
                return (BOOL)GetSysColorBrush(COLOR_MENU);
        }
        break;
    }
    return FALSE;
}

还要注意,当wParam应该为WM_CTLCOLORSTATIC提供HDC时,过滤WM_COMMAND的wParam参数会有点奇怪。

在MSDN中了解WM_CTLCOLORSTATIC通知


2
有没有一种方法可以在不处理CTLCOLORSTATIC消息的情况下完成这个操作? - viraj
7
以上解决方案至少存在一个GDI对象泄漏。在调用CreateSolidBrush时没有代码来调用DeleteObject。我不确定WM_CTLCOLORSTATIC是否在每次绘制操作时传递,或者它只是在对话框初始化时进行。但是,泄漏就是泄漏。上面的代码应该在WM_INITDIALOG中创建刷子,然后在WM_DESTROY中调用DeleteObject。或者,相比于调用CreateSolidBrush,GetSysColorBrush可能是以上代码的更好解决方案。 - selbie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接