Winforms 绘制渐变矩形的一种有效方法

Winforms 绘制渐变矩形的一种有效方法,winforms,gdi+,Winforms,Gdi+,我正在生成一组具有不同大小和位置的矩形对象。在GDI+中用渐变笔刷填充它们的最佳方式是什么 在WPF中,我可以创建一个LinearGradientBrush,设置起始点和结束点相对点点,WPF将处理其余部分 然而,在GDI+中,渐变笔刷构造函数需要绝对坐标中的位置,这意味着我必须为每个矩形创建一个笔刷,这将是一个非常复杂的操作 我是否遗漏了什么,或者这确实是唯一的方法?我建议您创建一个类似这样的通用方法: public void Paint_rectangle(object sender, Pa

我正在生成一组具有不同大小和位置的矩形对象。在GDI+中用渐变笔刷填充它们的最佳方式是什么

在WPF中,我可以创建一个LinearGradientBrush,设置起始点和结束点
相对点
点,WPF将处理其余部分

然而,在GDI+中,渐变笔刷构造函数需要绝对坐标中的位置,这意味着我必须为每个矩形创建一个笔刷,这将是一个非常复杂的操作


我是否遗漏了什么,或者这确实是唯一的方法?

我建议您创建一个类似这样的通用方法:

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);

如果gradrients颜色都相同,则可以缩短该方法。希望这有帮助。

如果只想声明一次笔刷,可以在应用渐变之前指定一个变换。请注意,使用转换将覆盖可在
LinearGradientBrush
上指定的许多构造函数参数

要修改变换,请调用与所需矩阵操作对应的笔刷对象上的方法。请注意,矩阵运算不是可交换的,因此顺序很重要。出于您的目的,您可能希望按以下顺序对矩形的每个格式副本执行这些操作:缩放、旋转、偏移/平移

请注意,系统级绘图工具实际上并不包含渐变笔刷的库存定义,因此如果您对制作多个笔刷的性能有顾虑,那么创建多个渐变笔刷的成本不应超过GDI+/system.drawing维护定义渐变和样式所需的数据的开销。您可以根据需要为每个矩形创建一个笔刷,而无需深入研究通过变换自定义笔刷所需的数学

下面是一个可以在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();
        }
    }
}
使用System.Drawing.Drawing2D;
命名空间TestMapTransform
{
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
私有void Form1_Paint(对象发送器、PaintEventArgs e)
{
矩形rBrush=新矩形(0,0,1,1);
Color startColor=Color.DarkRed;
Color endColor=Color.White;
LinearGradientBrush br=新的LinearGradientBrush(rBrush、startColor、endColor、LinearGradientMode.Horizontal);
int wpartions=5;
int hPartitions=5;
int w=this.ClientSize.Width;
w=w-(w%wPartitions)+wPartitions;
int h=this.ClientSize.Height;
h=h-(h%HPPartitions)+HPPartitions;
对于(int-hStep=0;hStephUnit?wUnit:hUnit;
br.ResetTransform();
br.ScaleTransform((float)maxUnit*(float)Math.Sqrt(2d),(float)maxUnit*(float)Math.Sqrt(2d),MatrixOrder.Append);
br.旋转变换(45f,矩阵顺序追加);
br.TranslateTransform(wUnit*wStep、hUnit*hStep、MatrixOrder.Append);
e、 图形填充矩形(br,rTile);
br.ResetTransform();
}
}
}
}
私有void Form1_Resize(对象发送方,事件参数e)
{
这个。使无效();
}
}
}
以下是输出的快照:


这无助于消除我对为每个矩形创建渐变笔刷的恐惧。我确实有两支画笔,我需要用来画1000个矩形。对不起,伙计,但我想你没有其他选择。如果您遇到性能问题,可以使用线程进行改进。你可以用它来减少时间。现在,通过为每个矩形创建一个LinearGradientBrush来填充所有这些矩形需要多长时间?我还没有测试,只是希望有和WPF中相同的笔刷创建过程,我觉得我遗漏了一些东西。但看起来这是唯一的方法。你应该先测试一下。也许没你想的那么久。Winforms有一些限制。但是等等,也许有人有更好的答案。祝你好运!嗨,Andres,我似乎不知道如何使用ColorBlend和LinearGradientBrush,它说名称空间不存在,我需要为我的项目添加引用吗?在我看来,我们还有很多计算要做。我会考虑为每个矩形使用一个画笔,看看它是如何运行的。谢谢澄清。欧根,量一下。看看什么是最好的方法。。您可以使用一些简单的方法,例如两个datetime。