MFC 编辑控件EN_KILLFOCUS问题



我正在使用Visual Studio 2013并制作基于MFC Dialog的应用程序。我在编辑控件的终止焦点方面遇到了奇怪的问题。

请看下面:

================================================================================================================================================================================================================================

在我的应用程序中,我有两个"编辑对话框上的控件"。

1st Edit Control -> IDC_EDIT_QUALITY1
2nd Edit Control -> IDC_EDIT_QUALITY2

我已经处理了两者的EN_KILLFOCUS事件来验证值。

BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
ON_EN_KILLFOCUS(IDC_EDIT_QUALITY1, &CTestDlg::OnQuality1EditKillFocus)
ON_EN_KILLFOCUS(IDC_EDIT_QUALITY2, &CTestDlg::OnQuality2EditKillFocus)
END_MESSAGE_MAP()
void CTestDlg::OnQuality1EditKillFocus()
{
ValidateQualityParams(IDC_EDIT_QUALITY1);
}
void CTestDlg::OnQuality2EditKillFocus()
{
ValidateQualityParams(IDC_EDIT_QUALITY2);
}
#define MIN_QUALITY_VALUE     1     
#define MAX_QUALITY_VALUE   100
void CTestDlg::ValidateQualityParams(int qualityParamID)
{
CString strQuality1;
if (IDC_EDIT_QUALITY1 == qualityParamID)
{
m_ctrlQuality1.GetWindowText(strQuality1);
if ((_ttoi(strQuality1) < MIN_QUALITY_VALUE) || (_ttoi(strQuality1) > MAX_QUALITY_VALUE))
{
CString strMessage;
strMessage.Format(_T("Quality1 value must be between %d to %d."), MIN_QUALITY_VALUE, MAX_QUALITY_VALUE);
**AfxMessageBox(strMessage);**
m_ctrlQuality1.SetSel(0, -1);
m_ctrlQuality1.SetFocus();
return;
}
}
CString strQuality2;
if (IDC_EDIT_QUALITY2 == qualityParamID)
{
m_ctrlQuality2.GetWindowText(strQuality2);
if ((_ttoi(strQuality2) < MIN_QUALITY_VALUE) || (_ttoi(strQuality2) > MAX_QUALITY_VALUE))
{
CString strMessage;
strMessage.Format(_T("Quality2 value must be between %d to %d."), MIN_QUALITY_VALUE, MAX_QUALITY_VALUE);
AfxMessageBox(strMessage);
m_ctrlQuality2.SetSel(0, -1);
m_ctrlQuality2.SetFocus();
return;
}
}
}

现在,在更改第一个编辑控件 (IDC_EDIT_QUALITY1) 中的值后,例如在其中输入 0 并按 TAB 键,流程如下所示时,就会出现问题:

  • void CTestDlg::OnQuality1EditKillFocus() 被调用。
  • 它调用 ValidateQualityParams(IDC_EDIT_QUALITY1)
  • 在 ValidateQualityParams 中,它转到 if (IDC_EDIT_QUALITY1 == qualityParamID) 条件。
  • 由于我输入的值小于MIN_QUALITY_VALUE,因此它通过调用AfxMessageBox来显示消息。
    - 现在,即使从 AfxMessageBox 的调用堆栈中,它也会在内部点击 void CTestDlg::OnQuality2EditKillFocus()。

虽然OnQuality1EditKillFocus的调用堆栈尚未完成,但OnQuality2EditKillFocus是从AfxMessageBox的调用堆栈调用的。

我不明白这个问题的原因。以前有人遇到过这样的问题吗?

在我的资源.h中,我有两个不同的值IDC_EDIT_QUALITY1IDC_EDIT_QUALITY2

#define IDC_EDIT_QUALITY1               1018
#define IDC_EDIT_QUALITY2               1020

请帮助解决这个问题。

我相信您收到的IDC_EDIT_QUALITY2控件的EN_KILLFOCUS通知不是由m_ctrlQuality1.SetFocus()调用引起的,而是由AfxMessageBox()调用引起的。

当您按下 [Tab] 键时,IDC_EDIT_QUALITY1会失去焦点,而IDC_EDIT_QUALITY2会获得焦点。然后,您会收到IDC_EDIT_QUALITY1EN_KILLFOCUS通知。显示错误消息,这会导致应用程序"生成"(再次开始处理消息),同时显示消息框。m_ctrlQuality1.SetFocus()调用不会在AfxMessageBox()返回之前发生,即在您关闭消息框之前,因此IDC_EDIT_QUALITY2EN_KILLFOCUS通知不能是该调用的结果。我想这是显示消息框的结果(IDC_EDIT_QUALITY2获得了焦点,但消息框使其丢失了焦点)。

你可以通过添加一个成员变量来解决它,正如 Staytuned123 建议的那样,但在不同的设置中:命名它,比如m_bKillFocusProcessing,并在处理任何EN_KILLFOCUS通知时将其设置为TRUE(AfxMessageBox() 加上 SetFocus()),并在处理完它时FALSE;如果它已经TRUE退出而不做任何事情。也就是说,一次只能处理一个EN_KILLFOCUS通知。

但是,这样的用户界面(在退出字段时显示消息框)相当奇怪。为什么要重新发明轮子,而不是使用MFC已经提供的DDX/DDV功能?可以定义与控件关联的成员变量,并执行各种检查,包括范围检查。调用UpdateData(TRUE)以执行检查(针对对话框上的所有控件)并将数据传输到成员变量。或者,可以放置一些错误显示控件(通常为红色),在发现错误时激活,例如在 .net 或 Web 中。

当您按 Tab 键时,IDC_EDIT_QUALITY2获得了焦点。但是由于输入的值超出界限,程序调用m_ctrlQuality1.SetFocus(),这反过来又导致OnQuality2EditKillFocus()被调用。 添加一个成员变量说m_bQuality1OutOfBound并在调用m_ctrlQuality1.SetFocus()之前将其设置为 true。在OnQuality2EditKillFocus()中,当m_bQuality1OutOfBound为真时,将其设置为 false,不要调用ValidateQualityParams(IDC_EDIT_QUALITY2)

最新更新