C++ 查找文本高度并设置BS_GROUPBOX控件的标题背景色
我正在设计一个组框控件,其目的是自动排列附加到它的控件 组框包含一个可选的标题文本,我的问题是,当我将C++ 查找文本高度并设置BS_GROUPBOX控件的标题背景色,c++,winapi,directx,C++,Winapi,Directx,我正在设计一个组框控件,其目的是自动排列附加到它的控件 组框包含一个可选的标题文本,我的问题是,当我将Y坐标设置为0(零)时,标题文本将重叠(不可见),如下所示: 我算出,标题文本的高度大约为20,因此如果我手动将Y坐标设置为20,我会得到正确的结果: 所以,我的第一个问题是,有没有一种传统的方法来获取分组框标题的高度 我确实看了一下GetSystemMetrics(),但似乎没有一个度量标准 第二个问题,您可以看到示例标题文本的背景如何不是相同的浅蓝色,而是灰色 我必须处理WM_PAINT
Y
坐标设置为0
(零)时,标题文本将重叠(不可见),如下所示:
我算出,标题文本的高度大约为20,因此如果我手动将Y
坐标设置为20,我会得到正确的结果:
所以,我的第一个问题是,有没有一种传统的方法来获取分组框标题的高度
我确实看了一下GetSystemMetrics()
,但似乎没有一个度量标准
第二个问题,您可以看到示例标题文本的背景如何不是相同的浅蓝色,而是灰色
我必须处理WM_PAINT
才能更改此颜色吗?我希望避免这种情况,因为只需处理WM_ERASEBKGND
就可以轻松设置组框背景色,但标题背景始终保持灰色(不在WM_ERASEBKGND
中处理)
下面是我用来擦除背景的代码。它是代码注释中链接中代码的修改版本。现在它使用了一些自定义类型、宏和DirectX,但这不适用于标题背景。我肯定我遗漏了一些东西来绘制标题颜色
case WM_ERASEBKGND:
{
/*
SYMPTOMS
========
When a BS_GROUPBOX style window is created, its background does not erase
correctly.
CAUSE
=====
The parent window of the BS_GROUPBOX style window has the WS_CLIPCHILDREN style,
which prevents the parent window from erasing the group box's background.
RESOLUTION
==========
Subclass the group box window to process the WM_ERASEBKGND message by erasing
its background. Listed below is a code fragment to demonstrate this procedure.
STATUS
======
This behavior is by design.
MORE INFORMATION
================
https://jeffpar.github.io/kbarchive/kb/079/Q79982/
*/
HRESULT hr = CreateGraphicsResources();
SmartObject<DrawableWindow> parent = nullptr;
if (FAILED(hr) || !mParent->IsDrawable())
return FALSE;
// Obtain parent window's background color.
parent = mParent;
const D2D1::ColorF color = parent->GetBackgroundColor();
mpBrush->SetColor(color);
// Other drawing variables
RECT rect{ };
HDC hDC = GetDC(mhWnd);
auto pRender = std::get<1>(mpRenderTarget);
const D2D1_SIZE_F size = pRender->GetSize();
const D2D1_RECT_F rectangle = D2D1::RectF(0, 0, size.width, size.height);
// Erase the group box's background.
GetClientRect(mhWnd, &rect);
pRender->BindDC(hDC, &rect);
pRender->BeginDraw();
pRender->FillRectangle(&rectangle, mpBrush);
hr = pRender->EndDraw();
if (FAILED(hr))
{
ShowError(ERR_BOILER, hr);
}
ReleaseDC(mhWnd, hDC);
// Instruct Windows to paint the group box text and frame.
InvalidateRect(mhWnd, &rect, FALSE);
// Insert code here to instruct the contents of the group box
// to repaint as well.
return TRUE; // Background has been erased.
}
case WM_ERASEBKGND:
{
/*
症状
========
创建BS_GROUPBOX样式的窗口时,其背景不会擦除
正确地
原因
=====
BS_GROUPBOX样式窗口的父窗口具有WS_CLIPCHILDREN样式,
这可以防止父窗口擦除组框的背景。
决议
==========
对group box窗口进行子类化,以通过擦除来处理WM_ERASEBKGND消息
它的背景。下面列出了一段代码来演示这个过程。
地位
======
这种行为是故意的。
更多信息
================
https://jeffpar.github.io/kbarchive/kb/079/Q79982/
*/
HRESULT hr=CreateGraphicsResources();
SmartObject父对象=nullptr;
if(失败(hr)| |!mParent->IsDrawable())
返回FALSE;
//获取父窗口的背景色。
父母=父母;
const D2D1::ColorF color=parent->GetBackgroundColor();
mpBrush->SetColor(颜色);
//其他图形变量
RECT{};
HDC HDC=GetDC(mhWnd);
auto-pRender=std::get(mpRenderTarget);
常量D2D1\u SIZE\u F SIZE=pRender->GetSize();
常量D2D1_RECT_F rectangle=D2D1::RectF(0,0,size.width,size.height);
//删除组框的背景。
GetClientRect(mhWnd和rect);
pRender->BindDC(hDC和rect);
pRender->BeginDraw();
pRender->FillRectangle(&rectangle,mpBrush);
hr=pRender->EndDraw();
如果(失败(小时))
{
淋浴器(锅炉,hr);
}
释放DC(mhWnd,hDC);
//指示Windows绘制组框文本和框架。
无效(mhWnd和rect、FALSE);
//在此处插入代码以指示分组框的内容
//还要重新油漆。
return TRUE;//背景已被擦除。
}
所以,我的第一个问题是,有没有一种传统的方法来获取
组框标题的高度
您可以使用GetTextExtentPoint32
进行高度测量。请参阅“”
第二个问题,您可以看到示例标题的背景如何
文本不是相同的浅蓝色,而是灰色
要更改标题背景色,可以通过handle message设置静态控件的文本背景色
case WM_CTLCOLORSTATIC:
{
if (GetDlgItem(hDlg, IDC_STATIC4) == (HWND)lParam)
{
HDC hdcStatic = (HDC)wParam;
SetBkColor(hdcStatic, RGB(0, 255, 0));
if (hbrBkgnd == NULL)
{
hbrBkgnd = CreateSolidBrush(RGB(0, 255, 0));
}
return (INT_PTR)hbrBkgnd;
}
}
结果如下:
我想你指的是高度,不是宽度。每个控件都可以有自己的字体,标题的高度将基于控件当前使用的字体。您可以通过多种方式获得字体的高度,其中一种方法是调用
GetTextExtentPoint32
@JonathanPotter谢谢,这个函数正是我想要的!你好,丽塔!我要感谢你1000次,你让我开心!我只需要编写从D2D1::Color
到COLOREF
的转换函数,其余的都很容易复制。