Recent

Author Topic: (SOLVED) Drag & Drop in TShellTreeview?  (Read 475 times)

linuxfan

  • New Member
  • *
  • Posts: 36
(SOLVED) Drag & Drop in TShellTreeview?
« on: June 18, 2019, 10:54:58 am »
Hi all.

I am porting a kindof file manager from delphi to Lazarus; when I saw the TShellTreeView I was very happy and it works very well also. But... what about Drag & Drop? I don't see any event handler related to drag and drop, like OnDragOver and so on. This is strange because the ShellTreeView ancestor has them.

So, what could I do to implement drag & drop to a ShellTreeView? I am not interested in dragging from the tree, only to drop in a precise position in it.

Thanks in advance for any idea.
« Last Edit: June 19, 2019, 08:10:51 am by linuxfan »

wp

  • Hero Member
  • *****
  • Posts: 6337
Re: Drag & Drop in TShellTreeview?
« Reply #1 on: June 18, 2019, 11:09:05 am »
Since TShellTreeView inherits (like TTreeView) directly from TCustomTreeView it has all the drag&drop features built-in, they just are not published.

You could declare an opener class and cast your ShellTreeView instance to it in order to get access to the still protected properties/events for drag and drop:
Code: Pascal  [Select]
  1. type
  2.   TShellTreeViewOpener = class(TShellTreeView);
  3.  
  4.   TForm1 = class(TForm)
  5.     ShellTreeView1: TShellTreeView;
  6.     procedure FormCreate(Sender: TObject);
  7.   private
  8.     procedure DragDropHandler(Sender, Source: TObject; X, Y: Integer);
  9.     procedure DragOverHandler(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
  10.   end;
  11.  
  12.   procedure TForm1.FormCreate(Sender: TObject);
  13.   begin
  14.     TShellTreeViewOpener(ShellTreeView1).OnDragDrop := @DragDropHandler;
  15.     TShellTreeViewOpener(ShellTreeView1).OnDragOver := @DragOverHandler;
  16.   end;
  17.  
  18.   procedure TForm1.DragDropHandler(Sender, Source: TObject; X,Y: Integer);
  19.   begin
  20.     // ... put the dragdrop stuff here
  21.   end;
  22.  
  23.   procedure TForm1.DragOverHandler(Sender, Source: TObject; X, Y: Integer;
  24.     State: TDragState; var Accept: Boolean);
  25.   begin
  26.     // ... put the dragover stuff here
  27.   end;

Please report if this works. Then I can try to publish the drag/drop related properties and events of TShellTreeView.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

linuxfan

  • New Member
  • *
  • Posts: 36
Re: Drag & Drop in TShellTreeview?
« Reply #2 on: June 18, 2019, 11:51:38 am »
Thank you wp for this.

Actually I thought to simply typecast my TShellTreeView to assign handlers... but then I decided to ask about before.

I will try this evening: giving that I am porting an old project, the code is already working. Then I will let you know how the things go.

See you later... and thanks again.

linuxfan

  • New Member
  • *
  • Posts: 36
Re: Drag & Drop in TShellTreeview?
« Reply #3 on: June 18, 2019, 07:27:48 pm »
Dear wp,

I'm sorry to inform you that it didn't work. When I drag something onto the ShellTreeView the mouse cursor changes to a "forbidden".

I tried to put a normal TreeView on the same form, and even without items in it the DragOver handler is called, and the cursor changes to an arrow+rectangle (correct behaviour). If, in the same TreeView, I delete the OnDragOver assignment, it correctly reverts back to not accepting drags.

Looking better at the hierarchy, it seems that OnDragOver is first declared in TTreeView, not TCustomTreeView which is the common ancestor.

I suppose I will have to use a normal TreeView and populate it by code. It should be not too difficult... unless someone else has some better idea!

Regards,
linuxfan


wp

  • Hero Member
  • *****
  • Posts: 6337
Re: Drag & Drop in TShellTreeview?
« Reply #4 on: June 18, 2019, 08:39:44 pm »
Looking better at the hierarchy, it seems that OnDragOver is first declared in TTreeView, not TCustomTreeView which is the common ancestor.
This is not correct. Drag and drop is introduced very early in the LCL class hierarchy, already in TControl. The reason that you don't see the related properties/events in TCustomTreeView is that they are just inherited from the ancestors. The reason why you do see them in TTreeView is that they are published here - they were protected in the ancestors.

I played with the issue myself and tried to drag an item of a listbox over a standard TreeView; it should be added as a child of the node on which the dragging mouse is released. It works.

In principle, the same code works also with a TShellTreeView (after having added the OnDragOver and OnDragDrop handlers manually as described in the other post) - it works because i see a child indicator after dropping the item. But when I want to open the new node the child node disappears again.

Of course this is clear: The ShellTreeView reflects the file system, and my simple drag and drop test did not change the file system. So, after creating a directory with the caption of the dropped listbox item the test program works as expected: the new node is persistent now.

Try the attached demo. But be careful - dropping the listbox item over the ShellTreeView (left-most control) will add a directory to the file system.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

linuxfan

  • New Member
  • *
  • Posts: 36
(SOLVED) Re: Drag & Drop in TShellTreeview?
« Reply #5 on: June 19, 2019, 08:10:29 am »
Dear wp,

you are totally right. About the protected fields, and about the dragdrop working flawlessly. My code (before and after your suggestion) was actually right, but I kept to debug the wrong way (delphi has some differences). I got confused... the dragover handler was actually called, but the code always set Accept to false. Stupid me...

Thank you, as always asking the forum was the right way to go. Now I can proceed with my conversion. Cheers!


« Last Edit: June 19, 2019, 08:12:53 am by linuxfan »