10

I need to load some fonts temporarily in my program. Preferably from a dll resource file.

Tom
  • 1,381
  • 3
  • 15
  • 26

3 Answers3

10

And here a Delphi version:

procedure LoadFontFromDll(const DllName, FontName: PWideChar);
var
  DllHandle: HMODULE;
  ResHandle: HRSRC;
  ResSize, NbFontAdded: Cardinal;
  ResAddr: HGLOBAL;
begin
  DllHandle := LoadLibrary(DllName);
  if DllHandle = 0 then
    RaiseLastOSError;
  ResHandle := FindResource(DllHandle, FontName, RT_FONT);
  if ResHandle = 0 then
    RaiseLastOSError;
  ResAddr := LoadResource(DllHandle, ResHandle);
  if ResAddr = 0 then
    RaiseLastOSError;
  ResSize := SizeOfResource(DllHandle, ResHandle);
  if ResSize = 0 then
    RaiseLastOSError;
  if 0 = AddFontMemResourceEx(Pointer(ResAddr), ResSize, nil, @NbFontAdded) then
    RaiseLastOSError;
end;

to be used like:

var
  FontName: PChar;
  FontHandle: THandle;
...
  FontName := 'DEJAVUSANS';
  LoadFontFromDll('Project1.dll' , FontName);
  FontHandle := CreateFont(0, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET,
    OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
    FontName);
  if FontHandle = 0 then
    RaiseLastOSError;
Francesca
  • 21,452
  • 4
  • 49
  • 90
2

I found this with Google. I have cut & pasted the relevant code below.

You need to add the font to your resource file:


34 FONT "myfont.ttf"

The following C code will load the font from the DLL resource and release it from memory when you are finished using it.

DWORD   Count;
HMODULE Module   = LoadLibrary("mylib.dll");
HRSRC   Resource = FindResource(Module,MAKEINTRESOURCE(34),RT_FONT);
DWORD   Length   = SizeofResource(Module,Resource);
HGLOBAL Address  = LoadResource(Module,Resource);
HANDLE  Handle   = AddFontMemResourceEx(Address,Length,0,&Count);

/* Use the font here... */

RemoveFontMemResourceEx(Handle);
FreeLibrary(Module);
Brian Matthews
  • 8,506
  • 7
  • 46
  • 68
1

Here's some code that will load/make available the font from inside your executable (ie, the font was embedded as a resource, rather than something you had to install into Windows generally).

Note that the font is available to any application until your program gets rid of it. I don't know how useful you'll find this, but I have used it a few times. I've never put the font into a dll (I prefer this 'embed into the exe' approach) but don't imagine it changes things too much.

procedure TForm1.FormCreate(Sender: TObject);
var
    ResStream : TResourceStream;
    sFileName : string;
begin
    sFileName:=ExtractFilePath(Application.ExeName)+'SWISFONT.TTF';

    ResStream:=nil;
    try
        ResStream:=TResourceStream.Create(hInstance, 'Swisfont', RT_RCDATA);
        try
            ResStream.SaveToFile(sFileName);
        except
            on E:EFCreateError Do ShowMessage(E.Message);
        end;
    finally
        ResStream.Free;
    end;

    AddFontResource(PChar(sFileName));
    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
end;


procedure TForm1.FormDestroy(Sender: TObject);
var
    sFile:string;
begin
    sFile:=ExtractFilePath(Application.ExeName)+'SWISFONT.TTF';
    if FileExists(sFile) then
    begin
        RemoveFontResource(PChar(sFile));
        SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
        DeleteFile(sFile);
    end;
end;
robsoft
  • 5,525
  • 4
  • 35
  • 47
  • NB the sFileName/sFile variables are used to create a local font file - in this case, in the directory where the application is hosted. – robsoft Sep 20 '08 at 11:19
  • The SendMessage is going to have problems on vista. Instead of SendMessage(HWND_BROADCAST,..) you will want to SendMessage(Application.Handle, ..) – smo Sep 20 '08 at 14:42
  • In fact, if the program is running in \Program Files, extracting the font to a file is also going to be problematic in Vista. You will want to load the font resource from memory as in bmatthew's example..but I also think you need to SendMessage. – smo Sep 20 '08 at 14:44
  • Just for completeness thought I'd update this - you don't need the SendMessage stuff if you're only going to use the font in your own program! – robsoft Jan 13 '10 at 09:50
  • 1
    Better use the [`AddFontResourceEx`](http://msdn.microsoft.com/en-us/library/windows/desktop/dd183327(v=vs.85).aspx) function with the `FR_PRIVATE` flag. That's meant for the private use in your process. – TLama Mar 09 '14 at 21:19