You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理Date Picker控件的日期变更通知?

Date Picker控件无法捕获日期变更通知的问题修复

问题说明

可以创建并显示Date Picker控件,也能通过点击修改控件显示的日期,但无法获取日期变更时的通知。预期在消息循环或窗口消息处理器中收到通知时,控制台输出提示信息。

复现代码

#include <windows.h>
#include <iostream>
#include "commctrl.h"

// 添加公共控件V6到清单
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

// 消息处理器
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
        EndPaint(hwnd, &ps);
    }
    return 0;

    case DTN_DATETIMECHANGE:
        std::cout << " date change\n";
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

HWND ConstructMainWindow()
{
    // 注册窗口类
    const char CLASS_NAME[] = "Sample Window Class";

    WNDCLASSA wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = NULL;
    wc.lpszClassName = CLASS_NAME;

    RegisterClassA(&wc);

    // 创建窗口
    HWND hwnd = CreateWindowExA(
        0,                          // 可选窗口样式
        CLASS_NAME,                 // 窗口类名
        "Date Picker Test", // 窗口标题
        WS_OVERLAPPEDWINDOW,        // 窗口样式

        // 尺寸和位置
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, // 父窗口
        NULL, NULL, NULL);
    if (hwnd == NULL)
    {
        std::cout << "main window failed\n";
        exit(1);
    }

    return hwnd;
}

void ConstructDatePicker(HWND main)
{
    // 初始化日期选择器控件
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(icex);
    icex.dwICC = ICC_DATE_CLASSES;
    if (!InitCommonControlsEx(&icex))
        std::cout << "InitCommonControlsEx failed\n";

    // 注册自定义窗口类以传递消息到WindowProc
    WNDCLASSA wc = {};
    wc.lpfnWndProc = &WindowProc;
    wc.hInstance = NULL;
    wc.lpszClassName = "DateTime";
    RegisterClassA(&wc);

    CreateWindowExA(0,
                    DATETIMEPICK_CLASSA,
                    "DateTime",
                    WS_BORDER | WS_CHILD | WS_VISIBLE | DTS_SHOWNONE,
                    30, 30, 200, 30,
                    main,
                    NULL,
                    NULL,
                    NULL);
}

int main()
{
    HWND hwnd = ConstructMainWindow();

    ConstructDatePicker(hwnd);

    ShowWindow(hwnd, 1);

    // 消息循环
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        if( msg.message == DTN_DATETIMECHANGE)
            std::cout << "message " << msg.message << "\n";
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

修复方案

问题核心在于:DTN_DATETIMECHANGE并非独立的窗口消息,而是作为子通知码通过WM_NOTIFY消息传递给父窗口。需要修改窗口消息处理器,添加对WM_NOTIFY的处理逻辑,同时移除原代码中直接捕获DTN_DATETIMECHANGE的无效分支。

修复后的消息处理代码片段:

case WM_NOTIFY:
{
    NMHDR *pnmhdr = reinterpret_cast<NMHDR *>(lParam);
    if (pnmhdr->code == DTN_DATETIMECHANGE)
    {
         LPNMDATETIMECHANGE lpChange = (LPNMDATETIMECHANGE)(lParam);
        std::cout << " 日期变更为 " <<
            lpChange->st.wYear <<"/" <<
            lpChange->st.wMonth <<"/" <<
            lpChange->st.wDay <<" "
            << lpChange->dwFlags << "\n";
    }
    break;
}

运行输出

日期变更为 2022/12/1 0
 日期变更为 2022/12/1 0

内容的提问来源于stack exchange,提问作者ravenspoint

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:15:21