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/)
-   -   Delphi Darstellbare Zeichenhöhen eines "Fixed-Font"? (https://www.delphipraxis.net/106350-darstellbare-zeichenhoehen-eines-fixed-font.html)

taaktaak 9. Jan 2008 15:56


Darstellbare Zeichenhöhen eines "Fixed-Font"?
 
Moin, Moin,

nach Anregung eines Beitrages aus der DP kann ich aus der Menge der in "Screen.Fonts" enthaltenen Schriftarten die nicht proportionalen Fonts (also Fonts mit fester Zeichenbreite) herausfiltern. Das funktioniert einwandfrei: Ich bekomme die gleiche Schriftenauswahl, die mir auch die Delphi-IDE in den Editoreigenschaften zur Auswahl anbietet.

So weit so gut. Nun sind aber nicht alle "Fixed-Fonts" auch True-Type-Fonts, so dass nicht immer skalierbaren Zeichenhöhen zur Verfügung stehen. Teilweise gibt es nur eine feste Zeichenhöhe für die Schriftart. Die Delphi-IDE ist in der Lage die Information über die möglichen Zeichenhöhen für jede Schriftart zu ermitteln - das gelingt MIR leider nicht. :pale:

Auch recht aufwendiges Suchen im MSDN hat mich noch nicht weitergebracht. Gibt es hier aus dem Kreise der Spezialisten eine Anregung, wie ich an diese Informationen herankomme?

Gruß Ralph

Reinhard Kern 9. Jan 2008 16:09

Re: Darstellbare Zeichenhöhen eines "Fixed-Font"?
 
Zitat:

Zitat von taaktaak
.... Die Delphi-IDE ist in der Lage die Information über die möglichen Zeichenhöhen für jede Schriftart zu ermitteln - das gelingt MIR leider nicht. ...
Gruß Ralph

Hallo Ralph,

was meinst du denn mit "MIR"? Wenn du den Fontdialog benutzt, zeigt der meines Wissens die Grössen korrekt an, d.h. in der Combobox sind nur die verfügbaren Schriftgrössen aufgelistet. Ich hab das jetzt aber nicht überprüft, ich behaupte das nur so aus dem Gedächtnis - ist auch nicht mehr das, was es mal war.

Gruss Reinhard

taaktaak 9. Jan 2008 16:18

Re: Darstellbare Zeichenhöhen eines "Fixed-Font"?
 
Hallo Reinhard,
ich benötige einen individuellen und selbst erstellten Dialog und kann den "fertigen" FontDialog daher nicht verwenden - ich muss die Informationen also selber ermitteln und darstellen.
Gruß Ralph

Reinhard Kern 10. Jan 2008 00:53

Re: Darstellbare Zeichenhöhen eines "Fixed-Font"?
 
Zitat:

Zitat von taaktaak
Hallo Reinhard,
ich benötige einen individuellen und selbst erstellten Dialog und kann den "fertigen" FontDialog daher nicht verwenden - ich muss die Informationen also selber ermitteln und darstellen.
Gruß Ralph

Hallo Ralph,

das geht in Delphi nicht, da musst du das Win32-API benutzen (EnumFontFamilies etc). Wie ist hier beschrieben:

http://www.catch22.net/tuts/enumfont.asp

Gruss Reinhard

taaktaak 10. Jan 2008 12:46

Re: Darstellbare Zeichenhöhen eines "Fixed-Font"?
 
Hallo Reinhard.

Vielen Dank! Das ist ja der absolut passende Link! Nun wollen wir nur hoffen, dass ich den offenbar in C geschriebenen Code auch nach Delphi übertragen kann.

By the way: Dass ich hier mit der Win32API arbeiten muss und mir Delphi selbst nicht weiterhilft, war mir schon klar. Hatte daher ja auch schon geraume Zeit bei MSDN gesucht und war (wenn ich mir den Code im Link anschaue) schon ziemlich nah an der Lösung.

Nur leider: Nah dran, ist nicht genug! Deshalb noch mal vielen Dank für den Link!!

Gruß Ralph :hi:

taaktaak 10. Jan 2008 19:43

Re: Darstellbare Zeichenhöhen eines "Fixed-Font"?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin, Moin,

dank des obenstehenden Links von Reinhard bin ich nun ein ganzes Stückchen weiter gekommen.

Da ich von C nun wirklich gar nix verstehe, hat mich die Code-Vorlage an den Rand der Verzweiflung gebracht. Aber schließlich ist dann doch etwas funktionierendes daraus entstanden. Ein kleines Beispielprogramm (und der Quellcode) ist unten beigefügt.

Der Vergleich mit der Liste in den "Editoreigenschaften" von Delphi zeigt identische Ergebnisse bis auf eine Ausnahme: Mein Programm ermittelt für "Courier" die Größen 9, 12 und 15 Punkte - Delphi zeigt für "Courier" 10, 12 und 15 Punkte - den Grund der Differenz kann ich nicht ermitteln. Hat da einer der geneigten Leser eine Idee?

Eine weitere Frage an die Experten:
Die Prozedur "GetFonts" verwendet 3 CallBack-Funktionen, da es mir nicht gelungen ist, das Selektionskriterium, das "GetFonts" übergeben wird, an die CallBack-Funktion zu übergeben - so wird für jedes Kriterium eine eigene CallBack-Funktion aufgerufen. Gibt es hier einen eleganteren Weg? Mir würde da im Augenblick nur eine Lösung mit einer globalen Variable einfallen ...

Gruß Ralph

taaktaak 12. Jan 2008 21:00

Re: Darstellbare Zeichenhöhen eines Fonts ermitteln
 
Moin, Moin,

auch wenn das Thema aktuell kein Interesse findet, möchte ich die in meinem letzten Beitrag beschriebene Abweichung aufklären: Usache ist der (unnötige) und falsche "Nachbau" der Funktion MulDiv(a,b,d). Hier die zum Thema des Threads gehörende Prozedur, die für alle Fonts (also auch die non-fixed Fonts) die verfügbaren Zeichenhöhen ermittelt.

Delphi-Quellcode:
procedure GetSizes(List:TStrings;FontName:String;Min,Max:Integer);
var DC : HDC;
    LF : TLogFont;

  function EnumSize(var LogFont:TLogFont;var TextMetric:TTextMetric;
                    FontType:Integer;Data:LParam):Integer; stdcall;
  const TTSizes : Array[0..15] of Integer
                = (8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72);
  var  i,H    : Integer;
        DC     : HDC;
  begin
   if FontType=TrueType_FontType then begin // get sizes from const array
     for i:=0 to High(TTSizes) do
       if TTSizes[i]>=iMin then
         if TTSizes[i]<=iMax then
           TStrings(Data).Add(IntToStr(TTSizes[i]));
     Result:=0;
     end
                                 else begin // get sizes from WinAPI
    DC:=GetDC(0);

    try
      with TextMetric do
        H:=MulDiv(tmHeight-tmInternalLeading,72,GetDeviceCaps(DC,LogPixelsY));
        //
        // folgende "Übersetzung" berechnet für Courier, 10 pts das falsche Ergebnis 9 pts
        // ist also NICHT äquivalent zu MulDiv()
        //
        // H:=((tmHeight-tmInternalLeading)*72) div GetDeviceCaps(DC,LogPixelsY);
        // 

      if H>=TTSizes[0] then // no smaller size than MinSize of TrueType
        if H>=iMin then
          if H<=iMax then
            if TStrings(Data).IndexOf(IntToStr(H))<0 then
              TStrings(Data).Add(IntToStr(H));
      Result:=1;

    finally
      ReleaseDC(0,DC);
      end;

    end;

  end;

  procedure SortList;
  var i   : Integer;
      t   : String;
      Done : Boolean;
  begin
    repeat
      Done:=true;
      for i:=0 to List.Count-2 do
        if StrToInt(List[i])>StrToInt(List[i+1]) then begin
          t       :=List[i];
          List[i] :=List[i+1];
          List[i+1]:=t;
          Done    :=false;
          end;
      until Done
  end;

begin
  DC:=GetDC(0);

  iMin:=Min;
  iMax:=Max;
  if iMax=0 then iMax:=999;

  try
    fillchar(LF,SizeOf(LF),0);
    LF.lfCharSet:=Default_CharSet;
    Move(FontName[1],LF.lfFaceName,length(FontName));

    List.BeginUpdate;
    List.Clear;
    EnumFontFamiliesEx(DC,LF,@EnumSize,LParam(List),0);
    Sortlist;
    List.EndUpdate;

  finally
    ReleaseDC(0,DC);
    end;

end;
Anmerkungen:
  • Mit den Parametern Min/Max kann die Auswahl der Schriftgrößen eingegrenzt werden (vgl. auch die gleichnamigen Properties im FontDialog) Mit Angabe 0/0 werden ALLE Werte an TStrings übergeben.
  • Für TrueType-Fonts sind die "üblichen" Werte als Konstanten-Array vorgegeben, natürlich ist diese Vorgabe grundsätzlich nicht bindend.
  • Die wiederholte Ermittlung von GetDeviceCaps in der CallBack-Funktion ist sicherlich nicht clever, da sich dieser Wert ja nicht ständig ändert. Die Ermittlung dieser quasi Konstanten sollte wohl ausgelagert werden!
  • Aufgrund der sehr geringen Anzahl der Werte wurde eine sehr einfache Sortprozedur verwendet (die "Empfänger der Werte, z.B. List- oder ComboBox sollten NICHT sortiert sein, da die Zahlen sonst in falscher Reihenfolge dargestellt werden).

Gruß Ralph :xmas: (hihihi, der letzte verfügbare Weihnachtsmann - ist der vergessen worden???)

// edit: Wer sich über die Zuweisung von Min an iMin und Max an iMax wundert >> iMin und iMax sind lokal in der Unit deklariert, damit die CallBack-Funktion darauf zugreifen kann.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:14 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