简体   繁体   English

MFC编辑控件EN_KILLFOCUS问题

[英]MFC Edit Control EN_KILLFOCUS issue

I am using Visual Studio 2013 and making MFC Dialog based application. 我正在使用Visual Studio 2013,并使基于MFC对话框的应用程序。 I am running into strange issue with Kill Focus of Edit Control. 我在编辑控件的Kill Focus方面遇到了一个奇怪的问题。

Please see below: 请看下面:

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

In my application, I have two Edit Controls on Dialog Box. 在我的应用程序中,我在对话框上有两个“编辑控件”。

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

I have handled both's EN_KILLFOCUS event to validate the value. 我已经处理了两个的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;
        }
    }
}

Now, the issue happens when, after changing the value in 1st Edit Control (IDC_EDIT_QUALITY1), say entering 0 in it and pressing TAB key, the flow goes as below: 现在,当在1st Edit Control(IDC_EDIT_QUALITY1)中更改值后,说在其中输入0并按TAB键时,流程将如下所示:

  • void CTestDlg::OnQuality1EditKillFocus() is called. 无效CTestDlg :: OnQuality1EditKillFocus()被调用。
  • It calls ValidateQualityParams(IDC_EDIT_QUALITY1) 它调用ValidateQualityParams(IDC_EDIT_QUALITY1)
  • Inside ValidateQualityParams, it goes to if (IDC_EDIT_QUALITY1 == qualityParamID) condition. 在ValidateQualityParams内部,检查条件是否为(IDC_EDIT_QUALITY1 == qualityParamID)。
  • As the value I entered is less than MIN_QUALITY_VALUE, so it shows the Message by calling AfxMessageBox. 由于我输入的值小于MIN_QUALITY_VALUE,因此它通过调用AfxMessageBox来显示消息。
    - Now, even from the callstack of AfxMessageBox, it hits void CTestDlg::OnQuality2EditKillFocus() internally. -现在,即使从AfxMessageBox的调用堆栈中,它也会在内部击中无效的CTestDlg :: OnQuality2EditKillFocus()。

Although callstack of OnQuality1EditKillFocus is NOT finished yet, OnQuality2EditKillFocus gets called from the callstack of AfxMessageBox. 尽管OnQuality1EditKillFocus的调用堆栈尚未完成,但是OnQuality2EditKillFocus会从AfxMessageBox的调用堆栈中调用。

I don't understand the cause of this issue. 我不了解此问题的原因。 Has anyone encountered such issue before? 有人遇到过这样的问题吗?

In my resource.h, I have two distinct values for IDC_EDIT_QUALITY1 and IDC_EDIT_QUALITY2 在我的resource.h中,我为IDC_EDIT_QUALITY1IDC_EDIT_QUALITY2有两个不同的值

 #define IDC_EDIT_QUALITY1               1018
 #define IDC_EDIT_QUALITY2               1020

Please help on this issue. 请帮助解决这个问题。

When you pressed TAB key, IDC_EDIT_QUALITY2 got focus. 当您按TAB键时,IDC_EDIT_QUALITY2成为焦点。 But because value entered was out of bound, the program called m_ctrlQuality1.SetFocus() , which in turn caused OnQuality2EditKillFocus() to get called. 但是由于输入的值超出范围,因此名为m_ctrlQuality1.SetFocus()的程序将导致OnQuality2EditKillFocus() Add a member variable says m_bQuality1OutOfBound and set it to true right before calling m_ctrlQuality1.SetFocus() . 添加一个名为m_bQuality1OutOfBound的成员变量,并在调用m_ctrlQuality1.SetFocus()之前将其设置为true。 In OnQuality2EditKillFocus() , when m_bQuality1OutOfBound is true, set it to false and don't call ValidateQualityParams(IDC_EDIT_QUALITY2) . OnQuality2EditKillFocus() ,当m_bQuality1OutOfBound为true时,将其设置为false并且不要调用ValidateQualityParams(IDC_EDIT_QUALITY2)

I believe the EN_KILLFOCUS notification for the IDC_EDIT_QUALITY2 control you are receiving is caused not by the m_ctrlQuality1.SetFocus() call, but instead by the AfxMessageBox() call. 我相信您收到的IDC_EDIT_QUALITY2控件的EN_KILLFOCUS通知不是由m_ctrlQuality1.SetFocus()调用引起的,而是由AfxMessageBox()调用引起的。

When you press the [Tab] key IDC_EDIT_QUALITY1 loses the focus, and IDC_EDIT_QUALITY2 gets the focus. 当您按[Tab]键时, IDC_EDIT_QUALITY1失去焦点,而IDC_EDIT_QUALITY2获得焦点。 Then you receive the EN_KILLFOCUS notification for IDC_EDIT_QUALITY1 . 然后,您会收到IDC_EDIT_QUALITY1EN_KILLFOCUS通知。 You display the error-message, which causes the application to "yield" (start processing messages again), while the message-box is displayed. 您显示错误消息,这会导致应用程序“屈服”(再次开始处理消息),同时显示消息框。 The m_ctrlQuality1.SetFocus() call won't take place before the AfxMessageBox() returns, ie before you close the message-box, and therefore the EN_KILLFOCUS notification for IDC_EDIT_QUALITY2 can't be the result of that call. AfxMessageBox()返回之前AfxMessageBox()即关闭消息框之前AfxMessageBox() ,不会发生m_ctrlQuality1.SetFocus()调用,因此IDC_EDIT_QUALITY2EN_KILLFOCUS通知不能是该调用的结果。 I guess it's the result of displaying the message-box ( IDC_EDIT_QUALITY2 has got the focus, but the message-box makes it lose it). 我猜这是显示消息框的结果( IDC_EDIT_QUALITY2获得了焦点,但是消息框使其失去了它)。

You may work around it by adding a memeber variable, as Staytuned123 suggested, but in a different setting: name it, say m_bKillFocusProcessing , and set it to TRUE while you are processing ANY EN_KILLFOCUS notification (AfxMessageBox() plus SetFocus()), and to FALSE when you are done processing it; 您可以按照Staytuned123的建议,通过添加一个memeber变量来解决该问题,但使用不同的设置:将其命名为m_bKillFocusProcessing ,并在处理任何EN_KILLFOCUS通知(AfxMessageBox()加SetFocus())时将其设置为TRUE ,以及完成处理后转为FALSE if it's already TRUE exit without doing anything. 如果已经为TRUE则不执行任何操作。 That is, only one EN_KILLFOCUS notification may be processed at a time. 也就是说,一次只能处理一个EN_KILLFOCUS通知。

However, such a user-interface (displaying a message-box on exiting a field) is rather weird. 但是,这样的用户界面(在退出字段时显示消息框)相当奇怪。 And why reinvent the wheel and not instead use the DDX/DDV feature, which MFC already offers? 为何还要重新发明轮子而不使用MFC已经提供的DDX / DDV功能呢? You can define member variables associated with controls, and perform various checks, including range-check. 您可以定义与控件关联的成员变量,并执行各种检查,包括范围检查。 Call UpdateData(TRUE) to perform the checks (for all controls on the dialog) and transfer the data to the member variables. 调用UpdateData(TRUE)以执行检查(针对对话框上的所有控件)并将数据传输到成员变量。 Or you can put some error-displaying controls (usually in red color), activated when an error is found, like in .net or the web. 或者,您可以放置​​一些错误显示控件(通常为红色),这些控件在发现错误时便会激活,例如在.net或Web中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM