Winapi 如何唯一列出系统上安装的字体名称?

Winapi 如何唯一列出系统上安装的字体名称?,winapi,fonts,windows-10,enumerate,Winapi,Fonts,Windows 10,Enumerate,我正在设置lf.lfFaceName[0]='\0'和lf.lfCharSet=默认字符集枚举系统上安装的唯一字体名称,但仍有重复。我错过了什么?我得到了这样的复制品: font-name: [Cascadia Mono] font-name: [Cascadia Mono] font-name: [Cascadia Mono] font-name: [Cascadia Mono] font-name: [Cascadia Mono] font-name: [Cascadia Mono] fon

我正在设置lf.lfFaceName[0]='\0'和
lf.lfCharSet=默认字符集
枚举系统上安装的唯一字体名称,但仍有重复。我错过了什么?我得到了这样的复制品:

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] = '\0';

    HDC dc = GetDC(NULL);
    EnumFontFamiliesEx(dc, &lf, (FONTENUMPROC)enumFontsCallback, 0, 0);
    ReleaseDC(NULL, dc);
}

int main()
{
    list();
    return 0;
}
我是这样列举的:

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] = '\0';

    HDC dc = GetDC(NULL);
    EnumFontFamiliesEx(dc, &lf, (FONTENUMPROC)enumFontsCallback, 0, 0);
    ReleaseDC(NULL, dc);
}

int main()
{
    list();
    return 0;
}
#pragma注释(lib,“user32.lib”)
#pragma注释(lib,“Comctl32.lib”)
#pragma注释(lib,“Gdi32.lib”)
#pragma注释(lib,“UxTheme.lib”)
#pragma注释(lib,“Comdlg32.lib”)
#定义WIN32_精益_和_平均值
#定义UNICODE
#定义UNICODE
#包括
#包括
LRESULT回调WndProc(HWND HWND,UINT msg,
WPARAM WPARAM,LPARAM LPARAM);
int回调enumFontsCallback(const LOGFONT*lpelfe,
常量TEXTMETRIC*lpntme,
德沃德·丰特派特,
LPARAM(LPARAM)
{
wprintf(L“字体名称:[%s]\r\n”,lpelfe->lfFaceName);
返回1;
}
作废清单()
{
LOGFONT lf={0};
lf.lfWeight=FW_DONTCARE;
lf.lfOutPrecision=OUT\u OUTLINE\u precision;
lf.lfQuality=默认质量;
lf.lfCharSet=默认字符集;
lf.lfClipPrecision=CLIP\u DEFAULT\u precision;
lf.lfPitchAndFamily=FF_DONTCARE;
lf.lfFaceName[0]='\0';
HDC dc=GetDC(空);
EnumFontFamiliesEx(dc,&lf,(FONTENUMPROC)enumFontsCallback,0,0);
ReleaseDC(NULL,dc);
}
int main()
{
list();
返回0;
}

文件中给出了重复的原因:“
EnumFontFamiliesEx
将枚举相同字体的次数,因为字体中有不同的字符集。[…]为了避免这种情况,应用程序应过滤字体列表”

要将列表向下筛选为唯一的字体名称,可以使用回调的
LPARAM
构建以前遇到的字体名称的运行列表,并跳过重复的字体名称

  • EnumFontFamiliesEx
    调用需要更改为以下内容

      unordered_set<wstring> wsFonts;
      EnumFontFamiliesEx(dc, &lf, (FONTENUMPROC)enumFontsCallback, (LPARAM)&wsFonts, 0);
    
    unordered\u设置wsFonts;
    EnumFontFamiliesEx(dc和lf,(FONTENUMPROC)enumFontsCallback,(LPRAM)和wsFonts,0);
    
  • 然后回调可以对照列表检查当前字体名称

      wstring wsFont = lpelfe->lfFaceName;
      if(((unordered_set<wstring> *)lParam)->insert(wsFont).second)
          wcout << L"font-name: " << wsFont << endl;
    
    wstring wsFont=lpelfe->lfFaceName;
    if((无序集*)lParam)->插入(wsFont.second)
    wcout