为何OnCommand无法检测DTN_DATETIMECHANGE?能否用其实现该检测?
问题解答
首先明确:DTN_DATETIMECHANGE消息无法通过OnCommand函数捕获。
原因很直接:Windows控件的通知消息分为两类,分别通过WM_COMMAND和WM_NOTIFY两个核心消息传递:
WM_COMMAND负责传递简单控件的通知(比如组合框的CBN_SELCHANGE、编辑框的EN_CHANGE、按钮的BN_CLICKED),这类消息会被MFC的OnCommand函数处理。WM_NOTIFY则用于传递更复杂的控件通知,包含额外的结构体数据(比如NMHDR),DateTimePicker控件的DTN_DATETIMECHANGE就属于这类,它只会被MFC的OnNotify函数处理,OnCommand根本接收不到这类消息。
替代实现方案
方案1:重写OnNotify统一处理
在对话框类中重写OnNotify函数,统一检测日期时间控件的变更通知:
BOOL CCongregationDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { NMHDR* pNMHDR = reinterpret_cast<NMHDR*>(lParam); if (IsWindowVisible() && pNMHDR->code == DTN_DATETIMECHANGE) { // 可选:区分不同的日期时间控件 if (pNMHDR->idFrom == IDC_DTP_MEETING_TIME || pNMHDR->idFrom == IDC_DTP_LAST_INVITED) { IsModified(true); SetControlStates(); } } return __super::OnNotify(wParam, lParam, pResult); }
方案2:为每个控件单独绑定消息处理
通过MFC消息映射为每个日期时间控件单独绑定处理函数:
- 在对话框头文件中声明处理函数:
afx_msg void OnMeetingTimeChanged(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnLastInvitedChanged(NMHDR* pNMHDR, LRESULT* pResult);
- 在cpp文件中添加消息映射:
BEGIN_MESSAGE_MAP(CCongregationDlg, CDialog) // 其他已有消息映射 ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTP_MEETING_TIME, &CCongregationDlg::OnMeetingTimeChanged) ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTP_LAST_INVITED, &CCongregationDlg::OnLastInvitedChanged) END_MESSAGE_MAP()
- 实现处理函数:
void CCongregationDlg::OnMeetingTimeChanged(NMHDR* pNMHDR, LRESULT* pResult) { IsModified(true); SetControlStates(); *pResult = 0; } void CCongregationDlg::OnLastInvitedChanged(NMHDR* pNMHDR, LRESULT* pResult) { IsModified(true); SetControlStates(); *pResult = 0; }
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

