![]() |
GDI-Handles Leck
Ich habe in einer Progress-Bar-Komponente folgenden Code zum anzeigen des Fortschritts als Text innerhalb der Komponente:
Delphi-Quellcode:
Da ich mit Hilfe des Process Explorers festgestellt habe, dass die Anzahl der GDI-Handles während der Benutzung dieser Komponente steigt, sobald sich der Text ändert, habe ich folgende Theorie:
procedure TIrgendEineKomponente.PaintText(PaintRect: TRect; Canv: TCanvas);
var Ima2 : TBitmap; s : string; X : Integer; Y : Integer; diffx : Integer; t: string; begin if fShowText then begin Ima2 := TBitmap.Create; Ima2.Width := Width; Ima2.Height := Height; diffx := 0; with Ima2.Canvas do begin CopyMode := cmBlackness; CopyRect(Rect(0, 0, Width, Height), Ima2.Canvas, Rect(0, 0, Width, Height)); CopyMode := cmSrcCopy; end; with Ima2.Canvas do begin Font := Self.Font; Brush.Style := bsClear; Font.Color := clWhite; case fTextKind of mrgsPercent: s := Format('%0.*f%%', [FNachkommstellen, FPercentage]); mrgsXofY: s := Format('%0.0n / %0.0n', [1.0 * FPosition, 1.0 * FMaxWert]); mrgsValueOnly: s := Format('%0.0n', [1.0 * FPosition]); mrgsOwnText: begin if (not (csDesigning in ComponentState)) then begin if Assigned(FOnOwnText) then s := FOnOwnText(Self); end; end; end; // case if fTextKind <> mrgsXofY then begin with PaintRect do begin X := (Right - Left + 1) div 2 - TextWidth(S) div 2; Y := (Bottom - Top + 1 - TextHeight(S)) div 2; end; // with end else begin with PaintRect do begin X := (Right - Left + 1) div 2 - TextWidth(' / ') div 2; X := X - TextWidth(Format('%0.0n', [1.0 * FPosition])); Y := (Bottom - Top + 1 - TextHeight(S)) div 2; end; end; TextRect(PaintRect, X, Y, s); end; // with Ima2.Canvas Canv.CopyMode := cmSrcInvert; Canv.Draw(0, 0, Ima2); FreeAndNil(Ima2); end; end; Im Code wird ja mit der Zeile
Delphi-Quellcode:
ein TBitmap erzeugt (steigt da die Anzahl der GDI-Handles?) und mit
Ima2 := TBitmap.Create;
Delphi-Quellcode:
wieder zerstört.
FreeAndNil(Ima2);
Was aber, wenn FreeAndNil nicht so funktioniert, wie es sollte, d.h. Ima2 NICHT zerstört wird? Dann würde ja das GDI-Handle nicht geschlossen werden, oder? Oder würde das automatisch mit dem beenden der Methode passieren? |
Re: GDI-Handles Leck
Warum sollte es nicht funktionieren? Ich würde das für sehr unwahrscheinlich halten. Meiner Meinung nach ist der Fehler an einer anderen Stelle zu suchen.
|
Re: GDI-Handles Leck
Ja, das liegt mer oder weniger an Windows.
Erstelle das Bitmap im Create deiner Komponente und gib sie im Destroy frei. Dru wrist sehen dass das Problem eingrenzt. |
Re: GDI-Handles Leck
Jetzt bin ich noch verwirrter.
Auf meinem Entwicklungsrechner (Vista Ultimate, 32bit, 2GB RAM) ändert sich die Anzahl der GDI-Handles für den Prozess nicht. Auf 3 Windows XP-Professional Rechnern (2 haben 1GB, einer 3GB RAM) steigt die Anzahl unaufhaltsam (und ich habe die selbe EXE-Datei verwendet). :gruebel: |
Re: GDI-Handles Leck
:wall:
Ich habe den QuellCode meines Programmes nun komplett zerlegt und habe das Problem endlich aufdecken können. Um prüfen zu können ob ein Text von der Breite her komplett in in ein TLabel passt, hole ich mir mit GetDC einen Handle auf das Label. Mit dem Handle kann ich nun ein TCanvas "misbrauchen" um die Breite mit Canvas.TextWidth zu bestimmen. Dummerweise habe vergessen, das Handle mit ReleaseDC wieder frei zu geben => irgendwann gehen die Resourcen zu ende. Warum ich aber keine Probleme unter Windows Vista habe und unter XP schon: :gruebel: |
Re: GDI-Handles Leck
Vista braucht von sich aus schon genug Resourcen ... vielleicht haben die ja einfach einige Grenzen entsprechend angehoben :roll:
Bei TLabel mit Autosize, könnte man notfalls auch nach dem Zuweisen einfach Width auslesen. (kommt aber darauf an, was man erreichen will und wie "schön" es werden soll) |
Re: GDI-Handles Leck
Zitat:
|
Re: GDI-Handles Leck
in D2009 kann man für Dateinamen follgende Einstellungen verwenden (kA. seit wann es das gibt)
.ShowAccelChar = False .EllipsisPosition = epPathEllipsis Ansonsten könnte man (glaub ich) auch TStaticText statt TLabel nutzen und das gleiche Verhalten über die WinAPI steuern (TStaticText nutzt doch das STATIC-Control von Windows :gruebel:) lassen (müßte dann aber mal schaun wie man das dem STATIC sagte, das es so kürzen soll) |
Re: GDI-Handles Leck
Evtl. bringt MinimizeName aus FileCtrl ja auch etwas.
|
Re: GDI-Handles Leck
Zitat:
Und selbst, wenn ich nur Pfade kürzen lassen wollte wäre MinimizeName nichts für mich. MinimizeName macht ja folgendes:
Delphi-Quellcode:
Ich möchte den Text so kürzen:
const
sPath = 'c:\Pfad\zur\meiner\Super-tollen\Applikation\VollKrass.exe'; ShowMessage(MinimizeName(sPath, Form1.Canvas, 200)); //results in a message: 'c:\...\VollKrass.exe'
Delphi-Quellcode:
Sollte es bereits so eine Funktion geben: Ich schau sie mir gerne an :)
const
sPath = 'c:\Pfad\zur\meiner\Super-tollen\Applikation\VollKrass.exe'; ShowMessage(MeinEigenesKuerzen(sPath, Form1.Canvas, 200)); //results in a message: '...r-tollen\Applikation\VollKrass.exe' |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:11 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