How to change background color of SysDateTimePick3

2019-08-12 00:01发布

问题:

I seem not to be able to change the background color of a SysDateTimePick32 control (white in this case):

in my Win32/MFC application.

I first tried overriding OnCtlColor notification message in the parent window, which wasn't even called.

I then tried a subclassing approach described here, which was called alright but the control did not change visually. (I did my tests on Windows 8.1 machine.)

So does anyone have idea how to do it?

PS. I need this to work on Windows XP and up.

回答1:

I'm not sure how much of a hack the following solution is, but it seems to work for a quick fix until someone suggests a better one. Again, it is based on this code, and also requires Windows Vista or later OS:

//Called from a subclassed WndProc
case WM_PAINT:
{
    PAINTSTRUCT ps;
    ::BeginPaint(hWnd, &ps);

    //Render control
    RenderWithBkgndColor(hWnd, ps.hdc, RGB(255, 0, 0));

    ::EndPaint(hWnd, &ps);

    return 0;
}


void RenderWithBkgndColor(HWND hWnd, HDC hDC, COLORREF clrBkgnd)
{
    //Render control with the background color
    //'clrBkgnd' = color for the background (if control is enabled)

    //SOURCE:
    //  http://comp.os.ms-windows.programmer.win32.narkive.com/0H8cHhw1/setting-color-for-sysdatetimepick32-control

    RECT rect;
    ::GetWindowRect(hWnd, &rect);
    ::MapWindowPoints(NULL, hWnd, (LPPOINT)&rect, 2);
    long nWidth = rect.right - rect.left, nHeight = rect.bottom - rect.top;

    HDC hDCMem = ::CreateCompatibleDC(hDC);
    HBITMAP hBitmap = ::CreateBitmap(nWidth, nHeight, ::GetDeviceCaps(hDC, PLANES), ::GetDeviceCaps(hDC, BITSPIXEL), (const void *) NULL);
    if (hBitmap)
    {
        HBITMAP hBitmapOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);

        //Render control itself
        ::SendMessage(hWnd, WM_PRINT, (WPARAM)hDCMem, PRF_CLIENT | PRF_CHILDREN | PRF_NONCLIENT);

        //Only if we have the color
        if(clrBkgnd != NULL)
        {
            //Only if control is enabled
            if((::GetWindowLongPtr(hWnd, GWL_STYLE) & (WS_VISIBLE | WS_DISABLED)) == (WS_VISIBLE | 0))
            {
                #define ALLOWED_DIFF 20

                DWORD dwBkgClr = ::GetSysColor(COLOR_WINDOW);   //0xFFFFFF;

                DWORD br0 = dwBkgClr & 0xFF;
                DWORD br1 = (dwBkgClr & 0xFF00) >> 8;
                DWORD br2 = (dwBkgClr & 0xFF0000) >> (8 * 2);

                for(int y = 0; y < nHeight; y++)
                {
                    for(int x = 0; x < nWidth; x++)
                    {
                        COLORREF clrPxl = ::GetPixel(hDCMem, x, y);

                        DWORD r0 = clrPxl & 0xFF;
                        DWORD r1 = (clrPxl & 0xFF00) >> 8;
                        DWORD r2 = (clrPxl & 0xFF0000) >> (8 * 2);

                        int nDiff_r0 = r0 - br0;
                        int nDiff_r1 = r1 - br1;
                        int nDiff_r2 = r2 - br2;

                        if(abs(nDiff_r0) < ALLOWED_DIFF &&
                            abs(nDiff_r1) < ALLOWED_DIFF &&
                            abs(nDiff_r2) < ALLOWED_DIFF)
                        {
                            ::SetPixel(hDCMem, x, y, clrBkgnd);
                        }
                    }
                }

            }

        }

        ::BitBlt(hDC, rect.left, rect.top, nWidth, nHeight, hDCMem, 0, 0, SRCCOPY);

        ::SelectObject(hDCMem, hBitmapOld);
        ::DeleteObject(hBitmap);
    }

    ::DeleteDC(hDCMem);
}