Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   ListView+Pointer lässt Anwendung manchmal crashen (https://www.delphipraxis.net/95238-listview-pointer-laesst-anwendung-manchmal-crashen.html)

dp_user 3. Jul 2007 20:45


ListView+Pointer lässt Anwendung manchmal crashen
 
Guten Abend,
bin neu hier in der DP und weiss noch nicht genau, in welches Forum ich meine Anfrage posten soll, da sie irgendwie nirgends richtig reinpasst.

Mein Problem ist folgendes:
Ich möchte bei einem ListView im "Data" Feld verschiedene Werte Speichern, um später beim "CustomDrawItem" darauf zugreifen zu können.
Das ganze funktioniert auch soweit ganz gut, in bestimmten Fällen treten jedoch massenweise "AccessViolations" auf - dies passiert z.B. IMMER dann
wenn ich den Windows Taskmanager aufrufe und die Prozessliste nach CPU- oder Speicherauslastung neu sortiere während das ListView sich noch aufbaut.

Habe das so gelöst:


Delphi-Quellcode:
PListViewData = ^TListViewData;
 TListViewData = Record
    Eintrag1: boolean;
    Eintrag2: string;
end;

var
ListDataEntry: PListViewData;
Delphi-Quellcode:
procedure TForm1.Button5Click(Sender: TObject);
var
i:integer;
begin
New(ListDataEntry);
ListDataEntry.Eintrag1=true;

for i:=0 to 600 do begin
Listview1.Items.Insert(0);

[..]

Listview1.Items[0].Data:=ListDataEntry;
end;

end;

Delphi-Quellcode:

procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin


  with Sender do begin

ListDataEntry:=Item.Data;
if ListDataEntry.Eintrag1=true then Canvas.Font.Style:=[fsbold];

end;
end;

DP-Maintenance 4. Jul 2007 06:09

DP-Maintenance
 
Dieses Thema wurde von "Sharky" von "Klatsch und Tratsch" nach "VCL / WinForms / Controls" verschoben.
Ich verschiebe den Thread mal nach hier.

DelphiKlaus 4. Jul 2007 06:39

Re: ListView+Pointer lässt Anwendung manchmal crashen
 
Hallo,

kann es sein, dass Du zuerst alle 600 Einträge in der Listview erzeugst, aber erst in einer weiteren Schleife die Zuweisung an Data machst? Wenn Du dann den Taskmanager aufrufst, wird dann vielleicht durch Hin- und Herschieben von Fenstern ein Teil der Listview mit Einträgen, denen noch nichts zugewiesen ist, sichtbar? Dann wird dir DrawItem-Methode aufgerufen und grift ins Leere?

Ist mal so'ne Vermutung.

Klaus

marabu 4. Jul 2007 06:40

Re: ListView+Pointer lässt Anwendung manchmal crashen
 
Herzlich willkommen in der Delphi-PRAXiS, dp_user.

Ein Problem mit dem von dir gezeigten Code ist, dass du zwar 601 Items erzeugst, aber nur das erste Item hat einen gültigen Data-Pointer.

Delphi-Quellcode:
procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  ListDataEntry: PListViewData;
begin
  with Sender do
  begin
    ListDataEntry := Item.Data;
    if Assigned(ListDataEntry) and ListDataEntry.Eintrag1 
      then Canvas.Font.Style := [fsbold]
      else { ... };
    // ...
  end;
end;
Außerdem ist es besser, wenn du den typisierten Zeiger ListDataEntry lokal deklarierst. Und die Abfrage einer Variablen des Typs Boolean auf True ist bestenfalls ungeschickt - die Variable selbst ist schon ein perfekter "logischer Ausdruck".

Freundliche Grüße vom marabu

oki 4. Jul 2007 07:14

Re: ListView+Pointer lässt Anwendung manchmal crashen
 
Auch von mir herzlich willkommen :dp:

so wie Marabu es schon gesagt hatte muß die Instanziierung deines Pointers in die Schleife.
Delphi-Quellcode:
procedure TForm1.Button5Click(Sender: TObject);
var i:integer;
begin
  for i:=0 to 600 do begin
    New(ListDataEntry);
    ListDataEntry.Eintrag1=true;
    Listview1.Items.Insert(0);

    [..]

    Listview1.Items[0].Data:=ListDataEntry;
  end;

end;
Mit der Prüfung, wie sie marabu angeboten hat bin ich mir aber nicht ganz sicher. bricht der Compiler nach der Prüfung mit Assign auf nil in der Abarbeitung ab, so dass die Prüfung auf and ListDataEntry.Eintrag1 nicht mehr ausgeführt wird, so ist alles o.k.
Da ich mir an der Stelle immer nicht ganz sicher bin mache ich es so:
Delphi-Quellcode:
procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  ListDataEntry: PListViewData;
begin
  with Sender do
  begin
    ListDataEntry := Item.Data;
    if Assigned(ListDataEntry) then
      if ListDataEntry.Eintrag1 then
        Canvas.Font.Style := [fsbold]
      else { ... };
    // ...
  end;
end;
gruß oki

[edit:oki] Formatierung korrigiert. [/edit]


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