Главная » C#, Компоненты » Слои и маркеры

0

При выборе компонента на форме дизайнер предоставляет возможность изменения размеров элемента управления с помощью маркеров (glyph). Количество и положение маркеров может меняться в зависимости от возможностей компонента. Так, например, кнопка имеет восемь маркеров, а компонент

Checkbox — ОДИН (рИС. 6.1 0).

Рис. 6.10. Маркеры изменения размера ‘

Класс System. Windows. Forms . Design.Behavior. Adorner представляет собой невидимую прослойку между дизайнером и пользователем. Каждый слой может содержать один или несколько маркеров, представленных классом System.windows.Forms.Design.Behavior.Glyph. Каждый слой может быть активным (видимым) или неактивным (скрытым). Только активные слои могут реагировать на действия пользователя. Элемент управления может иметь несколько слоев, например слой с маркерами изменения размера, невидимый слой для обработки действий мыши и т. д.

Класс Glyph является базовым для всех маркеров. Кроме него библиотека .NET включает в себя еще два класса маркеров, являющихся наследниками класса Glyph:

?    класс Component Glyph имеет дополнительное свойство RelatedComponent, возвращающее компонент, к которому привязан маркер;

О класс ControiBodyGiyph представляет собой маркер для изменения границ компонента.

Маркер имеет четыре основные "характеристики":

П свойство Behavior возвращает объект типа System.Windows. Forms.Design. Behavior, описывающий поведение маркера, т. е. его реакцию на действия пользователя;

?    свойство Bounds возвращает границы маркера;

?    метод GetHitTest О определяет реальные границы реакции маркера;

?    метод Paint () отвечает за отрисовку маркера.

Таким образом, для создания маркера достаточно определить его поведение, границы и вид. Для примера мы реализуем маркер, позволяющий уменьшать и увеличивать размер компонента (zoom glyph).

Для добавления маркера к компоненту -можно пойти двумя путями. Первый— добавить маркеры напрямую в коллекцию маркеров компонента. Второй — добавить новый слой и уже в него добавить маркер. Реализация первого способа показана в листинге 6.15. Дизайнер предоставляет доступ к маркерам с помощью метода GetGiyphs, возвращающего коллекцию System.Windows.Forms.Design.Behavior.GlyphCollection. Параметр selectionType этого метода описывает текущее состояние компонента: О значение GlyphSelectionType.Notseiected указывает, что компонент не выделен;

?    значение GlyphSelectionType.SelectedPrimary означает, ЧТО компонент ВЫ- бран и является первым в списке;

?    GlyphSelectionType.Selected означает, что компонент выбран, но первым в списке не является.

Перекрыв метод GetGiyphs о, мы добавляем в список маркеров свой маркер

ZoomGlyph:

if (selectionType != GlyphSelectionType.NotSelected)

{

glyphs.Add(new ZoomGlyph(this.BehaviorService, this.Control));

Дополнительная проверка состояния компонента нужна для того, чтобы маркер добавлялся в список, только если компонент выбран в дизайнере. Иначе маркер будет присутствовать всегда.

Лисгин! 6 15 Реализация метода Gutblyphs                                                                                             |

using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms.Design;

using System.Drawing;

using System.ComponentModel;

using System.Windows.Forms;

using System.Windows.Forms.pesign.Behavior;

namespace My Control {

class GradientLabelDesigner : ControlDesigner

{

public override GlyphCollection GetGlyphs{

GlyphSelectionType selectionType)

{

// Получаем коллекцию граничных меток

GlyphCollection glyphs = base.GetGlyphs(selectionType); // Добавляем свою метку

if (selectionType != GlyphSelectionType.NotSelected) {

glyphs.Add(new ZoomGlyph(this.BehaviorService, this.Control));

}

// Возвращаем результат return glyphs;

}

}

}

Второй способ показан в листинге 6.16. При инициализации дизайнера мы добавляем слой zoomAdorner, а затем добавляем в него маркер типа zoomGiyph. В деструкторе дизайнера мы удаляем слой. Управление видимостью также производится в методе GetGlyphs о, но в этом случае мы управляем видимостью не конкретного маркера, а всего слоя. Признаюсь, использовать метод GetGiypho для управления видимостью слоя не совсем правильно.

В разд. 7.5 мы будем рассматривать специальный сервис iselectionservice, который позволит решить вопрос более красиво.

Добавление слоя производится с помощью сервиса Behaviorservice, который предоставляет методы управления маркерами. Более подробно с работой сервисов мы будем разбираться в главе 7, пока же нам достаточно одного свойства и двух методов этого сервиса:

П свойство Adorners возвращает коллекцию слоев;

П метод controiToAdornerWindow() позволяет вычислить координаты границы (и, соответственно, центра) слоя;

? метод syncseiection() обновляет маркеры, синхронизируя их положение с текущим положением и размерами компонента.

Листинг 6 16. Добаплснис слоя

using System;

using System.Collections;

using System.Collections.Generic;

using System. Text;

using System.Windows.Forms.Design;

using System.Drawing;

using System.ComponentModel;

using System.Windows.Forms;

using System.Windows.Forms.Design.Behavior;

namespace MyControl

}

class GradientLabelDesigner : ControlDesigner

}

private Adorner zoomAdorner;

public override void Initialize(IComponent component)

}

base.Initialize(component);

// Добавляем слой zoomAdorner — new Adorner(); Behaviorservice.Adorners.Add(zoomAdorner); // Добавляем метку в новый слой

zoomAdorner.Glyphs.Add(new ZoomGlyph(Behaviorservice, Control));

protected override void Dispose(bool disposing) t

// Удаляем слой

if (disposing && zoomAdorner != null) {

BehaviorService b = BehaviorService; if (b !— null) (

b.Adorners.Remove(zoomAdorner);

}

}

}

public override GlyphCollection GetGlyphs(

GlyphSelectionType selectionType)

{

// Управляем видимостью слоя при изменении // выделенного компонента. Более правильно // использовать сервис ISelectionService. BehaviorService b = BehaviorService; if (b != null) f

int index = b.Adorners.IndexOf(zoomAdorner); if (index > 0) (

b.Adorners[index].Enabled =

(selectionType !- GlyphSelectionType.NotSelected);

}

}

return base.GetGlyphs(selectionType);

}

}

}

Реализация самого класса маркера приведена в листинге 6.17. В конструктор класса ZoomGiyph передаются два параметра: сервис BehaviorService и сам компонент. Свойство Bounds будет возвращать прямоугольник, размером 10×10, располагающийся в центре компонента (сложная калькуляция внутри аксессора как раз и вычисляет центр компонента). Соответственно, метод GetKitTesto будет возвращать курсор в виде руки (cursor.Hand), если указатель мыши попал в этот прямоугольник.

Метод Paint {) производит отрисовку нашей метки, которая будет выглядеть как синий кружок с красным крестом.

Листинг 6 17 Классы ZoomGlyph И ZoamEtehdviour

using System;

using System.Collections.Generic; using System.Text;

using System.Windows.Forms.Design.Behavior; using System.Drawing; using System.Windows.Forms;

namespace MyControl {

class ZoomGlyph : Glyph {

Control control;

BehaviorService behaviorService; Point center;

public ZoomGlyph(BehaviorService behaviorService, Control control) : base{new ZoomBehavior{behaviorService, control))

{

this.behaviorService = behaviorService; this.control = control;

}

// Границы метки

public override Rectangle Bounds {

get

{

// Используем метод сервиса для получения точки // края компонента

Point edge = behaviorService.ControlToAdornerWindow(control); // Размер компонента Size size = control.Size; // Вычисляем центр

center — new Point(edge.X + {size.Width / 2),

edge.Y + {size.Height /2)); // Граница – это прямоугольник 10×10 Rectangle bounds = new Rectangle(center.X – 5,

center.Y – 5, 10, 10);

return bounds;

}

)

// Возвращаем нужный курсор, если указатель мыши // попал на нашу границу. Иначе возвращаем null, public override Cursor GetHitTest(Point p) 1

if (Bounds.Contains(p)) {

return Cursors.Hand;

}

return null;

}

// Рисуем границу

public override void Paint(PaintEventArgs pe) {

// Рисуем кружок с крестиком

ре.Graphics.FillEllipse(Brushes.Blue, Bounds); Pen pen = new Pen(Color.Red); pe.Graphics.DrawLine(

pen, center.X , center.Y-4, center.X , center.Y+4); pe.Graphics.DrawLine(

pen, center.X-4, center.Y , center.X+4, center.Y);

}

// Определяем поведение при попадании курсора на маркер

class ZoomBehavior : Behavior

{

Behaviorservice behaviorservice; Control control;

public ZoomBehavior(Behaviorservice behaviorservice, Control control)

{

this.behaviorservice = behaviorservice; this.control = control;

}

public override bool OnMouseUp(Glyph g, MouseButtons button) {

if (button = MouseButtons.Left)

{

if ( (control.Width < (control.Parent.Width – 10)) && (control.Height < (control.Parent.Height – 10)))

{

// Пересчитываем размер control.Left -= 5; control.Top -= 5; control.Width += 10; control.Height += 10; // Обновляем границы behaviorService.SyncSelection();

}

}

if (button = MouseButtons.Right)

}

if ((controLWidth > 101 « (control.Height > 101)

}

// Пересчитываем размер control.Left += 5; control.Top += 5; control.Width -= 10; control.Height -= 10; // Обновляем границы behaviorService.SyncSelection();

}

}

// true означает, что мы обработали событие return true;

}

}

}

}

Теперь вернемся еще раз к конструктору класса ZoomGlyph. Обратите внимание, что в конструктор базового класса мы передали объект типа zoomBehavior, который будет реализовывать реакцию маркера на действия пользователя. Класс zoorreehavior перекрывает метод OnMouseup, который вызывается при щелчке мыши на маркере. Параметр button позволяет определить, какая именно кнопка мыши была нажата. При щелчке левой кнопкой мы будем увеличивать размер компонента, а при щелчке правой — уменьшать. Вызов метода syncseiection() необходим для перерисовки маркеров в соответствии с новыми размерами компонента.

Рис. 6.11. Маркер Zoom

Литература:

Агуров П. В. C#. Разработка компонентов в MS Visual Studio 2005/2008. – СПб.: БХВ-Петербург, 2008. — 480 е.: ил.

По теме:

  • Комментарии