在开发MFC应用程序时,经常需要处理用户输入的表单数据。通常情况下,会在用户点击"提交"按钮时进行数据验证和提交。但是,如果能够实现在用户输入数据并切换到下一个字段时即时验证,将大大提高用户体验。本文将介绍如何在MFC中实现这一功能。
实现实时验证的一种方法是重写每个编辑字段的OnKillFocus方法。这种方法在只有少数几个控件时是可行的,但如果需要在多个窗口和大量控件中实现,就会变得非常繁琐,并且容易遗漏。
对于旧的控件(如编辑控件、组合框等),可以通过重写WM_COMMAND消息来捕获焦点消息。以下是实现的示例代码:
BOOL CMyPropertyPage::OnCommand(WPARAM wParam, LPARAM lParam)
{
UINT notificationCode = (UINT) HIWORD(wParam);
if ((notificationCode == EN_KILLFOCUS) ||
(notificationCode == LBN_KILLFOCUS) ||
(notificationCode == CBN_KILLFOCUS) ||
(notificationCode == NM_KILLFOCUS) ||
(notificationCode == WM_KILLFOCUS)) {
CWnd *pFocus = CWnd::GetFocus();
if (pFocus && (pFocus->GetParent() == this)) {
if (pFocus->GetDlgCtrlID() != IDCANCEL) {
ValAndSubmit(LOWORD(wParam));
}
}
}
return CPropertyPage::OnCommand(wParam, lParam);
}
这段代码检查是否收到了Killfocus消息,并确保焦点没有离开窗口,然后调用ValAndSubmit方法来处理数据。
对于较新的控件,可以使用WM_NOTIFY消息来处理。以下是处理WM_NOTIFY消息的示例代码:
BOOL CMyPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
NMHDR* pNMHDR = (NMHDR *)lParam;
if (pNMHDR && pNMHDR->code == NM_KILLFOCUS) {
CWnd *pFocus = CWnd::GetFocus();
if (pFocus && (pFocus->GetParent() == this)){
if (pFocus->GetDlgCtrlID() != IDCANCEL) {
if (pNMHDR->idFrom){
ValAndSubmit(pNMHDR->idFrom);
}
}
}
}
return CPropertyPage::OnNotify(wParam, lParam, pResult);
}
这段代码与OnCommand方法类似,但需要处理lParam中的新值。
ValAndSubmit方法的作用是更新数据。以下是ValAndSubmit方法的示例代码:
BOOL CGenPage::ValAndSubmit(int DlgCtrlID)
{
BOOL bIsOk = FALSE;
UpdateData(TRUE);
switch (DlgCtrlID) {
case ID_EDNAME:
// 更新名称
break;
case ID_ADDRESS:
// 更新地址
break;
case ID_PHONE:
// 更新电话
break;
case ID_WHATEVER:
// 其他
break;
}
return bIsOk;
}
这个方法根据控件的ID更新应用程序中的数据。
为了避免在每个对话框中重复相同的代码,可以使用面向对象编程(OOP)的方法。创建一个基类,继承自CDialog或CPropertyPage,并在基类中实现OnCommand和OnNotify方法。然后在每个对话框中只需要实现ValAndSubmit方法。