I need to load some fonts temporarily in my program. Preferably from a dll resource file.
+1
A:
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
2008-09-20 11:18:16
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
2008-09-20 11:19:46
The SendMessage is going to have problems on vista. Instead of SendMessage(HWND_BROADCAST,..) you will want to SendMessage(Application.Handle, ..)
smo
2008-09-20 14:42:25
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
2008-09-20 14:44:04
Oh cool, thanks for pointing that out!
robsoft
2008-09-21 16:32:57
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
2010-01-13 09:50:49
+4
A:
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;
François
2008-09-21 10:14:19