【问题标题】:Win32 Use a resource font inside the applicationWin32 在应用程序内使用资源字体
【发布时间】:2020-03-01 22:04:50
【问题描述】:

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

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

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


    【解决方案1】:

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

    我已经对系统调用的返回值进行了一些检查,但您可以添加其他检查。您需要能够处理其中任何一个失败的情况(例如,提供默认字体)。

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

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

    【讨论】:

      【解决方案2】:

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

      要解决这个问题,传入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.来创建字体

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-04
        • 1970-01-01
        • 2017-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多