Win32 在应用程序中使用资源字体
Win32 Use a resource font inside the application
我有一个应用程序,我将一些字体导入到资源中。
现在,我想在应用程序中使用这些资源字体,而不是将它们安装到运行它的计算机上。
我想使用字体资源的方式是我想通过向它发送WM_SETFONT
消息来将标签的字体设置为资源字体。
一般情况下,如果电脑上已经安装了字体我会使用下面的代码:
HDC hdc = GetDC(hwnd);
//here hwnd is the handle to the window.
const TCHAR* fontName = TEXT("/* THE FONT NAME */");
//this is where I'd enter the font name, but it only works when the font is already installed on the computer.
const long nFontSize = NFONTSIZE(7);
//this is where I set the font size.
LOGFONT logFont = {0};
logFont.lfHeight = -MulDiv(nFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
logFont.lfWeight = FW_SEMIBOLD;
_tcscpy_s(logFont.lfFaceName, fontName);
HFONT font = CreateFontIndirect(&logFont); //get the font handle
一旦我获得 HFONT
句柄,就可以轻松地将 WM_SETFONT
消息发送到带有以下标签的标签:
SendMessage(hwnd, WM_SETFONT, (WPARAM)font, static_cast<LPARAM>(MAKELONG(TRUE, 0)));
//here hwnd is the handle of the static label.
但是现在,我不想通过这种方式来设置字体,因为这只有在计算机上已经安装了指定的字体时才有效。我有 我自己的 字体文件 .ttf
格式 作为资源 导入。我想将标签的字体设置为 THIS .ttf
字体。
假设您为资源 ID 定义了一个标记 IDF_MYFONT
,那么您可以在 .rc
(或 .rc2
)中使用如下一行将字体嵌入到可执行文件中脚本:
IDF_MYFONT BINARY "..\MyFont.ttf" // Or whatever the path to your font file is.
您可以使用如下代码加载和锁定字体资源:
HANDLE hMyFont = INVALID_HANDLE_VALUE; // Here, we will (hopefully) get our font handle
HINSTANCE hInstance = ::GetModuleHandle(nullptr); // Or could even be a DLL's HINSTANCE
HRSRC hFntRes = FindResource(hInstance, MAKEINTRESOURCE(IDF_MYFONT), L"BINARY");
if (hFntRes) { // If we have found the resource ...
HGLOBAL hFntMem = LoadResource(hInstance, hFntRes); // Load it
if (hFntMem != nullptr) {
void* FntData = LockResource(hFntMem); // Lock it into accessible memory
DWORD nFonts = 0, len = SizeofResource(hInstance, ares);
hMyFont = AddFontMemResourceEx(FntData, len, nullptr, &nFonts); // Fake install font!
}
}
然后,当您使用完该字体后,您可以像这样从内存中释放它:
RemoveFontMemResourceEx(hMyFont);
我已经包括 一些 对系统调用的 return 值的检查,但您可以添加其他检查。并且您将需要能够处理其中任何一个失败的情况(例如提供默认字体)。
虽然字体在内存中 loaded/locked,但您可以像安装在系统上一样使用它:例如,在 LOGFONT
结构中使用它的名称:
LOGFONT MyLogFont = { -8, 0, 0, 0, 400, FALSE, FALSE, FALSE, ANSI_CHARSET,
OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
VARIABLE_PITCH | FF_SWISS, L"MyFontName" };
随时要求进一步澄清and/or解释。
有趣的是,我昨天晚上刚在处理这个问题...
为了解决这个问题,传入FindResourceW
的值必须匹配资源类型:
const auto resourceHandle{ FindResourceW(nullptr, MAKEINTRESOURCE(IDR_FONT1), RT_FONT) };
const auto resourceLoad{ LoadResource(nullptr, resourceHandle) };
const auto pResource{ LockResource(resourceLoad) };
//do something with the resource pointer here...
FreeResource(resourceLoad);
这应该会给你一个指向资源的指针,然后你可以通过创建一个新文件来提取字体并使用 WriteFile.
写入它要获取资源的大小,请使用 SizeofResource
.
或者您可以通过将资源指针传入AddFontMemResourceEx.
来创建字体
我有一个应用程序,我将一些字体导入到资源中。
现在,我想在应用程序中使用这些资源字体,而不是将它们安装到运行它的计算机上。
我想使用字体资源的方式是我想通过向它发送WM_SETFONT
消息来将标签的字体设置为资源字体。
一般情况下,如果电脑上已经安装了字体我会使用下面的代码:
HDC hdc = GetDC(hwnd);
//here hwnd is the handle to the window.
const TCHAR* fontName = TEXT("/* THE FONT NAME */");
//this is where I'd enter the font name, but it only works when the font is already installed on the computer.
const long nFontSize = NFONTSIZE(7);
//this is where I set the font size.
LOGFONT logFont = {0};
logFont.lfHeight = -MulDiv(nFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
logFont.lfWeight = FW_SEMIBOLD;
_tcscpy_s(logFont.lfFaceName, fontName);
HFONT font = CreateFontIndirect(&logFont); //get the font handle
一旦我获得 HFONT
句柄,就可以轻松地将 WM_SETFONT
消息发送到带有以下标签的标签:
SendMessage(hwnd, WM_SETFONT, (WPARAM)font, static_cast<LPARAM>(MAKELONG(TRUE, 0)));
//here hwnd is the handle of the static label.
但是现在,我不想通过这种方式来设置字体,因为这只有在计算机上已经安装了指定的字体时才有效。我有 我自己的 字体文件 .ttf
格式 作为资源 导入。我想将标签的字体设置为 THIS .ttf
字体。
假设您为资源 ID 定义了一个标记 IDF_MYFONT
,那么您可以在 .rc
(或 .rc2
)中使用如下一行将字体嵌入到可执行文件中脚本:
IDF_MYFONT BINARY "..\MyFont.ttf" // Or whatever the path to your font file is.
您可以使用如下代码加载和锁定字体资源:
HANDLE hMyFont = INVALID_HANDLE_VALUE; // Here, we will (hopefully) get our font handle
HINSTANCE hInstance = ::GetModuleHandle(nullptr); // Or could even be a DLL's HINSTANCE
HRSRC hFntRes = FindResource(hInstance, MAKEINTRESOURCE(IDF_MYFONT), L"BINARY");
if (hFntRes) { // If we have found the resource ...
HGLOBAL hFntMem = LoadResource(hInstance, hFntRes); // Load it
if (hFntMem != nullptr) {
void* FntData = LockResource(hFntMem); // Lock it into accessible memory
DWORD nFonts = 0, len = SizeofResource(hInstance, ares);
hMyFont = AddFontMemResourceEx(FntData, len, nullptr, &nFonts); // Fake install font!
}
}
然后,当您使用完该字体后,您可以像这样从内存中释放它:
RemoveFontMemResourceEx(hMyFont);
我已经包括 一些 对系统调用的 return 值的检查,但您可以添加其他检查。并且您将需要能够处理其中任何一个失败的情况(例如提供默认字体)。
虽然字体在内存中 loaded/locked,但您可以像安装在系统上一样使用它:例如,在 LOGFONT
结构中使用它的名称:
LOGFONT MyLogFont = { -8, 0, 0, 0, 400, FALSE, FALSE, FALSE, ANSI_CHARSET,
OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
VARIABLE_PITCH | FF_SWISS, L"MyFontName" };
随时要求进一步澄清and/or解释。
有趣的是,我昨天晚上刚在处理这个问题...
为了解决这个问题,传入FindResourceW
的值必须匹配资源类型:
const auto resourceHandle{ FindResourceW(nullptr, MAKEINTRESOURCE(IDR_FONT1), RT_FONT) };
const auto resourceLoad{ LoadResource(nullptr, resourceHandle) };
const auto pResource{ LockResource(resourceLoad) };
//do something with the resource pointer here...
FreeResource(resourceLoad);
这应该会给你一个指向资源的指针,然后你可以通过创建一个新文件来提取字体并使用 WriteFile.
写入它要获取资源的大小,请使用 SizeofResource
.
或者您可以通过将资源指针传入AddFontMemResourceEx.