Moving Controls at Runtime: Example Please

I'm writting an app that will allow the user to drag/drop controls onto a container and then hook them up via a line.  The user can move the items a runtime.  Are there any examples out there?
1.  Moving controls at runtime
2.  creating this type of container object.
3.  linking controls with a line (that moves when the object is moved by user).

blitz051697Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

BoRiSCommented:
blitz

I can give you code as to how to move the controls at run time but dropping them on to a container i guess would have to be done by allowing the container to accept these objects and then link them...

if you want to code let me know.... by comment

remember it's only the code to move object at run time...

Later

BoRiS
interCommented:
Hi,

Here is doing it in one way. Do the following:

1 - Create and empty form
2 - Place a Panel and Button on the form. Those should be named as Panel1 and Button1
3 - Cut and paste the following code for your unit as follows:

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    procedure Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure Panel1DragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure FormDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure FormDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1.DragMode := dmAutomatic;
  Panel1.DragMode := dmAutomatic;
end;

procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := (Source is TControl) and (Source <> Sender);
end;

procedure TForm1.Panel1DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
  with (Source as TControl) do
  begin
    Parent := TWinControl(Sender);
    Left := X;
    Top := Y;
  end;
end;

procedure TForm1.FormDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
  with (Source as TControl) do
  begin
    Left := X;
    Top := Y;
  end;
end;

procedure TForm1.FormDragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := (Source is TControl);
end;

end.


Link events from object inspector to the above events. For example click on Panel and press F11 to show the object ispector. Switch to events tab and from the drop down list of OnDragOver event select Panel1DragOver etc...

Then run the project. Drag the button over Panel and drop. Then drag the panel over the form and drop. Is that what you want?

Regards,
Igor
interCommented:
Hi BoRis,

Sorry, I do not see you commenting while I prepare the answer.

Igor
Learn SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

BoRiSCommented:
hi inter

not to worry, lets see what blitz has to say

Later

BoRiS
interCommented:
Hi there,

excuse me, when you drag button back to the form it does not work so modify the following please:

procedure TForm1.FormDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
  with (Source as TControl) do
  begin
    Parent := TWinControl(Sender);
    Left := X;
    Top := Y;
  end;
end;

Regards,
Igor
blitz051697Author Commented:
boris, you say that you can move controls at runtime.  But does your code also allow drawing a graphical line to link them?  Will the line move as the control moves?  
BoRiSCommented:
blitz

let me see what i can do...

I'll let you know by comment

later

BoRiS
interCommented:
Hi there,

would you please explain 'drawing a graphical line to link them' more. In addition you may reject my answer so that BoRiS can be able to supply one.

Regards,
Igor
blitz051697Author Commented:
Two controls that are linked would have a line that is drawn between them.   This would be similar to a program like Visio or flowcharting tools. As I move the control (or box or whatever) the line continues to stay linked to any other attached controls.


d003303Commented:
Yo blitz,
I could offer you a bunch of code again. Some time ago I designed some basic flowcharting like classes with connector classes to graphically display a network environment. The classes are extendable, the base connector class supports 1<->1 connections, but any element supports an unlimited number of connections (and, yes, you can drag them around however you want).
Classes with sample app for 500 pts ? Your turn.

Slash/d003303
blitz051697Author Commented:
Ok Slash, What do ya got?

Blitz
d003303Commented:
Yo blitz,

here we go. The first unit is the foundation class. It contains the basic container class(wich holds all objects), the basic connector class (that connects the objects) and, of course, the basic class of the flowchart elements.
The second unit is an example how to extend the basic classes with customized controls.
The third is a sample app using the basic and example classes. All action is on the right mouse key.

////////////////////////////////
//
// base classes
//
// to be FloatCtrls.pas

unit FloatCtrls;

interface

uses Classes, Controls, StdCtrls, ExtCtrls;

type

  TCustomDragObject = class;
  TDragObjectClass = class of TCustomDragObject;

  TBasicConnector = class(TGraphicControl)
  private
    FConnSource,
    FConnTarget  : TCustomDragObject;
    UpsideDown   : Boolean;
  protected
    procedure Paint; override;
    procedure NewBounds;
  public
    constructor CreateConnection(AOwner : TComponent; AParent : TWinControl; ASource, ATarget : TCustomDragObject); virtual;
    procedure DestroyConnection;
    function ConnTarget(AnObject : TCustomDragObject): TCustomDragObject;
  end;

  TConnectorClass = class of TBasicConnector;

  TCustomDragObjectContainer = class(TCustomPanel)
  private
    FCurrentConnectorClass : TConnectorClass;
    FCurrentDragObjectClass : TDragObjectClass;
  public
    constructor Create(AOwner : TComponent); override;
    property CurrentConnectorClass: TConnectorClass read FCurrentConnectorClass write FCurrentConnectorClass;
    property CurrentDragObjectClass: TDragObjectClass read FCurrentDragObjectClass write FCurrentDragObjectClass;
  end;

  TCustomDragObject = class(TCustomPanel)
  private
    FContainer : TCustomDragObjectContainer;
    FIsDragAllowed : Boolean;
    FConnectedObjects : TStringList;
  protected
    procedure DblClick; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure SetIsDragAllowed(NewValue : Boolean);
    function GetConnectionFromTarget(AnObject : TCustomDragObject): TBasicConnector;
    function GetConnectionFromIndex(AnIndex : Integer): TBasicConnector;
    function GetIndexFromConnection(AnObject : TBasicConnector): Integer;
    procedure Connect(AnObject : TBasicConnector);
    procedure Disconnect(AnObject : TBasicConnector);
  public
    constructor CreateContainered(AOwner : TComponent; AContainer : TCustomDragObjectContainer); virtual;
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    procedure ConnectTo(AnObject : TCustomDragObject);
    procedure DisconnectFrom(AnObject : TCustomDragObject);
    procedure DisconnectFromIndex(AnIndex : Integer);
    property IsDragAllowed: Boolean read FIsDragAllowed write SetIsDragAllowed;
    property ConnectedObjects: TStringList read FConnectedObjects;
    property Caption;
  end;

implementation

uses Windows, Messages, SysUtils;

////////////////////////////////////////////////////////////////////////////////

constructor TBasicConnector.CreateConnection(AOwner : TComponent; AParent : TWinControl; ASource, ATarget : TCustomDragObject);
begin
  Create(AOwner);
  FConnSource := ASource;
  FConnTarget := ATarget;
  FConnSource.Connect(Self);
  FConnTarget.Connect(Self);
  Parent := AParent;
  NewBounds;
end;

procedure TBasicConnector.DestroyConnection;
begin
  FConnTarget.Disconnect(Self);
  FConnSource.Disconnect(Self);
  Free;
end;

function TBasicConnector.ConnTarget(AnObject : TCustomDragObject): TCustomDragObject;
begin
  if AnObject = FConnTarget
   then Result := FConnSource
   else Result := FConnTarget;
end;

procedure TBasicConnector.NewBounds;
var ALeft1, ATop1, ALeft2, ATop2, Offset,
    ALeft, ATop, AWidth, AHeight : Integer;
begin
  Offset := Canvas.Pen.Width div 2;
  ALeft1 := FConnSource.Left + FConnSource.Width div 2;
  ATop1 := FConnSource.Top + FConnSource.Height div 2;
  ALeft2 := FConnTarget.Left + FConnTarget.Width div 2;
  ATop2 := FConnTarget.Top + FConnTarget.Height div 2;
  if ALeft1 < ALeft2 then
   begin
    UpsideDown := false;
    ALeft := ALeft1;
    AWidth := ALeft2 - ALeft;
   end
  else
   begin
    UpsideDown := true;
    ALeft := ALeft2;
    AWidth := ALeft1 - ALeft;
   end;
  if ATop1 < ATop2 then
   begin
    ATop := ATop1;
    AHeight := ATop2 - ATop;
   end
  else
   begin
    UpsideDown := not UpsideDown;
    ATop := ATop2;
    AHeight := ATop1 - ATop;
   end;
  SetBounds(ALeft - Offset, ATop - Offset, AWidth + Offset, AHeight + Offset);
end;

procedure TBasicConnector.Paint;
var Offset : Integer;
begin
  inherited Paint;
  Offset := Canvas.Pen.Width div 2;
  if UpsideDown then
   begin
     Canvas.MoveTo(Offset, Height - Offset);
     Canvas.LineTo(Width - Offset, Offset);
   end
  else
   begin
     Canvas.MoveTo(Offset, Offset);
     Canvas.LineTo(Width - Offset, Height - Offset);
   end;
end;

////////////////////////////////////////////////////////////////////////////////

constructor TCustomDragObjectContainer.Create(AOwner : TComponent);
begin
  inherited Create(AOwner);
  FCurrentConnectorClass := TBasicConnector;
  FCurrentDragObjectClass := TCustomDragObject;
  BevelOuter := bvNone;
end;

////////////////////////////////////////////////////////////////////////////////

constructor TCustomDragObject.CreateContainered(AOwner : TComponent; AContainer : TCustomDragObjectContainer);
begin
  Create(AOwner);
  FContainer := AContainer;
end;

constructor TCustomDragObject.Create(AOwner : TComponent);
begin
  inherited Create(AOwner);
  FConnectedObjects := TStringList.Create;
  FIsDragAllowed := false;
  FContainer := nil;
end;

destructor TCustomDragObject.Destroy;
var Index : Integer;
begin
  Index := 0;
  while Index < FConnectedObjects.Count
   do (FConnectedObjects.Objects[Index] as TBasicConnector).DestroyConnection;
  FConnectedObjects.Free;
  inherited Destroy;
end;

function TCustomDragObject.GetConnectionFromTarget(AnObject : TCustomDragObject): TBasicConnector;
var Index : Integer;
begin
  Result := nil;
  Index := 0;
  while Index < FConnectedObjects.Count do
   begin
     if (FConnectedObjects.Objects[Index] as TBasicConnector).ConnTarget(Self) = AnObject then
      begin
        Result := (FConnectedObjects.Objects[Index] as TBasicConnector);
        Break;
      end;
     Inc(Index);
   end;
end;

function TCustomDragObject.GetConnectionFromIndex(AnIndex : Integer): TBasicConnector;
begin
  Result := (FConnectedObjects.Objects[AnIndex] as TBasicConnector)
end;

function TCustomDragObject.GetIndexFromConnection(AnObject : TBasicConnector): Integer;
var Index : Integer;
begin
  Result := -1;
  Index := 0;
  while Index < FConnectedObjects.Count do
   begin
     if (FConnectedObjects.Objects[Index] as TBasicConnector) = AnObject then
      begin
        Result := Index;
        Break;
      end;
     Inc(Index);
   end;
end;

procedure TCustomDragObject.Connect(AnObject : TBasicConnector);
begin
  FConnectedObjects.AddObject(AnObject.ConnTarget(Self).Caption, AnObject);
end;

procedure TCustomDragObject.Disconnect(AnObject : TBasicConnector);
var Index : Integer;
begin
  Index := GetIndexFromConnection(AnObject);
  if Index <> -1
   then FConnectedObjects.Delete(Index)
   else raise Exception.Create('Error while disconnecting from ' + AnObject.ConnTarget(Self).Caption);
end;

procedure TCustomDragObject.ConnectTo(AnObject : TCustomDragObject);
begin
  if GetConnectionFromTarget(AnObject) = nil then
   begin
     if FContainer <> nil
      then FContainer.CurrentConnectorClass.CreateConnection(Self, Parent, Self, AnObject)
      else TBasicConnector.CreateConnection(Self, Parent, Self, AnObject);
   end
  else raise Exception.Create('Already connected to ' + AnObject.Caption);
end;

procedure TCustomDragObject.DisconnectFrom(AnObject : TCustomDragObject);
var AConnector : TBasicConnector;
begin
  AConnector := GetConnectionFromTarget(AnObject);
  if AConnector <> nil
   then AConnector.DestroyConnection
   else raise Exception.Create('Not connected to ' + AnObject.Caption);
end;

procedure TCustomDragObject.DisconnectFromIndex(AnIndex : Integer);
begin
  GetConnectionFromIndex(AnIndex).Free;
end;

procedure TCustomDragObject.SetIsDragAllowed(NewValue : Boolean);
begin
  if FIsDragAllowed <> NewValue then
   begin
     FIsDragAllowed := NewValue;
     if FIsDragAllowed
      then BevelInner := bvLowered
      else BevelInner := bvNone;
   end;
end;

procedure TCustomDragObject.DblClick;
begin
  IsDragAllowed := not IsDragAllowed;
  inherited;
end;

procedure TCustomDragObject.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var Index : Integer;
begin
  if IsDragAllowed then
   begin
     ReleaseCapture;
     SendMessage(Handle, WM_SYSCOMMAND, 61458, 0);
     for Index := 0 to FConnectedObjects.Count - 1
      do (FConnectedObjects.Objects[Index] as TBasicConnector).NewBounds;
   end;
  inherited;
end;

end.

////////////////////////////////
//
// example extension classes
//
// to be ExtFloatCtrls.pas

unit ExtFloatCtrls;

interface

uses Classes, Menus, FloatCtrls;

type

  TMyConnector = class(TBasicConnector)
  public
    constructor Create(AOwner : TComponent); override;
  end;

  TMyDragObjectContainer = class(TCustomDragObjectContainer)
  private
    AContextMenu : TPopUpMenu;
    procedure OnNewItemClick(Sender: TObject);
    procedure OnBasicObjectClick(Sender: TObject);
    procedure OnEnhancedObjectClick(Sender: TObject);
    procedure OnBasicConnectorClick(Sender: TObject);
    procedure OnEnhancedConnectorClick(Sender: TObject);
  public
    constructor Create(AOwner : TComponent); override;
    procedure NewItem(ACaption : string; x, y : LongInt);
  end;

  TMyDragObject = class(TCustomDragObject)
  private
    AContextMenu : TPopUpMenu;
  protected
    procedure DeleteSubMenuItems;
    procedure OnContextMenuPopUp(Sender : TObject);
    procedure ConnectClick(Sender : TObject);
    procedure DisconnectClick(Sender : TObject);
    procedure ToggleMoveClick(Sender : TObject);
    procedure DeleteClick(Sender : TObject);
  public
    constructor Create(AOwner : TComponent); override;
  end;

implementation

uses Windows, SysUtils;

////////////////////////////////////////////////////////////////////////////////

constructor TMyConnector.Create(AOwner : TComponent);
begin
  inherited Create(AOwner);
  Canvas.Pen.Width := 6;
end;

////////////////////////////////////////////////////////////////////////////////

constructor TMyDragObjectContainer.Create(AOwner : TComponent);
var AMenuItem : TMenuItem;
begin
  inherited Create(AOwner);
  CurrentConnectorClass := TMyConnector;
  CurrentDragObjectClass := TMyDragObject;
  AContextMenu := TPopUpMenu.Create(Self);
  PopUpMenu := AContextMenu;

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&New';
  AMenuItem.OnClick := OnNewItemClick;
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '-';
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Objects...';
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Basic';
  AMenuItem.RadioItem := true;
  AMenuItem.OnClick := OnBasicObjectClick;
  AContextMenu.Items[2].Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Enhanced';
  AMenuItem.RadioItem := true;
  AMenuItem.Checked := true;
  AMenuItem.OnClick := OnEnhancedObjectClick;
  AContextMenu.Items[2].Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Connectors...';
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Basic';
  AMenuItem.RadioItem := true;
  AMenuItem.OnClick := OnBasicConnectorClick;
  AContextMenu.Items[3].Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Enhanced';
  AMenuItem.RadioItem := true;
  AMenuItem.Checked := true;
  AMenuItem.OnClick := OnEnhancedConnectorClick;
  AContextMenu.Items[3].Add(AMenuItem);
end;

procedure TMyDragObjectContainer.OnNewItemClick(Sender: TObject);
var APoint : TPoint;
begin
  GetCursorPos(APoint);
  APoint := ScreenToClient(APoint);
  NewItem(IntToStr(ControlCount + 1), APoint.x, APoint.y);
end;

procedure TMyDragObjectContainer.OnBasicObjectClick(Sender: TObject);
begin
  (Sender as TMenuItem).Checked := true;
  CurrentDragObjectClass := TCustomDragObject;
end;

procedure TMyDragObjectContainer.OnEnhancedObjectClick(Sender: TObject);
begin
  (Sender as TMenuItem).Checked := true;
  CurrentDragObjectClass := TMyDragObject;
end;

procedure TMyDragObjectContainer.OnBasicConnectorClick(Sender: TObject);
begin
  (Sender as TMenuItem).Checked := true;
  CurrentConnectorClass := TBasicConnector;
end;

procedure TMyDragObjectContainer.OnEnhancedConnectorClick(Sender: TObject);
begin
  (Sender as TMenuItem).Checked := true;
  CurrentConnectorClass := TMyConnector;
end;

procedure TMyDragObjectContainer.NewItem(ACaption : string; x, y : LongInt);
var NewDragObject : TCustomDragObject;
begin
  NewDragObject := CurrentDragObjectClass.CreateContainered(Self, Self);
  with NewDragObject do
   begin
     Top := y;
     Left := x;
     Width := 100;
     Height := 100;
     Parent := Self;
     Caption := ACaption;
   end;
end;

////////////////////////////////////////////////////////////////////////////////

constructor TMyDragObject.Create(AOwner : TComponent);
var AMenuItem : TMenuItem;
begin
  inherited Create(AOwner);
  AContextMenu := TPopUpMenu.Create(Self);
  AContextMenu.OnPopUp := OnContextMenuPopUp;
  PopUpMenu := AContextMenu;

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Connect to...';
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := 'D&isconnect from...';
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Moveable';
  AMenuItem.OnClick := ToggleMoveClick;
  AMenuItem.Checked := false;
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '-';
  AContextMenu.Items.Add(AMenuItem);

  AMenuItem := TMenuItem.Create(Self);
  AMenuItem.Caption := '&Delete';
  AMenuItem.OnClick := DeleteClick;
  AContextMenu.Items.Add(AMenuItem);
end;

procedure TMyDragObject.OnContextMenuPopUp(Sender : TObject);
var Index1, Index2 : Integer;
    AMenuItem : TMenuItem;
begin
  DeleteSubMenuItems;
  Self.AContextMenu.Items[2].Checked := IsDragAllowed;
  Index2 := 0;
  with (Parent as TCustomDragObjectContainer) do
   for Index1 := 0 to ControlCount - 1 do
    if (Controls[Index1] is TCustomDragObject) then
     begin
       // connect to submenu
       AMenuItem := TMenuItem.Create(Self);
       AMenuItem.Caption := IntToStr(Index2 + 1) + ': ' + (Controls[Index1] as TCustomDragObject).Caption;
       AMenuItem.OnClick := ConnectClick;
       AMenuItem.Tag := Index1;
       if Controls[Index1] = Self
        then AMenuItem.Enabled := false;
       Self.AContextMenu.Items[0].Add(AMenuItem);
       Inc(Index2);
     end;
   if ConnectedObjects.Count = 0
    then Self.AContextMenu.Items[1].Enabled := false
    else Self.AContextMenu.Items[1].Enabled := true;
   for Index1 := 0 to ConnectedObjects.Count - 1 do
    begin
      // connect to submenu
      AMenuItem := TMenuItem.Create(Self);
      AMenuItem.Caption := IntToStr(Index1 + 1) + ': ' + (ConnectedObjects.Objects[Index1] as TBasicConnector).ConnTarget(Self).Caption;
      AMenuItem.OnClick := DisconnectClick;
      AMenuItem.Tag := Index1;
      Self.AContextMenu.Items[1].Add(AMenuItem);
    end;
end;

procedure TMyDragObject.DeleteSubMenuItems;
var AMenuItem : TMenuItem;
 procedure DeleteSubs;
 begin
   while AMenuItem.Count <> 0
    do AMenuItem.Delete(0);
 end;
begin
  AMenuItem := AContextMenu.Items[0];
  DeleteSubs;
  AMenuItem := AContextMenu.Items[1];
  DeleteSubs;
end;

procedure TMyDragObject.ConnectClick(Sender : TObject);
begin
  // wildest typecast
  ConnectTo(((Parent as TCustomDragObjectContainer).Controls[(Sender as TMenuItem).Tag]) as TCustomDragObject);
end;

procedure TMyDragObject.DisconnectClick(Sender : TObject);
begin
  // not so wild typecast as above
  DisconnectFrom(((ConnectedObjects.Objects[(Sender as TMenuItem).Tag]) as TBasicConnector).ConnTarget(Self));
end;

procedure TMyDragObject.ToggleMoveClick(Sender : TObject);
begin
  IsDragAllowed := not IsDragAllowed;
  (Sender as TMenuItem).Checked := IsDragAllowed;
end;

procedure TMyDragObject.DeleteClick(Sender : TObject);
begin
  Free;
end;

end.

////////////////////////////////
//
// sample app
//
// to be _mover.pas

unit _mover;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, ExtFloatCtrls, Menus, StdCtrls;

type

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
     Container : TMyDragObjectContainer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Container := TMyDragObjectContainer.Create(Self);
  with Container do
   begin
     Parent := Self;
     Align := alClient;
   end;
end;

end.

////////////////////////////////
//
// to be _mover.dfm

object Form1: TForm1
  Left = 200
  Top = 108
  Width = 783
  Height = 551
  Caption = 'All options are on the right mouse button !'
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
end

////////////////////////////////
//
// to be mover.dpr

program mover;

uses
  Forms,
  _mover in '_mover.pas' {Form1},
  FloatCtrls in 'FloatCtrls.pas',
  ExtFloatCtrls in 'ExtFloatCtrls.pas';

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

////////////////////////////////

That's mainly it. Look at the sample source in ExtFloatCtrls.pas for the usage. If you have questions, just post them here.

Have fun,
Slash/d003303

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.