Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AddFontMemResourceEx

Tags:

c++

fonts

winapi

The following code should work to load a font from a binary resource stored in my executable to system memory according to all of the examples I have found but it is not working. "myfont" is the name of the ttf associated with IDR_FONT in the resource file.

    DWORD   Count ;
    HRSRC   Resource = FindResource(GetModuleHandle(NULL),MAKEINTRESOURCE(IDR_FONT),"BINARY") ;
    DWORD   Length   = SizeofResource(GetModuleHandle(NULL),Resource) ;
    HGLOBAL Address  = LoadResource(GetModuleHandle(NULL),Resource) ;
    HANDLE Handle = AddFontMemResourceEx(Address,Length,0,&Count) ;
    if(Handle==0)
    {
        MessageBox(hWnd,"Font load failed", "Error",NULL);
    }



        LOGFONT logfont; //set window font
        logfont.lfCharSet = DEFAULT_CHARSET;
        logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
        logfont.lfEscapement = 0;
        memcpy(logfont.lfFaceName, "myfont", LF_FACESIZE); 
        logfont.lfHeight = 14; 
        logfont.lfItalic = FALSE; 
        logfont.lfOrientation = 0;
        logfont.lfOutPrecision = OUT_TT_PRECIS;
        logfont.lfQuality = PROOF_QUALITY;
        logfont.lfStrikeOut = FALSE;
        logfont.lfUnderline = FALSE;
        logfont.lfWeight = FW_DONTCARE; 
        hFont = CreateFontIndirect(&logfont);

Any ideas what I am doing incorrectly?

like image 896
eric Avatar asked Dec 11 '25 09:12

eric


1 Answers

There are two problems with your code.

You are not checking any of the API functions for failure. Most likely, your call to FindResource() is failing because "BINARY" is not a standard resource type. User-defined resources should use RCDATA instead:

HRSRC Resource = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_FONT), RT_RCDATA);

Or maybe FONT if it is an actual standard FONT resource:

HRSRC Resource = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_FONT), RT_FONT);

The actual name of the resource type depends on the content of the .RC file you used to add the resource to the executable, though.

The other problem, and more importatly, is that you are not actually accessing the raw data of the resource so you can pass the real font data to AddFontMemResourceEx(). You need to use LockResource() for that.

Try something more like this instead:

HANDLE AddResourceFont(LPCTSTR ResID, DWORD *Installed)
{
    if (Installed) *Installed = 0;

    HMODULE hMod = GetModuleHandle(NULL);
    DWORD Count, ErrorCode;

    HRSRC Resource = FindResource(hMod, ResID, RT_RCDATA); // or RT_FONT or whatever your actual resource type is
    if (!Resource)
    {
        ErrorCode = GetLastError();
        //...
        return NULL;
    }

    DWORD Length = SizeofResource(hMod, Resource);
    if ((Length == 0) && (GetLastError() != 0))
    {
        ErrorCode = GetLastError();
        //...
        return NULL;
    }

    HGLOBAL Address = LoadResource(hMod, Resource);
    if (!Address)
    {
        ErrorCode = GetLastError();
        //...
        return NULL;
    }

    PVOID FontData = LockResource(Address);
    if (!FontData)
    {
        ErrorCode = GetLastError();
        //...
        return NULL;
    }

    HANDLE Handle = AddFontMemResourceEx(FontData, Length, 0, &Count);
    if (!Handle)
    {
        ErrorCode = GetLastError();
        //...
        return NULL;
    }

    if (Installed) *Installed = Count;
    return Handle;
}

.

DWORD Count = 0;
HANDLE hFont = AddResourceFont(MAKEINTRESOURCE(IDR_FONT), &Count);
if (hFont)
{
    //...
    RemoveFontMemResourceEx(hFont);
}
like image 121
Remy Lebeau Avatar answered Dec 14 '25 01:12

Remy Lebeau