EDIT コントロールのサブクラス化は、私にとってはうまくいきました。オブジェクト属性を編集するときに、書式設定情報をユーザーに表示する必要がありました (一部の属性は複数行になる可能性があります)。エイドリアンも彼の答えで言ったように、重要なことは、独自の描画の前にEDIT コントロールのプロシージャを呼び出すことです。後で呼び出すか、独自の BeginPaint/EndPaint (return 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 コントロールを実装しないことをお勧めします。