2017-02-13 3 views
0

私は小さな問題で立ち往生しています。
2つのことを想像してください:フォーム、カバーする必要がある - カバーフォーム。 Cover-Form-Tilesをカバーするフォームが含まれます。 私の主な目標は、私のカバーフォームをタイルでカバーすることです。それでタイルのように見えます。私はこのイメージを以下のイメージで説明します
enter image description here
イエローはカバーフォーム、茶色のフォーム - タイルです。このイメージでは、フォームが互いに接近しすぎて配置されていることがわかります。フォーム間には空きスペースがありません。それだけが必要。
しかし、私が同じ効果に到達しようとすると、満足できない結果しか得られません。下の画像に表示されます
enter image description here
2番目の画像に最後のタイルの後にオフセットがあります。それはフォームのサイズが異なるために起こります。 Cover-Formの幅は正確に分かりません。私は単にCover-Formの全幅を3つに分割します。しかし、Cover-Formの幅が173ピクセルの場合、各タイルの幅は173/3 = 57.6ピクセルになります。これは58に丸められますが、58 * 3 = 174になります。デルファイのフォームの位置計算の誤り

以下のコードは、2番目の画像と同様に状況を実行します。

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 px もちろん、このコードを改善する方法がありますが、主な目標が達成されています。 明日のタイルタイルを完成させて、この部分を公開することができると思います。
多くの点で、David氏のコメントは私にこれをどうやって行うかという考えを与えてくれます。ありがとう、デイビッド!

P.S.
私はDavidの最初のコメントを斜めに読んだので、別の方法で動作するようにコードを更新しますが、結果はまだ良くありません。あなたは下の写真でそれを見ることができます。
最初のタイルは57ピクセルです。幅; 2番目のもの - 59 px。 3番目のタイル - わずか31ピクセル。
Davidのコメントで提案されているアルゴリズムを使って、タイルを正しく配置する方法がわかりません。 enter image description here

P.S.S.
また、結果はありません。
enter image description here
右の赤い線は、最後のタイルの大きなサイズを示しています。各タイルの幅は58ピクセルです。
デビットはこれを書いています:

173/3 = 58です。 173-58 = 115。 115/2 = 58となる。 115-58 = 57。 57/1 = 57

実生活で計算することはできますが、コードで実装することはできません。
ソースコードが更新されました。

P.S.S.S.
ダビデの手続きは、何をすべきかをしません。下の図はそれを示しています。
enter image description here
最初のタイルと2番目のタイルとの間には隙間があり、前の画像と同じように右側に赤い線があります。

p.S.S.S.S.
この時点で、私の仕事の最初の部分が達成されます。もう1つはタイルを追加することですが、本当に必要なのかどうかはわかりません。そして、これに感謝してDavid Heffernan !!彼は私にいくつかのことを説明するのにとても時間を費やしています。そして、私は彼が単に「ありがとう」よりももっと彼に言いたいことを知らない。私は恐れるだけで、彼の評判を高め、答えとして彼のポストを受け入れることができます。それは本当に仕事です! 絵で私達は私が
enter image description here

を必要な結果を見ることができますP.S.S.S.S.S.S.
私はソースコードを更新しているので、タイルも垂直に配置することができます。
enter image description here

+1

173は3で割り切れるわけではありません。Ergo、各列に同じ幅を使用することはできません。代わりに、このようにします。 Npxピクセルで開始します。 Ncolで割る、ラウンド。その値をカラム0に使用します.Npxからその値を減算し、Ncol-1で割ります。その値を丸めて列1に使用します。ピクセルと列がなくなるまで繰り返します。 –

+0

また、簡潔にするために省略した理由がない限り、それぞれのタイルを別々のフォームに実装することはありません。代わりに、図形などを使用してください。 – DNR

+0

@DavidHeffernan、あなたは次の状況を意味しますよね?私はCover-Formの幅が173ピクセルであるとします。私は1列に3つのタイルを配置する必要があることを知っているので、173/3 = 57で割ります。これは各タイルの幅です。そして、私は3タイルを57に乗算して171を得る。私は171が173未満であることを知っている。この事実に従って、私はこれを行うべきである:173 - 171 = 2。これは最後のタイルの後のサイズの場所で、イメージなので、最後のTIleの幅を広げてCover-Formに完全にフィットさせるだけです。この方法についてどう思いますか? – Dima

答えて

2

は、私はこのような単純なアルゴリズムを使用します。ここでは

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)を使うことができます。それは、私が個人的には、浮動小数点演算を避けるべきであるという根拠に基づいて整数算術を選択することになるので、それはやや恣意的です。

+0

これは素晴らしいコードですが、動作しません。たぶん私は何か間違ったことをしました私の質問をもう一度見て、私はいくつかの情報を追加してください。 – Dima

+0

コードは正常に動作します。あなたはそれを間違って使用しています。 'EvenlySpacedColumns(173、3)'は '(57、58、58)'を返します。これらの3つの値の合計は「173」です。それをあなたのコードにどうフィットさせるかがあなたの問題です。私はあなたにもっと挑戦してほしい。あなたはあなたの問題について考えを止めたようです。 –

+0

'' P.SetBounds(F.Left + Arr [i] * i、F.Top、Arr [i]、Round(h)) 'が何をしているのかを自問してください。どうしてなぜあなたは 'Arr [i] * i'を使っていますか?確かに、私はあなたのためにあなたのコードを書くことができますが、それのポイントは何でしょう。あきらめてはいけない。 「自分のコードは機能しません」と宣言しないでください。問題はあなたです。ミラーで見つかると答える私が提示したコードが意図していることを実証することは非常に簡単です。これで、コントロールを正しくレイアウトする方法を理解するだけです。思うよ! –

関連する問題