通过遍历注册表遍历windows truetype字体

通过遍历注册表遍历windows truetype字体,找出字体名和字体文件的对应关系。
这个代码并没有找出字体名的本地化的名字。尝试使用摘录改编自Qt的qt_getEnglishName,但是GetFontData返回GDI_ERROR,失败。
下面是代码,测试通过。

#include <iostream>
#include <vector>
#include <Windows.h>
#include <string>
#include <locale.h>

std::string ws2s(const std::wstring& ws)
{
	std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";
 
	setlocale(LC_ALL, "chs");
 
	const wchar_t* _Source = ws.c_str();
	size_t _Dsize = 2 * ws.size() + 1;
	char *_Dest = new char[_Dsize];
	memset(_Dest,0,_Dsize);
	size_t out;
	wcstombs_s(&out, _Dest, _Dsize, _Source,_Dsize);
	std::string result = _Dest;
	delete []_Dest;
 
	setlocale(LC_ALL, curLocale.c_str());
 
	return result;
}


// copy and adapt from https://github.com/GiovanniDicanio/WinReg/blob/master/WinReg/WinReg.hpp

// call RegCloseKey(hKey) after usage.
HKEY RegOpenKeyForRead(
    const HKEY              hKeyParent,
    const std::string&     subKey
)
{
    HKEY hKey = nullptr;
    LONG retCode = RegOpenKeyExA(
        hKeyParent,
        subKey.c_str(),
        REG_NONE,           // default options
        KEY_READ,
        &hKey
    );
    if (retCode != ERROR_SUCCESS)
    {
        throw std::runtime_error("RegOpenKeyEx failed.");
    }

    // Take ownership of the newly created key
    return hKey;
}

std::string RegGetStringValue(HKEY hKey, const std::string& valueName)
{
    // Get the size of the result string
    DWORD dataSize = 0; // size of data, in bytes
    constexpr DWORD flags = RRF_RT_REG_SZ;
    LONG retCode = RegGetValueA(
        hKey,
        nullptr,    // no subkey
        valueName.c_str(),
        flags,
        nullptr,    // type not required
        nullptr,    // output buffer not needed now
        &dataSize
    );
    if (retCode != ERROR_SUCCESS)
    {
        return "";
    }

    // Allocate a string of proper size.
    // Note that dataSize is in bytes and includes the terminating NUL;
    // we have to convert the size from bytes to wchar_ts for wstring::resize.
    std::string result(dataSize / sizeof(char), ' ');

    // Call RegGetValue for the second time to read the string's content
    retCode = RegGetValueA(
        hKey,
        nullptr,    // no subkey
        valueName.c_str(),
        flags,
        nullptr,    // type not required
        &result[0], // output buffer
        &dataSize
    );
    if (retCode != ERROR_SUCCESS)
    {
        return "";
    }

    // Remove the NUL terminator scribbled by RegGetValue from the wstring
    result.resize((dataSize / sizeof(char)) - 1);

    return result;
}

void CloseRegKey(HKEY* key) {
	RegCloseKey(*key);
}


void trim(std::string &s)
{
	if (s.empty())
	{
		return;
	}

	s.erase(0, s.find_first_not_of(" "));
	s.erase(s.find_last_not_of(" ") + 1);
}

std::vector<std::pair<std::string, std::string>> EnumTrueTypeFonts()
{
	HKEY hKey = RegOpenKeyForRead(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
	std::unique_ptr<HKEY, decltype(&CloseRegKey)> wrapper(&hKey, CloseRegKey);
    // Get useful enumeration info, like the total number of values
    // and the maximum length of the value names
    DWORD valueCount = 0;
    DWORD maxValueNameLen = 0;
    LONG retCode = RegQueryInfoKeyA(
        hKey,
        nullptr,    // no user-defined class
        nullptr,    // no user-defined class size
        nullptr,    // reserved
        nullptr,    // no subkey count
        nullptr,    // no subkey max length
        nullptr,    // no subkey class length
        &valueCount,
        &maxValueNameLen,
        nullptr,    // no max value length
        nullptr,    // no security descriptor
        nullptr     // no last write time
    );
    if (retCode != ERROR_SUCCESS)
    {
		throw std::runtime_error("RegQueryInfoKey failed while preparing for value enumeration.");
    }

    // NOTE: According to the MSDN documentation, the size returned for value name max length
    // does *not* include the terminating NUL, so let's add +1 to take it into account
    // when I allocate the buffer for reading value names.
    maxValueNameLen++;

    // Preallocate a buffer for the value names
    auto nameBuffer = std::make_unique<char[]>(maxValueNameLen);

    // The value names and types will be stored here
    std::vector<std::pair<std::string, std::string>> valueInfo;

    // Reserve room in the vector to speed up the following insertion loop
    valueInfo.reserve(valueCount);

    // Enumerate all the values
    for (DWORD index = 0; index < valueCount; index++)
    {
        // Get the name and the type of the current value
        DWORD valueNameLen = maxValueNameLen;
        DWORD valueType = 0;
        retCode = RegEnumValueA(
            hKey,
            index,
            nameBuffer.get(),
            &valueNameLen,
            nullptr,    // reserved
            &valueType,
            nullptr,    // no data
            nullptr     // no data size
        );
        if (retCode != ERROR_SUCCESS)
        {
            throw std::runtime_error("Cannot enumerate values: RegEnumValue failed.");
        }
		if (valueType == REG_SZ) {
			// On success, the RegEnumValue API writes the length of the
			// value name in the valueNameLen output parameter
			// (not including the terminating NUL).
			// So we can build a wstring based on that
			std::string valueName{ nameBuffer.get(), valueNameLen };
			auto pos = valueName.rfind("(TrueType)");
			if (pos != std::string::npos) {
				const auto value = RegGetStringValue(hKey, nameBuffer.get());
				valueName = valueName.substr(0, pos);
				// string.split
				size_t pos1 = 0, pos2;
				while (true)
				{
					pos2 = valueName.find('&', pos1);
					auto valueName2 = valueName.substr(pos1, pos2 == std::string::npos? pos2 : pos2 - pos1);
					trim(valueName2);
					valueInfo.emplace_back(valueName2, value);
					if (pos2 == std::string::npos)
						break;
					pos1 = pos2 + 1;
				}
			}
		}
    }

    return valueInfo;
}

int main()
{
	auto fonts = EnumTrueTypeFonts();
	for (const auto& v : fonts)
	{
		std::cout << v.first.c_str() << "\t=>\t" << v.second.c_str() << std::endl;
	}
}

输出:

Arial   =>      arial.ttf
Arial Black     =>      ariblk.ttf
Arial Bold      =>      arialbd.ttf
Arial Bold Italic       =>      arialbi.ttf
Arial Italic    =>      ariali.ttf
Bahnschrift     =>      bahnschrift.ttf
Calibri =>      calibri.ttf
Calibri Bold    =>      calibrib.ttf
...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值