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 Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist (https://www.delphipraxis.net/190344-feststellen-ob-virtualtreeview-gerade-im-drag-mode-ist.html)

Codehunter 26. Sep 2016 08:21

Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Moin!

Hat der VST eine eingebaute Möglichkeit um festzustellen ob er gerade "eins übergezogen" bekommt? ;-) Hintergrund ist folgender: Ich möchte eine Möglichkeit schaffen, dass der Anwender die Nodes innerhalb des VST neu anordnen kann per Drag&Drop. Die Methodik dazu ist mir soweit klar. Allerdings benutze ich auch das Event VST.OnNodeClick, welches fälschlicherweise auch ausgelöst wird wenn man gerade einen Node "herumschubst" und über einem anderen Node loslässt. Heißt also, ich müsste in OnNodeClick abfragen ob gerade was "gedragt" wird oder nicht. Im Zweifel mache ich das über eine globale Boolean, aber eleganter wäre es über eine abfragbare Property.

Grüße
Cody

Aviator 26. Sep 2016 08:39

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Hi Codehunter,

schau dir mal die VirtualTreeView.TreeStates an. Da sollte dabei sein was du suchst. Unten mal ein Auszug. Das sollte eigentlich schon alles sein.

Delphi-Quellcode:
    tsVCLDragging,           // VCL drag'n drop in progress.
    tsVCLDragPending,        // One-shot flag to avoid clearing the current selection on implicit mouse up for VCL drag.
    tsVCLDragFinished,       // Flag to avoid triggering the OnColumnClick event twice
    tsOLEDragging,           // OLE dragging in progress.
    tsOLEDragPending,        // User has requested to start delayed dragging.

Codehunter 26. Sep 2016 08:58

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Hmmm jaaaa, prinzipiell wäre das die Lösung gewesen. Nur dummerweise scheint es so zu sein, dass OnNodeClick erst ausgelöst wird nachdem die Drag-Aktion schon abgearbeitet und tsDragXXX aus TreeStates entfernt wurde.

Das scheint allgemein ein Bug im VST zu sein. Denn ein NodeClick ist nach meiner Definition einmal LButtonDown und einmal LButtonUp auf dem selben Node, nicht auf zwei verschiedenen Nodes.

Das macht es aber auch mit einer globalen Boolean nicht einfacher weil OnDragDrop vor OnNodeClick gefeuert wird. So ein Shitkram :-(

Aviator 26. Sep 2016 09:01

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Müsste mir das jetzt auch genauer anschauen. Die Frage ist, was willst du damit bezwecken? Worum geht es dir? Ich musste die TreeStates bisher noch nie selbst auswerten.

Vielleicht ist dein Ansatz noch nicht ganz richtig und man könnte das viel einfacher lösen.

Die andere Frage wäre, ob du nicht mit OnMouseDown und OnMouseUp arbeiten könntest?!

Stevie 26. Sep 2016 09:03

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Einfach die fokussierte (gedraggte) Node mit HitInfo.HitNode vergleichen und noch ggf HitInfo.HitPositions abchecken.
Ist es dieselbe dann wars nen Klick, ansonsten hast du die Node woanders hingezogen und fallen gelassen.

Die genauen Überprüfungen kannst du auch im TBaseVirtualTree.HandleMouseUp sehen, ziemlich am Ende unter dem Kommentar: // Is the mouse still over the same node?

Codehunter 26. Sep 2016 09:15

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Zitat:

Zitat von Aviator (Beitrag 1348823)
Die andere Frage wäre, ob du nicht mit OnMouseDown und OnMouseUp arbeiten könntest?!

Es führen immer mehrere Wege nach Rom... OnMouseXX geht auch, hat aber den Nachteil dass man sich immer erst per GetNodeAt und Client-Screen-Koordinatenumrechnung den Zielnode holen muss. Da ist OnNodeClick manchmal komfortabler, manchmal aber auch kontraproduktiv.
Zitat:

Zitat von Stevie (Beitrag 1348824)
Einfach die fokussierte (gedraggte) Node mit HitInfo.HitNode vergleichen und noch ggf HitInfo.HitPositions abchecken.
Ist es dieselbe dann wars nen Klick, ansonsten hast du die Node woanders hingezogen und fallen gelassen.

Jupp, das scheint zu funktionieren. Scheint so als hättest du das Problem auch schon mal gehabt, ansonsten kommt man ja so schnell nicht darauf oder? ^^

Stevie 26. Sep 2016 09:20

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Zitat:

Zitat von Codehunter (Beitrag 1348827)
Scheint so als hättest du das Problem auch schon mal gehabt, ansonsten kommt man ja so schnell nicht darauf oder? ^^

Nicht genau dieses aber ich hab schon das eine oder andere mit dem Virtual Treeview gemacht ;)

Codehunter 26. Sep 2016 09:56

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Zitat:

Zitat von Stevie (Beitrag 1348828)
Nicht genau dieses aber ich hab schon das eine oder andere mit dem Virtual Treeview gemacht ;)

Ich ja eigentlich auch. Allerdings ist es bei dem Featuremonster nicht ganz einfach den Überblick zu behalten ^^

Aviator 26. Sep 2016 10:10

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Zitat:

Zitat von Codehunter (Beitrag 1348829)
Zitat:

Zitat von Stevie (Beitrag 1348828)
Nicht genau dieses aber ich hab schon das eine oder andere mit dem Virtual Treeview gemacht ;)

Ich ja eigentlich auch. Allerdings ist es bei dem Featuremonster nicht ganz einfach den Überblick zu behalten ^^

Er ist schon sehr umfangreich, dass ist richtig. Aber wenn man sich mehrere Jahre mit der Komponente und deren SourceCode beschäftigt hat, dann ist sie eigentlich wie jede andere Komponente auch. Nur eben sehr viel umfangreicher.

Die Komponente ist auch eigentlich DER Grund wieso ich nicht schonmal mit FMX gearbeitet habe. Würde mich brennend interessieren, aber ich will den VST nicht loslassen weil nahezu alle meine Anwendung daraus bestehen bzw. mindestens einen benutzen.

ConnorMcLeod 27. Sep 2016 17:17

AW: Feststellen ob VirtualTreeView gerade im "Drag-Mode" ist
 
Zitat:

Zitat von Codehunter (Beitrag 1348818)
eine Möglichkeit schaffen, dass der Anwender die Nodes innerhalb des VST neu anordnen kann per Drag&Drop.

Ich hab das mal gemacht mithilfe der Beispiele, die im Internet im Umlauf sind.
Das waren damals zwei VSTs, die beide diese Methoden zugewiesen bekamen. Wenn von einem zum anderen gedraggt wurde, dann wurde der Node von einem Tree zum anderen kopiert; wenn innerhalb eines Trees gezogen wurde, dann dorthin verschoben.
Hoffe, das hilft.
PTreeNodeData ist ein Pointer auf eine eigene Struktur und für das Beispiel nicht wichtig.

Delphi-Quellcode:
procedure TfrmFavMan.FormCreate(Sender: TObject);
begin
  trvSources.DragMode   := dmAutomatic;
  trvSources.OnDragOver := Tree1DragOver;
  trvSources.OnDragDrop := Tree1DragDrop;

  trvFavs.DragMode      := dmAutomatic;
  trvFavs.OnDragOver    := Tree1DragOver;
  trvFavs.OnDragDrop    := Tree1DragDrop;
end;

procedure TfrmFavMan.Tree1DragOver(Sender: TBaseVirtualTree; Source: TObject;
  Shift: TShiftState; State: TDragState; Pt: TPoint; Mode: TDropMode;
  var Effect: Integer; var Accept: Boolean);
begin
  Accept := (Source is TVirtualStringTree);
end;

procedure TfrmFavMan.Tree1DragDrop(Sender: TBaseVirtualTree; Source: TObject;
  DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
  Pt: TPoint; var Effect: Integer; Mode: TDropMode);
var
  Attachmode   : TVTNodeAttachMode;
  Nodes        : TNodeArray;
  I            : Integer;
  DataOfSender : PTreeNodeData;
  DataOfSource : PTreeNodeData;
  DataOfParent : PTreeNodeData;
  NewNode      : PVirtualNode;
  DrpTargetNode : PVirtualNode;
begin
  if (nil = Sender.DropTargetNode) then exit;
  if (Sender.GetFirst = Sender.DropTargetNode) and (Mode <> dmOnNode) then exit;

  if Source = Sender then
  begin
    Effect := DROPEFFECT_MOVE
  end
  else
  begin
    Effect := DROPEFFECT_COPY;
  end;

  // Translate the drop position into an node attach mode.
  case Mode of
    dmAbove : AttachMode := amInsertBefore;
    dmOnNode: AttachMode := amAddChildLast;
    dmBelow : AttachMode := amInsertAfter;
    else     AttachMode := amNowhere;
  end;

  Nodes := TVirtualStringTree(Source).GetSortedSelection(True);

  if Effect = DROPEFFECT_COPY then
  begin
    DrpTargetNode := Sender.DropTargetNode;

    for I := 0 to High(Nodes) do
    begin
      NewNode     := TVirtualStringTree(Sender).AddChild(DrpTargetNode);
      DataOfSource := TVirtualStringTree(Source).GetNodeData(Nodes[I]);
      DataOfSender := TVirtualStringTree(Sender).GetNodeData(NewNode);
      if (nil <> DataOfSource) then
      begin
        if (nil <> DataOfSender) then
        begin
          // Datenabgleich machen
        end;
      end;
    end;
    TVirtualStringTree(Sender).FullExpand(DrpTargetNode);

  end
  else
  begin
    DataOfParent := TVirtualStringTree(Source).GetNodeData(Sender.DropTargetNode);
    for I := 0 to High(Nodes) do
    begin
      TVirtualStringTree(Source).MoveTo(Nodes[I], Sender.DropTargetNode, AttachMode, False);
      DataOfSource := TVirtualStringTree(Source).GetNodeData(Nodes[I]);
      // Datenabgleich machen
    end;
  end;
end;


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