我正在使用Embarcadero RAD Studio(10.2 Tokyo Starter)和Windows GDI创建一个C++项目来绘制文本,使用DrawText()函数。
我最近看到,Windows 10提供了一个新的"Segoe UI Emoji"字体,可能允许文本函数绘制彩色表情符号。我找到了几个使用Direct2D的示例,但没有纯GDI函数的示例。
我还尝试过像这样的简单代码:
HDC hDC = ::GetDC(Handle);
std::auto_ptr<TCanvas> pCanvas(new TCanvas());
pCanvas->Handle = hDC;
pCanvas->Brush->Color = clWhite;
pCanvas->Brush->Style = bsSolid;
pCanvas->FillRect(TRect(0, 0, ClientWidth, ClientHeight));
const std::wstring text = L"Test ";
TRect textRect(10, 10, ClientWidth - 10, ClientHeight - 10);
hFont = ::CreateFont(-40,
0,
0,
0,
FW_DONTCARE,
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY,
VARIABLE_PITCH,
L"Segoe UI Emoji");
::SelectObject(hDC, hFont);
::DrawTextW(hDC,
text.c_str(),
text.length(),
&textRect,
DT_LEFT | DT_TOP | DT_SINGLELINE);
::DeleteObject(hFont);
输出结果的符号看起来不错,但它们是以黑白方式绘制的,没有颜色,正如您在下面的屏幕截图中看到的:
我找不到任何其他选项,可以使文本使用彩色符号而不是黑白符号进行绘制。是否有一种方法可以激活 GDI DrawText() 函数中的颜色支持?如果有,怎么做呢?或者只有 Direct2D 可以绘制带颜色的表情符号吗?
编辑于 2017 年 10 月 30 日
由于 GDI 无法完成任务(不幸的是,就像我想的那样),因此我在此发布了上述代码的 Direct2D 版本,这对我很有效。
const std::wstring text = L"Test ";
HDC hDC = ::GetDC(Handle);
std::auto_ptr<TCanvas> pGDICanvas(new TCanvas());
pGDICanvas->Handle = hDC;
pGDICanvas->Brush->Color = clWhite;
pGDICanvas->Brush->Style = bsSolid;
pGDICanvas->FillRect(TRect(0, 0, ClientWidth, ClientHeight));
::D2D1_RECT_F textRect;
textRect.left = 10;
textRect.top = 10;
textRect.right = ClientWidth - 10;
textRect.bottom = ClientHeight - 10;
std::auto_ptr<TDirect2DCanvas> pCanvas(new TDirect2DCanvas(hDC, TRect(0, 0, ClientWidth, ClientHeight)));
// configure Direct2D font
pCanvas->Font->Size = 40;
pCanvas->Font->Name = L"Segoe UI Emoji";
pCanvas->Font->Orientation = 0;
pCanvas->Font->Pitch = System::Uitypes::TFontPitch::fpVariable;
pCanvas->Font->Style = TFontStyles();
// get DirectWrite text format object
_di_IDWriteTextFormat pFormat = pCanvas->Font->Handle;
if (!pFormat)
return;
pCanvas->RenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
::D2D1_COLOR_F color;
color.r = 0.0f;
color.g = 0.0f;
color.b = 0.0f;
color.a = 1.0f;
::ID2D1SolidColorBrush* pBrush = NULL;
// create solid color brush, use pen color if rect is completely filled with outline
pCanvas->RenderTarget->CreateSolidColorBrush(color, &pBrush);
if (!pBrush)
return;
// set horiz alignment
pFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
// set vert alignment
pFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
// set reading direction
pFormat->SetReadingDirection(DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
// set word wrapping mode
pFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
IDWriteInlineObject* pInlineObject = NULL;
::DWRITE_TRIMMING trimming;
trimming.delimiter = 0;
trimming.delimiterCount = 0;
trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
// set text trimming
pFormat->SetTrimming(&trimming, pInlineObject);
pCanvas->BeginDraw();
pCanvas->RenderTarget->DrawText(text.c_str(), text.length(), pFormat, textRect, pBrush,
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
pCanvas->EndDraw();
当然,这段代码只会在当前最新版本的Windows 10及以上版本上绘制彩色表情符号。在早期版本中,文本将像上面一样绘制(并且该代码可能无法编译)。
U+FE0F
*"选择器"。这样可以让您指定您确实想要表情符号。它也可以反过来使用,您可以使用U+FE0E
选择器来指定文本渲染。你会认为GDI的人会看到"哦,他指定了U+FE0F,他一定非常喜欢表情符号。"*¯(°_o)/¯ - Ian Boyd