创建专用字体集合
PrivateFontCollection 类继承自 FontCollection 抽象基类。 可以使用 PrivateFontCollection 对象来维护专用于应用程序的一组字体。
专用字体集合可以包括已安装的系统字体以及尚未在计算机上安装的字体。 若要将字体文件添加到专用字体集合,请调用 PrivateFontCollection 对象的 PrivateFontCollection::AddFontFile 方法。
注意
使用 GDI+ API 时,绝不允许应用程序从不受信任的源下载任意字体。 操作系统需要提升的权限,以确保所有已安装的字体都受信任。
PrivateFontCollection 对象的 FontCollection::GetFamilies 方法返回 FontFamily 对象的数组。 在调用 FontCollection::GetFamilies 之前,必须分配一个足够大的缓冲区来保存该数组。 若要确定所需缓冲区的大小,请调用 FontCollection::GetFamilyCount 方法并将返回值乘以 size of (FontFamily) 。
专用字体集合中的字体系列数量不一定与已添加到集合中的字体文件数量相同。 例如,假设将文件 ArialBd.tff、Times.tff 和 TimesBd.tff 添加到集合中。 由于 Times.tff 和 TimesBd.tff 属于同一个系列,因此集合中将会有三个文件但只有两个系列。
以下示例将以下三个字体文件添加到 PrivateFontCollection 对象:
- C:\WINNT\Fonts\Arial.tff (Arial,常规)
- C:\WINNT\Fonts\CourBI.tff (Courier New,粗体斜体)
- C:\WINNT\Fonts\TimesBd.tff (Times New Roman, bold)
该代码调用 PrivateFontCollection 对象的 FontCollection::GetFamilyCount 方法来确定私有集合中的系列数,然后调用 FontCollection::GetFamilies 来检索 FontFamily 对象的数组。
对于集合中的每个 FontFamily 对象,代码调用 FontFamily::IsStyleAvailable 方法,以确定各种样式 (常规、粗体、斜体、粗体斜体、下划线和删除线) 是否可用。 传递给 FontFamily::IsStyleAvailable 方法的参数是 FontStyle 枚举的成员,该枚举在 Gdiplusenums.h 中声明。
如果特定的系列/样式组合可用,则使用该系列和样式构造 Font 对象。 传递给 Font 构造函数的第一个参数是字体系列名称 (不是 FontFamily 对象,就像 Font 构造函数的其他变体) 一样,最后一个参数是 PrivateFontCollection 对象的地址。 构造 Font 对象后,其地址将传递给 Graphics 类的 DrawString 方法,以显示系列名称以及样式的名称。
#define MAX_STYLE_SIZE 20
#define MAX_FACEANDSTYLE_SIZE (LF_FACESIZE + MAX_STYLE_SIZE + 2)
PointF pointF(10.0f, 0.0f);
SolidBrush solidBrush(Color(255, 0, 0, 0));
INT count = 0;
INT found = 0;
WCHAR familyName[LF_FACESIZE];
WCHAR familyNameAndStyle[MAX_FACEANDSTYLE_SIZE];
FontFamily* pFontFamily;
PrivateFontCollection privateFontCollection;
// Add three font files to the private collection.
privateFontCollection.AddFontFile(L"c:\\Winnt\\Fonts\\Arial.ttf");
privateFontCollection.AddFontFile(L"c:\\Winnt\\Fonts\\CourBI.ttf");
privateFontCollection.AddFontFile(L"c:\\Winnt\\Fonts\\TimesBd.ttf");
// How many font families are in the private collection?
count = privateFontCollection.GetFamilyCount();
// Allocate a buffer to hold the array of FontFamily
// objects returned by GetFamilies.
pFontFamily = new FontFamily[count];
// Get the array of FontFamily objects.
privateFontCollection.GetFamilies(count, pFontFamily, &found);
// Display the name of each font family in the private collection
// along with the available styles for that font family.
for(INT j = 0; j < count; ++j)
{
// Get the font family name.
pFontFamily[j].GetFamilyName(familyName);
// Is the regular style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleRegular))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Regular");
Font* pFont = new Font(
familyName, 16, FontStyleRegular, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the bold style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleBold))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Bold");
Font* pFont = new Font(
familyName, 16, FontStyleBold, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the italic style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleItalic))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Italic");
Font* pFont = new Font(
familyName, 16, FontStyleItalic, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the bold italic style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleBoldItalic))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" BoldItalic");
Font* pFont = new Font(familyName, 16,
FontStyleBoldItalic, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the underline style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleUnderline))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Underline");
Font* pFont = new Font(familyName, 16,
FontStyleUnderline, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0);
delete(pFont);
}
// Is the strikeout style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleStrikeout))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Strikeout");
Font* pFont = new Font(familyName, 16,
FontStyleStrikeout, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Separate the families with white space.
pointF.Y += 10.0f;
} // for
delete pFontFamily;
下图显示了上述代码的输出。
添加到上述代码示例中的专用字体集合的 Arial.tff () 是 Arial 常规样式的字体文件。 但是请注意,程序输出还会显示除常规 Arial 字体系列以外的几种可用样式。 这是因为 Windows GDI+ 可以模拟常规样式中的粗体、斜体和粗体斜体样式。 GDI+ 还可以从常规样式生成下划线和删除线。
同样,GDI+ 可以从粗体样式或斜体样式模拟粗斜体样式。 程序输出显示,即使 TimesBd.tff(Times New Roman,粗体)是集合中唯一的 Times 文件,粗斜体样式也可用于 Times 系列。
此表指定 GDI+ 支持的非系统字体。
格式 | GDI | Windows 7 上的 GDI+ | Windows 8 上的 GDI+ | DirectWrite |
---|---|---|---|---|
.FON | 是 | 否 | 否 | 否 |
.FNT | 是 | 否 | 否 | 否 |
.TTF | 是 | 是 | 是 | 是 |
.具有 TrueType 的 OTF | 是 | 是 | 是 | 是 |
.OTF 与 Adobe CFF | 是 | 否 | 是 | 是 |
Adobe 类型 1 | 是 | 否 | 否 | 否 |