Come posso caricare temporaneamente un font?
Domanda
Devo caricare temporaneamente alcuni caratteri nel mio programma. Preferibilmente da un file di risorse DLL.
Soluzione
Ed ecco una versione di Delphi:
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;
da usare come:
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;
Altri suggerimenti
Ho trovato questo con Google . Ho tagliato & amp; incollato il codice pertinente di seguito.
Devi aggiungere il carattere al tuo file di risorse:
34 FONT "myfont.ttf"
Il seguente codice C caricherà il carattere dalla risorsa DLL e lo rilascerà dalla memoria al termine dell'utilizzo.
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);
Ecco un po 'di codice che caricherà / renderà disponibile il carattere dall'interno del tuo eseguibile (cioè, il carattere è stato incorporato come risorsa, piuttosto che qualcosa che dovevi installare in Windows in generale).
Nota che il carattere è disponibile per qualsiasi applicazione fino a quando il tuo programma non lo elimina. Non so quanto utile lo troverai, ma l'ho usato alcune volte. Non ho mai messo il carattere in una dll (preferisco questo approccio 'incorpora nell'exe') ma non immagino che cambi troppo le cose.
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;