| netlib.narod.ru | < Назад | Оглавление | Далее > |
Помимо рисования и заливки, контуры позволяют определять область отсечения для объекта Graphics.
Методы SetClip класса Graphics (выборочно)
| void SetClip(GraphicsPath path) |
| void SetClip(GraphicsPath path, CombineMode cm) |
Пусть в контуре содержится эллипс. При вызове первой версии метода SetClip вывод всех элементов, которые будут нарисованы затем, будет ограничен областью, заданной этим эллипсом. О второй версии метода SetClip я расскажу чуть позже. А сейчас давайте сразу перейдем к демонстрационной программе. Программа Clover определяет контур из четырех перекрывающихся эллипсов, задающий область отсечения.
Clover.cs
//---------------------------------------
// Clover.cs (C) 2001 by Charles Petzold
//---------------------------------------
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class Clover: PrintableForm
{
public new static void Main()
{
Application.Run(new Clover());
}
public Clover()
{
Text = "Clover";
}
protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
{
GraphicsPath path = new GraphicsPath();
path.AddEllipse(0, cy / 3, cx / 2, cy / 3); // Левый
path.AddEllipse(cx / 2, cy / 3, cx / 2, cy / 3); // Правый
path.AddEllipse(cx / 3, 0, cx / 3, cy / 2); // Верхний
path.AddEllipse(cx / 3, cy / 2, cx / 3, cy / 2); // Нижний
grfx.SetClip(path);
grfx.TranslateTransform(cx / 2, cy / 2);
Pen pen = new Pen(clr);
float fRadius = (float) Math.Sqrt(Math.Pow(cx / 2, 2) +
Math.Pow(cy / 2, 2));
for (float fAngle = 0; fAngle < (float) Math.PI * 2;
fAngle += (float) Math.PI / 180)
{
grfx.DrawLine(pen, 0, 0, fRadius * (float) Math.Cos(fAngle),
-fRadius * (float) Math.Sin(fAngle));
}
}
}
Метод DoPage создает объект GraphicsPath. Созданный контур состоит из 4 эллипсов, размер которых зависит от размера клиентской области или страницы принтера. Метод SetClip задаст для объекта Graphics область отсечения, ограниченную созданным контуром.
Далее DoPage указывает начало координат в центре области рисования и рисует 360 линий, расходящихся от центра во все стороны. Линии обрезаются по границам внутренних областей эллипсов:

Нарисовать такую картинку любым другим способом было бы куда труднее. Заметьте: в область отсечения не входят области перекрытия эллипсов. Это результат режима заливки контуров, заданного по умолчанию, — FillMode.Alternate. Если перед вызовом SetClip изменить режим заливки:
path.FillMode = FillMode.Winding;
области перекрытия эллипсов станут частью области отсечения.
Алгоритм отсечения часто работает медленно. Я породил класс Clover от PrintableForm, так что можно распечатать картинку, щелкнув по клиентской области, но знайте: программа может печатать изображение час или даже дольше.
Естественно, возникает вопрос: как преобразование страницы и мировое преобразование повлияют на область отсечения?
При вызове SetClip предполагается, что координаты контура — это мировые координаты. Последние преобразуются в координаты устройства так же, как при прорисовке или заливке контура. При этом границы области отсечения сохраняются в координатах устройства и остаются таковыми. Например, после вызова SetClip в программе Clover можно как угодно менять преобразование страницы и мировое преобразование, но рисование линий по-прежнему будет ограничено той же областью окна. Фактически после вызова метода TranslateTransform расположение области отсечения в программе Clover не изменилось.
Вторая из версий SetClip позволяет дополнить существующую область отсечения новой, заданной этим методом.
Перечисление CombineMode
| Член | Значение | Описание |
| Replace | 0 | Область отсечения заменяется на новую |
| Intersect | 1 | Область отсечения — общий фрагмент старой и новой областей |
| Union | 2 | Область отсечения — объединение старой и новой областей |
| Xor | 3 | Область отсечения — объединение неперекрывающихся частей старой и новой областей |
| Exclude | 4 | Область отсечения — старая область без фрагментов, перекрывающихся новой |
| Complement | 5 | Область отсечения — новая область без фрагментов, перекрывающихся старой |
Следующая программа создаст область отсечения на основе двух перекрывающихся эллипсов. Команда меню позволяет выбирать значение перечисления CombineMode, определяющее способ объединения двух эллипсов. После этого программа целиком закрашивает клиентскую область. Как и в PathWarping, я присвоил каждому пункту меню значение от 1 до 5, соответствующее одному из значений перечисления CombineMode.
ClippingCombinations.cs
//-----------------------------------------------------
// ClippingCombinations.cs (C) 2001 by Charles Petzold
//-----------------------------------------------------
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class ClippingCombinations: PrintableForm
{
string strCaption = "CombineMode = ";
MenuItem miCombineMode;
public new static void Main()
{
Application.Run(new ClippingCombinations());
}
public ClippingCombinations()
{
Text = strCaption + (CombineMode)0;
Menu = new MainMenu();
Menu.MenuItems.Add("&CombineMode");
EventHandler ehClick = new EventHandler(MenuCombineModeOnClick);
for (int i = 0; i < 6; i++)
{
MenuItem mi = new MenuItem("&" + (CombineMode)i);
mi.Click += ehClick;
mi.RadioCheck = true;
Menu.MenuItems[0].MenuItems.Add(mi);
}
miCombineMode = Menu.MenuItems[0].MenuItems[0];
miCombineMode.Checked = true;
}
void MenuCombineModeOnClick(object obj, EventArgs ea)
{
miCombineMode.Checked = false;
miCombineMode = (MenuItem) obj;
miCombineMode.Checked = true;
Text = strCaption + (CombineMode)miCombineMode.Index;
Invalidate();
}
protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
{
GraphicsPath path = new GraphicsPath();
path.AddEllipse(0, 0, 2 * cx / 3, cy);
grfx.SetClip(path);
path.Reset();
path.AddEllipse(cx / 3, 0, 2 * cx / 3, cy);
grfx.SetClip(path, (CombineMode)miCombineMode.Index);
grfx.FillRectangle(Brushes.Red, 0, 0, cx, cy);
}
}
Вот результат выполнения программы при выборе режима объединения CombineMode.Xor.

Дополнительные версии метода позволяют задавать (или комбинировать) области отсечения при помощи прямоугольников:
Методы SetClip класса Graphics (выборочно)
| void SetClip(Rectangle rect) |
| void SetClip(Rectangle rect, CombineMode cm) |
| void SetClip(RectangleF rectf) |
| void SetClip(RectangleF rectf, CombineMode cm) |
В классе Graphics также есть методы IntersectClip и ExcludeClip, которые позволяют модифицировать существующую область отсечения. Чтобы задать обычную (т.е. бесконечно большую) область отсечения, вызовите метод ResetClip.
Метод ResetClip класса Graphics
| void ResetClip() |
| netlib.narod.ru | < Назад | Оглавление | Далее > |