当控件即将失去焦点时,是不是存在从 C++ 程序触发的事件?

Posted

技术标签:

【中文标题】当控件即将失去焦点时,是不是存在从 C++ 程序触发的事件?【英文标题】:Is there an event that fires from a C++ program when a control is about to lose focus?当控件即将失去焦点时,是否存在从 C++ 程序触发的事件? 【发布时间】:2018-04-17 17:14:44 【问题描述】:

我正在尝试修复 MFC CEdit 控件中的验证错误。目前,验证在OnChange 事件处理程序中执行。但这不起作用,因为它会在用户完成输入之前验证数据。

因此,相反,我尝试在 OnKillFocus 事件处理程序中进行验证。如果验证失败,那么我使用GotoDlgCtrl() 将焦点返回到包含无效数据的编辑框。当我调用GotoDlgCtrl() 时,kill focus 事件再次触发,我处于无限循环中。

所以,我想处理一个在控件失去焦点之前触发的事件,这样如果我确定数据无效,我可以阻止焦点离开,而是让用户输入正确的数据。

我知道我在某个地方看到过验证事件,但那可能是在 .Net 世界中。但它提供了我正在寻找的功能。

【问题讨论】:

在你走得太远之前,请阅读 Microsoft 的 Raymond Chen 的这篇文章:WM_KILLFOCUS is the wrong time to do field validation。 MFC 为dialog data validation 提供了一个框架,您可以对其进行自定义以满足您的特定要求。 【参考方案1】:

右键单击对话框资源并调用类向导:

接下来,转到虚拟功能选项卡,找到 PreTranslateMessage 并添加它:

然后,你可以这样做:

BOOL CTestDlgDlg::PreTranslateMessage(MSG* pMsg)

    if (pMsg->message == WM_CHAR)
    
        CWnd *pControl = GetDlgItem(IDC_EDIT1);
        if (pControl->GetSafeHwnd() == pMsg->hwnd)
        
            if (pMsg->wParam == _TINT('!'))
            
                AfxMessageBox(_T("Not allowed ! character"));
                return TRUE;
            
        
    

    return CDialogEx::PreTranslateMessage(pMsg);

通常,控件是CEdit 类型的成员变量,因此您可以改为与m_edit.GetSafeHwnd() 进行比较。

结果:

更新

我知道你说过:

但这不起作用,因为它会在用户完成输入之前验证数据。

您可以改用WM_KEYUP

BOOL CTestDlgDlg::PreTranslateMessage(MSG* pMsg)

    if (pMsg->message == WM_KEYUP)
    
        CWnd *pControl = GetDlgItem(IDC_EDIT1);
        if (pControl->GetSafeHwnd() == pMsg->hwnd)
        
            CString str;
            GetDlgItemText(IDC_EDIT1, str);
            if (str.Find(_T("!")) >= 0)
            
                AfxMessageBox(_T("Not allowed ! character"));
                return TRUE;
            
        
    

    return CDialogEx::PreTranslateMessage(pMsg);

这让您有机会在显示更新后进行验证。

另一种方法是自定义您的 DoDataExchange 处理程序。在那里您可以根据需要进行验证。然后在您的代码中简单地测试UpdataData(TRUE) 的返回值FALSE

【讨论】:

这个答案与问题中已被 OP 拒绝的 OnChange 验证有何不同? @MarkRansom 公平点。但他所要做的就是肯定地改变信息。 WM_KEYUP 也许。另外,我不明白为什么他不能只使用DoDataExchange 并在那里进行自定义验证。或者,他可以引入一个“应用”按钮,然后简单地测试所有值并根据需要进行处理。 这就是我最终所做的。由于我要验证的表单是属性表,因此我会自动获得 Apply 按钮。我已经有一个 OnApply() 方法。我只是将所有验证移到那里。我认为这是一个人试图通过验证每次击键来变得过于花哨的情况。 非常感谢 Truckle 先生的详细示例!

以上是关于当控件即将失去焦点时,是不是存在从 C++ 程序触发的事件?的主要内容,如果未能解决你的问题,请参考以下文章

当嵌入式 ActiveX 控件接收并失去键盘焦点时如何获得通知?

c#控件失去焦点事件

EXCEL 文本框控件点击文字变很小,失去焦点后又回复正常,这怎么解决?

文本框 失去焦点 是啥意思?

C# Winform 控件或窗体失去焦点时,获取键盘输入数据(我用winform获取另一个窗口的数据)

JAVA中如何判断JTextField的一些问题?求高手解答……谢谢