枚举已安装字体
在某些情况下,应用程序必须能够枚举可用字体并选择最适合特定操作的字体。 应用程序可以通过调用 EnumFonts 或 EnumFontFamilies 函数来枚举可用字体。 这些函数将有关可用字体的信息发送到应用程序提供的回调函数。 回调函数接收 LOGFONT 和 NEWTEXTMETRIC 结构中的信息。 (NEWTEXTMETRIC 结构包含有关 TrueType 字体的信息。当回调函数接收有关非 TrueType 字体的信息时,该信息包含在 TEXTMETRIC 结构中。) 通过使用此信息,应用程序可以将用户的选择限制为仅那些可用的字体。
EnumFontFamilies 函数类似于 EnumFonts 函数,但包含一些额外的功能。 EnumFontFamilies 允许应用程序利用 TrueType 字体可用的样式。 新的和升级的应用程序应使用 EnumFontFamilies 而不是 EnumFonts。
TrueType 字体围绕字体名称组织, (例如 Courier New) 和样式名称 (斜体、粗体和超粗) 。 EnumFontFamilies 函数枚举与指定系列名称关联的所有样式,而不仅仅是粗体和斜体属性。 例如,当系统包含名为 Courier New Extra-Bold 的 TrueType 字体时, EnumFontFamilies 会将其与其他 Courier New 字体一起列出。 EnumFontFamilies 的功能对于具有多种或不同寻常样式的字体以及跨越国际边界的字体非常有用。
如果应用程序不提供字样名称, 则 EnumFonts 和 EnumFontFamilies 函数会提供有关每个可用系列中一种字体的信息。 若要枚举设备上下文中的所有字体,应用程序可以为字样名称指定 NULL ,编译可用字样的列表,然后枚举每个字样中的每个字体。
以下示例使用 EnumFontFamilies 函数检索可用光栅、矢量和 TrueType 字体系列的数量。
UINT uAlignPrev;
int aFontCount[] = { 0, 0, 0 };
char szCount[8];
HRESULT hr;
size_t * pcch;
EnumFontFamilies(hdc, (LPCTSTR) NULL,
(FONTENUMPROC) EnumFamCallBack, (LPARAM) aFontCount);
uAlignPrev = SetTextAlign(hdc, TA_UPDATECP);
MoveToEx(hdc, 10, 50, (LPPOINT)NULL);
TextOut(hdc, 0, 0, "Number of raster fonts: ", 24);
itoa(aFontCount[0], szCount, 10);
hr = StringCchLength(szCount, 9, pcch);
if (FAILED(hr))
{
// TODO: write error handler
}
TextOut(hdc, 0, 0, szCount, *pcch);
MoveToEx(hdc, 10, 75, (LPPOINT)NULL);
TextOut(hdc, 0, 0, "Number of vector fonts: ", 24);
itoa(aFontCount[1], szCount, 10);
hr = StringCchLength(szCount, 9, pcch);
if (FAILED(hr))
{
// TODO: write error handler
}
TextOut(hdc, 0, 0, szCount, *pcch);
MoveToEx(hdc, 10, 100, (LPPOINT)NULL);
TextOut(hdc, 0, 0, "Number of TrueType fonts: ", 26);
itoa(aFontCount[2], szCount, 10);
hr = StringCchLength(szCount, 9, pcch);
if (FAILED(hr))
{
// TODO: write error handler
}
TextOut(hdc, 0, 0, szCount, *pcch);
SetTextAlign(hdc, uAlignPrev);
BOOL CALLBACK EnumFamCallBack(LPLOGFONT lplf, LPNEWTEXTMETRIC lpntm, DWORD FontType, LPVOID aFontCount)
{
int far * aiFontCount = (int far *) aFontCount;
// Record the number of raster, TrueType, and vector
// fonts in the font-count array.
if (FontType & RASTER_FONTTYPE)
aiFontCount[0]++;
else if (FontType & TRUETYPE_FONTTYPE)
aiFontCount[2]++;
else
aiFontCount[1]++;
if (aiFontCount[0] || aiFontCount[1] || aiFontCount[2])
return TRUE;
else
return FALSE;
UNREFERENCED_PARAMETER( lplf );
UNREFERENCED_PARAMETER( lpntm );
}
此示例使用两个掩码(RASTER_FONTTYPE和TRUETYPE_FONTTYPE)来确定要枚举的字体类型。 如果设置了RASTER_FONTTYPE位,则字体为光栅字体。 如果设置了TRUETYPE_FONTTYPE位,则字体为 TrueType 字体。 如果未设置这两个位,则字体为矢量字体。 第三个掩码,DEVICE_FONTTYPE,是在设备 (时设置的,例如,激光打印机) 支持下载 TrueType 字体;如果设备是显示适配器、点阵打印机或其他光栅设备,则为零。 应用程序还可以使用DEVICE_FONTTYPE掩码来区分 GDI 提供的光栅字体和设备提供的字体。 系统可以模拟 GDI 提供的光栅字体的粗体、斜体、下划线和删除线属性,但不适用于设备提供的字体。
应用程序还可以在 NEWTEXTMETRIC 结构的 tmPitchAndFamily 成员中检查位 1 和 2,以标识 TrueType 字体。 如果位 1 为 0,位 2 为 1,则字体为 TrueType 字体。
矢量字体分类为OEM_CHARSET而不是ANSI_CHARSET。 某些应用程序通过使用此信息来标识矢量字体,并检查 NEWTEXTMETRIC 结构的 tmCharSet 成员。 这种分类通常会阻止字体映射器选择矢量字体,除非有具体要求。 (大多数应用程序不再使用矢量字体,因为它们的笔划是单行,绘制时间比 TrueType 字体长,后者提供了许多需要矢量字体的相同缩放和旋转功能。)