Элемент Shape на С#

Контрол shape - это визуальный элемент, который имеет определенную форму (круг, эллипс, квадрат, звезда).

Когда Microsoft проапгрейдила Visual Studio 6 до Visual Studio 7 (.NET), многие привычные графические контролы (такие как: Image или Shape) были исключены из набора стандартных элементов. В то же время, схожей функциональности, присущей этим контролам, можно добиться используя соответствующие классы библиотеки .NET library, однако для этого требуется больше усилий.

После того, как я достаточно хорошо освоился с графическим программированием под .NET, я смог портировать большинство моих графических программ с VB6 на C#. Наверняка уже существуют множество подобных контролов Shape под .NET от сторонних производителей, но я не смог найти такого, который бы полностью удовлетворил мои потребности. Поэтому я нашел время и реализовал перенос всей функциональности элемента Shape с VB6 на .NET.

В данной статье я хотел бы поделиться с читателями опытом, как я пытался реализовать контрол Shape под .NET.

Sample Image - ShapeControldotNET.jpg

Не много теории...

В VB6 элемент Shape представляет из себя графический и в то же время не большой по размеру контрол. На самом деле он является не настоящим контролом и не обладает таким свойством как Hwnd . В .NET все подобные элементы являются полноценными контролами имеющими свойство Hwnd. В то же время, в Visual Studio .NET не существует контрола эквивалентного Shape, зато есть различные другие классы в библиотеке .NET library, которые при использовании в совокупности могут быть использованы для реализации контрола Shape.

В общих чертах контрол Shape - это некое изображение, которое имеет строго определенную форму. Для управления функциональностью изображения предусмотрены классы Image и Bitmap. Для фигур предусмотрен класс GraphicsPath.

Данные классы являются ключевыми компонентами при реализации контрола Shape.

Прозрачность (Transparency)

В VB6 мы можем использовать свойство DrawMode контрола Shape для достижения эффекта прозрачности (чтобы видеть сквозь контрол). Свойство DrawMode все еще может быть реализовано с использованием GDI/GDI+ функций в .NET, но существует более простое и элегантное решение. .NET поддерживает 32 битную ARGB прорисовку. В VB6 так же поддерживаются 32 битные ARGB значение, которые могут быть назначены цветам, но компонент A (Alpha) такого значения никогда не используется.

Для многих стандартных контролов, порожденных от System.Windows.Form.Control, существуют по крайней мере два свойства, которые используют значения цвета Color: BackColor и ForeColor. Каждое из этих свойств мы можем связать со значением ARGB.

Как же мы можем провести тест для прозрачности? Ответ очевиден - использовать свойство background. Все контролы должны помещаться в контейнеры. Для большинства случаев таким контейнером является форма. В то же время есть контейнеры, которые сами содержат другие контейнеры, например, контрол панели Panel. Для испытания прозрачности мы можем установить в качестве фона контейнера какую-нибудь картинку, а для основного цвета контрола, находящегося в этом контейнере установить значение цвета с where the Alpha меньше, чем 255 (например 100). Теперь вы сможете увидеть картинку-подложку сквозь контрол. Чем ниже значение Alpha, тем отчетливее виден оригинальный фон (background).

Фигура

В VB6 мы так же можем создать пользовательский контрол с различными фигурами. Но это может быть сделано только посредством вызовов Win32 API функций. В .NET каждый контрол имеет свойство Region, которое может быть использовано для задания формы. Когда происходит отрисовка контрола, Windows будет рисовать пиксели только внутри такого региона. Region может быть создан путем определения внешней границы (контура элемента). Контур может быть создан при помощи объекта GraphicsPath. Код, приведенный ниже, создает объект GraphicsPath, добавляет фигуру "эллипс" к траектории, и потом использует эту траекторию для инициализации нового объекта Region, который будет связан со свойством Region контрола. В результате контрол примет форму соотнесенную с данным Region, которым в данном примере является эллипс.

GraphicsPath _outline=new GraphicsPath();

_outline.AddEllipse(0,0,
100,
100);

this.Region=new Region(_outline);

Пользовательские редакторы стадии проектирования

Когда вы используете оболочку Visual Studio .NET IDE, чтобы задать свойства Color , вы можете делать это используя стандартный редактор цветов ( Color Editor), где вы можете выбрать из предложенного набора цветов, или вы можете напрямую впечатать значение При использовании стандартного редактора, вы не можете определять значение для канала Alpha. А если вы прямо прописываете значение для ARGB, вы не знаете, как будет выглядеть этот цвет . В обоих способах есть недостатки.

Однако, Visual Studio .NET позволяет вам создать ваш собственный редактор для редактирования значений свойств. Для контрола Shape я создал два редактора для стадии проектирования. Один для редактирования значения ARGB, а другой - для выбора формы для контрола Shape.

В данной статье я не буду останавливаться на вопросе, как создать пользовательский редактор для стадии проектирования. Вы можете получить по данному вопросу все необходимую информацию из документации .NET по разделу пространства имен для System.Drawing.Design.

Sample screenshot Sample screenshot

Расширение функциональности контрола Shape

Исходный код для представленного контрола Shape (ShapeControl.cs) позволяет легко добавлять/удалять фигуры. Все фигуры определены в блоке перечислений для типа ShapeType. Вы можете редактировать этот блок для добавления/удаления фигур.

public enum ShapeType{
                Rectangle,
                RoundedRectangle,
                Diamond,
                Ellipse,
                TriangleUp,
                TriangleDown,
                TriangleLeft,
                TriangleRight,
                BallonNE,
                BallonNW,
                BallonSW,
                BallonSE,
                CustomPolygon,
                CustomPie
            }

Соответствующий блок добавления/удаления, который отвечает за создание вешнего вида фигуры (по просту формы) выглядит следующим образом:

internal 
static 
void 
updateOutline(ref 
GraphicsPath outline, 
                     ShapeType shape, 
int width,int height)
{
    Switch (Shape)
    {
        Case ShapeType.CustomPie:
            outline.AddPie(0,0,width,height,180,270);
            break;
        Case ShapeType.CustomPolygon:
            outline.AddPolygon(new Point[]{
                          new Point(0,0),
                          new Point(width/2,height/4),
                          new Point(width,0),
                          new Point((width*3)/4,height/2),
                          new Point(width,height),
                          new Point(width/2,(height*3)/4),
                          new Point(0,height),
                          new Point(width/4,height/2)
                                          }
                );
            break;
        Case ShapeType.Diamond:
            outline.AddPolygon(new Point[]{
                        new Point(0,height/2),
                        new Point(width/2,0),
                        new Point(width,height/2),
                        new Point(width/2,height)
                                          });
            break;

        Case ShapeType.Rectangle:
            outline.AddRectangle(new Rectangle(0,0,width,height));
            break;
        .....

Выбор фигуры в редакторе во время создания приложения кодируется таким образом при этом запрашивается перечисления типа ShapeType и вызывается функция updateOutline во время отрисовки пользовательского интерфейса во время проектирования. При этом фигура будет корректно отображена.

Пример - Демо Приложение

Данное приложение было создано, чтобы показать особенности элемента shape. Левая панель демонстрирует прозрачность во время перетаскивания фигуры "алмаз" в рамках панели. Другие контролы - фигуры показывают различные формы и настройки.

Возможные улучшения

Проблемой для любого контрола shape является то, что наверняка потребуются фигуры, которых нет в доступном списке для выбора. Один из путей решения данной проблемы - создание редактора контуров (Outline editor) - для стадии разработки приложения для редактирования свойства Outline. Редактор контуров может позволить пользователю редактировать/создавать объекты GraphicsPath и назначать им свойства Outline (Контур) для контролов с этой формой.

Заключение

Я надеюсь, что читатели извлекут пользу не только от использования контрола shape для создания функционального пользовательского интерфейса, но так же и от изучения различных .NET классов, используемых для создания контрола shape.

<!-- Article Ends -->

Автор: Yang Kok Wah, перевод: cronOS, источник: www.codeproject.com.

Перевод выполнен специально для www.realcoding.net



Опубликовал admin
9 Июн, Четверг 2005г.



Программирование для чайников.