[英]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键时,流程将如下所示:
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_QUALITY1
和IDC_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_QUALITY1
的EN_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_QUALITY2
的EN_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.