【问题标题】:How can I get a list of installed fonts on Windows including font style using c++如何获取 Windows 上已安装字体的列表,包括使用 C++ 的字体样式
【发布时间】:2023-03-06 03:46:01
【问题描述】:

我一直在尝试获取 Windows 上已安装字体的列表,包括字体样式。

经过调查,发现需要使用:EnumFontFamiliesEx。 我使用它,但我只得到字体名称而不是该字体的所有样式。

例如:对于字体:“Verdana”

有四种不同的风格,但我只有一种——常规的。 我的问题是:如何获取包含所有样式的字体列表?

我的代码:

void getFonts()
{
    LOGFONT lf;
    memset(&lf, 0, sizeof(lf));
    lf.lfCharSet = DEFAULT_CHARSET;
    HDC hDC = GetDC(NULL);
    EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)(EnumFontFamExProc), NULL, 0);
}

int CALLBACK EnumFontFamExProc(
    ENUMLOGFONTEX *lpelfe,
    NEWTEXTMETRICEX *lpntme,
    DWORD FontType,
    LPARAM lParam
)
{
    UTF8String fontName = (lpelfe->elfFullName);
    return 1;
}

ENUMLOGFONTEX *lpelfe - 包含字体。但我没有得到所有不同的风格

经过更多调查,我发现如果我将 lfFaceName 更改为特定字体,该方法将返回所有样式。

// To enumerate all styles of all fonts for the ANSI character set 
lf.lfFaceName[0] = '\0';
lf.lfCharSet = ANSI_CHARSET;

// To enumerate all styles of Arial font that cover the ANSI charset 
hr = StringCchCopy( (LPSTR)lf.lfFaceName, LF_FACESIZE, "Arial" );

所以我不确定我应该做什么,我需要获取所有已安装字体的所有样式。

提前谢谢你

【问题讨论】:

    标签: c++ windows fonts


    【解决方案1】:

    查看EnumFontFamiliesEx 的详细信息,特别是lfFaceName 参数:

    如果设置为空字符串,该函数将枚举每个可用字体名称中的一种字体。如果设置为有效的字体名称,该函数将枚举具有指定名称的所有字体。

    最常见的情况是获取家族列表以显示在字体选择 UI(例如,下拉菜单)中,而不是所有个人面孔。出于这个原因,如果您在 lfFacename 设置为 "" 的情况下调用,您将得到:家庭列表。如果你真的想获得所有的个人面孔——每个家庭有多个面孔——那么你需要在 EnumFontFamiliesExProc 回调中递归调用,将家庭名称作为 lfFaceName 传递给内部循环——你可以只使用传递的 LOGFONT将回调作为参数传入到 EnumFontFamiliesEx 的内部循环调用中:

    int CALLBACK GdiFontEnumeration::EnumFontFamiliesExCallback(
        _In_ const ENUMLOGFONTEX    *lpelfe,
        _In_ const NEWTEXTMETRICEX *lpntme,
        _In_       DWORD      dwFontType,
        _In_       LPARAM     lParam
        )
    {
        // If no facename parameter was passed in the command line, then
        // lParam will be 0 the first time the callback is called for a
        // given family. We'll call EnumFontFamiliesEx again passing the 
        // LOGFONT, and that way we'll get callbacks for the variations 
        // within the given family. When making the inner-loop call, set 
        // lParam = 1 so that we don't keep recursing.
    
        if (lParam == 0)
        {
            LOGFONT lf = lpelfe->elfLogFont;
            HDC hdc = CreateDC(L"DISPLAY", NULL, NULL, NULL);
            int result = EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)EnumFontFamiliesExCallback, 1, 0);
        }
        else
    ...
    

    【讨论】:

      【解决方案2】:

      这个小程序将列出您系统上安装的所有字体。您可以通过仅查找后缀的样式将它们分开。它使用 C++17 特性,因此请记住使用正确的标准对其进行编译。

      i = Italic
      b = Bold
      bi = Bold and Italic
      ...
      
      #include <string>
      #include <iostream>
      #include <filesystem>
      
      int main()
      {
          std::string path = "C:\\Windows\\Fonts";
          for (const auto& entry : std::filesystem::directory_iterator(path))
              std::cout << entry.path() << std::endl;
      }
      

      【讨论】:

      • 谢谢,但是我得到了太多字体,我在字体文件夹下看不到,例如:8514fix.fon、8514fixe.fon、8514fixg.fon、8514fixr.fon、8514fixt.fon。 .
      • @coral 这些是系统可能使用的隐藏字体,你也可以过滤它们,如果你想让我在我的示例中附加一个过滤器,我很乐意这样做。
      • 是的,非常感谢您的帮助。并从哪里获得 I= 斜体、B = 粗体、bi = 粗体和斜体的定义。因为我有 z 或 s ..我在哪里可以找到定义?非常感谢!!!!
      • 我告诉你是因为我看到这个后缀有时会下载字体。现在做一些研究,我发现没有标准,或者不是每个字体都遵循它。这是我发现的,最遵循某种标准,这里是:i = italicb/bd = boldblk = blackl = lightli = light &amp; italicz / bi = italic &amp; bold
      • 谢谢,但我无法使用此解决方案。我需要获取所有样式的所有已安装字体。
      猜你喜欢
      • 2021-01-12
      • 2012-01-29
      • 2010-09-17
      • 1970-01-01
      • 2020-01-20
      • 2013-01-25
      • 1970-01-01
      • 1970-01-01
      • 2010-09-10
      相关资源
      最近更新 更多