如何更改 SysDateTimePick32 或 CDateTimeCtrl 的背景颜色?

2022-01-12 00:00:00 windows win32gui winapi c++ mfc

我似乎无法更改 SysDateTimePick32 控件的背景颜色(本例中为白色):

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

在我的 Win32/MFC 应用程序中.

in my Win32/MFC application.

我首先尝试在父窗口中覆盖 OnCtlColor 通知消息,该消息甚至没有被调用.

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

然后我尝试了一种子类化方法 描述在这里,这被称为好,但控件在视觉上没有改变.(我在 Windows 8.1 机器上进行了测试.)

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.我需要它才能在 Windows XP 及更高版本上工作.

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

推荐答案

我不确定以下解决方案有多大的技巧,但它似乎可以快速修复,直到有人提出更好的解决方案.同样,它基于 this代码,还需要Windows Vista或更高版本的操作系统:

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);
}

相关文章