Win32在应用程序内使用资源字体

问题描述 投票:2回答:2

我有一个应用程序,并且将一些字体导入到资源中。

现在,我想在应用程序内使用那些资源字体,而不将它们安装到运行它的计算机上。

[我想使用字体资源的方式是,我想通过向其发送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.

但是现在,我不想通过这种方式设置字体,因为这仅在计算机上已经安装了指定字体时才有效。我有MY OWN字体文件,格式为.ttf 作为资源导入。我想将标签的字体设置为THIS .ttf字体。

非常感谢您抽出宝贵的时间来帮助我回答这个问题。

欢迎任何建议和批评。

c++ winapi fonts resources hwnd
2个回答
2
投票

假设您已经为资源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);

我已包含some检查系统调用的返回值,但是您可以添加其他值。而且您将需要能够处理其中任何一种失败的情况(例如,提供默认字体)。

虽然字体已加载/锁定在内存中,但您可以像在系统上安装字体一样使用它:例如,在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" };

随时要求进一步的澄清和/或解释。


1
投票

有趣的是,昨天晚上我只是在处理这个问题...

要解决它,传递到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.中来创建字体。

© www.soinside.com 2019 - 2024. All rights reserved.