Recent

Author Topic: [Resolved] Drag'n'Drop from TVirtualStringTree to SpeedButton  (Read 3089 times)

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • Keep it simple.
Today my problem of the day is, that TSpeedButton does not seem to support handlers for DragOver and DragDrop.
Is there a way to get drag'n'drop  functionality attached to a SpeedButton? In case it helps: for this project a Windows only solution is acceptable.

Long story:

I have Drag''n'Drop enabled controls (VirtualStringTree and ListBox) controls on a form and implemented Drag'n'Drop in between them by implementing DragOver and DragDrop event handlers --> works great.

On the same form, I have a Speedbutton which deletes the currently selected nodes when clicked. Works too.

I thought it would be nice if mouse-addicted users can drag nodes from a tree or list and drop them on the Speedbutton to get them deleted. Unfortunately SpeedButtons, unlike ordinary Buttons or BitButtons, do not seem to support DragOver and DragDrop events.

I already tried clumsy workarounds, like putting a DnD enabled Panel underneath the Button or enabling Drag'n'Drop for the underlying form, but this won't work, sinde the drop is disabled as soon as the mouse cursor enters the rectangle of the Speedbutton. Furthermore I wonder why SpeedButtons won't publish those event handlers, I always though all VCL/LCL controls support them and was baffled to find out that Speedbuttons are an exception - there may be rasons?

Thnx,

Armin.
« Last Edit: May 13, 2021, 03:50:16 pm by Nimral »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Drag'n'Drop from TVirtualStringTree to SpeedButton
« Reply #1 on: May 13, 2021, 11:08:25 am »
The reason for TSpeedButton's lack of support for  drag and drop is that it is designed to be a lightweight control, descending from TGraphicControl, and so not able to receive focus, for instance.
Drag and drop functionality is introduced in the LCL at the level of TWinControl, and is available for all TWinControl descendants (which have a window handle).

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: Drag'n'Drop from TVirtualStringTree to SpeedButton
« Reply #2 on: May 13, 2021, 11:56:19 am »
Use a TBitBtn instead of the TSpeedButton.

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • Keep it simple.
Re: Drag'n'Drop from TVirtualStringTree to SpeedButton
« Reply #3 on: May 13, 2021, 02:42:37 pm »
The reason why I moved from TButton to TSpeedButton was because I do not want the focus taken away from another control. AFAIK BitBtns take the focus as well.

Wp showed me a different approach, though it is a bit hacky I guess that for my specific issue it is the ideal solution;

Code: Pascal  [Select][+][-]
  1. type
  2.   TSpeedButtonHack = class(TSpeedButton);  // access protected properties hack
  3.  
  4. ...
  5.  
  6. procedure TForm1.FormCreate(Sender: TObject);
  7. begin
  8.   TSpeedButtonHack(SpeedButton1).OnDragOver := @SpeedButtonDragOver;
  9.   TSpeedButtonHack(SpeedButton1).OnDragDrop := @SpeedButtonDragDrop;
  10. end;
  11.  

I decided for this specific situation the hack is my best option.

Thnx for your help,

Armin.
« Last Edit: May 13, 2021, 04:03:21 pm by Nimral »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Drag'n'Drop from TVirtualStringTree to SpeedButton
« Reply #4 on: May 13, 2021, 05:46:52 pm »
Wp showed me a different approach, though it is a bit hacky I guess that for my specific issue it is the ideal solution;
Code: Pascal  [Select][+][-]
  1. {... some code ...}

For such "kluges" an even better approach is to use an interposed class:
Code: Pascal  [Select][+][-]
  1. interface
  2.  
  3. uses
  4.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Buttons;
  5.  
  6. type
  7.   TSpeedButton = class(Buttons.TSpeedButton);  // access protected properties hack
  8.  
  9.   TForm1 = class(TForm)
  10. {... etc ...}

That way you can use your buttons normally, including access to protected methods/properties, without having to type-cast to a new class:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   SpeedButton1.OnDragOver := @SpeedButtonDragOver;
  4.   SpeedButton1.OnDragDrop := @SpeedButtonDragDrop;
  5. end;
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • Keep it simple.
Re: [Resolved] Drag'n'Drop from TVirtualStringTree to SpeedButton
« Reply #5 on: May 14, 2021, 10:39:05 am »
For specific kinds of problems a kludge is, IMHO, an appropriate and totally legal tool to solve them :-)

What astonished me is that your approach works. Meanwhile Socke explained it in the German forum.

I still tend to  go with wp's approach. Your interposed class is so inconspicious, it doesn't stick out for anyone reading this code after me (or me in 5 years) that something fishy was done here. The typecast in wp's approach sticks out like a blinking red signal torch - that's why I like it (in this specific situation).

Armin.
« Last Edit: May 14, 2021, 11:16:01 am by Nimral »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

 

TinyPortal © 2005-2018