![]() |
Nachricht NACH dem Löschen eines ListView.Item erhalten?
Hallo! Ich möchte eine Nachricht von einem Listview erhalten, NACHDEM ein Item aus der Listview gelöscht wurde. Ich habe folgenden Code probiert:
Delphi-Quellcode:
Es sollte die Anzahl der Items NACH dem Löschen angezeigt werden. Mit dem obigen Code wird aber die Anzahl der Items VOR dem Löschen des Items angezeigt!
private
{ Private-Deklarationen } OriginalListViewWindowProc: TWndMethod; procedure ListViewWindowProcEx(var Message: TMessage); procedure TForm1.FormCreate(Sender: TObject); begin OriginalListViewWindowProc := MyListView1.WindowProc; MyListView1.WindowProc := ListViewWindowProcEx; end; procedure TForm1.ListViewWindowProcEx(var Message: TMessage); begin if Message.Msg = CN_NOTIFY then begin if PNMHdr(Message.LParam)^.Code = LVN_DELETEITEM then begin // Funktioniert nicht, da das Item gelöscht wird, // NACHDEM die Nachricht gesendet wurde: Self.Caption := IntToStr(MyListView1.Items.Count); end; end; OriginalListViewWindowProc(Message); end; Wie kann man also eine Nachricht NACH dem Löschen eines Items erhalten? |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Delphi-Quellcode:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls,CommCtrl, StdCtrls; type TListView=Class(comCtrls.TListView) procedure CNNotify(var Message: TWMNotifyLV); message CN_NOTIFY; End; TForm2 = class(TForm) ListView1: TListView; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form2: TForm2; implementation {$R *.dfm} { TListView } procedure TListView.CNNotify(var Message: TWMNotifyLV); begin inherited; if Message.NMHdr.code=LVN_DELETEITEM then if Message.Result=1 then Showmessage('Deleted'); end; |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Hallo Bummi, vielen Dank für den Code. Aber leider ist das Problem damit nicht gelöst: Die Anzahl der Items ist beim Erhalt der Nachricht gleich groß wie vorher. Sie müsste aber um die Zahl des gelöschten Items vermindert sein, in dieser Reihenfolge:
1. Anzahl der Items vorher ist n 2. 1 Item wird gelöscht 3. Nachricht sagt, Anzahl der Items ist nun n - 1 Es müsste also eine Nachricht sein, die NACH dem Löschen des Items die verminderte Zahl der Items zurückgibt. Oder, wenn mehrere Items auf einmal gelöscht werden: 1. Anzahl der Items vorher ist n 2. x Items werden gelöscht 3. Nachricht sagt, Anzahl der Items ist nun n - x |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Mache dir doch ein eigenes Event was dir nach dem Löschen Befehl den neuen Count liefert. Was ist mit OnChange, OnDeletion des Listviews. Nach jedem Ändern bzw. Löschen wird es ausgelöst. Kannst du damit was anfangen ?
Irgendwie habe ich den Eindruck daß zu kompliziert gedacht wird. :gruebel: ... oder ich habe die Anforderung nicht richtig verstanden. |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Wenn du die Anzahl der Items nach dem Löschen ausgeben möchtest, dann ist OnChange genau das Event, was du suchst. Dieses Ereignis wird nach jeder Änderung am ListView aufgerufen.
Du kannst also auch Items hinzufügen, alle Items auf einmal löschen, whatever, das Event wird anschließend abgefeuert. |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
1. Nimm einfach eine "richtige" Komponente, nämlich z.B. die TVirtualStringTree:
![]() Dort gibt es das Event OnFreeNode, in dem die Anzahl bereits die neue ist:
Delphi-Quellcode:
Außerdem ist die Komponente auch deutlich schneller (und einfacher zu benutzen sobald man die GUI ordentlich von der Datenhaltung trennt).
procedure TForm236.VirtualStringTree1FreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin Caption := IntToStr(Sender.RootNode.ChildCount); end; 2. Da du an der Stelle weißt, dass das Item gelöscht werden wird, kannst du doch auch einfach eins von der Anzahl abziehen. |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Items.Count wird auch über eine Message abgerufen, zu einem Zeitpunkt zu dem das Messagehandling in dem Fall noch nicht abgeschlossen ist. "Ausbrechen" könnte man in der Art, zum weiterbasteln...
Delphi-Quellcode:
unit Unit2;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls,CommCtrl, StdCtrls; const WM_MyInfoMessage=WM_USER + 777; type TListView=Class(comCtrls.TListView) private FOnItemDeleted: TNotifyEvent; procedure CNNotify(var Message: TWMNotifyLV); message CN_NOTIFY; Procedure MyInfomessage(var Message: TWMNotify);message WM_MyInfoMessage; published Property OnItemDeleted:TNotifyEvent read FOnItemDeleted write FOnItemDeleted; End; TForm2 = class(TForm) ListView1: TListView; Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private procedure OnItemDel(sender: TObject); { Private-Deklarationen } public { Public-Deklarationen } end; var Form2: TForm2; implementation {$R *.dfm} { TListView } procedure TListView.CNNotify(var Message: TWMNotifyLV); begin inherited; if (Message.NMHdr.code = LVN_DELETEITEM) or (Message.NMHdr.code = LVN_DELETEALLITEMS ) then if Message.Result=1 then begin PostMessage(Handle,WM_MyInfoMessage,0,0); end; end; procedure TForm2.Button1Click(Sender: TObject); begin Showmessage('Before:'+IntToStr(ListView1.Items.Count)); ListView1.Items.Delete(0); end; procedure TForm2.FormCreate(Sender: TObject); begin ListView1.OnItemDeleted := OnItemDel; end; Procedure TForm2.OnItemDel(sender:TObject); begin Showmessage('After:' + IntToStr(TListView(Sender).Items.Count)); end; procedure TListView.MyInfomessage(var Message: TWMNotify); begin if Assigned(FOnItemDeleted) then FOnItemDeleted(Self); end; end. |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
Es ist mir aber noch nicht ganz klar, wieso. Du schickst beim Erhalt der LVN_DELETEITEM message einfach nochmals eine User-Message an das eigene Fenster. Wieso wird die dann erst NACH dem eigentlichen Delete-Ereignis verarbeitet, wenn die LVN_DELETEITEM Message noch VOR dem Delete gesendet wird? Hat das vielleicht etwas mit der Message-Warteschlange zu tun? |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Delphi-Quellcode:
hat mit der "Wartesschlange" zu tun , deshalb Postmessage statt SendMessage.
inherited; // hier ist schön gelöscht (Originalmessagehandling abgeschlossen), aber wir sind noch in der "Schlange"
if Message.NMHdr.code=LVN_DELETEITEM then if Message.Result=1 then // Result wird nach dem Löschen im inherited gesetzt BTW ich hatte es nochmals geändert, die Message wird jetzt innerhalb des LV verarbeitet, falls Du das ganze für eine Komponente brauchen solltest. |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Weil PostMessage wartet, bis die Nachricht verarbeitet wurde, und deshalb das das Delete-Ereignis dann schon abgearbeitet ist?
Du meinst, dass die User-Message nicht an das Fenster, sondern an die eigene ListView gesendet wird? VIELEN, VIELEN HERZLICHEN DANK!!! Ich spendiere dir hiermit ein frisches, kühles virtuelles Lager-Pils! |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
SendMessage wartet, Postmessage nicht, es wird einfach in die Schlange eingereiht...
habe nochmals etwas umgebaut .... |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
Wie löschst du denn sonst mehrere auf einmal? (Nebenbei kann der Benutzer selbst ohnehin nix löschen, sondern nur der Programmierer mit dem passenden Befehl, so dass der Zeitpunkt danach ohnehin feststeht und erreichbar ist...) |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Wie kann ein Anwender Einträge aus einer ListView löschen? Welche Tasten muss man da drücken?
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Leider bei Clear nicht hier wäre noch LVN_DELETEALLITEMS zu behandeln...
Delphi-Quellcode:
if (Message.NMHdr.code = LVN_DELETEITEM) or (Message.NMHdr.code = LVN_DELETEALLITEMS ) then
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
@Bummi: Wenn es nun aber mehrere Instanzen der so modifizierten TListView im Programm gibt: Wie könnte man erfahren, welche Instanz die Message gesendet hat? Wie würdest du diese Information so in PostMessage kodieren, dass sie in MyInfomessage wieder dekodiert werden kann? Und wie kann CNNotify erfahren, von welcher Instanz die Nachricht kommt?
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Ich hatte meinen Beitrag 2 mal geändert, in der letzen Version gibt es ein OnItemDeleted-Event, hier kannst Du über Sender gehen ....
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
Der Befehl kommt aus der Anwendung. Dort wird ja explizit das Löschen aufgerufen. Deshalb wird dafür eigentlich gar kein Event benötigt, da Events nur gebraucht werden, wenn der Programmierer etwas mitbekommen muss, von dem er sonst nicht mitbekommen würde, dass es passiert. Da die Aktion hier selbst per Quelltext gestartet wird, weiß man das aber schon. Deshalb ist die Logik schon etwas seltsam, aber letztlich schadet ein solches Event auch nicht. Es ist nur rein logisch überflüssig. Damit ist die Lösung, die du jetzt benutzt, schon ok, wenn auch nicht optimal. |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
|
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Darum geht es ja gerade gar nicht. Der Punkt ist, dass der Quelltext so aussieht:
Delphi-Quellcode:
Statt ganz einfach und simpel:
procedure A;
begin xy.DeleteItem; end; procedure OnDeleted; begin ShowMessage('Ha, gelöscht'); end;
Delphi-Quellcode:
Aber wenn es dir so lieber ist, ist das ja deine Sache. Genauso die Wahl der Komponente an sich. :wink:
procedure DeleteMyItem;
begin xy.DeleteItem; ShowMessage('Ha, gelöscht'); end; |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
Und ich verwende ja in meinem Code auch nicht TListView, sondern eine davon abgeleitete Klasse. Dass wir hier bei der Diskussion TListView nennen, ist ja nur eine Abstraktion. |
AW: Nachricht NACH dem Löschen eines ListView.Item erhalten?
Zitat:
Der ListView-Container ist eine Abbildung/Darstellung einer Liste. Du führst die Löschoperationen jedoch auf der Liste durch, und nicht auf der ListView selbst. Ich würde also der Liste (also der Datenstruktur) das Event "OnDeleted" bzw. "OnItemCountChanged" spendieren bzw. dort ansetzen. Grundsätzlich ist deine Vorgehensweise aber ok, denn in deiner Sichtweise wird die ListView verändert und soll immer und überall eine verbindliche und korrekte Aussage über die in ihr gespeicherten Daten geben können (hier: Anzahl), und zwar irgendwann auch, wenn die Löschoperation abgeschlossen ist. Derart (korrekt) mitteilsam ist die LV leider nicht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:39 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