1

TScrollBox に非常に多くの TPanel を追加した後、テスト アプリケーションの 1 つで、特定の量を超えて描画されたもので問題が発生することに気付きました。描画する前にスクロール ボックスを無効にすると、描画する前に常にクリアされるので、相対的な位置の問題はありません。最初は、ペイントする最大の高さに遭遇したのではないかと思いました。したがって、配置は垂直に積み重ねられたパネルを占有する幅であることを知っています。

そのため、問題を特定して取り組むために新しいプロジェクトを作成しましたが、問題の詳細が明らかになりました。家にいるときは、例とビデオを提供できますが、今は説明します。TScrollBox を持つフォームを spinedit にして、パネルをループで作成するためのボタンと、パネルを解放して別の試行のために配列を空にするためのボタンの数を指定します。識別のためにループ内の番号にキャプションを設定しました。

ビットが重要かどうかを確認するために、2 つのスタッキング方法を試しました。1 つは、高さの I 倍の位置を設定することです。高さが 200 の場合、i * 202 で 2px のスペースが与えられます。私が試した新しい方法は、代わりに align top を使用することでした。効果にはわずかな違いがあるかもしれませんが、一般的な問題は同じです。

新しい問題は、スクロール範囲にあります。ループが完了し、スクロール ボックスが有効になった後、一番下までスクロールすると、最後の番号付きパネルで停止します。しかし、その 200 パネルの 169 のすぐ下の 199 は場違いかもしれません。次に、スクロールバーが範囲を調整して、最後から2番目のパネル198を表示するためだけに一番下に到達できるようにします。これは、私のアプリでは発生しなかったため、上に揃える方法を使用して発生すると思います。さらにテストします。

下部パネルが脇に置かれていない その問題の解決策は、範囲を手動で計算して設定することだと思います。

align top を使用する代わりに位置を設定するときに私のアプリで発生する主な問題は、特定の数のパネルの後、それらがすべて同じ場所の最後に配置されることです。一定量になる前は 50 または 100 と言って問題ありませんが、非常に多くなると発生します。200 かける 200 はかなり小さい整数ですが、アドレス制限があるのでしょうか?

パネルの高さがそれに追加されるかどうかを確認する必要があるので、テストを続けます。しかし、これは既知の問題でなければならないと考えました。ちなみにDelphi 2009。

4

1 に答える 1

7

これは Windows の制限です。ウィンドウ化されたコントロールのサイズは 65,535 ピクセルを超えることはできません。

幅と高さが単一の 32 ビット パラメータで一緒に渡されるWM_SIZE メッセージに関するドキュメントを参照してください。

lParam

lParam の下位ワードは、クライアント領域の新しい幅を指定します。

lParam の上位ワードは、クライアント領域の新しい高さを指定します。

そのため、幅と高さの値は 16 ビットに制限されています。つまり、 whenSetWindowPosまたは alike が関与し、 によってSetBounds呼び出され、 設定によって呼び出されますTop

その後、Top負になる可能性があるコントロールの値は、15 ビットと 1 符号ビットに制限されるため、+-32,767 になります。具体的に言うと、それはControl.ClientOrigin.X/Yによってバインドされている場所です。たとえば、1920x1200 ピクセルの画面の中央に配置されたコントロールの最大Top値は 32,167 になります。

これが、最後のパネルがスクロール ボックス内の同じ場所に表示される理由です。

この制限は、Windows ハンドルのない VCL コントロールには適用されないことに注意してください。


の解き方?

スクロール ボックス内の子コントロールのTopプロパティは、ボックスの可視 clientrect に関連しています。スクロール バーをスクロールするTopと、すべての子のプロパティがリセットされます。

したがって、(ちょうど) 魔法の限界に達する前に、スクロール ボックスをスクロールして Windows を騙します。

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  J: Integer;
  P: TPanel;
begin
  ScrollBox1.DisableAlign;
  try
    ScrollBox1.VertScrollBar.Range := 400 * 202; // 80,800 ! ;-)
    for I := 0 to 3 do
    begin
      ScrollBox1.VertScrollBar.Position := I * 100 * 202;
      for J := 0 to 99 do
      begin
        P := TPanel.Create(Self);
        P.SetBounds(0, J * 202, 100, 200);
        P.Align := alCustom;
        P.Caption := IntToStr(I * 100 + J);
        P.ParentBackground := False;
        P.Color := Random(clWhite);
        P.Parent := ScrollBox1;
      end;
    end;
  finally
    ScrollBox1.VertScrollBar.Position := 0;
    ScrollBox1.EnableAlign;
  end;
end;

それをよりよく解決する方法は?

TPanel(a TWinControl)の代わりに、TControl導関数を使用して への API 呼び出しをバイパスしますSetWindowPos


それを最もよく解決する方法は?

TDBControlGrid多くの印象を与えながら、いくつかのパネルのみを表示する、仮想アプローチを使用します。

于 2013-02-01T23:20:14.147 に答える