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 Virtual Treeview und Drag'n'Drop (https://www.delphipraxis.net/105518-virtual-treeview-und-dragndrop.html)

Prototypjack 23. Dez 2007 14:13


Virtual Treeview und Drag'n'Drop
 
Moin,

So, nachdem ich jetzt schon einige Stunden an diesem Problem hänge, dachte ich mir, ich frage hier mal nach:

Ich habe in einem Projekt von mir zwei Virtual Treeviews (Eines links, das andere rechts). Die fertige Funktion der beiden sollte dann so aussehen: Die Items im rechten vst sollen per Drag'n'Drop verschoben werden(funktioniert bereits) und man soll Items aus dem Linken dem Rechten hinzufügen können(das Linke soll nichts können, außer diese Nodes wegzuschicken, um das Rechte weiter zu füllen).

Wie bereits gesagt, habe ich bereits 50% fertig. Denn alle Move-Operationen funktionieren perfekt. Nur wenn es dann an's Kopieren geht, habe ich einfach keine Ahnung wie ich an die Daten komme, um sie im neuen Node des rechten Vsts einzufügen.
(Achja, ich arbeite mit der OLE-Drag-Version. Sollte die VCL-Drag-Version für meine Zwecke besser geeignet sein, so lasst es mich bitte wissen!).

Hier mal was ich schon habe:
Delphi-Quellcode:
procedure TFrmSmartBarDlg.InsertData(Sender: TVirtualStringTree; DataObject:
  IDataObject; Formats: TFormatArray; Effect: Integer; Mode: TVTNodeAttachMode);
var
  FormatAccepted: Boolean;
  I: Integer;
begin
  FormatAccepted := False;
  for I := 0 to High(Formats) do
  begin
    if Formats[I] = CF_VIRTUALTREE then
    begin
      if not FormatAccepted then
      begin
        Sender.ProcessDrop(DataObject, Sender.DropTargetNode, Effect, Mode);
        FormatAccepted := True;
      end;
    end;
  end;
end;

procedure TFrmSmartBarDlg.vstRightDragDrop(Sender: TBaseVirtualTree;
  Source: TObject; DataObject: IDataObject; Formats: TFormatArray;
  Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode);

  procedure DetermineEffect;
  begin
    // Set Effect accordingly.
    if Source = Sender then
    begin
      Effect := DROPEFFECT_MOVE;
    end
    else
    begin
      Effect := DROPEFFECT_COPY;
    end;
  end;

var
  Attachmode: TVTNodeAttachMode;
  Nodes: TNodeArray;
begin
  Nodes := nil;
  // Translate the drop position into an node attach mode.
  case Mode of
    dmAbove:
      AttachMode := amInsertBefore;
    dmOnNode:
      AttachMode := amInsertAfter;
    dmBelow:
      AttachMode := amInsertAfter;
  else
    AttachMode := amNowhere;
  end;

  if DataObject <> nil then
  begin
    // OLE drag'n drop. Perform full processing.


    // Determine action in advance even if we don't use the dropped data.
    // Note: The Effect parameter is a variable which must be set to the action we
    //       will actually take, to notify the sender of the drag operation about remaining actions.
    //       This value determines what the caller will do after the method returns,
    //       e.g. if DROPEFFECT_MOVE is returned then the source data will be deleted.
    DetermineEffect;
    InsertData(Sender as TVirtualStringTree, DataObject, Formats, Effect, AttachMode);
  end;
end;
Als Clipboard-Format ist Virtual Tree Data gewählt, der DragType ist, wie bereits gesagt dtOLE und der DragMode ist dmAutomatic.

Ich hoffe ihr könnt mir aus meiner Verzweiflung wieder hinaushelfen ;)

Edit: Achja, das Kopieren des Nodes an sich funktioniert ja, das heißt, ich habe dann ein komplett leeres Node, an der Stelle wo ich das gezogenen einfügen wollte. Das Problem, welches sich mir stellt ist einfach wie ich an die Daten komme(die in Form eines Records vorliegen) und jene dann weiterleite, bzw. dem neuen Node anhänge.

Edit2: Auch die Suche hier um Forum und bei Mike direkt gibt nur sehr wenig her. Und falls ich mal was zu dem Thema finde, ist es entweder genau das, was ich nicht brauche, oder einfach unbeantwortet. Ebenfalls ist die Demo für meine Zwecke unbrauchbar, denn diese kopiert nur die Captions an sich, da ich aber mehrere Daten speichere, brauche ich direkt den Zugriff auf den betreffenden Record.

Danke schonmal & Grüße,
Max

ManfredG 23. Dez 2007 14:48

Re: Virtual Treeview und Drag'n'Drop
 
hi max,
ich habe etwas ähnliches, verwende aber zum kopieren / verschieben im gleichen prog nicht OLE.

Folgendes prinzip:
im quellensteuerelement wird mit OnMouseDown festgehalten, wo die maustaste gedrückt wird.
gleichzeitig gehen die daten, die zu verschieben sind in einen record (als zwischenspeicher).
dann überprüfe ich in OnMouseMove, ob die maus bei gedrückter taste gezogen wird.
entfernt sich die maus um einen bestimmten betrag von der stelle, wo geklickt wurde, wird im record ein kennzeichen gesetzt, daß einen dragoperation im gange ist.

wird nun die maustaste im zweiten steuerelement losgelassen, so kann man dort erfahren, daß sie aus dem ersten steuerelement gezogen wurde. der punkt, an dem sie losgelassen wurde ist das ziel und dorthin werden die daten aus dem record übernommen.

das ganze funktioniert ohne alle drag&drop-methoden.
nur noch eine kleine ergänzung ist sinnvoll: ich setze einen HOOK für die maus, um von jeder stelle zu erfahren, ob die maus gehengelassen wurde. letzteres hat zur folge, daß im record das kennzeichen zurückgesetzt wird, durch das man erfährt, daß eine dragoperation im gange ist.

manfred

Prototypjack 23. Dez 2007 16:22

Re: Virtual Treeview und Drag'n'Drop
 
Zitat:

Zitat von ManfredG
hi max,
ich habe etwas ähnliches, verwende aber zum kopieren / verschieben im gleichen prog nicht OLE.

Folgendes prinzip:
im quellensteuerelement wird mit OnMouseDown festgehalten, wo die maustaste gedrückt wird.
gleichzeitig gehen die daten, die zu verschieben sind in einen record (als zwischenspeicher).
dann überprüfe ich in OnMouseMove, ob die maus bei gedrückter taste gezogen wird.
entfernt sich die maus um einen bestimmten betrag von der stelle, wo geklickt wurde, wird im record ein kennzeichen gesetzt, daß einen dragoperation im gange ist.

wird nun die maustaste im zweiten steuerelement losgelassen, so kann man dort erfahren, daß sie aus dem ersten steuerelement gezogen wurde. der punkt, an dem sie losgelassen wurde ist das ziel und dorthin werden die daten aus dem record übernommen.

das ganze funktioniert ohne alle drag&drop-methoden.
nur noch eine kleine ergänzung ist sinnvoll: ich setze einen HOOK für die maus, um von jeder stelle zu erfahren, ob die maus gehengelassen wurde. letzteres hat zur folge, daß im record das kennzeichen zurückgesetzt wird, durch das man erfährt, daß eine dragoperation im gange ist.

manfred

Uiui, das klingt aber irgendwie, naja, sehr umständlich (der Hook besonders). Es muss doch irgendwie mit Bordmitteln zu lösen sein. Ich werd' wahnsinnig :(

Grüße & Hilfe,
Max

ManfredG 23. Dez 2007 18:29

Re: Virtual Treeview und Drag'n'Drop
 
alles ansichtssache, ich finde es zB etwas aufwendig, wenn ich windows für drag&drop
bemühen soll, solange alles in einem prog bleibt...
sonst aber garnicht so schlimm, wird dir gefallen...
ist nicht von mir, habe ich auch in DP gefunden.

im formular deklarieren:
Delphi-Quellcode:
  protected (z.B.)
    HookID : HHook;
    IsMouseDown: boolean;
...
in FormCreate:
(Formular heißt HF)

Delphi-Quellcode:
procedure THF.FormCreate(Sender: TObject);
...
  HookId:=SetWindowsHookEx(WH_MOUSE,MouseProc,0,GetCurrentThreadId());
...
dann eine funktion erstellen
Delphi-Quellcode:
// HOOK zur Feststellung von WM_LBUTTONDOWN und WM_LBUTTONUP auch
// außerhalb des Programmes (Es wird die Variable IsMouseDown gesetzt)
function MouseProc(nCode: Integer; wParam, lParam: Longint): Longint; stdcall;
begin
  case nCode < 0 of
  True:
    Result := CallNextHookEx(HF.HookID, nCode, wParam, lParam)
  else begin
    case wParam of
      WM_LBUTTONDOWN : HF.IsMouseDown:=TRUE;
      WM_LBUTTONUP  : HF.IsMouseDown:=FALSE;
    end; { of case }
    Result := CallNextHookEx(HF.HookID, nCode, wParam, lParam); end
  end;
end;
und in FormClose wieder freigeben

Delphi-Quellcode:
procedure THF.FormClose(Sender: TObject; var Action: TCloseAction);
...
  if HookID <> 0 then UnHookWindowsHookEx(HookID);
...
gruß

ManfredG 23. Dez 2007 18:31

Re: Virtual Treeview und Drag'n'Drop
 
ps: das MouseUp wird auch dann erkannt, wenn sich die maus außerhalb des programmes befindet

Manfred

generic 23. Dez 2007 20:24

Re: Virtual Treeview und Drag'n'Drop
 
klingt irgendwie alles kompliziert was ihr macht.

du hast doch im drop ereignis die variable source.
das ist der tree/obj aus dem die daten kommen.
also einfach testen ob das die gültige quelle ist.
in der gültigen quelle brauchst du dann doch nur die "selected" nodes auswerten und einfügen/kopieren.

Prototypjack 24. Dez 2007 10:46

Re: Virtual Treeview und Drag'n'Drop
 
Zitat:

Zitat von generic
klingt irgendwie alles kompliziert was ihr macht.

du hast doch im drop ereignis die variable source.
das ist der tree/obj aus dem die daten kommen.
also einfach testen ob das die gültige quelle ist.
in der gültigen quelle brauchst du dann doch nur die "selected" nodes auswerten und einfügen/kopieren.

In der Tat, mein Ansatz war wohl etwas, naja, kompliziert. Danke für deine Hilfe, auf diesem Wege hat es sofort und ohne Zwischenfälle geklappt.

Vor lauter Wald sieht man keine Bäume mehr, oder wie war das noch? :mrgreen:

Danke & Grüße,
Max


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