6

サイズと位置が異なる一連のRectangleFオブジェクトを生成しています。GDI +のグラデーションブラシでそれらを埋める最良の方法は何でしょうか?

WPFでは、LinearGradientBrushを作成し、開始点と終了relative点を設定すると、残りはWPFが処理します。

ただし、GDI +では、グラデーションブラシコンストラクターは絶対座標での位置を必要とします。つまり、長方形ごとにブラシを作成する必要があり、これは非常に複雑な操作になります。

私は何かが足りないのですか、それともそれが唯一の方法ですか?

4

2 に答える 2

1

ブラシを一度だけ宣言したい場合は、グラデーションが適用される直前に変換を指定できます。変換を使用すると、 で指定できるコンストラクター引数の多くがオーバーライドされることに注意してくださいLinearGradientBrush

LinearGradientBrush.Transform プロパティ (System.Drawing.Drawing2D)

変換を変更するには、目的のマトリックス操作に対応するブラシ オブジェクトのメソッドを呼び出します。行列演算は可換ではないため、順序が重要であることに注意してください。目的のために、おそらく、長方形の各レンディションに対して、スケール、回転、オフセット/移動の順序でそれらを実行することをお勧めします。

LinearGradientBrush.ResetTransform メソッド @ MSDN

LinearGradientBrush.ScaleTransform メソッド (Single、Single、MatrixOrder) @ MSDN

LinearGradientBrush.RotateTransform メソッド (Single、MatrixOrder) @ MSDN

LinearGradientBrush.TranslateTransform メソッド (Single、Single、MatrixOrder) @ MSDN

システム レベルの描画ツールにはグラデーション ブラシのストック定義が実際には含まれていないことに注意してください。そのため、複数のブラシを作成することにパフォーマンス上の懸念がある場合、多数のグラデーション ブラシを作成しても、GDI+/システムのオーバーヘッド以上のコストはかからないはずです。グラデーションとスタイリングを定義するために必要なデータを保持する.Drawing。変換を介してブラシをカスタマイズするために必要な数学に飛び込むことなく、必要に応じて四角形ごとにブラシを作成するのと同じくらいうまくいくかもしれません。

ブラシ関数 (Windows) @ MSDN

WinForms アプリでテストできるコード例を次に示します。このアプリは、45 度のグラデーションを使用してグラデーション ブラシでタイルをペイントし、タイルの最大寸法にスケーリングします (単純に計算されます)。値と変換をいじると、自明でないグラデーション定義がある場合、すべての四角形に変換を設定する手法を使用する価値がないことに気付くかもしれません。それ以外の場合、変換はワールド レベルで適用されることに注意してください。GDI の世界では、y 軸が上下逆になっていますが、デカルトの数学の世界では、下から上に並べられています。これにより、角度も時計回りに適用されますが、三角法では、上向きの y 軸の値が増加するにつれて、角度は反時計回りに進みます。

using System.Drawing.Drawing2D;

namespace TestMapTransform
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Rectangle rBrush = new Rectangle(0,0,1,1);
            Color startColor = Color.DarkRed;
            Color endColor = Color.White;
            LinearGradientBrush br = new LinearGradientBrush(rBrush, startColor, endColor, LinearGradientMode.Horizontal);

            int wPartitions = 5;
            int hPartitions = 5;

            int w = this.ClientSize.Width;
            w = w - (w % wPartitions) + wPartitions;
            int h = this.ClientSize.Height;
            h = h - (h % hPartitions) + hPartitions;

            for (int hStep = 0; hStep < hPartitions; hStep++)
            {
                int hUnit = h / hPartitions;
                for (int wStep = 0; wStep < wPartitions; wStep++)
                {
                    int wUnit = w / wPartitions;

                    Rectangle rTile = new Rectangle(wUnit * wStep, hUnit * hStep, wUnit, hUnit);

                    if (e.ClipRectangle.IntersectsWith(rTile))
                    {
                        int maxUnit = wUnit > hUnit ? wUnit : hUnit;

                        br.ResetTransform();
                        br.ScaleTransform((float)maxUnit * (float)Math.Sqrt(2d), (float)maxUnit * (float)Math.Sqrt(2d), MatrixOrder.Append);
                        br.RotateTransform(45f, MatrixOrder.Append);
                        br.TranslateTransform(wUnit * wStep, hUnit * hStep, MatrixOrder.Append);

                        e.Graphics.FillRectangle(br, rTile);

                        br.ResetTransform();
                    }
                }
            }
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            this.Invalidate();
        }
    }
}

出力のスナップショットを次に示します。

グラデーション タイル ペインティングを使用した 5x5 フォーム

于 2013-02-25T20:29:12.700 に答える
0

次のようなジェネリック メソッドを作成することをお勧めします。

public void Paint_rectangle(object sender, PaintEventArgs e)
    {
        RectangleF r = new RectangleF(0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
        if (r.Width > 0 && r.Height > 0)
        {
            Color c1 = Color.LightBlue;
            Color c2 = Color.White;
            Color c3 = Color.LightBlue;

            LinearGradientBrush br = new LinearGradientBrush(r, c1, c3, 90, true);
            ColorBlend cb = new ColorBlend();
            cb.Positions = new[] { 0, (float)0.5, 1 };
            cb.Colors = new[] { c1, c2, c3 };
            br.InterpolationColors = cb;

            // paint
            e.Graphics.FillRectangle(br, r);
        }
    }

次に、すべての長方形に対して次のように呼び出します。

yourrectangleF.Paint += new PaintEventHandler(Paint_rectangle);

グラデーションの色がすべて同じである場合は、そのメソッドを短くすることができます。それが役に立ったことを願っています..

于 2013-02-25T18:59:44.557 に答える