1

PictureBox コンポーネントの縦横比 (実際の画像またはその SizeMode とは相互に依存) を維持しながら、画面上の指定されたスペースに最適に収まるように拡大するにはどうすればよいですか?

FlowLayout の Dock と PictureBox を Fill に設定してテストしました。また、Panel をラッパーとして使用してテストし、AutoSize と AutoSizeMode のさまざまな設定をテストしました。

背景に関する詳細情報を提供するには: アプリケーションのビューポートで画像を動的に追加および削除したいので、TableLayout は最初のステップで静的になります。位置のサイズを手動で計算すること、または TableLayout の行と列の数を動的に調整することも考えていたことを認めなければなりませんが、エラーが発生しやすいようです。FlowLayout と自動的にサイズ変更されたコンポーネントを使用するのが正しい方法だと思いましたが、そのようには機能しないようです。(Web 開発者として言えば、単に「画像を左にフロート」し、「幅と高さを「自動」に設定」し、スクロールしないようにしたいだけです。)

画像はこれを少し視覚化する必要があります。最初の図は、PictureBox が 1 つしかない場合のレイアウトを示している必要があります。スペース全体 (または指定されたアスペクト比で可能な限り大きく) を使用します。2 つ目は、2 つ (3 つまたは 4 つ) の画像がある場合にレイアウトをどのようにしたいかを示しています。3 番目の図は、基本的に 3 つ (6 つ) の画像を含むサイズ変更されたウィンドウを示しています。

私が見逃している点はありますか?

PictureBox コンポーネントを動的に追加したり、アプリケーションのサイズを変更したりする際の PictureBox コンポーネントの望ましい動作

4

1 に答える 1

0

このコード スニペットは次のことを行います。

縦横比 (コード内の R 変数を参照) に関してコンテナー内に表示されるコントロールを配置し、コンテナーのマージン値を使用して項目間の水平および垂直のギャップを取得します。コンテナのパディングも処理されます。

public static void Arrange(Control container)
{
    var H = container.DisplayRectangle.Height;
    var W = container.DisplayRectangle.Width;
    var N = container.Controls.OfType<Control>().Count(c => c.Visible);
    var R = 4 / 3d; // item aspect ratio

    var margin = container.Margin;
    var padding = container.Padding;

    var horizontalGap = margin.Left + margin.Right;
    var verticalGap = margin.Top + margin.Bottom;

    if (N == 0)
        return;

    var bestSizedItem = (

        // Try n rows
        Enumerable.Range(1, N).Select(testRowCount =>
        {
            var testItemHeight = (H - verticalGap * (testRowCount - 1)) / testRowCount;

            return new
            {
                testColCount = (int)Math.Ceiling((double)N / testRowCount),
                testRowCount = testRowCount,
                testItemHeight = (int)testItemHeight,
                testItemWidth = (int)(testItemHeight * R)
            };
        })

        // Try n columns
        .Concat(
        Enumerable.Range(1, N).Select(testColCount =>
        {
            var testItemWidth = (W - horizontalGap * (testColCount - 1)) / testColCount;

            return new
            {
                testColCount = testColCount,
                testRowCount = (int)Math.Ceiling((double)N / testColCount),
                testItemHeight = (int)(testItemWidth / R),
                testItemWidth = (int)testItemWidth
            };
        })))

        // Remove when it's too big
        .Where(item => item.testItemWidth * item.testColCount + horizontalGap * (item.testColCount - 1) <= W &&
                       item.testItemHeight * item.testRowCount + verticalGap * (item.testRowCount - 1) <= H)

        // Get the biggest area
        .OrderBy(item => item.testItemHeight * item.testItemWidth)
        .LastOrDefault();

    Debug.Assert(bestSizedItem != null);

    if (bestSizedItem == null)
        return;

    int x = container.DisplayRectangle.X;
    int y = container.DisplayRectangle.Y;

    foreach (var control in container.Controls.OfType<Control>().Where(c => c.Visible))
    {
        control.SetBounds(x, y,
            bestSizedItem.testItemWidth,
            bestSizedItem.testItemHeight);

        x += bestSizedItem.testItemWidth + horizontalGap;
        if (x + bestSizedItem.testItemWidth - horizontalGap > W)
        {
            x = container.DisplayRectangle.X;
            y += bestSizedItem.testItemHeight + verticalGap;
        }
    }
}

このスニペットをGistに置いたので、必要に応じて貢献できます。

于 2013-05-22T20:29:30.260 に答える