MFC C++ 从 CEdit 派生并派生 GetWindowText
MFC C++ Derive from CEdit and derive GetWindowText
我从 CEdit 派生,以制作自定义控件。如果像 MFC Feature Pack 控件(Mask,Browsable)一样,我可以更改 GetWindowText 以实际报告而不是控件上通常显示的内容(例如,在十六进制和十进制之间转换数据,然后 return返回那个字符串)。
在派生的 CEdit 中这可能吗?
将 WM_GETTEXT
和 WM_GETTEXTLENGTH
的消息映射条目添加到派生的 CEdit
class:
BEGIN_MESSAGE_MAP( CMyEdit, CEdit )
ON_WM_GETTEXT()
ON_WM_GETTEXTLENGTH()
END_MESSAGE_MAP()
当我们覆盖这些消息时,我们需要一种方法来获取编辑控件的原始文本,而无需进行无休止的递归。为此,我们可以直接调用名为 DefWindowProc
:
的默认 window 过程
CStringW CMyEdit::GetTextInternal()
{
CStringW text;
LRESULT len = DefWindowProcW( WM_GETTEXTLENGTH, 0, 0 );
if( len > 0 )
{
// WPARAM = len + 1 because the length must include the null terminator.
len = DefWindowProcW( WM_GETTEXT, len + 1, reinterpret_cast<LPARAM>( text.GetBuffer( len ) ) );
text.ReleaseBuffer( len );
}
return text;
}
以下方法获取原始 window 文本并对其进行转换。这里一切皆有可能,包括十六进制和十进制之间的转换示例。为简单起见,我只是用破折号将文本括起来。
CStringW CMyEdit::GetTransformedText()
{
CStringW text = GetTextInternal();
return L"--" + text + L"--";
}
现在是 WM_GETTEXT
的实际处理程序,它将转换后的文本复制到输出缓冲区。
int CMyEdit::OnGetText( int cchDest, LPWSTR pDest )
{
// Sanity checks
if( cchDest <= 0 || ! pDest )
return 0;
CStringW text = GetTransformedText();
// Using StringCchCopyExW() to make sure that we don't write outside of the bounds of the pDest buffer.
// cchDest defines the maximum number of characters to be copied, including the terminating null character.
LPWSTR pDestEnd = nullptr;
HRESULT hr = StringCchCopyExW( pDest, cchDest, text.GetString(), &pDestEnd, nullptr, 0 );
// If our text is greater in length than cchDest - 1, the function will truncate the text and
// return STRSAFE_E_INSUFFICIENT_BUFFER.
if( SUCCEEDED( hr ) || hr == STRSAFE_E_INSUFFICIENT_BUFFER )
{
// The return value is the number of characters copied, not including the terminating null character.
return pDestEnd - pDest;
}
return 0;
}
WM_GETTEXTLENGTH
的处理程序不言自明:
UINT CMyEdit::OnGetTextLength()
{
return GetTransformedText().GetLength();
}
感谢大家给我指出正确的方向。我尝试了 OnGetText
,但问题似乎是我无法获取底层字符串,或者在调用 GetWindowText
时它会崩溃(或者只是再次调用 OnGetText
......并且不能找到底层字符串)。
在看到他们在masked control上做了什么之后,我做了一个更简单的答案,就像这样。有什么缺点吗?它似乎不会引起任何问题或副作用...
直接来自GetWindowText
void CConvertibleEdit::GetWindowText(CString& strString) const
{
CEdit::GetWindowText(strString);
ConvertibleDataType targetDataType;
if (currentDataType == inputType)
{
}
else
{
strString = ConvertEditType(strString, currentDataType, inputType);
}
}
我从 CEdit 派生,以制作自定义控件。如果像 MFC Feature Pack 控件(Mask,Browsable)一样,我可以更改 GetWindowText 以实际报告而不是控件上通常显示的内容(例如,在十六进制和十进制之间转换数据,然后 return返回那个字符串)。
在派生的 CEdit 中这可能吗?
将 WM_GETTEXT
和 WM_GETTEXTLENGTH
的消息映射条目添加到派生的 CEdit
class:
BEGIN_MESSAGE_MAP( CMyEdit, CEdit )
ON_WM_GETTEXT()
ON_WM_GETTEXTLENGTH()
END_MESSAGE_MAP()
当我们覆盖这些消息时,我们需要一种方法来获取编辑控件的原始文本,而无需进行无休止的递归。为此,我们可以直接调用名为 DefWindowProc
:
CStringW CMyEdit::GetTextInternal()
{
CStringW text;
LRESULT len = DefWindowProcW( WM_GETTEXTLENGTH, 0, 0 );
if( len > 0 )
{
// WPARAM = len + 1 because the length must include the null terminator.
len = DefWindowProcW( WM_GETTEXT, len + 1, reinterpret_cast<LPARAM>( text.GetBuffer( len ) ) );
text.ReleaseBuffer( len );
}
return text;
}
以下方法获取原始 window 文本并对其进行转换。这里一切皆有可能,包括十六进制和十进制之间的转换示例。为简单起见,我只是用破折号将文本括起来。
CStringW CMyEdit::GetTransformedText()
{
CStringW text = GetTextInternal();
return L"--" + text + L"--";
}
现在是 WM_GETTEXT
的实际处理程序,它将转换后的文本复制到输出缓冲区。
int CMyEdit::OnGetText( int cchDest, LPWSTR pDest )
{
// Sanity checks
if( cchDest <= 0 || ! pDest )
return 0;
CStringW text = GetTransformedText();
// Using StringCchCopyExW() to make sure that we don't write outside of the bounds of the pDest buffer.
// cchDest defines the maximum number of characters to be copied, including the terminating null character.
LPWSTR pDestEnd = nullptr;
HRESULT hr = StringCchCopyExW( pDest, cchDest, text.GetString(), &pDestEnd, nullptr, 0 );
// If our text is greater in length than cchDest - 1, the function will truncate the text and
// return STRSAFE_E_INSUFFICIENT_BUFFER.
if( SUCCEEDED( hr ) || hr == STRSAFE_E_INSUFFICIENT_BUFFER )
{
// The return value is the number of characters copied, not including the terminating null character.
return pDestEnd - pDest;
}
return 0;
}
WM_GETTEXTLENGTH
的处理程序不言自明:
UINT CMyEdit::OnGetTextLength()
{
return GetTransformedText().GetLength();
}
感谢大家给我指出正确的方向。我尝试了 OnGetText
,但问题似乎是我无法获取底层字符串,或者在调用 GetWindowText
时它会崩溃(或者只是再次调用 OnGetText
......并且不能找到底层字符串)。
在看到他们在masked control上做了什么之后,我做了一个更简单的答案,就像这样。有什么缺点吗?它似乎不会引起任何问题或副作用...
直接来自GetWindowText
void CConvertibleEdit::GetWindowText(CString& strString) const
{
CEdit::GetWindowText(strString);
ConvertibleDataType targetDataType;
if (currentDataType == inputType)
{
}
else
{
strString = ConvertEditType(strString, currentDataType, inputType);
}
}