AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Stringlänge parsen

Ein Thema von EWeiss · begonnen am 4. Sep 2017 · letzter Beitrag vom 7. Sep 2017
Antwort Antwort
Seite 1 von 2  1 2      
EWeiss
(Gast)

n/a Beiträge
 
#1

AW: Stringlänge parsen

  Alt 4. Sep 2017, 12:49
Zitat:
Ich möchte die gesamte länge eines String parsen\vergleichen bsp. von 30 Einträgen und den längsten davon
verwenden um mein Sub Menu auf die weite auszurichten.
QuickSort und dann das hier vielleicht?

Delphi-Quellcode:
function getTextWidth(aForm: TForm; const aString: string): Integer;
begin
 if aString <> 'then
  Result := aForm.Canvas.TextWidth(aString)
 else
  Result := 0;
end;
Sorry irgendwie werde ich nicht verstanden.. das nutzt mir nichts und ist auch nicht wichtig.
Da ich den Text mit GDI+ zeichne und ein mix mit der Winapi ist da nicht das wahre.

Denke werde es dann wohl doch mit Length(string) in einer schleife machen müssen.

Zitat:
Verschiedene Zeichen sind ja unterschiedlich breit.
ja das ist klar

Ich mache es hier mit aber erst dann wenn ich den längsten String ermittelt habe. (einmalig..)

Delphi-Quellcode:
function GetTextBound(UseText: WideString; UseFont: WideString; UseSize: single; var bW: integer;
  var bH: integer; UseStrFormat: integer): GPSTATUS; stdcall;
var
  Graphics: cardinal;
  Fam: GpFontFamily;
  TempFont: GpFont;
  DC: HDC;
begin

  result := GenericError;
  strFormat := nil;
  Fam := nil;
  // Create matching font
  try
    GdipCheck(GdipCreateFontFamilyFromName(UseFont, nil, Fam));
    if Assigned(Fam) then
    begin
      GdipCheck(GdipCreateFont(Fam, UseSize, 0, 2, TempFont));
      if Assigned(TempFont) then
      begin
        DC := GetDC(GetDesktopWindow);

        GdipCheck(GdipCreateStringFormat(0, 0, strFormat));
        GdipCheck(GdipCreateFromHDC(DC, Graphics));

        GdipCheck(GdipMeasureString(Graphics, PWideChar(UseText), length(UseText), TempFont,
            @layoutRect, strFormat, @boundingBox, nil, nil));

        if Assigned(strFormat) then
          GdipCheck(GdipDeleteStringFormat(strFormat));

        bW := round(boundingBox.Width - boundingBox.X);
        bH := round(boundingBox.Height - boundingBox.Y);

        if UseStrFormat <> 0 then
          Swap(bW, bH);

        ReleaseDc(GetDesktopWindow, DC);
      end;
    end;
  finally
    if Graphics <> 0 then
      GdipCheck(GdipDeleteGraphics(Graphics));
    if Assigned(TempFont) then
      GdipCheck(GdipDeleteFont(TempFont)); // Lösche das Font Object
    if Assigned(Fam) then
      GdipCheck(GdipDeleteFontFamily(Fam)); // Lösche das Font Family Object
  end;

end;
gruss

Geändert von EWeiss ( 4. Sep 2017 um 12:52 Uhr)
  Mit Zitat antworten Zitat
Glados
(Gast)

n/a Beiträge
 
#2

AW: Stringlänge parsen

  Alt 4. Sep 2017, 12:53
Zitat:
Sorry irgendwie werde ich nicht verstanden..
Doch wirst du.

Zitat:
Denke werde es dann wohl doch mit Length(string) in einer schleife machen müssen.
Auf Systemen mit einer anderen DPI als deine eigene wirst du Probleme bekommen.

Meine oben genannte Funktion gibt die Länge eines Strings in Pixeln zurück.
Mit QuickSort kannst du dann sehr einfach den längsten String raussuchen.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.073 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Stringlänge parsen

  Alt 4. Sep 2017, 14:45
Ich mache es hier mit aber erst dann wenn ich den längsten String ermittelt habe. (einmalig..)

Delphi-Quellcode:
function GetTextBound(UseText: WideString; UseFont: WideString; UseSize: single; var bW: integer;
  var bH: integer; UseStrFormat: integer): GPSTATUS; stdcall;
var
  Graphics: cardinal;
  Fam: GpFontFamily;
  TempFont: GpFont;
  DC: HDC;
begin

  result := GenericError;
  strFormat := nil;
  Fam := nil;
  // Create matching font
  try
    GdipCheck(GdipCreateFontFamilyFromName(UseFont, nil, Fam));
    if Assigned(Fam) then
    begin
      GdipCheck(GdipCreateFont(Fam, UseSize, 0, 2, TempFont));
      if Assigned(TempFont) then
      begin
        DC := GetDC(GetDesktopWindow);

        GdipCheck(GdipCreateStringFormat(0, 0, strFormat));
        GdipCheck(GdipCreateFromHDC(DC, Graphics));

        GdipCheck(GdipMeasureString(Graphics, PWideChar(UseText), length(UseText), TempFont,
            @layoutRect, strFormat, @boundingBox, nil, nil));

        if Assigned(strFormat) then
          GdipCheck(GdipDeleteStringFormat(strFormat));

        bW := round(boundingBox.Width - boundingBox.X);
        bH := round(boundingBox.Height - boundingBox.Y);

        if UseStrFormat <> 0 then
          Swap(bW, bH);

        ReleaseDc(GetDesktopWindow, DC);
      end;
    end;
  finally
    if Graphics <> 0 then
      GdipCheck(GdipDeleteGraphics(Graphics));
    if Assigned(TempFont) then
      GdipCheck(GdipDeleteFont(TempFont)); // Lösche das Font Object
    if Assigned(Fam) then
      GdipCheck(GdipDeleteFontFamily(Fam)); // Lösche das Font Family Object
  end;

end;
Ich will ja nicht meckern, aber hast du das gerade aus dem Gedächtnis abgetippt oder irgendwoher kopiert?
Weil so kompiliert es zumindest in höheren Versionen (Berlin, Tokyo) nicht.
Ggf. unterscheidet sich der dort mitgelieferte übersetzte Header Winapi.GDIAPI.pas (von http://www.progdigy.com, hgourvest@progdigy.com, 15-02-2002) von deiner GDIPlus-Unit.
Ist die selbstgemacht oder irgendwoher kopiert?

Außerdem sind da einige Fehler drin, die ein funktionieren unmöglich gemacht haben.
Hier eine entsprechende korrigierte Version:

Delphi-Quellcode:
function GetTextBound(UseText: WideString; UseFont: WideString; UseSize: single; var bW: integer;
  var bH: integer; UseStrFormat: integer): GPSTATUS; stdcall;
var
  Graphics: GPGRAPHICS; // Tigü: Hier war ein falscher Typ (Cardinal)
  Fam: GpFontFamily;
  TempFont: GpFont;
  DC: HDC;
  strFormat: GPSTRINGFORMAT; // Tigü: war nicht definiert
  boundingBox, layoutRect: TGPRectF; // Tigü: war nicht definiert
begin
  Result := GPSTATUS.GenericError; // Tigü: Result ist immer GenericError?? Wird nirgens auf GPStatus.ok gesetzt
  strFormat := nil;
  Fam := nil;
  TempFont := nil; // Tigü: war nicht initialisiert!
  // Create matching font
  try
    GdipCheck(GdipCreateFontFamilyFromName(PWideChar(UseFont), nil, Fam)); // Tigü: PWideChar fehlte
    if Assigned(Fam) then
    begin
      GdipCheck(GdipCreateFont(Fam, UseSize, 0, 2, TempFont));
      if Assigned(TempFont) then
      begin
        DC := GetDC(GetDesktopWindow);

        GdipCheck(GdipCreateStringFormat(0, 0, strFormat));
        GdipCheck(GdipCreateFromHDC(DC, Graphics));

        FillChar(boundingBox, SizeOf(boundingBox), 0); // Tigü: waren nicht initialisiert, Werte waren "unendlich" klein oder groß
        FillChar(layoutRect, SizeOf(layoutRect), 0); // Tigü: waren nicht initialisiert, Werte waren "unendlich" klein oder groß
                                                                  //
        GdipCheck(GdipMeasureString(Graphics, PWideChar(UseText), Length(UseText), TempFont,
          @layoutRect, strFormat, @boundingBox, nil, nil));

        if Assigned(strFormat) then
          GdipCheck(GdipDeleteStringFormat(strFormat));

        bW := round(boundingBox.Width - boundingBox.x);
        bH := round(boundingBox.Height - boundingBox.y);

        if UseStrFormat <> 0 then
          Swap(bW, bH);

        if (bW <> 0) or (bH <> 0) then
          Result := GPSTATUS.Ok; // Tigü: Wenns klappt, sollte das so auch per Result mitgeteilt werden!!

        ReleaseDc(GetDesktopWindow, DC);
      end;
    end;
  finally
    if Assigned(Graphics) then // Tigü: entsprechend des neuen Typs anpassen
      GdipCheck(GdipDeleteGraphics(Graphics));
    if Assigned(TempFont) then
      GdipCheck(GdipDeleteFont(TempFont)); // Lösche das Font Object
    if Assigned(Fam) then
      GdipCheck(GdipDeleteFontFamily(Fam)); // Lösche das Font Family Object
  end;
end;

Geändert von TiGü ( 4. Sep 2017 um 14:54 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

AW: Stringlänge parsen

  Alt 4. Sep 2017, 14:48
Zitat:
Ist die selbstgemacht oder irgendwoher kopiert?
Bitte? Was sollen deine Anmachungen andauernd.
Suche dir dafür in Zukunft jemand anderen... und ja es funktioniert auch ohne deine Verschlimmbesserungen.

Nur mal so zum Mitschreiben..
Result := GPSTATUS.Ok; // Tigü: Wenns klappt, sollte das so auch per Result mitgeteilt werden!! Quatsch!
GdipCheck liefert die Rückgabe..

Delphi-Quellcode:
function GdipCreateFontFamilyFromName(
  name: WideString;
  fontCollection: Pointer;
  out FontFamily: GpFontFamily
): GPSTATUS; stdcall; external LibGdiPlus;
Was für ein PWideChar?
und so könnte ich weiter machen... aber lassen wir das.

gruss

Geändert von EWeiss ( 4. Sep 2017 um 15:05 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.073 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Stringlänge parsen

  Alt 4. Sep 2017, 15:05
Zitat:
Ist die selbstgemacht oder irgendwoher kopiert?
Bitte? Was sollen deine Anmachungen andauernd.
Suche dir dafür in Zukunft jemand anderen... und ja es funktioniert auch ohne deine Verschlimmbesserungen.
Das ist doch eine ganz normale Frage?
Sind wir heute wieder besonderes dünnhäutig?

Anbei noch ein Screenshot des Line Timer von der Nexus Quality Suite (https://www.nexusdb.com/support/inde...etimerfeatures).
Die Funktion habe ich 100 mal aufgerufen und in der linken Spalte siehst du die Zeiten in Millisekunden.
Alles größer 0,5 habe ich mal farblich markiert.

Du könntest also am meisten Zeit sparen, wenn du - insofern die Schrifteinstellungen für alle Einträge im Menü gleich sind - Das Erstellen der FontFamily, der GDIPlus-Font und das Graphics-Objekt nur einmalig machst und dann über deine Strings iterierst und dir entsprechend die Objekte übergibst.

Delphi-Quellcode:
//Pseudocode:

    GdipCheck(GdipCreateFontFamilyFromName(PWideChar(UseFont), nil, Fam)); // PWideChar
    if Assigned(Fam) then
    begin
      GdipCheck(GdipCreateFont(Fam, UseSize, 0, 2, TempFont));
      if Assigned(TempFont) then
      begin
        DC := GetDC(GetDesktopWindow);

        GdipCheck(GdipCreateStringFormat(0, 0, strFormat));
        GdipCheck(GdipCreateFromHDC(DC, Graphics));
        DoFindLongestStringWidth(strFormat, TempFont, Graphics, UseTexts {hier natürlich dann eine Liste oder Array mit den Strings übergeben}, bW, bH, UseStrFormat);

        ReleaseDc(GetDesktopWindow, DC);

...
Angehängte Grafiken
Dateityp: png GetTextBound.PNG (61,8 KB, 28x aufgerufen)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: Stringlänge parsen

  Alt 4. Sep 2017, 15:09
Zitat:
Das ist doch eine ganz normale Frage?
Jo einmalig aber nicht fortlaufend.

Zitat:
Ich will ja nicht meckern, aber hast du das gerade aus dem Gedächtnis abgetippt oder irgendwoher kopiert?
Ist die selbstgemacht oder irgendwoher kopiert?
Mache ich überhaupt was selbst oder kopiere ich nur alles... LOL.
Ach was soll's

gruss
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.073 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Stringlänge parsen

  Alt 4. Sep 2017, 15:10

Delphi-Quellcode:
function GdipCreateFontFamilyFromName(
  name: WideString;
  fontCollection: Pointer;
  out FontFamily: GpFontFamily
): GPSTATUS; stdcall; external LibGdiPlus;
Was für ein PWideChar?
und so könnte ich weiter machen... aber lassen wir das.
Bist du fertig mit editieren oder kann man mal antworten?
Immer diese Unart, die Beiträge nachträglich zu editieren und neues Zeug rein zuschreiben, anstatt einen neuen Beitrag zu erstellen.
Kannst du dir das nicht mal abgewöhnen?

Die von dir genannte Funktion ist bspw. bei mir so definiert:

Delphi-Quellcode:
//----------------------------------------------------------------------------
// FontFamily APIs
//----------------------------------------------------------------------------

  function GdipCreateFontFamilyFromName(name: PWCHAR;
    fontCollection: GPFONTCOLLECTION;
    out FontFamily: GPFONTFAMILY): GPSTATUS; stdcall;
  {$EXTERNALSYM GdipCreateFontFamilyFromName}
Daher meine Frage, woher deine GDIPlus-Übersetzung stammt.
Wenn du willst, kann ich dir ja mal meine Pascal-Unit zukommen lassen.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#8

AW: Stringlänge parsen

  Alt 4. Sep 2017, 15:20
Ich habe diese Funktion editiert da sie mit PWCHAR nicht mit meinem Wrapper kompatible ist.
Und nein es gibt keine Problem sonst hätte mir GdipCheck das schon gemeldet.

Ich verwende nix von progdigy sondern habe meine eigene Unit erstellt auf der Basis von Win32Api.
Delphi hat die Eigenschaft alles unnötig aufzubauschen.
Sieht man ja an den Kompilaten

mag ja sein das ich ein zwei Sachen nicht initialisiert habe.. meine Regel ist solange der Compiler nicht meckert kompiliert
und alles rund läuft sollte das schon gut sein.

gruss
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#9

AW: Stringlänge parsen

  Alt 4. Sep 2017, 15:31
Ach so das noch
Neue Post!

Delphi-Quellcode:
strFormat: GPSTRINGFORMAT; // Tigü: war nicht definiert
boundingBox, layoutRect: TGPRectF; // Tigü: war nicht definiert
war definiert nur nicht in der Funktion daher muss hier auch nix auf NIL gesetzt werden da GLOBAL!

Delphi-Quellcode:
var
  strFormat: GPSTRINGFORMAT;
  boundingBox: TGPRectF;
  layoutRect: TGPRectF;
  rcLayout: TGPRectF;
  brush: Pointer;
Das kannst du natürlich nicht sehen.

EDIT:

Graphics: GPGRAPHICS; // Tigü: Hier war ein falscher Typ (Cardinal)
Der Typ ist nicht falsch wenn er das wäre würde mein ganzer Quelltext nicht funktionieren.
Das ist eine Auslegungs Sache wie ich Graphics definiere.
IN VB ist es Long, in PowerBasik ist es DWORD und bei mir ist es Cardinal (DWORD) wenn du so willst.

gruss

Geändert von EWeiss ( 4. Sep 2017 um 15:41 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.073 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Stringlänge parsen

  Alt 4. Sep 2017, 15:57
EDIT:

Graphics: GPGRAPHICS; // Tigü: Hier war ein falscher Typ (Cardinal)
Der Typ ist nicht falsch wenn er das wäre würde mein ganzer Quelltext nicht funktionieren.
Das ist eine Auslegungs Sache wie ich Graphics definiere.
IN VB ist es Long, in PowerBasik ist es DWORD und bei mir ist es Cardinal (DWORD) wenn du so willst.
Ich möchte dich an dieser Stelle ausdrücklich warnen!
Das funktioniert wunderbar für 32-Bit bis ans Ende aller Tage.

Aber unter 64-Bit wirst du schnell merkwürdige Fehler (höchstwahrscheinlich) bekommen (können).
Die GDIPLUS-DLL wird dir 64-Bit Zeiger geben (Länge 8 Byte) und du wirst hart auf 32-Bit Länge casten und damit die Adresse abschneiden.
Das führt unweigerlich zu merkwürdigen Fehlern und Zugriffsverletzungen.
Das gilt auch für alle anderen Typen wie bpsw. Brush, Texture, Gradienten, Pen, Image, Bitmap, StringFormat, FontFamily etc. pp.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:30 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz