EnumFontFamiliesExW 返回太多重复的字体名称,不适合呈现所有字体以供用户选择。我正在使用 EnumFontFamExProc 的 lpelfe->lfCharSet 进行过滤,希望得到最好的一个。
int CALLBACK EnumFontFamExProc(
const LOGFONT *lpelfe,
const TEXTMETRIC *lpntme,
DWORD FontType,
LPARAM lParam
);
过滤算法基于 GetSystemDefaultLangID 的返回,这是我的代码。
switch (GetSystemDefaultLangID()) {
case 0x0004/*zh-Hans*/:
case 0x0804/*zh-CN*/:
case 0x1004/*zh-SG*/:
case 0x7804/*zh*/:
preferCharSet = GB2312_CHARSET;
break;
case 0x7C04/*zh-Hant*/:
case 0x0404/*zh-TW*/:
case 0x0C04/*zh-HK*/:
case 0x1404/*zh-MO*/:
preferCharSet = CHINESEBIG5_CHARSET;
break;
case 0x0011/*ja*/:
case 0x0411/*ja-JP*/:
case 0x0811/*ja-Ploc-JP, reserved*/:
preferCharSet = SHIFTJIS_CHARSET;
break;
/*omit others*/
}
GB2312_CHARSET、CHINESEBIG5_CHARSET 和 SHIFTJIS_CHARSET 在 WinGDI.h 中定义如下:
#define ANSI_CHARSET 0
#define DEFAULT_CHARSET 1
#define SYMBOL_CHARSET 2
#define SHIFTJIS_CHARSET 128
#define HANGEUL_CHARSET 129
#define HANGUL_CHARSET 129
#define GB2312_CHARSET 134
#define CHINESEBIG5_CHARSET 136
#define OEM_CHARSET 255
#if(WINVER >= 0x0400)
#define JOHAB_CHARSET 130
#define HEBREW_CHARSET 177
#define ARABIC_CHARSET 178
#define GREEK_CHARSET 161
#define TURKISH_CHARSET 162
#define VIETNAMESE_CHARSET 163
#define THAI_CHARSET 222
#define EASTEUROPE_CHARSET 238
#define RUSSIAN_CHARSET 204
#define MAC_CHARSET 77
#define BALTIC_CHARSET 186
我的 switch case 语句不包括所有语言,例如 0x0439 印度语言,我找不到上面的印地语字体常量。我想知道是否有办法根据LANGID找到Windows系统首选项XXX_CHARSET。
字符集是一个遗留的东西,对应于 8 位和多字节预 Unicode 编码的代码页。字体有一个称为“OS/2”表的数据表(是的,它可以追溯到 OS/2 操作系统),其中包括用于声明可以支持的代码页的位字段。 EnumFontFamiliesEx 将为 OS/2 表中指示的每个 Windows 代码页调用一次回调函数。除非您维护仍然使用代码页的非常旧的代码,否则任何字符集变体都不重要:您可以过滤到任何一个。
如果传递给 EnumFontFamiliesEx 的 LOGFONT 有指定的字符集,那么 GDI 将根据该字符集过滤字体。大多数字体都标有“ANSI”字符集(即代码页 1252),但绝对不是全部。例如,Windows 附带了一些仅具有 ShiftJIS 字符集集的日语字体。因此,不幸的是,除非您知道您只需要该特定字符集的字体,否则通过预先设置字符集来让 GDI 进行过滤是不可靠的 - 但听起来这不是您的情况(例如,您提到印地语)。
所以,我建议您过滤回调。例如,建立一个地图,并在地图中搜索返回的lfFacename;如果找到,则继续;否则将 lfFacename 添加到地图中。