Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Move/resize components at runtime like IDE

1,196 views
Skip to first unread message

Bernhard Egger

unread,
Apr 21, 2000, 3:00:00 AM4/21/00
to
Does anybody know how to move/resize any visible components on a form at
runtime like in the IDE ?

Components that have the OnPaint, OnMouseMove and Canvas properties are
easy, but I need the same functionality also for TLabel, TButton, ...

Thanx for any help !
Bernhard

Peter Below

unread,
Apr 21, 2000, 3:00:00 AM4/21/00
to
In article <3900225e@dnews>, Bernhard Egger wrote:
> Does anybody know how to move/resize any visible components on a form at
> runtime like in the IDE ?
>
Bernhard,

perhaps this example can get you going:

Example for creating controls on the fly, dragging and resizing them
with the mouse at run-time.

unit Unit1;

interface

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

Type
TControlDragKind =
(dkNone, dkTopLeft, dkTop, dkTopRight, dkRight, dkBottomRight,
dkBottom, dkBottomLeft, dkLeft, dkClient);

TForm1 = class(TForm)
procedure FormClick(Sender: TObject);
private
{ Private declarations }
FDownPos : TPoint; { position of last mouse down,
screen-relative }
FDragKind: TcontrolDragKind; { kind of drag in progress }

procedure ControlMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ControlMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure ControlMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
function GetDragging: Boolean;
public
{ Public declarations }
property DraggingControl: Boolean read GetDragging;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}
Const
{ Set of cursors to use while moving over and dragging on controls. }
DragCursors : Array [TControlDragKind] of TCursor =
( crDefault, crSizeNWSE, crSizeNS, crSizeNESW, crSizeWE,
crSizeNWSE, crSizeNS, crSizeNESW, crSizeWE, crHandPoint );

{Width of "hot zone" for dragging around the control borders. }
HittestMargin = 3;

Type
TCracker = Class(TControl);
{ Needed since TControl.MouseCapture is protected }

{ Perform hittest on the mouse position. Position is in client coordinates
for the passed control. }
function GetDragKind(control: TControl; X,Y: Integer): TControlDragKind;
var
r: TRect;
begin
r:= control.Clientrect;
Result := dkNone;
If Abs(X-r.left) <= HittestMargin Then
If Abs( Y - r.top ) <= HittestMargin Then
Result := dkTopLeft
Else If Abs( Y - r.bottom) <= HittestMargin Then
Result := dkBottomLeft
Else
Result := dkLeft
Else If Abs(X-r.right) <= HittestMargin Then
If Abs( Y - r.top ) <= HittestMargin Then
Result := dkTopRight
Else If Abs( Y - r.bottom) <= HittestMargin Then
Result := dkBottomRight
Else
Result := dkRight
Else If Abs( Y - r.top ) <= HittestMargin Then
Result := dkTop
Else If Abs( Y - r.bottom) <= HittestMargin Then
Result := dkBottom
Else If PtInRect( r, Point(X,Y)) Then
Result := dkClient;
end; { GetDragKind }

procedure TForm1.FormClick(Sender: TObject);
var
pt: TPoint;
begin
// get cursor position, convert to client coordinates
GetCursorPos( pt );
pt := ScreenToClient( pt );
// create label with top left corner at mouse position
With TLabel.Create( Self ) Do Begin
SetBounds( pt.x, pt.y, width, height );
Caption := Format('Hit at %d,%d',[pt.x, pt.y]);
Color := clBlue;
Font.Color := clWhite;
Autosize := False; { Otherwise resizing is futile. }
Parent := Self;

// attach the drag handlers
OnMouseDown := ControlMouseDown;
OnMouseUp := ControlMouseUp;
OnMouseMove := ControlMouseMove;
End; { With }
end; { FormClick }

procedure TForm1.ControlMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
{ Go into drag mode if left mouse button went down and no modifier key
is pressed. }
If (Button = mbLeft) and (Shift = [ssLeft]) Then Begin
{ Determine where on the control the mouse went down. }
FDragKind := GetDragKind( Sender As TControl, X, Y );
If FDragKind <> dkNone Then Begin
With TCracker(Sender) Do Begin
{ Record current position screen-relative, the origin for the
client-relative position will move if the form is moved or
resized on left/top sides. }
FDownPos:= ClientToScreen( Point( X, Y ));
MouseCapture := True;
Color := clRed;
End; { With }
End; { If }
End; { If }
end; { ControlMouseDown }

procedure TForm1.ControlMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
dx, dy: Integer;
pt: TPoint;
r: TRect;
begin
{ Set controls cursor depending on position in control. }
(Sender as TControl).Cursor :=
DragCursors[ GetDragKind( TControl(Sender), X, Y )];

{ If we are dragging the control, get amount the mouse has moved since
last call and calculate a new boundsrect for the control from it,
depending on drag mode. }
If DraggingControl Then
with Sender As TControl Do Begin
pt:= ClientToScreen( Point( X, Y ));
dx:= pt.X - FDownPos.X;
dy:= pt.Y - FDownPos.Y;
{ Update stored mouse position to current position. }
FDownPos := pt;
r:= BoundsRect;
Case FDragKind Of
dkTopLeft: Begin
r.Left := r.Left + dx;
r.Top := r.Top + dy;
End; { Case dkTopLeft }
dkTop: Begin
r.Top := r.Top + dy;
End; { Case dkTop }
dkTopRight: Begin
r.Right := r.Right + dx;
r.Top := r.Top + dy;
End; { Case dkTopRight }
dkRight: Begin
r.Right := r.Right + dx;
End; { Case dkRight }
dkBottomRight: Begin
r.Right := r.Right + dx;
r.Bottom := r.Bottom + dy;
End; { Case dkBottomRight }
dkBottom: Begin
r.Bottom := r.Bottom + dy;
End; { Case dkBottom }
dkBottomLeft: Begin
r.Left := r.Left + dx;
r.Bottom := r.Bottom + dy;
End; { Case dkBottomLeft }
dkLeft: Begin
r.Left := r.Left + dx;
End; { Case dkLeft }
dkClient: Begin
OffsetRect( r, dx, dy );
End; { Case dkClient }
End; { Case }
{ Don't let the control be resized to nothing }
If ((r.right - r.left ) > 2*HittestMargin) and
((r.bottom - r.top ) > 2*HittestMargin)
Then
Boundsrect := r;
End; { With }
end; { ControlMouseMove }

procedure TForm1.ControlMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
If DraggingControl then Begin
{ Revert to non-dragging state. }
FDragKind := dkNone;
With TCracker(Sender) Do Begin
MouseCapture := False;
Color := clBlue;
End; { With }
End; { If }
end; { ControlMouseUp }

{ Read method for ControlDragging property, returns true if form is in
drag
mode. }
function TForm1.GetDragging: Boolean;
begin
Result := FDragKind <> dkNone;
end;

end.

Peter Below (TeamB) 10011...@compuserve.com)
No e-mail responses, please, unless explicitly requested!


Bernhard Egger

unread,
Apr 25, 2000, 3:00:00 AM4/25/00
to
Peter,

thanks a lot, it's exactly what I've been looking for !

Just one more question: I tested all components I need in my app,
all are ok except TComboBox, TRadioGroup and TBevel.

Do you know why ?

Regards,
Bernhard

Peter Below

unread,
Apr 25, 2000, 3:00:00 AM4/25/00
to
In article <39058B1E...@iiic.ethz.ch>, Bernhard Egger wrote:
> thanks a lot, it's exactly what I've been looking for !
>
> Just one more question: I tested all components I need in my app,
> all are ok except TComboBox, TRadioGroup and TBevel.
>
> Do you know why ?

What kind of problems do you have with these? TCombobox would probably
resist attempt to change its height but i don't see why the other two
would cause problems.

Bernhard Egger

unread,
Apr 25, 2000, 3:00:00 AM4/25/00
to
> What kind of problems do you have with these? TCombobox would probably
> resist attempt to change its height but i don't see why the other two
> would cause problems.
>

hmmm, I look like a fool now...at home, under Delphi5/Win2K everything runs
like you said: only the TComboBox does'nt change its height...but at the
university (NT 4 WKS, SP5, Delphi 4) the components mentioned before didn't
move/resize at all ! I'll try to reproduce this tomorrow.

I would like to look the component moving/resizing exactly like in the IDE,
i.e. with 'hot spots' to change the size and a rectangle when I move the
component.
My idea is to put a TMoveResizeFrame (which I would have to develop) onto
the selected component and propagate changes to the underlying component.
This TMoveResizeFrame would have nice little blax boxes on the edges and
look like a rectangle while moving.
Do you think this could work ? What would be your approach ?

One last question: is it possible to create a class by its class name ? Like
class := CreateClassByName("TClassName"); // or some other 'magic' function

Thanks a lot,
Bernhard


Peter Below (TeamB)

unread,
Apr 27, 2000, 3:00:00 AM4/27/00
to
In article <390605a3@dnews>, Bernhard Egger wrote:
> I would like to look the component moving/resizing exactly like in the IDE,
> i.e. with 'hot spots' to change the size and a rectangle when I move the
> component.
>

Go fishing for a component named TStretchHandle on the sites below. It gives
you such grab handles.

Delphi Super Page http://sunsite.icm.edu.pl/delphi/
US mirror site: http://www.cdrom.com/pub/delphi_www/
German mirror :
http://ftp.uni-erlangen.de/pub/source/MIRRORS/sunsite.icm.edu.pl/pub/delphi
Other mirrors : http://ftp.sunet.se/delphi/
Torry's Delphi Pages http://www.torry.ru/
the Delphi Box http://Inner-Smile.com .
http://www.delphisource.com/
The DELPHI Deli http://www.delphix.com/
The Delphi EXchange http://www.delphiexchange.com/

0 new messages