如何处理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
相关产品推荐
相关产品推荐

