有没有办法在日期时间选择器 (DTP) 中获取输入字段的句柄?

Is there a way to get the handle of the entry field in a date time picker (DTP)?

通过发送 DTM_GETDATETIMEPICKERINFO 消息获得的 DATETIMEPICKERINFO 结构有一个字段 hwndEdit ,这可能是我正在寻找的。但是,我总是得到 NULL 所以我想知道它的实际含义是什么。如果没有,有没有办法获取输入字段的句柄?

恐怕没有办法得到你想要的。我刚刚创建了一个简单的 Win32 应用程序来测试这种可能性。如果我使用 DTM_GETDATETIMEPICKERINFOhwndDropDownhwndEdithwndUD,请给我 NULL。如果我尝试枚举子 window,那么在我这样做之前我会用 Spy++ 检查它,运气不好,没有子 window 与之关联。

最后,我尝试了 GetFocus()WindowFromPoint(),两者都只给我 DateTimePicker 本身的 HWND

这是我的测试代码:

#pragma comment(lib, "comctl32.lib")
#include <windows.h>
#include <tchar.h>
#include <commctrl.h>

enum MYID {
    MYID_FIRST = WM_APP,
    MYID_DTP
};

LPCTSTR const g_MyWndClass = _T("DTPTest");
LPCTSTR const g_MyWndTitle = _T("DTPTest");

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void OnWindowCreate(HWND);
void OnTimer(HWND);

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int nCmdShow)
{
    INITCOMMONCONTROLSEX icex{};
    icex.dwSize = sizeof(icex);
    icex.dwICC = ICC_DATE_CLASSES;
    InitCommonControlsEx(&icex);
    WNDCLASSEX wcex{};
    wcex.cbSize = sizeof(wcex);
    wcex.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.lpfnWndProc = WndProc;
    wcex.lpszClassName = g_MyWndClass;
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClassEx(&wcex);
    HWND hwnd = CreateWindowEx(0,
        g_MyWndClass, g_MyWndTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, 600, 400,
        nullptr, nullptr, nullptr, nullptr);
    if (!hwnd) { return 99; }
    SetTimer(hwnd, 0, 100, nullptr);
    ShowWindow(hwnd, nCmdShow);
    MSG msg{};
    while (GetMessage(&msg, nullptr, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return static_cast<int>(msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
    switch (msg) {
    case WM_CREATE:
        OnWindowCreate(hwnd);
        break;
    case WM_TIMER:
        OnTimer(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, w, l);
    }
    return 0;
}

void OnWindowCreate(HWND hwnd)
{
    HWND hwndDTP = CreateWindowEx(0, DATETIMEPICK_CLASS, nullptr,
        WS_CHILD | WS_VISIBLE | DTS_SHOWNONE,
        20, 50, 220, 20,
        hwnd, reinterpret_cast<HMENU>(MYID_DTP), nullptr, nullptr);
    DATETIMEPICKERINFO info{};
    info.cbSize = sizeof(DATETIMEPICKERINFO);
    SendMessage(hwndDTP, DTM_GETDATETIMEPICKERINFO, 0,
        reinterpret_cast<LPARAM>(&info));
    if (!info.hwndDropDown && !info.hwndEdit && !info.hwndUD)
    {
        MessageBox(hwnd, _T("No luck with DTM_GETDATETIMEPICKERINFO"),
            nullptr, MB_ICONERROR);
    }
}

void OnTimer(HWND hwnd)
{
    POINT pt{};
    GetCursorPos(&pt);
    HWND hwndPoint = WindowFromPoint(pt);
    HWND hwndFocus = GetFocus();
    TCHAR buf[99]{};
    wsprintf(buf, _T("Pointing at %p, focusing %p"),
        hwndPoint, hwndFocus);
    SetWindowText(hwnd, buf);
}

hwndEdit 似乎仅在控件具有 DTS_APPCANPARSE 样式并且您使用鼠标 单击 日期文本时才有效(我用OutputDebugString 和一个计时器)。编辑控件是动态创建和销毁的。 hwndUD 句柄仅在设置 DTS_UPDOWN 时有效,hwndDropDown 仅在下拉列表可见时有效。

它没有在文档中提到,但 DTM_GETDATETIMEPICKERINFO 被标记为 Vista+,这通常意味着该功能仅在 ComCtl32 v6 中实现,因此您还必须确保您有一个请求此版本的清单。

要更改颜色,您可以尝试 DTM_SETMCCOLOR,但只有 MCSC_BACKGROUND 被记录为在视觉样式处于活动状态时有效。