![]() |
EllipsisCharacter funktioniert nicht
Mein Code
Delphi-Quellcode:
Wenn ich nun die Column in meiner Anwendung verschiebe so das sie über den zu langen Text steht
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 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 |
AW: EllipsisCharacter funktioniert nicht
Hallo,
was ist denn das für eine Komponente, die das property Column besitzt? |
AW: EllipsisCharacter funktioniert nicht
Zitat:
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 |
AW: EllipsisCharacter funktioniert nicht
Thema hat sich erledigt funktioniert nun.
Es war nicht die API selbst sondern die Zuweisung eines nicht Korrekten Rect.
Delphi-Quellcode:
coole Musik. Oder? LOL
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; gruss |
AW: EllipsisCharacter funktioniert nicht
BTW: schon mal try finally end in Erwägung gezogen?
|
AW: EllipsisCharacter funktioniert nicht
Zitat:
Brauch ich nicht. Uninteressant, Müllt meinen Code zu.
Delphi-Quellcode:
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 |
AW: EllipsisCharacter funktioniert nicht
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:
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?
if GdipCreateFromHDC(DC, Graphics) = Ok then
if Assigned(Fam) then if Assigned(TempFont) then if boundingBox.Width > Width then end else ...; end; end; end; 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. |
AW: EllipsisCharacter funktioniert nicht
Zitat:
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 |
AW: EllipsisCharacter funktioniert nicht
Zitat:
Delphi-Quellcode:
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
var
A: TObject; begin A := TObject.Create; try finally A.Free; end; end ![]() 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. Zitat:
Zitat:
![]() ![]()
Delphi-Quellcode:
bzw.
Graphics
Delphi-Quellcode:
ungültig. Mag sein, dass die GDI+ hier gnädig ist, aber andere APIs z.b.
TempFont
![]() Worauf Luckie allerdings (vermutlich) hinauswollte, ist die tiefe Verschachtelung und die redundante Finalisierung im
Delphi-Quellcode:
Block. Beides kannst du nämlich mit try..finally sehr elegant vermeiden:
if boundingBox.Width > Width then
Delphi-Quellcode:
Die Exception-Hilfsfunktion ist hierbei natürlich optional und kann auch durch ein
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;
Delphi-Quellcode:
ersetzt werden, da nach dem
if (GdipCreateFromHDC(DC, Graphics) <> Ok) then Exit
Delphi-Quellcode:
ebenfalls in jedem Falle der Finally-Block ausgeführt wird.
Exit
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:
Variante 2 (mit Exit/goto):
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;
Delphi-Quellcode:
Dahingegen die Variante mit try..finally:
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;
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; |
AW: EllipsisCharacter funktioniert nicht
Gut erklärt ;) Danke für die Mühe
Dem muss ich zustimmen
Delphi-Quellcode:
Wobei das aber nicht zwingend voraussetzt das ich try..finally Blöcke verwenden muss.
if (Graphics <> 0) then GdipDeleteGraphics(Graphics);
if (Fam <> nil) then GdipDeleteFontFamily(Fam); if (TempFont <> nil) then GdipDeleteFont(TempFont); 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.
Delphi-Quellcode:
if Assigned(Fam) then
Ob ich jetzt hier
Delphi-Quellcode:
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:
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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:06 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