Search code examples
c++winapigdi

Changing win32's radio button text color


Upon color change, i listen to WM_CTLCOLORSTATIC and act accordingly:

LRESULT ProcessWindowMessage(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_CTLCOLORSTATIC:
            LRESULT lBrush = ::DefWindowProc(hWnd, uMsg, wParam, lParam); // get default brush used so far
            ::SetBkMode((HDC)wParam, TRANSPARENT);
            ::SetTextColor((HDC)wParam, RGB(m_color.red, m_color.green, m_color.blue));
            return lBrush;
        }
    }

This works well with regular static-texts: labels and so on, but has no effect on regular radio buttons.

During my debugging attempts, I've tried listening to:

  1. WM_DRAWITEM - doesn't receive any events
  2. WM_CTLCOLORBTN - receive events only for regular push buttons( OK / CANCEL)
  3. WM_CTLCOLOREDIT - doesn't receive any events.

I'm subclassing to another window not generated / created by me, but constructed by my process.


Solution

  • @igal k said SetWindowTheme does not work. Since the comment is not enough for the sample code. I post it as an answer.

    First the result.

    enter image description here

    Code:

    OnInitDialog:
        ::SetWindowTheme(GetDlgItem(IDC_RADIO1)->GetSafeHwnd(), L"wstr", L"wstr");
    
    HBRUSH CMFCApplication1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
        // Call the base class implementation first! Otherwise, it may 
        // undo what we're trying to accomplish here.
        HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
        // Are we painting the IDC_MYSTATIC control? We can use 
        // CWnd::GetDlgCtrlID() to perform the most efficient test. 
        if (pWnd->GetDlgCtrlID() == IDC_RADIO1)
        {
            // Set the text color to red
            pDC->SetTextColor(RGB(255, 0, 0));
    
            // Set the background mode for text to transparent  
            // so background will show thru.
            pDC->SetBkMode(TRANSPARENT);
    
            // Return handle to our CBrush object
            hbr = m_brush;
        }
    
        return hbr;
    }