Delphi - 图像在桌面坐标内随机移动

Delphi - Image move randomly inside desktop coordinates

我想创建一个小应用程序,它可以将图像平滑地移动到桌面坐标中。 我想知道如何限制图像保留在桌面内? 我试过那样移动图像:

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; 

感谢任何帮助。

谢谢。

您的图像是放在 Windows 桌面上还是放在您 TForm1 上?我猜是后者。所以你必须关心 WINDOW 大小,而不是桌面大小。

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。在不太可能的情况下,您确实需要 Windows DESKTOP 坐标,而不是您的表单坐标,您可以在

处获取它们

http://docwiki.embarcadero.com/Libraries/XE7/en/Vcl.Forms.TScreen.DesktopRect

但是要使用该信息,您必须解决另一个问题 - 如何将 Image1 放在桌面上而不是表格上,这对您来说要复杂得多。所以我不认为你真的是指桌面....

更新。上面的代码虽然非常简单易懂,但它几乎没有做出正确工作的隐含假设。这些假设是:

  • window(form) 大小是一次性固定的,永远不会改变大小。
  • 图片框大小是一次性固定的,永远不会调整。
  • window 在两个维度上都比图像框大。
  • 只有我们的程序可以移动图像框,没有别的可以移动它。

鉴于这些假设(许多年前对于固定屏幕尺寸的计算机来说是自然的),没有必要分析移动物体是太左还是太右、太高或太低。只有新坐标正确与否才重要 - 如果它不再正确,那么 "bouncing" - 反转方向而不看它是哪个 - 就足够了。但是,例如,如果用户可以突然调整 window 的大小并使其变得如此之小以至于图像框会落在它的外面 - 那么这种方法将无限切换方向,因为坐标总是不正确给那些非常小的改动"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; 

更新。几个控件在移动。

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;

.....等等。完成从一到多的转换作为你的家庭任务。