Forms 格式错误';Delphi中的位置计算

Forms 格式错误';Delphi中的位置计算,forms,delphi,vcl,Forms,Delphi,Vcl,我遇到了一个小问题。 想象两件事:形式,应该被掩盖——掩盖形式;以及覆盖模板的模板-瓷砖。 我的主要目标是用瓷砖覆盖我的封面。所以它看起来像瓷砖。我用下图来说明这个想法 黄色为封面形式,棕色为瓷砖形式。在这张图片上,您可以看到表单彼此之间的位置太近,它们之间没有可用空间。这就是我需要的。 但当我试图达到同样的效果,我只是得到了不满意的结果。如下图所示 第二个图像在最后一个平铺后有偏移。这是因为形状的大小不同。我不知道我的封面表格的确切宽度。我只是把封面的整个宽度分成三部分。但如果封面形式有宽

我遇到了一个小问题。
想象两件事:形式,应该被掩盖——掩盖形式;以及覆盖模板的模板-瓷砖。 我的主要目标是用瓷砖覆盖我的封面。所以它看起来像瓷砖。我用下图来说明这个想法

黄色为封面形式,棕色为瓷砖形式。在这张图片上,您可以看到表单彼此之间的位置太近,它们之间没有可用空间。这就是我需要的。
但当我试图达到同样的效果,我只是得到了不满意的结果。如下图所示

第二个图像在最后一个平铺后有偏移。这是因为形状的大小不同。我不知道我的封面表格的确切宽度。我只是把封面的整个宽度分成三部分。但如果封面形式有宽度,例如173像素,我的每个瓷砖的宽度将等于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. 我修改了上面代码的一些部分。现在,它可以完美地工作,即使是非常小和大的覆盖形式宽度-从67像素。到1237像素。 当然有办法改进这段代码,但主要目标已经实现。 我想我明天就能完成垂直瓷砖的放置,并在那里发布此部分。
在很多方面,大卫的评论给了我一个如何做到这一点的想法。谢谢你,大卫

p.S.S.
我已经从对角线方向阅读了David的第一条评论,所以我更新了代码,以另一种方式工作,但结果仍然不好。您可以在下图中看到它。
第一个磁贴有57像素。宽度;第二个-59像素。;第三块瓷砖-仅31像素。
我就是不知道如何使用David评论中建议的算法正确放置瓷砖。

p.S.S.
同样没有结果。

右红线显示最后一块瓷砖的大尺寸。每个瓷砖的宽度为58像素。
大卫写道:

173/3=58。173-58=115. 115/2=58. 115-58=57. 57/1=57

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

p.S.S.S.
David的程序做不到它应该做的。下面的图片说明了这一点。

第一块和第二块瓷砖之间有一个间隙,右侧有一条红线,如上图所示

p.S.S.S.S.
嗯,现在我的第一部分任务已经完成了。第二个问题是增加更多的瓷砖,但我不确定我是否真的需要它们。我很感谢你能这么做!!他花了这么多时间给我解释一些事情,我不知道该怎么对他说,只是简单地说“非常感谢”。恐怕,我只能提高他的声誉,接受他的职位作为回答。它真的很管用! 在图片上,我们可以看到我需要的结果

p.S.S.S.S.S.
我已经更新了源代码,因此它也可以垂直放置平铺。

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

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;
函数EvenlySpacedColumns(PixelCount,ColumnCount:Integer):TArray;
变量
i:整数;
开始
断言(像素计数>0);
断言(ColumnCount>0);
SetLength(结果、列数);
对于i:=低(结果)到高(结果)确实开始
结果[i]:=PixelCount div ColumnCount;
dec(像素计数,结果[i]);
dec(列计数);
结束;
结束;

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

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

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;
函数EvenlySpacedColumns(PixelCount,ColumnCount:Integer):TArray;
变量
i:整数;
开始
断言(像素计数>0);
断言(ColumnCount>0);
SetLength(结果、列数);
对于i:=低(结果)到高(结果)确实开始
结果[i]:=PixelCount div ColumnCount;
dec(像素计数,结果[i]);
dec(列计数);
结束;
结束;

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

173不能被3整除。因此,不能对每列使用相同的宽度。而是这样做。从Npx像素开始。除以Ncol,取整。将该值用于列0。从Npx中减去该值,然后除以Ncol-1。将该值四舍五入并用于第1列。重复此操作,直到用尽像素和列。此外,除非为了简洁起见有充分的理由遗漏,否则不会将每个磁贴实现为单独的形式。改用形状或其他更合适的东西。@DavidHeffernan,你是说下一种情况,对吗?假设我有173像素宽的封面。我知道我应该每行放置三块瓷砖,所以我除以173/3=57。这是每个瓷砖的宽度。然后我将3个瓦片乘以57,得到171。我知道171小于173,根据这个事实,我应该这样做:173-171=2。这是在第二张图像上显示的最后一块瓷砖之后的一个大小位置,所以我只是增加最后一块瓷砖的宽度,以完全适合封面形式。你觉得这个方法怎么样?@DNR,不幸的是,形状不是一个好的解决方案。不。按照我描述的方式做。不需要多个应用程序。您只需要消耗一个像素库,对于每一列