c++ - 如何在 DirectWrite 中使用默认 UI 字体绘制文本?

标签 c++ windows winapi fonts directwrite

CreateTextFormat方法需要一个 fontFamilyName 参数。如何创建使用默认 UI 字体的 IDWriteTextFormat?

最佳答案

请注意,这里的所有代码都是在没有任何检查的情况下完成的(这里有太多方法返回 HRESULT,会破坏这个示例!)。

要获取系统宽字体,您应该使用:

(这是来自另一个 stackoverflow 问题!)

NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
HFONT hFont = CreateFontIndirect(&(ncm.lfMessageFont)); //

对于油漆现在使用这个:

HDC hdc = BeginPaint(...); //Creates a device context
SelectObject(hdc, hFont);
//Your font is now set for the current device context
//do something

DeleteObject(hFont); //Don't forget to do this at the end!

this 略有不同问题!

这个解决方案确实很原始,而且在我看来很丑陋。

替代解决方案确实获得了 IDWriteFont(看起来丑陋但很好):

//just the same as above except the hfont, instead use
NONCLIENTMETRICS ncm;

ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);

IDWriteFactory *dwriteFactory_;
DWriteCreateFactory(
    DWRITE_FACTORY_TYPE_SHARED,
    __uuidof(IDWriteFactory),
    reinterpret_cast<IUnknown**>(&dwriteFactory_)
);

IDWriteGdiInterop* gdiInterop = NULL;
dwriteFactory_->GetGdiInterop(&gdiInterop);

IDWriteFont* sys_font = nullptr;
gdiInterop->CreateFontFromLOGFONT(&ncm.lfMessageFont, &sys_font); //Now we have it!

//The text format can now be aquired like this
//We need the font family of our font
IDWriteFontFamily* family = nullptr;
sys_font->GetFontFamily(&family);

//Now we have to get the "localized" name of our family
IDWriteLocalizedStrings* font_family_name = nullptr;
family->GetFamilyNames(&font_family_name);
UINT32 index = 0;
UINT32 length = 0;
BOOL exists = false;
font_family_name->FindLocaleName(L"en-us", &index, &exists);
font_family_name->GetStringLength(index, &length);
wchar_t* name = new wchar_t[length + 1];
font_family_name->GetString(index, name, length + 1);
wprintf(L"%s\n", name);

//Some user defined stuff
DWRITE_FONT_WEIGHT font_weight = DWRITE_FONT_WEIGHT_BLACK;
DWRITE_FONT_STYLE font_style = DWRITE_FONT_STYLE_ITALIC;
DWRITE_FONT_STRETCH font_stretch = DWRITE_FONT_STRETCH_EXPANDED;

IDWriteTextFormat* text_format = nullptr;
dwriteFactory_->CreateTextFormat(name, nullptr, font_weight, font_style, font_stretch, 10.0, L"en-us", &text_format);

即使没有检查,代码在我的计算机上运行也不会出现任何问题,并给出与第一个解决方案相同的结果(Windows 10,字体系列名称为 Segoe UI)。

来源: General Microsoft DirectWrite API documentation

CreateIndirectFont Documentation

How to enumerate font families, Microsoft documentation

关于c++ - 如何在 DirectWrite 中使用默认 UI 字体绘制文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41505151/

相关文章:

c++ - 什么是 boost::ptr_vector::pop_front() 返回类型?

c++ - 是什么导致 "OpenCV(4.0.1) Error : Assertion failed(m.dims <= 2)"

c++ - 为什么显式给出的模板参数不能为 “deduced”

c++ - pygraphviz 的 Python 3 pip 安装失败, "Microsoft Visual C++ is required",已安装 Visual Studio 2017

c - 从键盘获取输入,无需等待输入

c# - 桌面图标操作 - 当启用带有图片旋转的主题时如何获取 SysListView32 的句柄

c++ - 使用 MSVC 并发异步写入文件?

php - 取消链接但文件日期大小保留在新文件上

可以使用 SetWindowLongPtr + GWLP_USERDATA 来存储数据(不是指针)

windows - 在 DisableProcessWindowsGhosting 之后,有没有办法重新打开 Windows 重影功能?