Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen (https://www.delphipraxis.net/211264-eigene-font-datei-ueber-die-deployment-liste-via-msix-datei-installieren-lassen.html)

philipp.hofmann 23. Aug 2022 19:40

eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen
 
Wie muss ich eine eigene Font-Datei in der Deployment-Liste für die msix-Datei (WindowsStore) bereitstellen?
Beim der Installer-Variante mache ich dies ja via Innosetup:

Source: "C:\Daten\Philipp\Delphi-Projects\icTrainer\delivery\Inter.ttf"; DestDir: "{autofonts}"; FontInstall: "Inter"; Flags: onlyifdoesntexist uninsneveruninstall

Aber es muss ja auch irgendwie über den Store gehen.

venice2 23. Aug 2022 20:52

AW: eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen
 
Zitat:

installieren lassen
Ist das überhaupt nötig?
Zumindest unter Windows lade ich alle TrueType Fonts dynamisch aus dem Anwendungspfad.

philipp.hofmann 23. Aug 2022 21:11

AW: eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen
 
Seit ich dies mache, habe ich ein instabiles Anwendungsverhalten (wobei ich es nicht 100% auf die Font-Datei beziehen kann). Manchmal beendete sich die App nicht 100% und dann war die Font-Datei auch blockiert, manchmal dauerte es ewig, bis die App wirklich startete. Und die Hauptanpassung in der betroffenen Version war der eigene Font, den ich folgendermaßen eingebunden hatte:

Delphi-Quellcode:
unit ChangeDefaultFont;

interface
uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  {$IFDEF MSWINDOWS}
    WinAPI.Messages,
    WinAPI.Windows,
  {$ENDIF}
  FMX.graphics;

type
  TDefaultFont = class (TInterfacedObject, IFMXSystemFontService)
  public
    function GetDefaultFontFamilyName: string;
    function GetDefaultFontSize: Single;
    class procedure uninstallFont();
    constructor create();

end;

implementation

constructor TDefaultFont.create();
{$IFDEF MSWINDOWS}
var wStr:WideString;
    pWStr:PWideChar;
{$ENDIF}
begin
  {$IFDEF MSWINDOWS}
    wStr:=ExtractFilePath(ParamStr(0))+'Font.ttf';
    pwstr:=PWideChar(wStr);
    AddFontResource(pwstr);
    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
    freemem(pWStr);
  {$ENDIF}
end;

class procedure TDefaultFont.uninstallFont();
{$IFDEF MSWINDOWS}
var wStr:WideString;
    pWStr:PWideChar;
{$ENDIF}
begin
  {$IFDEF MSWINDOWS}
    wStr:=ExtractFilePath(ParamStr(0))+'Font.ttf';
    pwstr:=PWideChar(wStr);
    RemoveFontResource(pwstr);
    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
    freemem(pWStr);
  {$ENDIF}
end;

function TDefaultFont.GetDefaultFontFamilyName: string;
begin
  Result := 'Inter';
end;

function TDefaultFont.GetDefaultFontSize: Single;
begin
  Result := 13.0;
end;

initialization
   TFont.FontService := TDefaultFont.Create;
end.
Vielleicht reicht es ja auch aus, dies einmalig zu laden und auf das uninstallFont zu verzichten. Für den Installer habe ich jetzt den Font per Innosetup reingenommen und für die msix-Version scheint es eine genehmigungspflichtige Anpassung der AppxManifest.template.xml-Datei zu sein:

Code:
     
      xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
      ...
      <Extensions>
         <uap4:Extension Category="windows.sharedFonts">
           <uap4:SharedFonts>
             <uap4:Font File="Inter.ttf"/>
           </uap4:SharedFonts>
         </uap4:Extension>
      </Extensions>
Zumindest habe ich den Code für das dynamische Laden und Entladen entfernt um zu sehen, ob dies das Problem auslöst.

Grüße, Philipp

venice2 23. Aug 2022 22:36

AW: eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen
 
Würde dir da gern weiterhelfen aber mit FMX habe ich leider nichts am Hut.
Selbst verwende ich GDI+ für solche Sachen was aber wohl unter FMX nicht möglich zu sein scheint.

Aber vielleicht hilft das.
https://stackoverflow.com/questions/...y-and-using-it

philipp.hofmann 23. Aug 2022 23:03

AW: eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen
 
Im ersten Step schaue ich mal, ob es jetzt ohne Font-Initialisierung funktioniert und ob dies negative Seiteneffekte hat und dann schaue ich, dass ich die Intiialisierung zum einen nach FormCreate verfrachte und zum anderen dann wahrscheinlich die Ex-Variante nutze, da man diese nicht deinstallieren muss. Dies passiert dann automatisch. Mal schauen. Ich werde hier berichten.

himitsu 24. Aug 2022 01:24

AW: eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen
 
Wieso pWStr freigeben, obwohl niemals Speicher reserviert wurde?

Dein Glück, dass im Default-Constructor des TInterfacedObject und TObject nichts drin steht,
ansonsten schäm dich, dass du das Inherited vergessen hast.


AddFontResource und RemoveFontResource sind als PChar definiert ... wie kannst du da einfach so PWideChar benutzen?
Wenn doch, dann solltest du gefälligst AddFontResourceW und RemoveFontResourceW verwenden.

Niemand ruft uninstallFont auf. Wieso? Warum nicht ins Destroy?

'Font.ttf' ... Meinst nicht 'Inter.ttf'?


Zitat:

Vielleicht reicht es ja auch aus, dies einmalig zu laden und auf das uninstallFont zu verzichten.
Natürlich nicht ... steht doch auch so in der Hilfe.

MSDN-Library durchsuchenAddFontResource
Man sollte auch die Bemerkungen/Remarks lesen.

Datei in der Registry registrieren
oder einfach nach %windir%\Fonts kopieren. (dort wird es automatisch registriert, wenn ich mich nicht irre)

philipp.hofmann 24. Aug 2022 11:50

AW: eigene Font-Datei über die Deployment-Liste via msix-Datei installieren lassen
 
Die Klasse TDefaultFont stammt nicht von mir, die habe ich irgendwo gezogen und zur Ehrenrettung, dass freemem war auskommentiert (hatte ich nur falsch hier rein übertragen) und uninstallFont() wurde im FormDestroy durchaus aufgerufen. Ich habe die Klasse jetzt aber angepasst und den Font per res/rc-Datei integriert:

- nun rufe ich selbst im FormCreate das loadFont auf und ich muss es nicht mehr entladen.

Delphi-Quellcode:
unit ChangeDefaultFont;

interface
uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  {$IFDEF MSWINDOWS}
    WinAPI.Messages,
    WinAPI.Windows,
  {$ENDIF}
  FMX.graphics;

type
  TDefaultFont = class (TInterfacedObject, IFMXSystemFontService)
  public
    function GetDefaultFontFamilyName: string;
    function GetDefaultFontSize: Single;
    class function loadFont(rcname:String):boolean;
end;

implementation

uses MyLog;

class function TDefaultFont.loadFont(rcname:String):boolean;
{$IFDEF MSWINDOWS}
var ResStream : tResourceStream;
   FontsCount : integer;
   hFont : tHandle;
{$ENDIF}
begin
  result:=false;
  {$IFDEF MSWINDOWS}
    try
      ResStream := tResourceStream.Create(hInstance, rcname, Pchar('MYFONT'));
      try
        hFont := AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount);
        result := (hFont <> 0);
      finally
        ResStream.Free();
      end;
    except on E: Exception do
      mlog.info('Error by loading font: '+e.message);
    end;
  {$ENDIF}
end;

function TDefaultFont.GetDefaultFontFamilyName: string;
begin
  Result := 'Inter';
end;

function TDefaultFont.GetDefaultFontSize: Single;
begin
  Result := 13.0;
end;

initialization
   TFont.FontService := TDefaultFont.Create;
end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:42 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz