Recent

Author Topic: [solved] Letting users rearrange buttons  (Read 4050 times)

Joanna

  • Hero Member
  • *****
  • Posts: 1419
[solved] Letting users rearrange buttons
« on: March 21, 2024, 09:57:30 am »
Hi everyone I just got an idea for a new custom componet.
I want to make a tflowpanel descendant control with some buttons in it.

The buttons will be created from either a constant string array or stringlist.
I want to let the users to change the order in which buttons appear by dragging them.  Is this possible do drag drop in the preferred spot?

I also will need to store the button order in an inifile for next time program is used. Most likely I will store them by name.

How difficult is this to do? I haven’t dragged things since Visual Basic a long time ago. I’m guessing that the end drag event can detect other button in same spot and maybe change the index in controls list or something like that?
« Last Edit: March 26, 2024, 08:11:30 am by Joanna »

egsuh

  • Hero Member
  • *****
  • Posts: 1760
Re: Letting users rearrange buttons and saving
« Reply #1 on: March 21, 2024, 11:43:24 am »
It is not very difficult, but at first you need some understanding. See the following:

https://wiki.freepascal.org/LCL_Drag_Drop

I do not have a direct example of moving buttons, but an example with TTreeView. First you have to define "dragover" event, where Accept must be set as true or false.

Then define DragDrop event handler.

My example is dragging and dropping a tree node over another node. Some nodes are possible to move while others are not, depending on the integer value stored in the "tag" property of each treenode.

When dragged and dropped over another tree node, the "dragged" node take the position and "dropped over" node goes down to next position.

Code: Pascal  [Select][+][-]
  1. procedure TfrQList.tvQListDragOver(Sender, Source: TObject; X, Y: Integer;
  2.   State: TDragState; var Accept: Boolean);
  3.   // DragOver - Sender: Treeview,  Source: dragged object
  4. var
  5.    TNode, SNode, PNode: TTreeNode;
  6.    SQT, TQT: integer;
  7. begin
  8.    // Find Qtype of Dragged over (source) question
  9.    if (Source is TToolButton)
  10.       then SQT:= (Source as TToolButton).Tag
  11.       else if (Source is TTreeView) then begin
  12.          SNode:= (Source as TTreeView).Selected;
  13.          if SNode <> nil then SQT:= TQuestion(SNode.Data).QType;
  14.       end;
  15.  
  16.    if SQT = qtBlockEnd then begin
  17.       Accept:= False;
  18.       Exit;
  19.    end;
  20.  
  21.    TNode:= TVQList.GetNodeAt(X, Y);
  22.  
  23.    if TNode = nil then Accept:= True
  24.    else begin
  25.       PNode:= TNode.Parent;
  26.       if PNode = nil then Accept:= True
  27.       else begin
  28.          TQT:= TQuestion(PNode.Data).QType;
  29.          if TQT = qtPageStart
  30.          then
  31.              Accept:= not (SQT in [qtIfBlock, qtLoopStart, qtJump, qtQuotaCheck,
  32.                             qtRTime, qtAHP, qtTradeOff, qtBlockEnd])
  33.       end;
  34.    end;
  35. end;
  36.  
  37.  
  38. procedure TfrQList.tvQListDragDrop(Sender, Source: TObject; X, Y: Integer);
  39. var
  40.    SNode, TNode: TTreeNode;
  41.    TQ: TQuestion;
  42. begin
  43.    TNode := TVQList.GetNodeAt(X,Y);
  44.  
  45.    if (Source is TToolButton) then begin  // New create
  46.       TQ:= NewQuestion((Source as TControl).Tag);
  47.       tvQList.Selected:= InsertNewQNode(TNode, TQ);
  48.    end
  49.    else begin  // Move within Treeview
  50.       SNode := TVQList.Selected;
  51.       MoveCurrentNodeTo(SNode, TNode);
  52.    end;
  53. end;
  54.  

Handoko

  • Hero Member
  • *****
  • Posts: 5524
  • My goal: build my own game engine using Lazarus
Re: Letting users rearrange buttons and saving
« Reply #2 on: March 21, 2024, 11:51:29 am »
Maybe not needed but rvk's furious programming's moveable rectangle might be useful:


https://forum.lazarus.freepascal.org/index.php/topic,43376.msg303582.html#msg303582
« Last Edit: March 21, 2024, 03:39:29 pm by Handoko »

Joanna

  • Hero Member
  • *****
  • Posts: 1419
Re: Letting users rearrange buttons and saving
« Reply #3 on: March 21, 2024, 01:43:15 pm »
Thanks for the links I looked at the code and it seems that I have to actually code the movement but I wonder if flowpanel will interfere because it does some sort of alignment. I’ll have to check. There is also an onstartdrag event,  I’ll try out the code

I don’t remember dragging being so complicated before..

wp

  • Hero Member
  • *****
  • Posts: 13421
Re: Letting users rearrange buttons and saving
« Reply #4 on: March 21, 2024, 06:30:12 pm »
Adding a little project which demonstrates drag and drop of buttons in a flowpanel.

Zvoni

  • Hero Member
  • *****
  • Posts: 3307
Re: Letting users rearrange buttons and saving
« Reply #5 on: March 22, 2024, 09:27:15 am »
Thanks for the links I looked at the code and it seems that I have to actually code the movement but I wonder if flowpanel will interfere because it does some sort of alignment. I’ll have to check. There is also an onstartdrag event,  I’ll try out the code

I don’t remember dragging being so complicated before..

On that note, what i do in such cases, if i'm not sure about the "logic" behind it:
In your case (Moving Buttons):
Take 4-5 poker-cards (as many buttons as you have), put them on a table and arrange them like the buttons you have, and then start "simulating" moving them (from left to right, dropping them in between two others etc.), and then note down each and evry step that happens there ("starting moving card 1 to the right" etc.)

You'll note pretty quickly, that e.g. you want to move the most left button to the right, that any button right of it you pass over HAS to be moved to the left etc....
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Joanna

  • Hero Member
  • *****
  • Posts: 1419
Re: Letting users rearrange buttons and saving
« Reply #6 on: March 22, 2024, 01:30:05 pm »
I did some experimentation.
If the button is inside the flowpanel it doesn’t move at all. Probably because the flowpanel is managing it. If I change button parent to parent of flow panel I can move the button but it is difficult to control and doesn’t always move where I want it to. I fact it sometimes disappears  :o there are also Two duplicate images of button appearing when I drag it.

As for the start drag event for button, that doesn’t seem to happen at all.

I don’t really understand what drag events are for if I have to rely on mouse move to do anything . I will look at examples again...

morknot

  • Jr. Member
  • **
  • Posts: 55
  • still learning
Re: Letting users rearrange buttons and saving
« Reply #7 on: March 23, 2024, 12:44:16 pm »
This probably isn't of any use - it doesn't work if the Button's parent is the flow panel, it has to be the Form. It's just another way of moving a control without using drag and drop.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     FlowPanel1: TFlowPanel;
  17.     procedure Button1MouseDown(Sender: TObject; Button: TMouseButton;
  18.       Shift: TShiftState; X, Y: Integer);
  19.     procedure Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  20.       Y: Integer);
  21.     procedure Button1MouseUp(Sender: TObject; Button: TMouseButton;
  22.       Shift: TShiftState; X, Y: Integer);
  23.     procedure FormShow(Sender: TObject);
  24.   private
  25.  
  26.   public
  27.   FDownX,FDownY:Integer;
  28.     FDragging:Boolean;
  29.   end;
  30.  
  31. var
  32.   Form1: TForm1;
  33.  
  34. implementation
  35.  
  36. {$R *.lfm}
  37.  
  38. type
  39. TMoveCracker=class(TControl);
  40.  
  41. { TForm1 }
  42.  
  43. procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
  44.   Shift: TShiftState; X, Y: Integer);
  45. begin
  46.   FDownX:=X;
  47.   FDownY:=Y;
  48.   FDragging:=True;
  49.   TMoveCracker(Sender).MouseCapture:=True;
  50. end;
  51.  
  52. procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  53.   Y: Integer);
  54. begin
  55.  
  56.  If Fdragging then
  57.  begin
  58.  
  59. With Sender as TButton do
  60. begin
  61.  If (X-FDownX+Left>=FlowPanel1.Left) and (X-FDownX+Left+Width<=FlowPanel1.Left+FlowPanel1.Width) then
  62.  Left:= X-FDownX+Left;
  63.  
  64.  If (Y-FDownY+Top>=FlowPanel1.Top) and (Y-FDownY+Top+(Sender as Tbutton).Height<=FlowPanel1.Top+FlowPanel1.Height)then
  65.  Top:= Y-FDownY+Top;
  66. end;
  67.  
  68. end;
  69.  
  70. end;
  71.  
  72. procedure TForm1.Button1MouseUp(Sender: TObject; Button: TMouseButton;
  73.   Shift: TShiftState; X, Y: Integer);
  74. begin
  75.   if FDragging then
  76.      begin
  77.      FDragging:=False;
  78.      TMoveCracker(Sender).MouseCapture:=False;
  79.  
  80.     end;
  81. end;
  82.  
  83. procedure TForm1.FormShow(Sender: TObject);
  84. begin
  85.   Fdragging:=False;
  86.  Button1.Left:=FlowPanel1.Left;
  87.  Button1.Top:=FlowPanel1.Top;
  88.  
  89.  
  90. end;
  91.  
  92. end.            
  93.  
  94.  
  95.  

wp

  • Hero Member
  • *****
  • Posts: 13421
Re: Letting users rearrange buttons and saving
« Reply #8 on: March 23, 2024, 01:47:16 pm »
I did some experimentation.
If the button is inside the flowpanel it doesn’t move at all. Probably because the flowpanel is managing it. If I change button parent to parent of flow panel I can move the button but it is difficult to control and doesn’t always move where I want it to. I fact it sometimes disappears  :o there are also Two duplicate images of button appearing when I drag it.

As for the start drag event for button, that doesn’t seem to happen at all.

I don’t really understand what drag events are for if I have to rely on mouse move to do anything . I will look at examples again...
Did you look at my sample code above?

The controls in the FlowPanel are collected in a ControlList (type TFlowPanelControlList) which descends from TCollection. The collection items are of type TFlowpanelControl, and each item is responsible for one control (accessible as the item's Control property). Since TCollectionItems have a Index property you simply have to change the Index if you want to move the item and the control associated with it to another place.

Using the ControlList.IndexOfControl method determine the index of the TFlowPanelControl which holds the dragged button. Then you move the mouse to where the button is to be dropped; this is another button - the dragged button should be inserted before the button where it is dropped. So, you use ControlList.IndexOfControl again to determine the Index of the FlowPanelControl of the target button. Simply set the Index of the FlowPanelControl with the dropped button to the index of the FlowPanelControl with the target button. But you must be careful, when the dragged button is in front of the target button - in this case you must correct the index by 1. And the final case is that you want to drag the button to the end of the list: do not drop it on a button but on the empty flowpanel areas; setting the Index to FlowPanel.ControlList.Count-1 does the job.

Of course, all this works exactly like this only when the button parent is a TFlowPanel because it automatically takes care of rearranging the buttons. On a normal panel a different methodology must be used.

Joanna

  • Hero Member
  • *****
  • Posts: 1419
Re: Letting users rearrange buttons and saving
« Reply #9 on: March 23, 2024, 02:13:27 pm »
 Thanks for the example and links
I've written some test code far from finished
Code: Pascal  [Select][+][-]
  1.  UNIT PAGE_UNIT_2024; //Created March 19,2024  trying to improve tpagecontrol
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. INTERFACE
  6.  
  7. USES
  8.   CLASSES, SYSUTILS,ComCtrls,Dialogs,Controls,Graphics,Themes,LCL,LCLIntf,
  9.   LCLType,FLOWPANEL_UNIT_2024,BUTTONS_UNIT_2024,HELPERS_UNIT_2024,UTIL_2023,
  10.   StdCtrls,ExtCtrls,CustomDrawnControls;
  11. TYPE
  12.  {
  13.  create some buttons using an array or stringlist
  14.  be able to rearrance the buttons and save their order to inifile
  15.  }
  16.  
  17.  { TBUTTON_TABS }
  18.  
  19.  TBUTTON_TABS = CLASS (TMYFLOWPANEL) // replacement for cdpage control non working tabs
  20.  CONSTRUCTOR CREATE( THEOWNER: TCOMPONENT) ; OVERRIDE;
  21.  PROCEDURE ACTIVATE; OVERRIDE;
  22.  PROCEDURE CREATE_BUTTONS (CONST BNAMES:TStringArray); VIRTUAL;
  23.  PROCEDURE STARTDRAG( SENDER: TOBJECT; VAR DRAGOBJECT: TDRAGOBJECT) ;
  24.  PROCEDURE MOUSE_MOVE ( SENDER: TOBJECT; SHIFT: TSHIFTSTATE; X, Y: INTEGER) ;
  25.  PROCEDURE DRAG_OVER ( SENDER, SOURCE: TOBJECT; X, Y: INTEGER; STATE: TDRAGSTATE; VAR ACCEPT: BOOLEAN) ;
  26.  PROCEDURE DRAG_DROP( SENDER, SOURCE: TOBJECT; X, Y: INTEGER) ;
  27.  PROCEDURE TEST; OVERRIDE;
  28.  END;
  29.  
  30. IMPLEMENTATION
  31.  
  32. { TBUTTON_TABS }
  33.  
  34.  CONSTRUCTOR TBUTTON_TABS.CREATE( THEOWNER: TCOMPONENT) ;
  35. BEGIN
  36.   INHERITED CREATE( THEOWNER) ;
  37.  // TEST;
  38. END;
  39.  
  40.  PROCEDURE TBUTTON_TABS.ACTIVATE;
  41.  BEGIN
  42.    //SET_CHANGE_EVENT(@CHANGE_EVENT);
  43.   //INHERITED;
  44.  END;
  45.  
  46.  PROCEDURE TBUTTON_TABS.CREATE_BUTTONS( CONST BNAMES: TSTRINGARRAY) ;
  47.            VAR X:INTEGER;
  48.  BEGIN                        //
  49.  CREATE_CONTROLS(Length(BNAMES),TcdBUTTON);
  50.  FOR X:=  LOW (BNAMES) TO HIGH (BNAMES) DO
  51.      WITH Controls[X] AS TCDButton DO
  52.            BEGIN
  53.            Name := BNAMES[X];
  54.            OnStartDrag := @STARTDRAG;
  55.            OnMouseMove := @Mouse_Move;
  56.            DragMode := dmAutomatic;
  57.            DoubleBuffered := true;
  58.            OnDragOver := @DRAG_OVER;
  59.            OnDragDrop := @DRAG_DROP;
  60.            END;
  61.  END;
  62.  
  63.  PROCEDURE TBUTTON_TABS.STARTDRAG( SENDER: TOBJECT; VAR DRAGOBJECT: TDRAGOBJECT) ;
  64.  BEGIN
  65.  BANNER ('starting drag on '+ sender.ClassName);//  DRAGOBJECT.Control.Name);
  66.  END;
  67.  
  68.  PROCEDURE TBUTTON_TABS.MOUSE_MOVE( SENDER: TOBJECT; SHIFT: TSHIFTSTATE; X, Y: INTEGER) ;
  69.  BEGIN
  70.  IF NOT (SENDER IS TBUTTON) OR NOT (ssLeft IN SHIFT) THEN EXIT;
  71.  WITH SENDER AS TControl DO
  72.       BEGIN
  73.       parent:= self.parent;
  74.       Left:= X + (WIDTH DIV 2);
  75.       TOP:= Y + (HEIGHT DIV 2);
  76.       END;
  77.  END;
  78.  
  79.  PROCEDURE TBUTTON_TABS.DRAG_OVER(SENDER,SOURCE:TOBJECT;X,Y:INTEGER;STATE:TDRAGSTATE;VAR ACCEPT:BOOLEAN);
  80.  BEGIN
  81.  banner ('dragging over '+tcontrol(sender).Name+'  ' +TControl(source).Name);
  82.  END;
  83.  
  84.  PROCEDURE TBUTTON_TABS.DRAG_DROP( SENDER, SOURCE: TOBJECT; X, Y: INTEGER) ;
  85.  BEGIN
  86.  banner ('drag drop');
  87.  END;
  88.  
  89.  PROCEDURE TBUTTON_TABS.TEST;
  90.            CONST AR_NAMES: ARRAY[0..2] OF String = ('ONE','TWO','THREE');
  91. BEGIN
  92.   CREATE_BUTTONS(AR_NAMES);
  93. END;
  94.  
  95.  END.

It seems that the dragover event fires as soon as the button is clicked even though the button hasn't moved. i also noticed that the cursor sometimes changes as i drag.

wp ill read your code more thoroughly and make improvements as i go ..
I don’t understand how to insert The button I’m dragging.apparently the button being dragged is called the source and the button it’s being dropped on is the sender..very confusing.
I don’t understand how to insert it..
« Last Edit: March 23, 2024, 03:10:03 pm by Joanna »

wp

  • Hero Member
  • *****
  • Posts: 13421
Re: Letting users rearrange buttons and saving
« Reply #10 on: March 23, 2024, 08:00:25 pm »
I modified your sample component to include the drag-and-drop code from the previous example.

Since I did not want to install the customdrawn components for this example, I made the TButton_Tabs component to be very versatile and to accept any button descending from TCustomButton; you must set the ButtonClass property to the class of the buttons to be created; by default it is a standard TButton. If there are further properties to be set you can hook into the event OnBtnCreate which fires immediately after the button has been created. (The attached demo project adds TBitBtns to the controls and uses this event to set the image index).

Another event is the OnBtnClick event which fires when a button has been clicked; it has the clicked button (as a general TCustomButton variable) and its index as parameters.

Regarding Drag-and-drop there is a property EnableBtnDragDrop which must be set to true in order to allow drag and drop. After having done this, it must be mentioned that drag-and-drop seems to interfere with standard clicks. I avoided this by triggering the drag-and-drop operation only when the CTRL key is pressed. Maybe this should be made more general in a final version.

The attachment contains the component together with a small run-time demo.

egsuh

  • Hero Member
  • *****
  • Posts: 1760
Re: Letting users rearrange buttons and saving
« Reply #11 on: March 24, 2024, 05:17:49 am »
I'm trying to make a simple example. I could make a button is dragged and dropped.

Here, with all of FlowPanel1, Button2, Button3, Button5 and Button6,

1) DragMode = dmAutomatic
2) OnDragOver = FlowPanel1DragOver
3) OnDragDrop = FlowPanel1DragDrop.

Problem is I cannot change the position. "Button2" is always returned by "ControlAtPos", and I cannot proceed any more.

Can anybody check this, please?

Code: Pascal  [Select][+][-]
  1. unit Unit2;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.    Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,ExtCtrls;
  9.  
  10. type
  11.  
  12.    { TForm2 }
  13.  
  14.    TForm2 = class(TForm)
  15.       Button2: TButton;
  16.       Button3: TButton;
  17.       Button5: TButton;
  18.       Button6: TButton;
  19.       FlowPanel1: TFlowPanel;
  20.       procedure FlowPanel1DragDrop(Sender, Source: TObject; X, Y: Integer);
  21.       procedure FlowPanel1DragOver(Sender, Source: TObject; X, Y: Integer;
  22.          State: TDragState; var Accept: Boolean);
  23.    private
  24.  
  25.    public
  26.  
  27.    end;
  28.  
  29. var
  30.    Form2: TForm2;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm2 }
  37.  
  38. procedure TForm2.FlowPanel1DragDrop(Sender, Source: TObject; X, Y: Integer);
  39. var
  40.    AButton: TButton;
  41.    AControl: TControl;
  42. begin
  43.    AControl := FlowPanel1.ControlAtPos(Point(X,Y), false, true);
  44.    if AControl <> nil then  showmessage(AControl.Name);  // <--- Always Button2
  45.  
  46.    { // ----------- I'd like to test followings --- changing Taborder or controlindex
  47.    if (AControl is TButton) then begin
  48.       AButton := AControl as TButton;
  49.       (Source as TButton).TabOrder := AButton.TabOrder;  // or ControlIndex
  50.    end;  // }
  51. end;
  52.  
  53. procedure TForm2.FlowPanel1DragOver(Sender, Source: TObject; X, Y: Integer;
  54.    State: TDragState; var Accept: Boolean);
  55. var
  56.    AControl: TControl;
  57. begin
  58.    AControl := FlowPanel1.ControlAtPos(Point(X,Y), true, true);
  59.    if (AControl is TButton) then begin
  60.       Accept := True;
  61.    end
  62.    else Accept := False;
  63. end;
  64.  
  65. end.
  66.  

Joanna

  • Hero Member
  • *****
  • Posts: 1419
Re: Letting users rearrange buttons and saving
« Reply #12 on: March 24, 2024, 11:14:56 am »
i tried to test control at position too
Code: Pascal  [Select][+][-]
  1. PROCEDURE TBUTTON_TABS.DRAG_OVER(SENDER,SOURCE:TOBJECT;X,Y:INTEGER;STATE:TDRAGSTATE;
  2.                                   VAR ACCEPT:BOOLEAN);
  3.  BEGIN
  4.  IF SENDER = SOURCE THEN EXIT; // it hasnt moved
  5.  if self.ControlAtPos(point(x,y),true,true)<> nil
  6.     then banner ('dragging over-> control at position = '+self.ControlAtPos(point(x,y),true,true).Name);
  7.  WITH TControl(SENDER) DO
  8.       Color := InvertColor(COLOR);
  9. ACCEPT:= (SOURCE IS TCDBUTTON) AND ((SENDER IS TCDButton) OR (SENDER is TFlowPanel));
  10.  END;

for me it seems to always return button1 and if i don't check for nil there is often no control at position at all and it crashes. I've never used control at position before so I'm unfamiliar with it. I'm starting to think that flovwpanel and dragging are not a good combination. i will study the example projects further

wp

  • Hero Member
  • *****
  • Posts: 13421
Re: Letting users rearrange buttons and saving
« Reply #13 on: March 24, 2024, 12:51:39 pm »
I'm trying to make a simple example. I could make a button is dragged and dropped.

Here, with all of FlowPanel1, Button2, Button3, Button5 and Button6,

1) DragMode = dmAutomatic
2) OnDragOver = FlowPanel1DragOver
3) OnDragDrop = FlowPanel1DragDrop.

Problem is I cannot change the position. "Button2" is always returned by "ControlAtPos", and I cannot proceed any more.

Can anybody check this, please?
"Sender" and "Source" really are not clear names for the controls involved in a drag-and-drop operation. I myself always have to insert WriteLn or DebugLn instructions in the code to learn which one is which.

In case of the OnDragDrop and OnDragOver event, "Source" turns out to be the control which is being dragged, and "Sender" is is the control over which the dragged control is moved momentarily. A bit strange, I know, I would expect it to be the other way round, and maybe I wrote it like that already somewhere - but the statement here is based on the code shown at the end.

As usual, Sender is the control which fires the event, and thus it reports the coordinates X, Y relative to itself. But the FlowPanel.ControlAtPos wants coordinates relative to the FlowPanel - but it gets coordinates relative to the button, and thus reports always the same button.

You simply must convert the coordinates X,Y to be relative to the flowpanel by calling the ClientToParent method of the Sender:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FlowPanel1DragOver(Sender, Source: TObject; X, Y: Integer;
  2.   State: TDragState; var Accept: Boolean);
  3. var
  4.   P: TPoint;
  5.   C: TControl;
  6. begin
  7.   Write('[OnDragOver] Sender=', TControl(Sender).Name,
  8.     ' Source=', TControl(Source).Name,
  9.     ' X=', X, ' Y=', Y
  10.   );
  11.   if Sender <> FlowPanel1 then
  12.   begin
  13.     P := TControl(Sender).ClientToParent(Point(X, Y));
  14.     C := FlowPanel1.ControlAtPos(P, true, true);
  15.     Write(' P=(', P.X, ',', P.Y, '), ControlAtPos(P)=', C.Name);
  16.   end;
  17.   WriteLn;
  18. ...
  19. end;

But why are you doing this at all? If done correctly it will just return the control which you already know as being the Sender parameter. Look at the output of above code...
« Last Edit: March 24, 2024, 01:49:05 pm by wp »

egsuh

  • Hero Member
  • *****
  • Posts: 1760
Re: Letting users rearrange buttons and saving
« Reply #14 on: March 25, 2024, 02:57:06 am »
Quote
But why are you doing this at all?

Hi wp,

Thank you for your kind explanation. I have implemented several drag and drop features, mostly within TTreeview. I'm simply experimenting several other controls because they might be necessary in the future.

 

TinyPortal © 2005-2018