我正在使用Visual Studio 2013并制作基于MFC对话框的应用程序。我在编辑控件的Kill Focus方面遇到了一个奇怪的问题。
请参见以下内容:
================================================ =========================
在我的应用程序中,我在对话框上有两个编辑控件。
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;
}
}
}
现在,当在1st Edit Control(IDC_EDIT_QUALITY1)中更改值后,说在其中输入0并按TAB键时,流程将发生如下情况:
尽管OnQuality1EditKillFocus的调用栈尚未完成,但从AfxMessageBox的调用栈中调用了OnQuality2EditKillFocus。
我不了解此问题的原因。有人遇到过这样的问题吗?
在resource.h中,我为IDC_EDIT_QUALITY1
和IDC_EDIT_QUALITY2
有两个不同的值
#define IDC_EDIT_QUALITY1 1018
#define IDC_EDIT_QUALITY2 1020
请帮助解决此问题。
答案 0 :(得分:0)
按TAB键时,IDC_EDIT_QUALITY2成为焦点。但是由于输入的值超出范围,因此程序调用{{1}},进而导致m_ctrlQuality1.SetFocus()
被调用。
添加一个名为m_bQuality1OutOfBound的成员变量,并在调用OnQuality2EditKillFocus()
之前将其设置为true。在m_ctrlQuality1.SetFocus()
中,当m_bQuality1OutOfBound为true时,请将其设置为false并且不要调用OnQuality2EditKillFocus()
。
答案 1 :(得分:0)
我相信您收到的EN_KILLFOCUS
控件的IDC_EDIT_QUALITY2
通知不是由m_ctrlQuality1.SetFocus()
调用引起的,而是由AfxMessageBox()
调用引起的。
当您按下[Tab]键时,IDC_EDIT_QUALITY1
失去焦点,而IDC_EDIT_QUALITY2
获得焦点。然后,您收到EN_KILLFOCUS
的{{1}}通知。您显示错误消息,这会导致应用程序“屈服”(再次开始处理消息),同时显示消息框。 IDC_EDIT_QUALITY1
调用不会在m_ctrlQuality1.SetFocus()
返回之前(即关闭消息框之前)进行,因此AfxMessageBox()
的{{1}}通知不能是通话结果。我想这是显示消息框的结果(EN_KILLFOCUS
获得了焦点,但是消息框使它迷失了它。)
您可以按照Staytuned123的建议通过添加一个memeber变量来解决该问题,但是要使用不同的设置:在处理任何{{时,将其命名为IDC_EDIT_QUALITY2
,并将其设置为IDC_EDIT_QUALITY2
。 1}}通知(AfxMessageBox()加上SetFocus()),并在完成处理后发送到m_bKillFocusProcessing
;如果已经TRUE
退出,则不执行任何操作。也就是说,一次只能处理一个EN_KILLFOCUS
通知。
但是,这样的用户界面(在退出字段时显示消息框)相当奇怪。为何还要重新发明轮子而不使用MFC已经提供的DDX / DDV功能呢?您可以定义与控件关联的成员变量,并执行各种检查,包括范围检查。调用FALSE
进行检查(对对话框上的所有控件)并将数据传输到成员变量。或者,您可以放置一些错误显示控件(通常为红色),这些控件在发现错误时便会激活,例如在.net或网络中。