AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein EllipsisCharacter funktioniert nicht
Thema durchsuchen
Ansicht
Themen-Optionen

EllipsisCharacter funktioniert nicht

Ein Thema von EWeiss · begonnen am 14. Feb 2017 · letzter Beitrag vom 22. Feb 2017
Antwort Antwort
Seite 1 von 2  1 2      
EWeiss
(Gast)

n/a Beiträge
 
#1

EllipsisCharacter funktioniert nicht

  Alt 14. Feb 2017, 22:10
Mein Code

Delphi-Quellcode:
      else if UseStrFormat = StringFormatFlagsNoWrap then
      begin
        if GdipCreateStringFormat(0, 0, strFormat) = OK then
        begin
          GdipSetStringFormatFlags(strFormat, UseStrFormat);
          GdipSetStringFormatLineAlign(strFormat, StringAlignmentFar);
          GdipSetStringFormatTrimming(strFormat, StringTrimmingEllipsisCharacter);
        end;
        GdipDrawString(Graphics, sTxt, length(sTxt), curFont, @rcLayout, strFormat, brush)
      end
Wenn ich nun die Column in meiner Anwendung verschiebe so das sie über den zu langen Text steht
sollte dieser eigentlich abgeschnitten werden und Ellipsis (...) addiert werden.
Nur leider funktioniert das nicht, keine Ahnung warum.

am Code kann es nicht liegen es sei denn ich habe noch etwas vergessen.

EDIT:
Es geht grundsätzlich schon aber nur von Hand also eigener Code
was mir da nur nicht gefällt sind die unterschiedlichen Abstände da ich die einzelnen Chars in der Weite nicht gegenprüfe.
Das ist der Grund warum ich diese API verwenden möchte.

gruss

Geändert von EWeiss (11. Jul 2019 um 16:45 Uhr)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: EllipsisCharacter funktioniert nicht

  Alt 15. Feb 2017, 05:23
Hallo,
was ist denn das für eine Komponente,
die das property Column besitzt?
Heiko
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: EllipsisCharacter funktioniert nicht

  Alt 15. Feb 2017, 17:07
Hallo,
was ist denn das für eine Komponente,
die das property Column besitzt?
Sehe nicht das da irgendwas von property steht nur was von ListView.
Damit aber die blinden hier das auch verstehen..

Wenn ich die Spaltenbreite in der Anwendung verändere.. bla, bla.
Aber schlauer bist du deshalb auch nicht so das du helfen könntest oder?

gruss

Geändert von EWeiss (16. Feb 2017 um 03:17 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

AW: EllipsisCharacter funktioniert nicht

  Alt 18. Feb 2017, 20:14
Thema hat sich erledigt funktioniert nun.
Es war nicht die API selbst sondern die Zuweisung eines nicht Korrekten Rect.

Delphi-Quellcode:
procedure TSkinListView.DrawEllipsisText(DC: HDC; UseText: WideString; rec: TRect;
  ColrARGB: COLORREF; UseFont: WideString; UseSize: single; FontStyle: TFontStyle;
  ShadowOffset: single; UseStrFormat: integer; WordWrap: Bool = False);
var
  Width: Integer;
  Fam: GpFontFamily;
  TempFont: GpFont;
  Graphics: Cardinal;
  rectF: TGPRectF;
  Rect, rc, rc2: Trect;
  strFormat: Pointer;
begin

  Graphics := 0;
  strFormat := nil;
  TempFont := nil;
  Fam := nil;
  if GdipCreateFromHDC(DC, Graphics) = Ok then
  begin
    GdipCreateFontFamilyFromName(UseFont, nil, Fam);
    if Assigned(Fam) then
    begin
      GdipCreateFont(Fam, UseSize, FontStyle, 2, TempFont);
      if Assigned(TempFont) then
      begin
        GdipCreateStringFormat(0, 0, strFormat);
        GdipMeasureString(Graphics, UseText, length(UseText), TempFont, @layoutRect, strFormat,
          @boundingBox, nil, nil);

        GetWindowRect(HeaderHandle, rc);
        GetWindowRect(Handle, rc2);

        Width := (rec.Right - rec.Left) + (rc.Left - rc2.Left);
        if boundingBox.Width > Width then
        begin
          rectF := MakeRect(rec.Left, rec.Top, Width, rec.Bottom);
          Rect.Left := round(rectF.X);
          Rect.Top := round(rectF.Y);
          Rect.Bottom := round(rectF.Height);
          Rect.Right := round(rectF.Width);

          UseStrFormat := ZD_Ellipsis;
          DrawTextToDC(DC, UseText, Rect, ColrARGB, UseFont, UseSize, FontStyle, ShadowOffset,
            UseStrFormat, True);

          GdipDeleteGraphics(Graphics); // Lösche das Graphics Object
          GdipDeleteFont(TempFont); // Lösche das Font Object
          GdipDeleteFontFamily(Fam); // Lösche das Font Family Object
          GdipDeleteStringFormat(strFormat); // Lösche das StringFormat
          exit;
        end else
        DrawTextToDC(DC, UseText, rec, ColrARGB, UseFont, UseSize, FontStyle, ShadowOffset,
          UseStrFormat, WordWrap);
      end;
    end;
  end;
  GdipDeleteGraphics(Graphics);
  GdipDeleteFont(TempFont);
  GdipDeleteFontFamily(Fam);
  GdipDeleteStringFormat(strFormat);
end;
coole Musik. Oder? LOL

gruss

Geändert von EWeiss (11. Jul 2019 um 16:46 Uhr)
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.456 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: EllipsisCharacter funktioniert nicht

  Alt 21. Feb 2017, 16:47
BTW: schon mal try finally end in Erwägung gezogen?
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: EllipsisCharacter funktioniert nicht

  Alt 21. Feb 2017, 19:03
BTW: schon mal try finally end in Erwägung gezogen?
Nö.. will ich nicht.
Brauch ich nicht. Uninteressant, Müllt meinen Code zu.

if GdipCreateFromHDC(DC, Graphics) = Ok then

Ist für mich try, finally genug.
Abgesehen von Delphi hab ich noch keine Sprache verwendet die ein so Sinnloses Konstrukt nötig hätte.
Schon gar nicht mit der Win32API.
try.. except OK! Dann hört es aber auch schon auf.

gruss

Geändert von EWeiss (21. Feb 2017 um 19:28 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

AW: EllipsisCharacter funktioniert nicht

  Alt 21. Feb 2017, 21:59
Da WinAPI Funktionen in der Regel keine Exceptions werfen, wäre es sinnlos Exceptions behandeln zu wollen. Das gilt natürlich auch für try...finally.

Sie aber als sinnlos bin der objektorientierten Programmierung abzutun hat die objektorientierte Programmierung nicht verstanden. Das sieht man auch sehr schön an deinen Code:
Delphi-Quellcode:
if GdipCreateFromHDC(DC, Graphics) = Ok then
  if Assigned(Fam) then
    if Assigned(TempFont) then
     if boundingBox.Width > Width then
     
     end
     else
       ...;
   end;
  end;
end;
Da Windows API Funktionen nur Fehlercodes zurück geben muss man diese jedes mal prüfen und entsprechend reagieren, was zu solchen Verschachtelungsorgien führt. Btw. wo ist die Fehlerbehandlung, wenn der Funktionsaufruf fehlschlägt bei dir?

In der objektorientierten Programmierung schreibt man den Code einfach runter unter macht im Except-Block eine Fehlerbehandlung für alles. Und in Exyception.message steht dann drin welcher Methodenaufruf aus welchem Grund fehlgeschlagen ist.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#8

AW: EllipsisCharacter funktioniert nicht

  Alt 21. Feb 2017, 22:18
Zitat:
Sie aber als sinnlos bin der objektorientierten Programmierung abzutun hat die objektorientierte Programmierung nicht verstanden.
In wie weit.
Was sieht man da sehr schön ?

Wenn ich zu dumm bin zu erkennen wann ich meine Daten Freigeben muss und an welcher stelle dann hilft auch kein try.. finally.
Unnötiger Code.
Würde ich das in jeder Funktion/procedure verwenden wäre 1/3 des Gesamten Code nur mit try.. finally gefüllt.
Wie gesagt brauch ich nicht.

Ob du mich in dem Fall für Dumm hinstellst kann mir egal sein.
Wie gesagt NUR Delphi hat diese komische Angewohnheit alles in Blöcke zu packen.
Nach deiner Schilderung dürften dann alle anderen Sprachen NICHT objektorientiert sein.. Lustig diese Annahme.
Muss dann also davon ausgehen das man nur mit Delphi objektorientiert Programmieren kann. LOL

Ich denke du verstehst nicht das dass nur ein Delphi Ding ist.
Oder brauchst du so was in C++, CSharp, VB, NET usw..

Sorry da kannst du mich nicht überzeugen und die Begründung(Unterstellung) ist quatsch.

gruss

Geändert von EWeiss (21. Feb 2017 um 22:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: EllipsisCharacter funktioniert nicht

  Alt 22. Feb 2017, 00:10
Ich denke du verstehst nicht das dass nur ein Delphi Ding ist.
Oder brauchst du so was in C++, CSharp, VB, NET usw..
Das stimmt so nicht. Alle diese Sprachen - mit Ausnahme von C++ unterstützen - try..finally Blöcke als Sprachfeature. Das "Delphi Ding" sind Resourcenschutzblöcke bei Verwendung von Objekten:
Delphi-Quellcode:
var
  A: TObject;
begin
  A := TObject.Create;
  try
  
  finally
    A.Free;
  end;
end
Dass man sowas in .NET / C# beispielsweise nicht braucht, liegt daran, dass diese Sprachen eine automatische Referenzzählung bzw. einen Garbage-Collector besitzen, der unreferenzierte Klasseninstanzen automatisch freigibt. C++ wurde zumdem explizit für das RAII Prinzip entwickelt und alloziiert Objekte standardmäßig auf dem Stack (statt auf dem Heap). Hierdurch ist die Lebensdauer durch das aktuelle Scope limitiert und benötigt auch keine zusätzliche Finalisierung.

Es mag Leute geben, die try..finally unter Delphi ausschließlich als Resourcenschutzblock verwenden, aber dennoch sind dies zwei getrennte Dinge und man sollte den Nutzen dieses Sprachkonstrukts im Bezug auf andere Dinge keinesfalls unterschätzen. Grade auch bei Verwendung der WinAPI.

Was sieht man da sehr schön ?
Dein Code ist fehlerhaft; genauer gesagt gibt er unter Umständen Objekte frei, welche gar nicht korrekt initialisiert wurden (und du vergisst diverse Rückgabewerte zu prüfen). Exemplarisch hier mal nur folgender Abschnitt:
Delphi-Quellcode:
procedure TSkinListView.DrawEllipsisText(...);
begin
  ...
  if GdipCreateFromHDC(DC, Graphics) = Ok then
  begin
    GdipCreateFontFamilyFromName(UseFont, nil, Fam);
    if Assigned(Fam) then
    begin
      GdipCreateFont(Fam, UseSize, FontStyle, 2, TempFont);
      ...
    end;
  end;
  GdipDeleteGraphics(Graphics);
  GdipDeleteFont(TempFont);
  ...
Was passiert, wenn MSDN-Library durchsuchenGdipCreateFromHDC oder MSDN-Library durchsuchenGdipCreateFontFamilyFromName fehlschlägt? Dann ist Graphics bzw. TempFont ungültig. Mag sein, dass die GDI+ hier gnädig ist, aber andere APIs z.b. MSDN-Library durchsuchenCloseHandle würden in diesem Falle bereits einen Fehler signalisieren - oder noch schlimmer: Du gibst ein anderes, zufälliges Handle deiner Anwendung frei.

Worauf Luckie allerdings (vermutlich) hinauswollte, ist die tiefe Verschachtelung und die redundante Finalisierung im if boundingBox.Width > Width then Block. Beides kannst du nämlich mit try..finally sehr elegant vermeiden:
Delphi-Quellcode:
procedure GdipCheck(Status: GPSTATUS);
begin
  if (Status <> Ok) then raise Exception.Create('GDI+ Exception');
end

...

procedure TSkinListView.DrawEllipsisText(...);
begin
  Graphics := 0;
  Fam := nil;
  TempFont := nil;
  ...
  GdipCheck(GdipCreateFromHDC(DC, Graphics));
  try
    GdipCheck(GdipCreateFontFamilyFromName(UseFont, nil, Fam));
    GdipCheck(GdipCreateFont(Fam, UseSize, FontStyle, 2, TempFont));
    GdipCheck(GdipCreateStringFormat(0, 0, strFormat));
    ...
  finally
    if (Graphics <> 0) then GdipDeleteGraphics(Graphics);
    if (Fam <> nil) then GdipDeleteFontFamily(Fam);
    if (TempFont <> nil) then GdipDeleteFont(TempFont);
    ...
  end;
Die Exception-Hilfsfunktion ist hierbei natürlich optional und kann auch durch ein if (GdipCreateFromHDC(DC, Graphics) <> Ok) then Exit ersetzt werden, da nach dem Exit ebenfalls in jedem Falle der Finally-Block ausgeführt wird.

Noch ein kleiner Nachtrag: Aus eigener Erfahrung kann ich sagen, dass man try..finally wirklich schmerzhaft vermisst, wenn es einem nicht zur Verfügung steht. Ok, C++ hat RAII als Ersatz und da ist es wohl als persönliche Präferenz zu sehen, dass ich dieses Prinzip nicht uneingeschränkt sinnvoll finde (aus zahlreichen Gründen, die hier aber wohl über das Thema hinausschießen), aber selbst pures C wird bei Verwendung der WinAPI teilweise extrem redundant, was Finalisierungen angeht. Kleines (nicht sehr sinnvolles) Beispiel (der Einfachheit halber in Delphi-Code, aber im C-Stil, also ohne try..finally).

Variante 1 (verschachtelt):
Delphi-Quellcode:
begin
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, false, 1337);
  if (hProcess <> 0) then
  begin
    Mem := VirtualAllocEx(hProcess, nil, SizeOf(Value), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
    if Assigned(Mem) then
    begin
      Value := 0;
      if WriteProcessMemory(hProcess, Mem, @Value, SizeOf(Value), BytesWritten) and
        (BytesWritten = SizeOf(Value)) then
      begin
        hThread := CreateRemoteThread(hProcess, nil, 0,
          GetProcAddress(GetModuleHandle('kernel32.dll'), 'ExitProcess'), Mem, CREATE_SUSPENDED, TID);
        if (hThread <> 0) then
        begin
          ResumeThread(hThread);
          // Das könnte sich hier ewig so weiterschachteln ...
        end;
        CloseHandle(hThread);
      end;
      VirtualFreeEx(hProcess, Mem, 0, MEM_RELEASE);
    end;
    CloseHandle(hProcess);
  end;
end;
Variante 2 (mit Exit/goto):
Delphi-Quellcode:
begin
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, false, 1337);
  if (hProcess <> 0) then
  begin
    Mem := VirtualAllocEx(hProcess, nil, SizeOf(Value), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
    if not Assigned(Mem) then
    begin
      // 1 Finalisierung
      CloseHandle(hProcess);
      Exit;
    end;
    Value := 0;
    if (not WriteProcessMemory(hProcess, Mem, @Value, SizeOf(Value), BytesWritten)) or
      (BytesWritten <> SizeOf(Value)) then
    begin
      // 2 Finalisierungen
      VirtualFreeEx(hProcess, Mem, 0, MEM_RELEASE);
      CloseHandle(hProcess);
      Exit;
    end;
    hThread := CreateRemoteThread(hProcess, nil, 0,
      GetProcAddress(GetModuleHandle('kernel32.dll'), 'ExitProcess'), Mem, CREATE_SUSPENDED, TID);
    if (hThread = 0) then
    begin
      // 3 Finalisierungen
      CloseHandle(hThread);
      VirtualFreeEx(hProcess, Mem, 0, MEM_RELEASE);
      CloseHandle(hProcess);
      Exit;
    end;
    ResumeThread(hThread);
    // Und am Ende nochmal alles redundant
    CloseHandle(hThread);
    VirtualFreeEx(hProcess, Mem, 0, MEM_RELEASE);
    CloseHandle(hProcess);
  end;
end;
Dahingegen die Variante mit try..finally:
Delphi-Quellcode:
begin
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, false, 1337);
  if (hProcess <> 0) then
  try
    // Mini-Nachteil: Man muss alle Variablen am Anfang nullen
    Mem := nil;
    hThread := 0;
    // Los gehts:
    Mem := VirtualAllocEx(hProcess, nil, SizeOf(Value), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
    if not Assigned(Mem) then
      Exit;
    Value := 0;
    if (not WriteProcessMemory(hProcess, Mem, @Value, SizeOf(Value), BytesWritten)) or
      (BytesWritten <> SizeOf(Value)) then
      Exit;
    hThread := CreateRemoteThread(hProcess, nil, 0,
      GetProcAddress(GetModuleHandle('kernel32.dll'), 'ExitProcess'), Mem, CREATE_SUSPENDED, TID);
    if (hThread = 0) then
      Exit;
    ResumeThread(hThread);
    // .. kann endlos so weitergehen, ohne immer tiefere Verschachtelung oder Redundanz
  finally
    if (hThread <> 0) then CloseHandle(hThread);
    if (Mem <> nil) then VirtualFreeEx(hProcess, Mem, 0, MEM_RELEASE);
    CloseHandle(hProcess);
  end;
end;
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl (22. Feb 2017 um 00:40 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#10

AW: EllipsisCharacter funktioniert nicht

  Alt 22. Feb 2017, 00:28
Gut erklärt Danke für die Mühe

Dem muss ich zustimmen

Delphi-Quellcode:
if (Graphics <> 0) then GdipDeleteGraphics(Graphics);
if (Fam <> nil) then GdipDeleteFontFamily(Fam);
if (TempFont <> nil) then GdipDeleteFont(TempFont);
Wobei das aber nicht zwingend voraussetzt das ich try..finally Blöcke verwenden muss.
Ich sehe auch nach deiner Erklärung keinen sinn dahinter da man alles auch ohne diese Blöcke erledigen kann.

Andererseits prüfe ich nie auf Nil..
Sondern auf bsp. if Assigned(Fam) then

Ob ich jetzt hier
if boundingBox.Width > Width then

mit begin.. end else oder mit try.. finally abarbeite ist gehüpft wie gesprungen.
Ich sehe keine Bereicherung bei dieser Verwendung.

Zitat:
Die Exception-Hilfsfunktion ist hierbei natürlich optional
Es ist Gewohnheit die Bedingungen direkt ohne Umwege zu prüfen. (Sehe da kein Manko in irgendeiner weise).

Wenn du mir einen triftigen Grund nennen kannst warum das Konstrukt so lebenswichtig ist lasse ich mich gerne überzeugen.
Ich sehe da aber so wie bei meinem Beispiel zur zeit keinen der mich dazu veranlassen könnte.
Das kann ich alles mit Bedingungen und der korrekten Freigabe von Objekten erledigen.. on the fly

gruss

Geändert von EWeiss (22. Feb 2017 um 00:50 Uhr)
  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 07:33 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