我有一个CEdit派生控件,当未定数据为空时显示字符串“N / A”。我最近添加了代码来清空控件(SetWindowText(“”);)当它获得焦点时设置是否回到“N / A”(SetWindowText(“N / A”))当焦点丢失时如果用户离开控制空。
唯一的问题是将窗口文本设置为“”或“N / A”会触发EN_CHANGE,因此我的对话框会认为数据已更改。
如何在调用SetWindowText(WM_SETTEXT)时避免触发EN_CHANGE?
注意
- 我知道我可以将编辑控件设置为Multiline = TRUE,但这对我来说是不可接受的。
- 我的应用程序是MBCS,所以我不能使用SetCueBanner
- 我想要一个优雅的解决方案。暂时将父窗口设置为NULL不是一个优雅的解决方案。
编辑:
- 我希望解决方案在我的自定义控件中,而不是在每个对话框中
由于
答案 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。