从 C++/Windows 中的名称和样式获取字体文件路径

Get a font filepath from name and style in C++/Windows

本文关键字:样式 获取 字体 路径 文件 C++ Windows      更新时间:2023-10-16

我目前正在我的一个项目中实现FreeType 2,因此需要我的系统上字体的文件路径。我需要一个仅采用字体名称和所需字体样式的解决方案(例如。体或斜体),然后返回字体的文件路径。

我已经尝试了这个Stack Overflow问题的答案,但它在Windows 7上不起作用(可能在Vista上也不起作用),但显然我需要一个适用于这些系统和未来系统的解决方案。

我曾经为Windows平台编写代码,以查找基于"Arial Bold"或类似名称的字体文件。代码发布在下面。它正在扫描注册表并尝试查找字体名称与 Windows 字体目录中文件的匹配项。它可能不是防弹的,但它确实起作用了。获得文件名后,您可以将其传递给FreeType。

// Get system font file path
std::string GetSystemFontFile(const std::string &faceName) {
  static const LPWSTR fontRegistryPath = L"Software\Microsoft\Windows NT\CurrentVersion\Fonts";
  HKEY hKey;
  LONG result;
  std::wstring wsFaceName(faceName.begin(), faceName.end());
  // Open Windows font registry key
  result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, fontRegistryPath, 0, KEY_READ, &hKey);
  if (result != ERROR_SUCCESS) {
    return "";
  }
  DWORD maxValueNameSize, maxValueDataSize;
  result = RegQueryInfoKey(hKey, 0, 0, 0, 0, 0, 0, 0, &maxValueNameSize, &maxValueDataSize, 0, 0);
  if (result != ERROR_SUCCESS) {
    return "";
  }
  DWORD valueIndex = 0;
  LPWSTR valueName = new WCHAR[maxValueNameSize];
  LPBYTE valueData = new BYTE[maxValueDataSize];
  DWORD valueNameSize, valueDataSize, valueType;
  std::wstring wsFontFile;
  // Look for a matching font name
  do {
    wsFontFile.clear();
    valueDataSize = maxValueDataSize;
    valueNameSize = maxValueNameSize;
    result = RegEnumValue(hKey, valueIndex, valueName, &valueNameSize, 0, &valueType, valueData, &valueDataSize);
    valueIndex++;
    if (result != ERROR_SUCCESS || valueType != REG_SZ) {
      continue;
    }
    std::wstring wsValueName(valueName, valueNameSize);
    // Found a match
    if (_wcsnicmp(wsFaceName.c_str(), wsValueName.c_str(), wsFaceName.length()) == 0) {
      wsFontFile.assign((LPWSTR)valueData, valueDataSize);
      break;
    }
  }
  while (result != ERROR_NO_MORE_ITEMS);
  delete[] valueName;
  delete[] valueData;
  RegCloseKey(hKey);
  if (wsFontFile.empty()) {
    return "";
  }
  // Build full font file path
  WCHAR winDir[MAX_PATH];
  GetWindowsDirectory(winDir, MAX_PATH);
  std::wstringstream ss;
  ss << winDir << "\Fonts\" << wsFontFile;
  wsFontFile = ss.str();
  return std::string(wsFontFile.begin(), wsFontFile.end());
}

请问为什么需要物理文件的路径?

  • 如果只需要字体的二进制数据,可以使用 GetFontData。
  • 如果需要字体的度量,可以创建 HFONT,将 HFONT 选择到字体持有者 HDC 中,然后使用 GetOutlineTextMetrics。
  • 如果您需要有关字体链接的信息,请查看我的项目:font_link.cpp。
  • 以上都是纯 GDI 函数。如果您确实需要字体路径,并且不介意使用 DirectWrite,请查看 IDWriteFontFile::GetReferenceKey 和 IDWriteLocalFontFileLoader::GetFilePathFromKey。这将为您提供比GDI更多的未来保险。