Dynamiczne rejestrowanie własnych fontów – katorgi ciąg dalszy

Dynamiczne rejestrowanie własnych fontów – katorgi ciąg dalszy
flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

Znów mam problem z rejestrowaniem fontów – tym razem nie chodzi o ich dodawanie z zewnętrznych plików (tamto śmiga), a z ładowaniem z zasobów aplikacji. Już sam nie pamiętam czy wsześniej działało czy nie, nieważne.

Mam plik fonts.lrs, w którym dodane są trzy fonty. Plik ten dodaję do projektu w sekcji initialization:

Kopiuj
initialization
begin
  {$INCLUDE resources\fonts.lrs}
end;

Wszystko gra. Dodaję nagłówki funkcji AddFontMemResourceEx i RemoveFontMemResourceEx manualnie, bo ich brakuje:

Kopiuj
function AddFontMemResourceEx(pbFont: PVOID; cbFont: DWORD; pdv: PVOID; pcFonts: LPDWORD): HANDLE; external 'gdi32.dll' name 'AddFontMemResourceEx';
function RemoveFontMemResourceEx(fh: HANDLE): LongBool; external 'gdi32.dll' name 'RemoveFontMemResourceEx';

Tu też wszystko gra. Dla testu ładuję jeden font. Inicjalizacja zmiennych:

Kopiuj
var
  FontHandle: THandle = 0;
  FontCount: UInt32 = 0;

Teraz procedura ładująca font z zasobów – ona nie działa prawidłowo. Poniższy sposób znalazłem na forum Lazarusa (jeśli chodzi o wykorzystanie klasy TLazarusResourceStream i takie jak niżej przekazanie wartości z właściwości strumienia do parametrów funkcji), więc powinien działać:

Kopiuj
procedure LoadFont(const AResourceName, AResourceType: String);
var
  LStream: TLazarusResourceStream;
begin
  LStream := TLazarusResourceStream.Create(AResourceName, PChar(AResourceType));
  try
    FontHandle := AddFontMemResourceEx(LStream.Memory, LStream.Size, nil, @FontCount);

    if (FontHandle = 0) or (FontCount = 0) then
      Exit;
  finally
    LStream.Free();
  end;

  SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
end;

Funkcja AddFontMemResourceEx zwraca 0, więc nie udało się załadować fontu. Procedurę wołam tak:

Kopiuj
LoadFont('font_ubuntu_regular', 'TTF');

Po stronie wywołania wszystko gra – nazwa zasobu zgadza się, typ zasobu też, dlatego też strumień tworzy się prawidłowo, ale pomimo tego font nie jest instalowany.

Jeśli ktoś jest w stanie wskazać błąd to byłbym bardzo wdzięczny. Do załączników dodaję testowy, malutki projekt, testowany pod Lazarusem 1.8.0 32-bit, czyli w najnowszej stabilnej wersji.

  • Rejestracja: dni
  • Ostatnio: dni
0

U mnie działa :>
Lazarus 1.8.0, Windows 10

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

Sprawdzałeś pod debuggerem? Choć jeśli dołączone exe włącza się to instaluje poprawnie. ;)

Kurde… pod WinXP nie śmiga, a na tym systemie też mi zależy. Nie wiem czy ma znaczenie to, że testowy font mam już zainstalowany w systemie. W każdym razie funkcja AddFontResource w takim przypadku nie protestuje i poprawnie instaluje.

  • Rejestracja: dni
  • Ostatnio: dni
0

Choć jeśli dołączone exe włącza się to instaluje poprawnie

exe sam kompilowałem (w zipie nie było).

Sprawdzałeś pod debuggerem?

Tak. Nawet dodałem label i ustawiłem mu tą czcionkę.

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

Racja, exe nie dołączałem, bo w wersji debug ważył za dużo.

Czyli wychodzi na to, że problem występuje w WinXP. Po południu sprawdzę czy działa pod Win7.

KA
  • Rejestracja: dni
  • Ostatnio: dni
1

@furious programming Win32 API używa stdcall.
zmień

Kopiuj
function AddFontMemResourceEx(pbFont: PVOID; cbFont: DWORD; pdv: PVOID; pcFonts: LPDWORD): HANDLE; external 'gdi32.dll' name 'AddFontMemResourceEx';
function RemoveFontMemResourceEx(fh: HANDLE): LongBool; external 'gdi32.dll' name 'RemoveFontMemResourceEx';

na

Kopiuj
function AddFontMemResourceEx(pbFont: PVOID; cbFont: DWORD; pdv: PVOID; pcFonts: LPDWORD): HANDLE; stdcall external 'gdi32.dll' name 'AddFontMemResourceEx';
function RemoveFontMemResourceEx(fh: HANDLE): LongBool; stdcall external 'gdi32.dll' name 'RemoveFontMemResourceEx';
flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

Chciałem dodać stdcall, nawet na siłę, uwierz mi… i dodałem:

Kopiuj
function AddFontMemResourceEx(pbFont: PVOID; cbFont: DWORD; pdv: PVOID; pcFonts: LPDWORD): HANDLE; external 'gdi32.dll' name 'AddFontMemResourceEx'; stdcall;

Dostałem błąd kompilacji:

Kopiuj
Error: Procedure directive "STDCALL" has conflicts with other directives

więc uznałem, że go nie dam rady dołożyć. Patrzę na Twój kod i zastanawiam się nad tym, gdzie ja miałem głowę pakując ten modyfikator na koniec deklaracji nagłówka funkcji… Chyba przedawkowałem komputer, bo to nie miało absolutnie żadnego sensu, już nie wspominając o błędnej składni…


Oczywiście Twoja propozycja rozwiązuje problem – fonty ładują się prawidłowo. Dziękuję za pomoc, pewnie siedziałbym nad tym z tydzień, zanim zauważyłbym ten bubel… ;)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.