gpt4 book ai didi

c++ - 编辑控件中的搜索图标与输入区域重叠

转载 作者:可可西里 更新时间:2023-11-01 18:00:01 31 4
gpt4 key购买 nike

我正在尝试在 MFC 中创建一个搜索编辑控件,该控件始终在控件窗口中显示一个图标(无论控件的状态和文本如何)。很多年前我写过类似的东西并且工作得很好,但代码不再适用于 Windows 7 和更新版本(甚至可能是 Vista,但没有尝试过)。发生的情况是控件中显示的图像与输入区域重叠(见下图)。

代码背后的想法:

  • 有一个派生自 CEdit 的类(处理 OnPaint 中的绘画)
  • 右侧显示图标,编辑区域根据图标大小缩小
  • 调整大小对单行和多行编辑是不同的。对于单行,我调用 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);
}
}
}

下图显示了单行编辑的问题(图像已放大以获得更好的 View )。黄色背景仅用于突出显示,在实际代码中我使用的是 COLOR_WINDOW 系统颜色。您可以看到,当单行编辑包含文本和输入时,左侧图像被覆盖。这不会发生在 SetRect 正确设置格式矩形的多行编辑中。

enter image description here

我试过使用 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);
}
}
}

我看过类似编辑控件的其他实现,它们现在都有同样的错误。

很明显,问题是如何从控件的输入区域中排除图像区域?

最佳答案

认为 发生的事情是 CPaintDC 调用 BeginPaint(),它将 WM_ERASEBKGND 发送到编辑框。我无法忽略它,所以我猜它可能被发送到一个内部 STATIC 窗口?不确定。

OnPaint() 处理程序中调用 ExcludeClipRect() 不会执行任何操作,因为 EDIT 会将剪辑区域重置为整个客户端BeginPaint() 或其自己的 WM_PAINT 处理程序中的区域。

然而,EDIT 发送一个 WM_CTRCOLOREDIT 给它的父对象,就在绘制它自己之前,但似乎是在设置剪裁区域之后。所以你可以在那里调用 ExcludeClipRect()。听起来像是一个实现细节,可能会随着公共(public)控件的 future 版本而改变。事实上,它似乎已经这样做了。

我在 Windows 7 上做了一个没有 MFC 的快速测试,这是我的窗口过程:

LRESULT CALLBACK wnd_proc(HWND h, UINT m, WPARAM wp, LPARAM lp)
{
switch (m)
{
case WM_CTLCOLOREDIT:
{
const auto dc = (HDC)wp;
const auto hwnd = (HWND)lp;

RECT r;
GetClientRect(hwnd, &r);

// excluding the margin, but not the border; this assumes
// a one pixel wide border
r.left = r.right - some_margin;
--r.right;
++r.top;
--r.bottom;

ExcludeClipRect(dc, r.left, r.top, r.right, r.bottom);

return (LRESULT)GetStockObject(DC_BRUSH);
}
}

return ::DefWindowProc(h, m, wp, lp);
}

然后我将 EDIT 窗口子类化以在 WM_PAINT 中绘制我自己的图标,然后转发消息以便我不必自己绘制其他所有内容。

LRESULT CALLBACK edit_wnd_proc(
HWND h, UINT m, WPARAM wp, LPARAM lp,
UINT_PTR id, DWORD_PTR data)
{
switch (m)
{
case WM_PAINT:
{
const auto dc = GetDC(h);

// draw an icon

ReleaseDC(h, dc);
break;
}
}

return DefSubclassProc(h, m, wp, lp);
}

请注意,我无法在 中调用 BeginPaint()EndPaint()(相当于构造一个 CPaintDC) WM_PAINT 因为边框不会被绘制。我猜它与调用 BeginPaint() 两次(一次手动,一次通过 EDIT)和 WM_ERASEBKGND 的处理有关。 YMMV,尤其是 MFC。

最后,我在创建 EDIT 后立即设置边距:

SendMessage(
e, EM_SETMARGINS,
EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELPARAM(0, margin));

如果系统字体发生变化,您可能还需要再次更新边距。

关于c++ - 编辑控件中的搜索图标与输入区域重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38891350/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com