发送WM_SETTEXT时如何避免EN_CHANGE通知?

Gol*_*k84 6 c++ user-controls mfc visual-studio

我有一个CEdit派生控件,当未定数据为空时显示字符串"N/A".我最近添加了代码来清空控件(SetWindowText("");)当它获得焦点时设置如果返回到"N/A"(SetWindowText("N/A"))当焦点丢失时如果用户离开控制空.

唯一的问题是将窗口文本设置为""或"N/A"会触发EN_CHANGE,因此我的对话框认为数据已更改.

如何在调用SetWindowText(WM_SETTEXT)时避免触发EN_CHANGE?

笔记

- 我知道我可以将编辑控件设置为Multiline = TRUE,但这对我来说是不可取的.

- 我的应用程序是MBCS所以我不能使用SetCueBanner

- 我想要一个优雅的解决方案.暂时将父窗口设置为NULL不是一个优雅的解决方案.

编辑:

- 我希望解决方案在我的自定义控件中,而不是在每个对话框中

谢谢

Mik*_*Mik 7

我以前做过的方式(上次,就像20分钟前一样;事实上我正在考虑提出同样的问题),就是设置一个标志.当我要以编程方式设置文本时,我设置了标志,并在EN_CHANGE处理程序中检查它:

void CMyDialog::MyFunction()
{    
    setEditTextProgramatically = true;  
    c_Edit.SetWindowText(_T("Whatever"));  
    setEditTextProgramatically = false;
}

void CMyDialog::OnEnChangeEdit()
{
    if (!setEditTextProgramatically)
    {
        // Do whatever you need to do
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道这不是最优雅的解决方案,但它起作用,至少对我而言.

我一直想知道为什么MFC没有提供区分用户输入和代码更改的方法,但这就是它的方式.


Gol*_*k84 6

我终于找到了适合我的问题的解决方案。

首先,我在派生控件的头文件中添加了一个标志,并在构造函数中将其初始化为 false

bool m_bNoEnChange;
Run Code Online (Sandbox Code Playgroud)

我在派生控件的头文件中覆盖了 OnChildNotify,在实现中,我使用 EN_CHANGE 参数检查了 WM_COMMAND 消息。然后我返回 TRUE 以防止将消息发送到父级(对话框/页面)

virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult);
Run Code Online (Sandbox Code Playgroud)
BOOL CADEdit::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult) 
{
    if(message == WM_COMMAND && HIWORD(wParam) == EN_CHANGE)
    {
        //If the flag is set, don't send the message to the parent window
        if(m_bNoEnChange)
            return TRUE;
    }

    return CEdit::OnChildNotify(message, wParam, lParam, pLResult);
}
Run Code Online (Sandbox Code Playgroud)

最后,当控件获得和失去焦点时,我用我的标志包装了有问题的 SetWindowText

m_bNoEnChange = true;
SetWindowText(_T(""));
m_bNoEnChange = false;
Run Code Online (Sandbox Code Playgroud)

这个解决方案对我来说是最好的,因为我不必修改每个对话框。