Author Topic: [SOLVED] Inserting button by dragging  (Read 419 times)


  • Hero Member
  • *****
  • Posts: 1067
[SOLVED] Inserting button by dragging
« on: September 01, 2022, 01:35:08 pm »
I have four tbuttons on a TFlowPanel (or TPanel). All of them are same sizes, aligned as alTop, and widths match the width of the parent panel. So, then are in a row from top to bottom (let's say button1, button2, button3, and button4).

Is there any way that I can move the position of buttons, by dragging one button over and dropping it on another button? Form example, if I drag & drop Button3 on button1 then the order would be buttons 3,1,2,4.  And from here, if I drag and drop button4 on to button1 then the order would be 3,4,1,2. 

Is this possible?
« Last Edit: September 05, 2022, 05:05:22 am by egsuh »


  • Hero Member
  • *****
  • Posts: 1067
Re: Inserting button by dragging
« Reply #1 on: September 01, 2022, 01:37:53 pm »
Or not necessarily drag & drop. By any other event (e.g. buy clicking other buttons), I'd like to move them.


  • Full Member
  • ***
  • Posts: 133
Re: Inserting button by dragging
« Reply #2 on: September 03, 2022, 07:52:21 am »
This is the simplest method I've found. It works for most control types which are aligned to top in a TPanel. The main code is:
Code: Pascal  [Select][+][-]
  1. procedure TFormMain.Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
  2. var LControl: TControl;
  3. begin
  4.   LControl := Sender as TControl;
  5.   if LControl.Parent = PanelButtons then begin
  6.     LControl.ControlStyle := LControl.ControlStyle + [csCaptureMouse];
  7.     if csLButtonDown in LControl.ControlState then begin
  8.       LControl.Top := LControl.Top + (Y - LControl.Height div 2);
  9.     end;
  10.   end;
  11. end;

An up/down style re-order (as used in Lazarus's menu editor, TListView items editor) requires a way to select an item. So, your buttons would have to be TToggleButton's or some other method. The problem with the above, is, the control list order is not changed. So, you would have to find another way to extract the ordering. ie: Sorting controls by Y.

I do recommend you look at other interfaces which are more suited to re-ordering by the user. eg TListView.


  • Hero Member
  • *****
  • Posts: 10469
Re: Inserting button by dragging
« Reply #3 on: September 03, 2022, 12:27:05 pm »
Is this question about designtime or about runtime?

If I understand correctly, the buttons are filling a panel, arranged from top to bottom, all having the same size. This can be achieved most easily with the ChildSizing property of the panel: Set panel.ChildSizing.ControlsPerLine=1, .EnlargeHorizontal=crsHomogenousChildResize, .Layout=cclLeftToRightThenTopToBottom, and .ShrinkVertical=crsHomogenousChildResize. Then add the buttons - they will be added from top to bottom and exanded over the entire panel width (and if you had set ChildSizing.EnlargeVertical and .ShrinkVertical to crsHomogenousChildResize, too, they will also fill the panel vertically).

If you want to rearrange buttons at designtime, right-click the button that you want to move and select "Z-order" > (one of the items in that context menu) to change the button's z-order index.

If you want to do this at runtime find out the z index of the destination button by calling Panel.GetControlIndex(button) and change the z index of the dropped button by calling Panel.SetControlIndex(dropped_button, destination_button_index). This can be incorporated in a short drag-and-drop code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ButtonDragOver(Sender, Source: TObject; X, Y: Integer;
  2.   State: TDragState; var Accept: Boolean);
  3. begin
  4.   if (Source is TButton) and (TButton(Source).Parent = Panel1) then
  5.     Accept := true;
  6. end;
  8. // Source = button dragged
  9. // Sender = button on which Source is dropped
  10. procedure TForm1.ButtonDragDrop(Sender, Source: TObject; X, Y: Integer);
  11. var
  12.   pos: Integer;
  13. begin
  14.   // Find position of "Sender" in the panel's Z-order.
  15.   pos := Panel1.GetControlIndex(TControl(Sender));
  17.   // Move "Source" to position of "Sender" in the panel's Z-order.
  18.   Panel1.SetControlIndex(TControl(Source), pos);
  20.   // Update the childsizing
  21.   Panel1.Realign;
  22. end;
« Last Edit: September 03, 2022, 12:36:41 pm by wp »


  • Hero Member
  • *****
  • Posts: 1067
Re: Inserting button by dragging
« Reply #4 on: September 04, 2022, 05:40:48 am »
Thank you wp.

I had been almost neat to your example, except that I missed Panel1. in

           Panel1.getControlIndex and Panel1.setControlIndex,

and Panel1.Realign;.   All the buttons' DragMode must be dmAutomatic to work only with the codes.

And thank you for other advises --- they are much helpful.


TinyPortal © 2005-2018