使用 GDI (C++) 绘制带轮廓的文本
DrawText with outline using GDI (C++)
我正在使用此代码对来自网络摄像头的帧进行签名:
Font = CreateFont(18, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, "times");
...
HDC hDC = CreateCompatibleDC(NULL);
unsigned char * img = 0;
HBITMAP hBitmap = CreateDIBSection(hDC, &BMI, DIB_RGB_COLORS, (void**)&img, NULL, 0);
memcpy(img, CameraFrame.data, CameraFrame.size());
free(CameraFrame.data);
CameraFrame.data = img;
SelectObject(hDC, hBitmap);
SelectObject(hDC, Font);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(255,255,255));
string Text = "Test";
DrawTextA(hDC, Text.c_str(), Text.size(), &rect, DT_CENTER | DT_WORDBREAK);
DeleteDC(hDC);
当然框架的色阶会有所不同,无论如何我都需要文字可见。
如何DrawText
带轮廓?例如,白色文本带有黑色轮廓。
两种方法:
将文本绘制成黑色,但稍微放大 2 个像素(祝你好运)和 偏移 (-1,-1) 然后通常在中间是白色。
用黑色绘制文本,但偏移 { (-1,-1), (1,1), (-1,1), (1,-1) }
然后在中心用白色绘制。
对于 GDI,您可以使用 BeginPath、DrawText、EndPath,然后使用 StrokeAndFillPath,只要您使用 "outline" 字体(如 TrueType 或 OpenType)即可。
::BeginPath(ps.hdc);
RECT rc;
GetClientRect(&rc);
::DrawTextW(ps.hdc, L"Hello", 5, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
::EndPath(ps.hdc);
::StrokeAndFillPath(ps.hdc);
StrokeAndFillPath 将使用当前选定的笔作为轮廓并使用当前选定的画笔来填充它。您可以在 BeginPath/EndPath.
中使用 TextOut 或其他 GDI 调用
您不会像使用常规文本输出那样获得任何抗锯齿功能,因此它不会像常规 ClearType 文本那样清晰。在更大的尺寸下,这不是一个大问题。
以下是我的推荐:
- 使用带有 PS_DASH 的 CreatePen 或 ExtCreatePen 创建虚线样式的自定义笔。
- 使用 DT_CALCRECT 和您想要的样式绘制文本,以查看文本的实际位置。
- 从#1 中选择将 HPEN 对象放入您的 HDC
- 使用 MoveToEx 和 LineTo 根据 #2 中检索到的矩形绘制框架的 4 条边(根据需要添加一些填充)。此处示例代码:https://msdn.microsoft.com/en-us/library/windows/desktop/dd145182(v=vs.85).aspx
步骤 1 发生在初始化时。每次绘画时都会执行步骤 2-4。
我正在使用此代码对来自网络摄像头的帧进行签名:
Font = CreateFont(18, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, "times");
...
HDC hDC = CreateCompatibleDC(NULL);
unsigned char * img = 0;
HBITMAP hBitmap = CreateDIBSection(hDC, &BMI, DIB_RGB_COLORS, (void**)&img, NULL, 0);
memcpy(img, CameraFrame.data, CameraFrame.size());
free(CameraFrame.data);
CameraFrame.data = img;
SelectObject(hDC, hBitmap);
SelectObject(hDC, Font);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(255,255,255));
string Text = "Test";
DrawTextA(hDC, Text.c_str(), Text.size(), &rect, DT_CENTER | DT_WORDBREAK);
DeleteDC(hDC);
当然框架的色阶会有所不同,无论如何我都需要文字可见。
如何DrawText
带轮廓?例如,白色文本带有黑色轮廓。
两种方法:
将文本绘制成黑色,但稍微放大 2 个像素(祝你好运)和 偏移 (-1,-1) 然后通常在中间是白色。
用黑色绘制文本,但偏移
{ (-1,-1), (1,1), (-1,1), (1,-1) }
然后在中心用白色绘制。
对于 GDI,您可以使用 BeginPath、DrawText、EndPath,然后使用 StrokeAndFillPath,只要您使用 "outline" 字体(如 TrueType 或 OpenType)即可。
::BeginPath(ps.hdc);
RECT rc;
GetClientRect(&rc);
::DrawTextW(ps.hdc, L"Hello", 5, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
::EndPath(ps.hdc);
::StrokeAndFillPath(ps.hdc);
StrokeAndFillPath 将使用当前选定的笔作为轮廓并使用当前选定的画笔来填充它。您可以在 BeginPath/EndPath.
中使用 TextOut 或其他 GDI 调用您不会像使用常规文本输出那样获得任何抗锯齿功能,因此它不会像常规 ClearType 文本那样清晰。在更大的尺寸下,这不是一个大问题。
以下是我的推荐:
- 使用带有 PS_DASH 的 CreatePen 或 ExtCreatePen 创建虚线样式的自定义笔。
- 使用 DT_CALCRECT 和您想要的样式绘制文本,以查看文本的实际位置。
- 从#1 中选择将 HPEN 对象放入您的 HDC
- 使用 MoveToEx 和 LineTo 根据 #2 中检索到的矩形绘制框架的 4 条边(根据需要添加一些填充)。此处示例代码:https://msdn.microsoft.com/en-us/library/windows/desktop/dd145182(v=vs.85).aspx
步骤 1 发生在初始化时。每次绘画时都会执行步骤 2-4。