MFC编辑控件EN_KILLFOCUS问题

时间:2019-04-05 12:28:17

标签: visual-c++ mfc

我正在使用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键时,流程将发生如下情况:

  • 将调用void CTestDlg :: OnQuality1EditKillFocus()。
  • 它调用ValidateQualityParams(IDC_EDIT_QUALITY1)
  • 在ValidateQualityParams中,检查是否为(IDC_EDIT_QUALITY1 == qualityParamID)条件。
  • 由于我输入的值小于MIN_QUALITY_VALUE,因此它通过调用AfxMessageBox显示消息。
    -现在,即使从AfxMessageBox的调用堆栈中,它也会在内部击中无效的CTestDlg :: OnQuality2EditKillFocus()。

尽管OnQuality1EditKillFocus的调用栈尚未完成,但从AfxMessageBox的调用栈中调用了OnQuality2EditKillFocus。

我不了解此问题的原因。有人遇到过这样的问题吗?

在resource.h中,我为IDC_EDIT_QUALITY1IDC_EDIT_QUALITY2有两个不同的值

 #define IDC_EDIT_QUALITY1               1018
 #define IDC_EDIT_QUALITY2               1020

请帮助解决此问题。

2 个答案:

答案 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或网络中。