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 | < Назад | Оглавление | Далее > |