Вы можете указать преобразование в момент, когда применяется градиент, если вы хотите объявить кисть только один раз. Обратите внимание, что использование преобразований переопределит многие аргументы конструктора, которые могут быть указаны на LinearGradientBrush
.
LinearGradientBrush.Transform Property (System.Drawing.Drawing2D)
Чтобы изменить преобразование, вызывать методы объекта кисти, соответствующие желаемым матричных операций. Обратите внимание, что операции с матрицами не являются коммутативными, поэтому порядок важен. Для ваших целей вы, вероятно, захотите сделать их в этом порядке для каждого исполнения ваших прямоугольников: масштабирование, поворот, смещение/перевод.
LinearGradientBrush.ResetTransform Method @ MSDN
LinearGradientBrush.ScaleTransform Method (Single, Single, MatrixOrder) @ MSDN
LinearGradientBrush.RotateTransform Method (Single, MatrixOrder) @ MSDN
LinearGradientBrush.TranslateTransform Method (Single, Single, MatrixOrder) @ MSDN
Обратите внимание, что инструменты для рисования на системном уровне фактически не содержат определения запаса для градиентной кисти, так что если у вас есть проблемы с производительностью о создании нескольких кистей, создание множества градиентных кистей не должно стоить больше, чем накладные расходы на GDI +/System.Drawin g сохраняя данные, необходимые для определения градиента и стиля. Вы можете быть таким же хорошим, чтобы создавать Brush на каждый прямоугольник по мере необходимости, без необходимости погружаться в математику, необходимую для настройки кисти с помощью преобразования.
Brush Functions (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();
}
}
}
Вот снимок выхода:
Это не поможет против моего страха создания градиента кисти для каждого прямоугольника. У меня действительно есть 2 кисти, которые мне нужно использовать для рисования 1000 прямоугольников. – Eugen
Прошу прощения, но я думаю, у вас нет другого выбора. У вас возникают проблемы с производительностью, которые вы можете улучшить с помощью потоков. Вы можете сократить время с этим. Сколько времени требуется, чтобы заполнить все эти прямоугольники, создав один LinearGradientBrush на каждый прямоугольник? – Andres
Я еще не тестировал, просто надеялся, что у меня будет такой же процесс создания кисти, как в WPF, и у меня появилась идея, что я что-то упустил. Но похоже, что это единственный способ. – Eugen