简体   繁体   English

当一个控件即将失去焦点时,是否有一个从C ++程序触发的事件?

[英]Is there an event that fires from a C++ program when a control is about to lose focus?

I am trying to fix a validation bug in a MFC CEdit control. 我试图修复MFC CEdit控件中的验证错误。 Currently, validation is performed in an OnChange event handler. 目前,验证是在OnChange事件处理程序中执行的。 But this does not work because it validates data before the user is finished entering it. 但这不起作用,因为它在用户完成输入之前验证数据。

So, instead, I am trying to validate inside an OnKillFocus event handler. 所以,相反,我试图在OnKillFocus事件处理程序内验证。 If validation fails, then I use GotoDlgCtrl() to return focus to the edit box that contained the invalid data. 如果验证失败,那么我使用GotoDlgCtrl()将焦点返回到包含无效数据的编辑框。 And when I call GotoDlgCtrl() , the kill focus event fires again, and I'm in an infinite loop. 当我调用GotoDlgCtrl() ,kill focus事件再次触发,我处于无限循环中。

So, I'd like to handle an event that fires just before the control loses focus, so that if I determine that the data is invalid, I can stop focus from leaving and instead get the user to enter correct data. 因此,我想处理在控件失去焦点之前触发的事件,这样如果我确定数据无效,我可以停止焦点离开,而是让用户输入正确的数据。

I know I've seen a Validating event someplace, but that was probably in the .Net world. 我知道我在某个地方看到过验证事件,但那可能是在.Net世界中。 But it offers the functionality I'm looking for. 但它提供了我正在寻找的功能。

Right-click the dialog resource and invoke Class Wizard: 右键单击对话框资源并调用类向导:

类向导

Next, go to the Virtual Functions tab, locate PreTranslateMessage and add it: 接下来,转到Virtual Functions选项卡,找到PreTranslateMessage并添加它:

虚函数

Then, you can do something like this: 然后,你可以做这样的事情:

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);
}

Normally the control is a member variable of type CEdit so you could compare against m_edit.GetSafeHwnd() instead. 通常,控件是CEdit类型的成员变量,因此您可以与m_edit.GetSafeHwnd()进行比较。

Results: 结果:

结果

Update 更新

I realise you stated: 我意识到你说:

But this does not work because it validates data before the user is finished entering it. 但这不起作用,因为它在用户完成输入之前验证数据。

You could use WM_KEYUP instead: 你可以改用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);
}

That is give you a chance to validate after the display has been updated. 这样,您就有机会在显示更新后进行验证。

An alternative it to customize your DoDataExchange handler. 另一种方法是自定义DoDataExchange处理程序。 In there you can validate as required. 在那里,您可以根据需要进行验证。 Then in your code you simple test the return value of UpdataData(TRUE) for FALSE . 然后在您的代码中,您可以简单地测试UpdataData(TRUE)的返回值为FALSE

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

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