9

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

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

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

笔记

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

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

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

编辑:

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

谢谢

4

6 回答 6

10

我以前做过的方式(上次,比如 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 没有提供一种方法来区分用户输入和代码更改,但事实就是这样。

于 2012-07-03T16:02:03.053 回答
6

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

首先,我在派生控件的头文件中添加了一个标志,并在构造函数中将其初始化为 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;

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

于 2012-07-04T19:21:29.023 回答
1

您可以在发送之前禁用(EnableWindow(FALSE)WM_ENABLE使用参数 FALSE 发送控件,WM_SETTEXT然后再启用它。这应该防止EN_CHANGE

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

于 2012-07-03T15:29:30.883 回答
1

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

标题

// 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);
}
于 2015-08-19T15:29:54.497 回答
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;
}
于 2020-08-05T07:16:05.517 回答
-1

万一其他人发现这个讨论......

正如 Steven 所写,UpdateData 不会导致发送 EN_CHANGE。

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

于 2014-08-20T15:24:00.717 回答