MFC C++ Извлечь из CEdit и получить GetWindowText

Я наследую от CEdit, чтобы сделать пользовательский элемент управления. Было бы неплохо, если бы, как и элементы управления MFC Feature Pack (Mask, Browsable), я мог изменить GetWindowText, чтобы он фактически отображал не то, что обычно отображается в элементе управления (например, преобразовывать данные между шестнадцатеричным и десятичным, а затем возвращать обратно, что строка).

Возможно ли это в производном CEdit?

2 ответа

Решение

Добавить записи карты сообщений для WM_GETTEXT а также WM_GETTEXTLENGTH к вашему производному CEdit учебный класс:

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

Следующий метод получает исходный текст окна и преобразует его. Здесь возможно все, в том числе пример преобразования между hex и dec. Для простоты я просто заключаю текст в тире.

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 снова... и не смог найти основную строку).

Посмотрев, что они сделали на маскирующем контроле, я сделал более простой ответ, как этот. Есть ли недостатки? Казалось, не вызывает никаких проблем или побочных эффектов...

Получите непосредственно из GetWindowText

void CConvertibleEdit::GetWindowText(CString& strString) const
{
    CEdit::GetWindowText(strString);

    ConvertibleDataType targetDataType;
    if (currentDataType == inputType)
    {

    }
    else
    {
        strString = ConvertEditType(strString, currentDataType, inputType);
    }
}
Другие вопросы по тегам