コントロール ウィンドウに常にアイコンが表示される検索編集コントロールを MFC で作成しようとしています (コントロールの状態とテキストに関係なく)。私は何年も前にこのようなものを書き、非常にうまく機能しましたが、コードはWindows 7以降では機能しなくなりました(おそらくVistaでも動作しますが、試していません). コントロールに表示される画像が入力領域に重なって表示されます (下の図を参照)。
コードの背後にあるアイデア:
- から派生したクラスを持つ
CEdit
(OnPaint での描画を処理する) - アイコンは右側に表示され、編集領域はアイコンのサイズに基づいて縮小されます
- サイズ変更は、単一行編集と複数行編集で異なる方法で行われます。1 行の場合はSetMarginsを呼び出し、複数行の編集の場合はSetRectを呼び出します。
- この編集のサイズ変更は に適用され
PreSubclassWindow()
、OnSize()
OnSetFont()
これは、編集入力サイズが適用される方法です。
void CSymbolEdit::RecalcLayout()
{
int width = GetSystemMetrics( SM_CXSMICON );
if(m_hSymbolIcon)
{
if (GetStyle() & ES_MULTILINE)
{
CRect editRect;
GetRect(&editRect);
editRect.right -= (width + 6);
SetRect(&editRect);
}
else
{
DWORD dwMargins = GetMargins();
SetMargins(LOWORD(dwMargins), width + 6);
}
}
}
次の画像は、単一行編集の問題を示しています (画像は見やすくするために拡大されています)。黄色の背景は強調表示のみを目的としており、実際のコードではCOLOR_WINDOW
システム カラーを使用しています。単一行の編集にテキストがあり、入力がある場合、左側の画像が塗りつぶされていることがわかります。SetRect
これは、書式設定の四角形を正しく設定する複数行編集では発生しません。
ExcludeClipRectを使用して、画像が表示されている編集領域を削除しようとしました。
CRect rc;
GetClientRect(rc);
CPaintDC dc(this);
ExcludeClipRect(dc.m_hDC, rc.right - width - 6, rc.top, rc.right, rc.bottom);
DWORD dwMargins = GetMargins();
SetMargins(LOWORD(dwMargins), width + 6);
これは結果に影響を与えないようです。
参考までに、これはペイント方法で、何年も前に書かれ、Windows XP でうまく機能していましたが、現在は正しくありません。
void CSymbolEdit::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect( &rect );
// Clearing the background
dc.FillSolidRect( rect, GetSysColor(COLOR_WINDOW) );
DWORD dwMargins = GetMargins();
if( m_hSymbolIcon )
{
// Drawing the icon
int width = GetSystemMetrics( SM_CXSMICON );
int height = GetSystemMetrics( SM_CYSMICON );
::DrawIconEx(
dc.m_hDC,
rect.right - width - 1,
1,
m_hSymbolIcon,
width,
height,
0,
NULL,
DI_NORMAL);
rect.left += LOWORD(dwMargins) + 1;
rect.right -= (width + 7);
}
else
{
rect.left += (LOWORD(dwMargins) + 1);
rect.right -= (HIWORD(dwMargins) + 1);
}
CString text;
GetWindowText(text);
CFont* oldFont = NULL;
rect.top += 1;
if(text.GetLength() == 0)
{
if(this != GetFocus() && m_strPromptText.GetLength() > 0)
{
oldFont = dc.SelectObject(&m_fontPrompt);
COLORREF color = dc.GetTextColor();
dc.SetTextColor(m_colorPromptText);
dc.DrawText(m_strPromptText, rect, DT_LEFT|DT_SINGLELINE|DT_EDITCONTROL);
dc.SetTextColor(color);
dc.SelectObject(oldFont);
}
}
else
{
if(GetStyle() & ES_MULTILINE)
CEdit::OnPaint();
else
{
oldFont = dc.SelectObject(GetFont());
dc.DrawText(text, rect, DT_SINGLELINE | DT_INTERNAL | DT_EDITCONTROL);
dc.SelectObject(oldFont);
}
}
}
同様の編集コントロールの他の実装を見てきましたが、現在はすべて同じ問題があります。
明らかに問題は、コントロールの入力領域から画像領域を除外するにはどうすればよいかということです。