Delphi

时间:2017-02-13 14:54:09

标签: forms delphi vcl

我遇到了小问题 想象一下两件事:形式,应该涵盖 - 封面形式;和表格将涵盖封面 - 瓷砖。 我的主要目标是用瓷砖覆盖我的封面。所以它看起来像瓷砖。我用下面的图片说明了这个想法 enter image description here
黄色是封面形式,棕色形式 - 瓷砖。在此图像上,您可以看到表单彼此之间的距离太近 - 它们之间没有自由空间。这就是我需要的。
但是当我试图达到同样的效果时,我得到的结果并不令人满意。如下图所示 enter image description here
第二个图像在最后一个图块之后有一个偏移。这是因为形式的大小不同。我不确切知道Cover-Form的宽度是多少。我简单地将Cover-Form的整个宽度分成三部分。但是如果Cover-Form有宽度,例如173像素,我的每个Tiles的宽度将等于173/3 = 57.6像素,这将是圆形到58,但是58 * 3 = 174并且它很糟糕。

以下代码在第二张图像上运行情况。

type
  TTileArray = Array of Array of TPoint;

// This routine comes here from David's answer below and were changed by me
procedure EvenlySpacedTiles(PixelCountH, PixelCountV, TileCount: Integer; var ArrayOut: TTileArray);
var
  X: Integer;
  Y: Integer;
  OldH: Integer;
  OldV: Integer;
  OldCount: Integer;
  OldCount1: Integer;
  TempInt: Integer;
begin
  if (PixelCountH) or (PixelCountV) or(TileCount) = 0 then
    Exit;

  OldH := PixelCountH;
  OldCount1 := TileCount;
  for X:=Low(ArrayOut) to High(ArrayOut) do
    begin
      OldV := PixelCountV;
      OldCount := TileCount;

      TempInt := OldH div OldCount1;
      Dec(OldH, TempInt);
      Dec(OldCount1);
      for Y:=Low(ArrayOut) to High(ArrayOut) do
        begin
          ArrayOut[X, Y] := Point(TempInt, OldV div OldCount);
          Dec(OldV, ArrayOut[X, Y].Y);
          Dec(OldCount);
        end;
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  F: TForm;
  P: TForm;
  Delta: Integer;
  PrevLeft: Integer;
  PrevTop: Integer;
  X:Integer;
  Y: Integer;
  Arr: TTileArray;
  IncLeft: Integer;
begin
  Delta := 3;

  F := TForm.Create(Application);
  F.BorderStyle := Forms.bsNone;
  F.SetBounds(0, 0, 173, 115);
  F.Position := poDesktopCenter;
  F.Color := $11DFEE;
  F.Show;

  SetLength(Arr, Delta, Delta);
  EvenlySpacedTiles(F.Width, F.Height, Delta, Arr);
  PrevLeft := F.Left;
  PrevTop := F.Top;
  IncLeft := 0;
  for X:=Low(Arr) to High(Arr) do
    begin
      PrevTop := F.Top;
      Inc(PrevLeft, IncLeft);
      for Y:=Low(Arr) to High(Arr) do
        begin
          P := TForm.Create(Application);
          P.FormStyle := fsStayOnTop;
          P.BorderStyle := Forms.bsNone;
          P.Color := Random($FFFFFF);//clSkyBlue;
          P.Show;
          P.Width := Arr[X, Y].X;
          P.Height := Arr[X, Y].Y;
          P.Left := PrevLeft;
          P.Top := PrevTop;
          P.Canvas.Rectangle(P.ClientRect);
          Inc(PrevTop, Arr[X, Y].y);
          IncLeft := Arr[X, Y].X;
        end;
    end;
end;

所以我的问题是:如何调整所有瓷砖的宽度(每行3个),与封面形式的宽度无关?

提前致谢。

已修改

P.S。 我修改了上面代码的一些部分。现在它可以完美地工作,即使是极小和大的Cover-Form宽度 - 从67像素。到1237像素。 当然有一种方法可以改进这个代码,但主要目标是实现的。 我想我明天可以完成垂直瓷砖的放置并在那里发布这个部分 在许多方面,大卫的评论让我知道如何做到这一点。谢谢你,大卫!

P.S.S。
我已经在对角线上阅读了David的第一条评论,所以我更新代码以另一种方式工作,但结果仍然不好。您可以在下面的图片中看到它 第一块瓷砖有57像素。宽度;第二个--59像素。第三个瓷砖 - 仅31 px 我只是无法使用David的评论中建议的算法来正确放置Tiles。 enter image description here

P.S.S.S。
再没有结果 enter image description here
右侧红线表示最后一块瓷砖的大尺寸。每个瓷砖的宽度为58像素 大卫写道:

  

3分之173= 58。 173-58 = 115。 2分之115= 58。 115-58 = 57。 57/1 = 57

我能够在现实生活中计算它,但我无法在代码中实现它 源代码已更新。

P.S.S.S.S。
大卫的程序没有做它应该做的事情。下图说明了它 enter image description here
第一个和第二个Tile之间有一个间隙,右侧的红色线与前一个图片之间有一个间隙。

P.S.S.S.S.S。
那么,此时我的任务的第一部分已经完成。第二个 - 添加更多瓷砖,但我不确定我是否真的需要它们。我感谢David Heffernan !!他花了很多时间向我解释一些事情,我不知道如何更多地说出他而不是“非常感谢你”。我担心,我能够提高他的声誉并接受他的帖子作为答案。它确实做到了! 在图片上,我们可以看到我需要的结果 enter image description here

P.S.S.S.S.S.S。
我已经更新了源代码,所以它也可以垂直放置瓷砖 enter image description here

1 个答案:

答案 0 :(得分:3)

我会使用这样一个简单的算法:

function EvenlySpacedColumns(PixelCount, ColumnCount: Integer): TArray<Integer>;
var
  i: Integer;
begin
  Assert(PixelCount>0);
  Assert(ColumnCount>0);
  SetLength(Result, ColumnCount);
  for i := low(Result) to high(Result) do begin
    Result[i] := PixelCount div ColumnCount;
    dec(PixelCount, Result[i]);
    dec(ColumnCount);
  end;
end;

这里我使用的div实际上使用了除法后截断。但如果您愿意,也可以使用Round(PixelCount / ColumnCount)。它有点武断,所以我个人会选择整数运算,理由是如果没有必要,应该避免浮点运算。