Search code examples
imagevisual-c++mfcbackground-colorpicturebox

Picture Control background is gray and I want it white


My application has a picture control, whose background is gray and I want it to be white. I already tried several things, like: derive a class and override OnPaint method; respond to WM_CTLCOLOR message (adding ON_WM_CTLCOLOR()and processing it), but no success.

Entry on Message map:

ON_WM_CTLCOLOR()

Implementation:

BOOL CMyDialog::OnInitDialog()
{
    __super::OnInitDialog();

    white.CreateSolidBrush(RGB(255,255,255));

    //...

    return TRUE;  // return TRUE  unless you set the focus to a control
}


HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    if (pWnd == GetDlgItem(IDC_PICTURE))
    {
        return white;
    }

    return __super::OnCtlColor(pDC, pWnd, nCtlColor);
}

Header file class definition:

CBrush white;

HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);

gray back


Solution

  • After some debugging using Spy++, I've realized the Picture Control is a Static Control and the message I have to process is not WM_CTLCOLOR but WM_CTLCOLORSTATIC

    enter image description here

    So, on the dialog that contains it I changed the message map from

    ON_WM_CTLCOLOR()
    

    to

    ON_MESSAGE(WM_CTLCOLORSTATIC, OnCtlColorStatic)
    

    On the implementation, change the method from

    HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
        if (pWnd == GetDlgItem(IDC_PICTURE))
        {
            return white;
        }
    
        return __super::OnCtlColor(pDC, pWnd, nCtlColor);
    }
    

    to

    LRESULT CMyDialog::OnCtlColorStatic(WPARAM wParam, LPARAM lParam)
    {
        HWND hWnd = (HWND)lParam;
    
        if (::GetDlgCtrlID(hWnd) == IDC_PICTURE)
            return (LRESULT)white.GetSafeHandle();
    
        return DefWindowProc(WM_CTLCOLORSTATIC, wParam, lParam);
    }
    

    And in the header file, change also the method from

    HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    

    to

    LRESULT OnCtlColorStatic(WPARAM wParam, LPARAM lParam);
    

    Notice a subtle difference: the old one worked by returning the HBRUSH brush handle directly; the new one expects a function returning a LRESULT typed variable, so the cast.

    The result is what I was expecting:

    enter image description here

    UPDATE: I recently needed to do a thing where I had to set the Text Color of a Static and discovered that I can get its device context also:

    HDC hDC= (HDC)wParam;
    HWND hWnd = (HWND)lParam;
    

    So, after I could easily do it by:

    SetBkMode(hDC, TRANSPARENT);
    SetTextColor(hDC, RGB(0,127,127));