如何列出系统上安装的唯一字体名称?
How to list uniquely font names installed on system?
我正在设置 lf.lfFaceName[0] = '[=12=]';
和 lf.lfCharSet = DEFAULT_CHARSET;
以枚举系统上安装的唯一字体名称,但我仍然得到重复项。我错过了什么?我得到这样的重复项:
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
我是这样列举的:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "UxTheme.lib")
#pragma comment(lib, "Comdlg32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam);
int CALLBACK enumFontsCallback(const LOGFONT *lpelfe,
const TEXTMETRIC *lpntme,
DWORD FontType,
LPARAM lParam)
{
wprintf(L"font-name: [%s]\r\n", lpelfe->lfFaceName);
return 1;
}
void list()
{
LOGFONT lf = {0};
lf.lfWeight = FW_DONTCARE;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfPitchAndFamily = FF_DONTCARE;
lf.lfFaceName[0] = '[=11=]';
HDC dc = GetDC(NULL);
EnumFontFamiliesEx(dc, &lf, (FONTENUMPROC)enumFontsCallback, 0, 0);
ReleaseDC(NULL, dc);
}
int main()
{
list();
return 0;
}
重复的原因在 remarks 下的文档中给出:“EnumFontFamiliesEx
将枚举相同的字体多次,因为字体中有不同的字符集. [...] 为了避免这种情况,应用程序应该过滤字体列表”。
要将列表过滤为唯一的字体名称,回调的 LPARAM
可用于构建以前遇到的字体名称的 运行 列表,并跳过重复项。
EnumFontFamiliesEx
调用需要更改为如下所示。
unordered_set<wstring> wsFonts;
EnumFontFamiliesEx(dc, &lf, (FONTENUMPROC)enumFontsCallback, (LPARAM)&wsFonts, 0);
然后回调可以根据列表检查当前字体名称。
wstring wsFont = lpelfe->lfFaceName;
if(((unordered_set<wstring> *)lParam)->insert(wsFont).second)
wcout << L"font-name: " << wsFont << endl;
为了 std::unordered_set
的方便,以上假定使用 C++,但当然可以使用手工制作的唯一字符串列表将其写入纯 C。
我正在设置 lf.lfFaceName[0] = '[=12=]';
和 lf.lfCharSet = DEFAULT_CHARSET;
以枚举系统上安装的唯一字体名称,但我仍然得到重复项。我错过了什么?我得到这样的重复项:
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
font-name: [Cascadia Mono SemiBold]
我是这样列举的:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "UxTheme.lib")
#pragma comment(lib, "Comdlg32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam);
int CALLBACK enumFontsCallback(const LOGFONT *lpelfe,
const TEXTMETRIC *lpntme,
DWORD FontType,
LPARAM lParam)
{
wprintf(L"font-name: [%s]\r\n", lpelfe->lfFaceName);
return 1;
}
void list()
{
LOGFONT lf = {0};
lf.lfWeight = FW_DONTCARE;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfPitchAndFamily = FF_DONTCARE;
lf.lfFaceName[0] = '[=11=]';
HDC dc = GetDC(NULL);
EnumFontFamiliesEx(dc, &lf, (FONTENUMPROC)enumFontsCallback, 0, 0);
ReleaseDC(NULL, dc);
}
int main()
{
list();
return 0;
}
重复的原因在 remarks 下的文档中给出:“EnumFontFamiliesEx
将枚举相同的字体多次,因为字体中有不同的字符集. [...] 为了避免这种情况,应用程序应该过滤字体列表”。
要将列表过滤为唯一的字体名称,回调的 LPARAM
可用于构建以前遇到的字体名称的 运行 列表,并跳过重复项。
EnumFontFamiliesEx
调用需要更改为如下所示。unordered_set<wstring> wsFonts; EnumFontFamiliesEx(dc, &lf, (FONTENUMPROC)enumFontsCallback, (LPARAM)&wsFonts, 0);
然后回调可以根据列表检查当前字体名称。
wstring wsFont = lpelfe->lfFaceName; if(((unordered_set<wstring> *)lParam)->insert(wsFont).second) wcout << L"font-name: " << wsFont << endl;
为了 std::unordered_set
的方便,以上假定使用 C++,但当然可以使用手工制作的唯一字符串列表将其写入纯 C。