MFC 编辑控件 EN_KILLFOCUS 问题
Posted
技术标签:
【中文标题】MFC 编辑控件 EN_KILLFOCUS 问题【英文标题】:MFC Edit Control EN_KILLFOCUS issue 【发布时间】:2019-04-05 12:28:16 【问题描述】:我正在使用 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;
现在,问题发生在更改第一个编辑控件(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 的调用栈中调用。
我不明白这个问题的原因。有没有人遇到过这样的问题?
在我的 resource.h 中,IDC_EDIT_QUALITY1
和 IDC_EDIT_QUALITY2
有两个不同的值
#define IDC_EDIT_QUALITY1 1018
#define IDC_EDIT_QUALITY2 1020
请帮助解决这个问题。
【问题讨论】:
为什么不直接使用 MFC 提供的标准验证属性?当您将变量添加到控件时,您可以告诉它有效范围,然后系统使用它? 【参考方案1】:我相信您收到的IDC_EDIT_QUALITY2
控件的EN_KILLFOCUS
通知不是由m_ctrlQuality1.SetFocus()
调用引起的,而是由AfxMessageBox()
调用引起的。
当您按下 [Tab] 键时,IDC_EDIT_QUALITY1
失去焦点,IDC_EDIT_QUALITY2
获得焦点。然后您会收到IDC_EDIT_QUALITY1
的EN_KILLFOCUS
通知。您显示错误消息,这会导致应用程序“屈服”(再次开始处理消息),同时显示消息框。 m_ctrlQuality1.SetFocus()
调用不会在AfxMessageBox()
返回之前发生,即在您关闭消息框之前,因此IDC_EDIT_QUALITY2
的EN_KILLFOCUS
通知不能是该调用的结果。我猜这是显示消息框的结果(IDC_EDIT_QUALITY2
获得了焦点,但消息框使其失去焦点)。
您可以按照 Staytuned123 的建议通过添加成员变量来解决此问题,但设置不同:将其命名为 m_bKillFocusProcessing
,并在处理任何 EN_KILLFOCUS
通知时将其设置为 TRUE
(AfxMessageBox () 加上 SetFocus()),并在完成处理后发送到 FALSE
;如果它已经是TRUE
退出而不做任何事情。也就是说,一次只能处理一个EN_KILLFOCUS
通知。
但是,这样的用户界面(在退出字段时显示消息框)相当奇怪。为什么要重新发明***,而不是使用 MFC 已经提供的 DDX/DDV 功能?您可以定义与控件关联的成员变量,并执行各种检查,包括范围检查。调用UpdateData(TRUE)
执行检查(针对对话框上的所有控件)并将数据传输到成员变量。或者您可以放置一些显示错误的控件(通常为红色),当发现错误时激活,例如在 .net 或 web 中。
【讨论】:
您好,Constantine Georgiou,非常感谢您提供如此详细的解释。我已经设法使用 m_bKillFocusProcessing 逻辑获得了有效的解决方案。我会考虑尝试 DDX/DDV 和 UpdateData(TRUE),看看它是否会减少条件检查开销。再次感谢,确实!问候。【参考方案2】:当您按下 TAB 键时,IDC_EDIT_QUALITY2 获得焦点。但是因为输入的值越界,程序调用m_ctrlQuality1.SetFocus()
,这反过来又导致OnQuality2EditKillFocus()
被调用。
添加一个成员变量 m_bQuality1OutOfBound 并在调用 m_ctrlQuality1.SetFocus()
之前将其设置为 true。在OnQuality2EditKillFocus()
中,当m_bQuality1OutOfBound为true时,设置为false,不要调用ValidateQualityParams(IDC_EDIT_QUALITY2)
。
【讨论】:
嗨,Staytuned123,我已经尝试合并 m_bQuality1OutOfBound 并进行了相关更改。但是,它仍然不起作用。我是 *** 的新手,正在学习共享代码和帖子的正确方法。同时,我已将源代码上传到:drive.google.com/open?id=17E1B6ZGeXttRKK-Fyf708cS37cfchx1I 请您看一下包含源代码的 Test.zip 并提出可行的解决方案。问候,哈迪克·沙阿 我试用了你的程序员。不要在 OnQuality2EditKillFocus() 中将 m_bQuality1OutOfBound 设置为 false。其他一切都保持不变。这将解决你的问题。请记住对 IDC_EDIT_QUALITY1 和 IDC_EDIT_QUALITY2 应用相同的更改。 嗨,Staytuned123,尝试使用 m_bQuality1OutOfBound 方法,仍然遗漏了一些情况,即验证仅被触发一次并且没有再次触发,即使它应该被触发。我尝试了 m_bKillFocusProcessing (正如上面的康斯坦丁乔治欧所建议的那样),它正在解决我的问题。感谢您检查我的代码并提供建议的所有努力。问候。以上是关于MFC 编辑控件 EN_KILLFOCUS 问题的主要内容,如果未能解决你的问题,请参考以下文章