コントロールの状態とテキストに関係なく、常にコントロールウィンドウにアイコンが表示されている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);
}
}
}
次の画像は、単一の行の編集の問題を示しています(より良い視野のために画像が拡大されている)。黄色い背景は、実際のコードでは、システムカラーを使用しています。 1行の編集にテキストがあり、入力があると、左側のイメージが塗りつぶされていることがわかります。これは、SetRect
が書式指定の矩形を正しく設定する複数行編集では発生しません。
Iは、画像が表示されている編集の領域を除去する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);
}
}
}
私は同様のエディットコントロールの他の実装を見てきましたが、今はすべて同じフォールトがあります。
明らかに、問題はコントロールの入力領域からイメージ領域を除外することですか?私は何が起こっているの思い
あなたの 'OnPaint'オーバーライドは、編集コントロールのペイントルーチンと戦っています。 'CPaintDC'を使ってコントロールを手作業でペイントし、時には' CEdit :: OnPaint'を呼び出します。そして 'CPaintDC'を再度呼び出して、クライアントエリアを再描画するデフォルトの処理を行います。編集コントロールのフォーカスが合ったり外れたりしたとき、またはペイントメッセージが受信されたときには、これは失敗します。 –
'CEdit :: OnPaint()'は複数行の編集に対してのみ呼び出されますが、これは私の心配ではありません。私は1行編集コントロールしか使用していません。この場合、境界を正しく設定すると、複数行の編集について述べました。 –
'CWnd :: OnCtlColor()'をオーバーライドし、そこから 'ExcludeClipRect()'を呼び出すとどうなりますか?クイックテストではうまく動作するようですが、MFCはありません。 'OnPaint()'で再びクリッピングを変更しなければならないかもしれません。 – isanae