I want to created a small application, which should move images smoothly into the desktop coordinates. I was wondering how can I limit that the image remains inside the desktop? I have try like that to move the image:
procedure TForm1.Timer1Timer(Sender: TObject);
Var
X, Y :Integer;
begin
X:= random(2+1);
Y:= random(2+1);
Image1.Left:= Image1.Left + X;
Image1.Top:= Image1.Top + Y;
Image1.Refresh;
end;
Any help is appreciated.
Thanks.
Is you image placed over Windows Desktop - or over you TForm1
? I guess the latter. So you would have to care about the WINDOW size, not the DESKTOP size.
type TForm1=class(TForm)
....
private
ImageMovesLeft, ImageMovesUp: Boolean;
end;
.....
procedure TForm1.Timer1Timer(Sender: TObject);
Var
dX, dY, NewLeft, NewTop :Integer;
FormSize: TRect;
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - Image1.Height - 1;
FormSize.Right := FormSize.Right - Image1.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImageMovesLeft then dX := -dX;
If ImageMovesUp then dY := -dY;
NewLeft := Image1.Left + dX;
NewTop := Image1.Top + dY;
if ( NewTop >= FormSize.Top ) and ( NewTop <= FormSize.Bottom ) then begin
Image1.Top := NewTop; // we fit into the allowed box
end else begin
ImageMovesUp := not ImageMovesUp; // we did not fit and have to bounce back
end;
if ( NewLeft >= FormSize.Left ) and ( NewLeft <= FormSize.Right ) then begin
Image1.Left := NewLeft; // we fit into the allowed box
end else begin
ImageMovesLeft := not ImageMovesLeft; // we did not fit and have to bounce back
end;
end;
PS. In an unlikely case you really do need the Windows DESKTOP coordinates and not your Form coordinates you can get them at
http://docwiki.embarcadero.com/Libraries/XE7/en/Vcl.Forms.TScreen.DesktopRect
But to use that information you would have to solve another problem - how to place your Image1
over desktop and not over the form, which is much more complex for you. So I do not think you really meant Desktop....
UPD. The code above if very simple and easy to understand, but it makes few implicit assumptions to work correctly. Those assumptions are:
Given those assumptions ( natural for fixed screen size computers many many years ago ) there is no need to analyze if the moving object got too left o too right, too above or too below. It only matters if the new coordinate is correct or not - if it is no more correct, then "bouncing" - reversing the direction without looking which one it was - is enough. But if, for example, user can suddenly resize the window and make it so small that the imagebox would fall outside of it - then this method would stuck infinitely switching directions, because the coordinates would always be incorrect given those very small changes "smooth" movement allows to have.
To adapt to possible sudden and large changes in geometry there can be a number of approaches, but the most simple one would be to make two changes: distinction between two cases of wrong coordinates (too little or too large now would be different cases) and instant jumps of the image into the allowed box when needed, even if the jump would be large and not-smooth.
procedure TForm1.Timer1Timer(Sender: TObject);
var
dX, dY, NewLeft, NewTop :Integer;
FormSize: TRect;
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - Image1.Height - 1;
FormSize.Right := FormSize.Right - Image1.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImageMovesLeft then dX := -dX;
If ImageMovesUp then dY := -dY;
NewLeft := Image1.Left + dX;
NewTop := Image1.Top + dY;
if NewLeft > FormSize.Right then begin
ImageMovesLeft := True;
NewLeft := FormSize.Right;
end;
if NewLeft < FormSize.Left then begin
ImageMovesLeft := False;
NewLeft := FormSize.Left;
end;
if NewTop > FormSize.Bottom then begin
ImageMovesUp := True;
NewTop := FormSize.Bottom;
end;
if NewTop < FormSize.Top then begin
ImageMovesUp := False;
NewTop := FormSize.Top;
end;
Image1.Top := NewTop;
Image1.Left := NewLeft;
end;
UPD. Several controls moving.
type TControlledObject = record
obj: TControl;
MovesLeft, MovesUp: Boolean;
end;
type TForm1=class(TForm)
....
private
images: array of TControlledObject;
end;
procedure TForm1.FormShow(....);
begin
SetLength(images, 3);
with images[0] do begin
obj := Self.Image1;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
with images[1] do begin
obj := Self.Image2;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
with images[2] do begin
obj := Self.Image3;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer
begin
for i := 0 to Length(images)-1 do
MoveImage(images[i]);
end;
procedure TForm1.MoveImage(var ImgRec: TControlledObject);
var .....
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - ImgRec.obj.Height - 1;
FormSize.Right := FormSize.Right - ImgRec.obj.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImgRec.MovesLeft then dX := -dX;
If ImgRec.MovesUp then dY := -dY;
....and so on. Finish the conversion from one to many as your home task.