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

时间:2012-07-03 15:20:22

标签: c++ visual-studio user-controls mfc

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

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

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

注意

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

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

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

编辑:

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

由于

6 个答案:

答案 0 :(得分: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
    }
}

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

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

答案 1 :(得分:4)

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

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

bool m_bNoEnChange;

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

virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult);

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

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

m_bNoEnChange = true;
SetWindowText(_T(""));
m_bNoEnChange = false;

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

答案 2 :(得分:1)

您可以在发送(EnableWindow(FALSE)之后禁用WM_ENABLE或发送WM_SETTEXT param FALSE)控件,然后再启用它。这应该会阻止EN_CHANGE

可能有一些更优雅的方法:p

答案 3 :(得分:1)

以下代码使用C ++ 11功能,但可以轻松更改。

HEADER

// CEditOptionalNotify.h
//
// CEdit derived class allowing the control's text value to be
// set without (optionally) causing EN_CHANGE processing.
//
#pragma once

class CEditOptionalNotify : public CEdit
{
    //DECLARE_DYNAMIC(CEditOptionalNotify)
    // Enable use of RUNTIME_CLASS macro and CObject::IsKindOf()

public:

    CEditOptionalNotify();
    virtual ~CEditOptionalNotify();

    enum class PerformOnChangeProcessing { No, Yes };
    void vSetText(const TCHAR* pText, PerformOnChangeProcessing e);

protected:

    afx_msg BOOL bConsiderEnChangeAsHandled();

    bool m_bChangeNotificationsEnabled;

    DECLARE_MESSAGE_MAP()
};

实施

// EditOptionalNotify.cpp : implementation file
//

#include "stdafx.h"
#include <EditOptionalNotify.h>

//IMPLEMENT_DYNAMIC(CEditOptionalNotify, CEdit)

CEditOptionalNotify::CEditOptionalNotify() :
    m_bChangeNotificationsEnabled(true)
{ 
}

CEditOptionalNotify::~CEditOptionalNotify()
{
}


BEGIN_MESSAGE_MAP(CEditOptionalNotify, CEdit)
    ON_CONTROL_REFLECT_EX(EN_CHANGE, bConsiderEnChangeAsHandled)
END_MESSAGE_MAP()


BOOL CEditOptionalNotify::bConsiderEnChangeAsHandled()
{
    return (m_bChangeNotificationsEnabled ? FALSE : TRUE);
}


void CEditOptionalNotify::vSetText(const TCHAR* pText, PerformOnChangeProcessing e)
{
    bool bChangeNotificationsDesired = (PerformOnChangeProcessing::No == e ? false : true);

    if (bChangeNotificationsDesired != m_bChangeNotificationsEnabled)
    {
        m_bChangeNotificationsEnabled = bChangeNotificationsDesired;
        CEdit::SetWindowText(pText);
        m_bChangeNotificationsEnabled = (bChangeNotificationsDesired ? false : true);
    }
    else
        CEdit::SetWindowText(pText);
}

答案 4 :(得分:0)

LRESULT CMainDlg::OnEnUpdateEditID(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{   
    //using static variable
    static bool isCodeChangeText = false;
    if(isCodeChangeText) 
        return 0;

    ……//Deal Window Text

    if(old == new)
        return 0; 

    int nSel = m_editPID.GetSel();//record cursor pos

    isCodeChangeText = true;
    m_editID.SetWindowText(new);
    m_editID.SetSel(nSel);
    isCodeChangeText = false;

    return 0;
}

答案 5 :(得分:-1)

如果有人发现这个讨论...

史蒂文写道,UpdateData不会导致发送EN_CHANGE。

引擎盖MFC调用AfxSetWindowText,可以指定一个hwnd。