Подклассы элемента управления EDIT работали хорошо для меня - нужно было отображать некоторую информацию о форматировании пользователю при редактировании атрибутов объекта (и некоторые атрибуты могут быть несколькими строками). Важная вещь, как сказал Адриан в своем ответе, также заключается в том, чтобы вызвать процедуру управления EDIT до вашего собственного чертежа. Вызов его позже или выдача собственного BeginPaint / EndPaint (с возвратом 0 или DefWindowProc) вызвали у меня проблемы с текстом, не отображаемым вообще, с отображением только при изменении размера, но не после редактирования, до оставления помета на экране остатка каретки. С этим у меня не было никаких проблем, независимо от других раз перекраски элемента управления EDIT.
Некоторые настройки:
SetWindowSubclass(attributeValuesEdit, &AttributeValueEditProcedure, 0, reinterpret_cast<DWORD_PTR>(this));
// Not only do multiline edit controls fail to display the cue banner text,
// but they also ignore the Edit_SetCueBannerText call, meaning we can't
// just call GetCueBannerText in the subclassed function. So store it as
// a window property instead.
SetProp(attributeValuesEdit, L"CueBannerText", L"<attribute value>");
Обратный звонок:
LRESULT CALLBACK AttributeValueEditProcedure(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
UINT_PTR subclassId,
DWORD_PTR data
)
{
...
case WM_PRINTCLIENT:
case WM_PAINT:
{
auto textLength = GetWindowTextLength(hwnd);
if (textLength == 0 && GetFocus() != hwnd)
{
// Get the needed DC with DCX_INTERSECTUPDATE before the EDIT
// control's WM_PAINT handler calls BeginPaint/EndPaint, which
// validates the update rect and would otherwise lead to drawing
// nothing later because the region is empty. Also, grab it from
// the cache so we don't mess with the EDIT's DC.
HDC hdc = (message == WM_PRINTCLIENT)
? reinterpret_cast<HDC>(wParam)
: GetDCEx(hwnd, nullptr, DCX_INTERSECTUPDATE|DCX_CACHE|DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS);
// Call the EDIT control so that the caret is properly handled,
// no caret litter left on the screen after tabbing away.
auto result = DefSubclassProc(hwnd, message, wParam, lParam);
// Get the font and margin so the cue banner text has a
// consistent appearance and placement with existing text.
HFONT font = GetWindowFont(hwnd);
RECT editRect;
Edit_GetRect(hwnd, OUT &editRect);
// Ideally we would call Edit_GetCueBannerText, but since that message
// returns nothing when ES_MULTILINE, use a window property instead.
auto* cueBannerText = reinterpret_cast<wchar_t*>(GetProp(hwnd, L"CueBannerText"));
HFONT previousFont = SelectFont(hdc, font);
SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, cueBannerText, int(wcslen(cueBannerText)), &editRect, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_NOCLIP);
SelectFont(hdc, previousFont);
ReleaseDC(hwnd, hdc);
// Return the EDIT's result (could probably safely just return zero here,
// but seems safer to relay whatever value came from the edit).
return result;
}
}
break;
Написание собственного элемента управления EDIT (который я на самом деле делал более одного раза, с частичной степенью полноты по сравнению со встроенным) не так уж много работы, если вы выполняете минимум (возможно, только на английском языке с базовой поддержкой каретки) ), но это МНОГО работы, чтобы получить исправление, если вы хотите плавную навигацию по сложным сценариям с кластерами переменного размера, выделению по диапазонам, поддержке IME, контекстным меню с копированием и вставкой, высококонтрастным режимам и функциям доступности, таким как преобразование текста в речь , Поэтому, в отличие от многих других ответов, я рекомендую , а не реализовать свой собственный элемент управления EDIT только для текста баннера.