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/)
-   -   Delphi Problem mit VST Node Löschen nach Edit (https://www.delphipraxis.net/137723-problem-mit-vst-node-loeschen-nach-edit.html)

Assertor 27. Jul 2009 16:27


Problem mit VST Node Löschen nach Edit
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi DPler,

Ich nutze Inplace Editors (IVTEditLink) und habe nun ein Problem damit: Ich möchte einen neuen Node, wenn der Benutzer keine Daten eingegeben hat gleich wieder löschen.

Wo mache ich das am besten?

Delphi-Quellcode:
procedure TEditPropertyLink.DoCancelEdit;
var
  NodeData: PGridNodeData;
  Item: TBLItemSizesObject;
begin
  inherited;
  NodeData := FTree.GetNodeData(FNode);
  // delete added row if user has not entered any data
  if Assigned(NodeData) and (NodeData.FieldData.Name = '') then
  begin
    Item := NodeData.FieldData;
    FTree.DeleteNode(FNode, True);
    // Item.Delete; // remove Item from ObjectList
  end;
end;
Das Problem ist jetzt: Es klappt genau 1x: Benutzer klickt hinzufügen, drückt ESC - alles ok soweit. Benutzer klickt nun erneut hinzufügen: AV, ListIndex Fehler (hier wird versucht bei der OL auf den Index 605800x zuzugreifen - obwohl es nur 4 Elemente gibt), EOutOfMemory - je nach Wahl und Ansatz.

Code zum Hinzufügen:
Delphi-Quellcode:
procedure TfrmEditItemSizes.actAddExecute(Sender: TObject);
var
  Idx: Integer;
  Node: PVirtualNode;
  NodeData: PGridNodeData;
begin
  Idx := FItemSizes.Add;
  Node := vstList.AddChild(nil);
  vstList.ValidateNode(Node, False);
  NodeData := vstList.GetNodeData(Node);
  if Assigned(NodeData) then
  begin
    NodeData.FieldData := FItemSizes[Idx];
    vstList.EditNode(Node, 0);
  end;
end;
Der Record ist so definiert:
Delphi-Quellcode:
type
  TGridNodeData = record
    FieldData: TBLItemSizesObject;
  end;
  PGridNodeData = ^TGridNodeData;
Node wird in InitNode zugewiesen:
Delphi-Quellcode:
procedure TfrmEditItemSizes.vstListInitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  NodeData: PGridNodeData;
begin
  NodeData := Sender.GetNodeData(Node);
  NodeData.FieldData := FItemSizes[Node.Index];
end;
Ich habe schon überlegt, die Nodes besser in vst.OnEditCancelled zu löschen.

Gesucht habe ich schon sehr lange, hier und in Google ;) Aber eine gute Beschreibung zum IVTEditLink finde ich nicht, ich habe mich an die interne Implementation vom TVTEdit und StringEditor gehalten.

Hat jemand eine Idee?

Edit: Ganz vergessen, setzte FastMM4 im FullDebugMode ein, alle Checks manuell eingeschaltet und ScanMemoryPoolForCorruption ist auch an. Der Stacktracke im Debugger ist für mich aber nicht nachvollziehbar an dieser Stelle:

Gruß Assertor

Stacktrace:
Zitat:

:7795fbae kernel32.RaiseException + 0x58
FastMM4.RaiseMemoryCorruptionError
FastMM4.InternalScanSmallBlockPool($40C926,4294967 295,0)
FastMM4.InternalScanMemoryPool(4294967295,0)
FastMM4.ScanMemoryPoolForCorruptions
FastMM4.DebugGetMem(72)
System.@GetMem(???)
System.@NewUnicodeString(???)
:0040331E __linkproc__ __linkproc__ GetMem(Size=????)
Classes.TList.Get(???)
Contnrs.TObjectList.GetItem(???)
DataModuleBLBase.TBaseBLObjectList.GetItem(6050168 )
DataModuleBLItemSizes.TBLItemSizesObjectList.GetIt em(6050168)
FormEditItemSizes.TfrmEditItemSizes.vstListInitNod e($7EA08960,$5C546C,$7E9FA6C0,[])
VirtualTrees.TBaseVirtualTree.DoInitNode($5C546C,$ 7E9FA6C0,[])
VirtualTrees.TBaseVirtualTree.InitNode($7E9FA6C0)
VirtualTrees.TBaseVirtualTree.GetDisplayRect($7E9F A6C0,-1,False,False,False)
VirtualTrees.TBaseVirtualTree.InvalidateNode($7E9F A6C0)
VirtualTrees.TCustomVirtualStringTree.InvalidateNo de($7E9FA6C0)
VirtualTrees.TBaseVirtualTree.DoFocusNode($7E9FA78 0,True)
VirtualTrees.TBaseVirtualTree.SetFocusedNode($7E9F A780)
VirtualTrees.TBaseVirtualTree.EditNode($7E9FA780,0 )
FormEditItemSizes.TfrmEditItemSizes.actAddExecute( $7FF5A330)
Classes.TBasicAction.Execute
ActnList.TContainedAction.Execute
ActnList.TCustomAction.Execute
Classes.TBasicActionLink.Execute(???)
Controls.TControl.Click
StdCtrls.TCustomButton.Click
StdCtrls.TCustomButton.CNCommand(???)
Controls.TControl.WndProc(???)
Controls.TWinControl.WndProc((48401, 1304, 2753816, 0, 1304, 0, 1304, 42, 0, 0))
StdCtrls.TButtonControl.WndProc(???)
Controls.TControl.Perform(???,???,2753816)
Controls.DoControlMsg(???,(no value))
Controls.TWinControl.WMCommand((273, 1304, 0, 2753816, 0))
Forms.TCustomForm.WMCommand(???)
Controls.TControl.WndProc(???)
Controls.TWinControl.WndProc((273, 1304, 2753816, 0, 1304, 0, 1304, 42, 0, 0))
Forms.TCustomForm.WndProc(???)
Controls.TWinControl.MainWndProc(???)
Classes.StdWndProc(2232188,273,1304,2753816)
:7786fd72 ; C:\Windows\system32\USER32.dll
:7786fe4a ; C:\Windows\system32\USER32.dll
:77870943 ; C:\Windows\system32\USER32.dll
:77870b36 USER32.SendMessageW + 0x49
:7511b4b2 ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6002.18005_none_5cb7 2f96088b0de0\comctl32.dll
:7511b514 ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6002.18005_none_5cb7 2f96088b0de0\comctl32.dll
:7511b61f ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6002.18005_none_5cb7 2f96088b0de0\comctl32.dll
:7786fd72 ; C:\Windows\system32\USER32.dll
:7786fe4a ; C:\Windows\system32\USER32.dll
:778709d3 USER32.CallWindowProcW + 0x75
:77870979 USER32.CallWindowProcW + 0x1b
Controls.TWinControl.DefaultHandler(???)
:0046DD44 __linkproc__ TWinControl::DefaultHandler(Self=????, Message=????)
:0046DC48 __linkproc__ TWinControl::WndProc(Self=:7FE8E4D0, Message=:0012F9D4)
:0044F515 __linkproc__ TButtonControl::WndProc(Self=????, Message=????)
:00436046 __linkproc__ StdWndProc(Window=2753816, Message=514, WParam=0, LParam=655394)
:7786fd72 ; C:\Windows\system32\USER32.dll
:7786fe4a ; C:\Windows\system32\USER32.dll
:7787018d ; C:\Windows\system32\USER32.dll
:7787022b USER32.DispatchMessageW + 0xf
:0048B436 __linkproc__ TApplication::ProcessMessage(Self=????, Msg=????)

semo 27. Jul 2009 20:29

Re: Problem mit VST Node Löschen nach Edit
 
Ich habe eben versucht dein Problem nachzuvollziehen:
Ich habe einen VirtualStringTree und einen Button auf eine leere Form in einem neuen Projekt platziert.
Dazu habe ich die Eigenschaft MiscOptions --> toEditable des Trees auf True gesetzt.
Events siehe unten.
Im OnEditCancelled funktioniert es wunderbar...

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  VirtualStringTree1.RootNodeCount := 1;
end;

procedure TForm1.VirtualStringTree1EditCancelled(Sender: TBaseVirtualTree; Column: TColumnIndex);
begin
  VirtualStringTree1.DeleteNode(VirtualStringTree1.RootNode.FirstChild, True);
end;
Versuch mal in kleinen Einzelschritten deinen Code an diesen BeispielCode anzupassen.
Scheinbar hast du da einen kleinen Bug hinsichtlich des Indexes drin?!

Assertor 27. Jul 2009 20:36

Re: Problem mit VST Node Löschen nach Edit
 
Hallo Marus,

danke für Deine Antwort!

Zitat:

Zitat von M. Hassmann
Im OnEditCancelled funktioniert es wunderbar...

Versuch mal in kleinen Einzelschritten deinen Code an diesen BeispielCode anzupassen.
Scheinbar hast du da einen kleinen Bug hinsichtlich des Indexes drin?!

Naja, die Frage ist nicht, ob das Löschen an sich geht - das einfache Löschen funktioniert. Die Frage ist vielmehr: Wie lösche ich innerhalb eines IVTEditLink Property Editors. Aus Gefühl würde ich inzwischen sagen: Das geht nicht, denn der Node wird bis der Editor freigegeben ist benötigt.

Ich werde mal jetzt ein Testprojekt erstellen, welches das Problem verdeutlich. Unter Umständen, sehe ich damit schon klarer ;) Ich werde auf jeden Fall hier nochmal posten.

Gruß Assertor

madas 28. Jul 2009 06:55

Re: Problem mit VST Node Löschen nach Edit
 
Vielleicht ist es ja auch sinnvoller den leeren Node an einer anderen Stelle wieder zu entfernen.

z.B. im OnExit oder OnFocusChanged des VST

So hat der Benutzer immer noch die Chance in den leeren Node was einzugeben und muss nicht erneut auf den Add Button drücken.

Assertor 28. Jul 2009 13:08

Re: Problem mit VST Node Löschen nach Edit
 
Hi,

Zitat:

Zitat von madas
Vielleicht ist es ja auch sinnvoller den leeren Node an einer anderen Stelle wieder zu entfernen.

Richtig. Ich habe jetzt ein Testprojekt erstellt, wenn ein Node innerhalb des Property Editors gelöscht wird, kommt es zu diesem merkwürdigen Verhalten. Der nächste Zugriff innerhalb des Source von VirtualTrees.pas knallt dann - aber leider etwas verzögert.

Lösche ich außerhalb, also z.B. per PostMessage() im IVTEditLink an das Form und dann innerhalb des Forms, geht es :)

Somit stelle ich das mal auf gelöst.

Danke für die Hilfe!

Gruß Assertor


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