TVirtualDrawTree.OnDragDrop Event

Virtual Tree View

Drag'n drop support event.

Pascal
property OnDragDrop: TVTDragDropEvent;
Description

Triggered when either a VCL or a OLE drop action occured. Accepting drag and drop actions is not trivial. In order to maintain a minimum compatibility with the VCL drag'n drop system Virtual Tree accepts not only OLE drop actions but also those issued by the Delphi VCL (which is totally different to the OLE way, unfortunately), provided toAcceptOLEDrop is set in TreeOptions.MiscOptions. The code snippet below is taken from a sample project provided with Virtual Tree. It shows a general way to deal with dropped data. The following check list can be used as orientation and additional comment to the code: 

 

 

  1. Determine what kind of drop data is passed. If DataObject is nil or Formats is empty then the drag source is a VCL control. The event is not triggered for OLE drag'n drop if there is no OLE format is available (which should never occur).
  2. If the event is triggered by a VCL control then use Source to access either the control or the drag object, depending on the circumstances of the action.
  3. For OLE drag'n drop iterate through the Formats list to find a format you can handle.
  4. If you find CF_VIRTUALTREE then the source of the drag operation is a Virtual Treeview. Since this is the native tree format you can pass it to the Sender's ProcessDrop method which will take care to retrieve the data and act depending on Effect and Mode. No further action by the application is usually required in this case.
  5. If you do not find CF_VIRTUALTREE then the operation has been initiated by another application, e.g. the Explorer (then you will find CF_HDROP or CF_SHELLIDLIST in formats) or Notepad (then you will get CF_TEXT and perhaps CF_UNICODETEXT) etc., depending on the data which is actually dropped.
  6. Use the provided DataObject to get the drop data via IDataObject.GetData and act depending on the format you get.
  7. Finally set Effect to either DROPEFFECT_COPY, DROPEFFECT_MOVE or DROPEFFECT_NONE to indicate which operation needs to be finished in Sender when the event returns. If you return DROPEFFECT_MOVE then all marked nodes in the source tree will be deleted, otherwise they stay where they are.

 

procedure TMainForm.VTDragDrop(Sender: TBaseVirtualTree; Source: TObject; DataObject: IDataObject;
  const Formats: array of Word; Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode);

var
  I: Integer;
  AttachMode: TVTNodeAttachMode;

begin
  if Length(Formats) > 0 then
  begin
    // OLE drag'n drop
    // If the native tree format is listed then use this and accept the drop, otherwise recject (ignore) it.
    // It is recommend by Microsoft to order available clipboard formats in decreasing detail richness so
    // the first best format which we can accept is usually the best format we can get at all.
    for I := 0 to High(Formats) do
      if Formats[I] = CF_VIRTUALTREE then
      begin
        case Mode of
          dmAbove:
            AttachMode := amInsertBefore;
          dmOnNode:
            AttachMode := amAddChildLast;
          dmBelow:
            AttachMode := amInsertAfter;
        else
          if Assigned(Source) and (Source is TBaseVirtualTree) and (Sender <> Source) then
            AttachMode := amInsertBefore
          else
            AttachMode := amNowhere;
        end;
        // in the case the drop target does an optimized move Effect is set to DROPEFFECT_NONE
        // to indicate this also to the drag source (so the source doesn't need to take any further action)
        Sender.ProcessDrop(DataObject, Sender.DropTargetNode, Effect, AttachMode);
        Break;
      end;
  end
  else
  begin
    // VCL drag'n drop, Effects contains by default both move and copy effect suggestion,
    // as usual the application has to find out what operation is finally to do
    Beep;
  end;
end;
Class
Links
What do you think about this topic? Send feedback!