Главная » Silverlight » Пример использования событий мыши

0

Рассмотрим пример, иллюстрирующий модель событий мыши и динамическое соз­дание элементов управления.

На рис. 4.6 показано приложение Silverlight, позволяющее перетаскивать небольшие окружности по объекту Canvas. При каждом щелчке на панели Canvas появляется крас­ная окружность. Если щелкнуть на окружности, ее цвет изменяется на зеленый. При отпускании кнопки мыши окружность становится оранжевой. Любую окружность мож­но перетаскивать. Многократно щелкая на панели, можно создать произвольное коли­чество окружностей.

Рис. 4.6. Перетаскивание фигур

Каждая окружность является экземпляром элемента Ellipse — одной из фигур, используемых для двухмерного рисования в Silverlight. Очевидно, определить все окруж­ности в разметке XAML невозможно. Необходим способ генерировать объекты Ellipse динамически при каждом щелчке пользователем на панели Canvas.

Создать объект Ellipse несложно, как и любой объект .NET. После создания нуж­но установить его свойства и подключить обработчики событий. С помощью мето­да SetValue () можно даже устанавливать подключенные свойства, чтобы разместить объект в заданной позиции на холсте. Однако необходим способ размещения объекта Ellipse на панели Canvas. Для этого можно воспользоваться тем, что класс Canvas пре­доставляет коллекцию Children, содержащую все дочерние элементы. В результате до­бавления элемента в коллекцию он выводится на холсте.

В разметке XAML данного примера используется единственный обработчик события Canvas .MouseLeftButtonDown. Никакие другие элементы не определяются.

cCanvas x:Name="parentCanvas" Background="White" MouseLeftButtonDown="canvas_Click">

</Canvas>

В фоновом классе необходимы две переменные, отслеживающие текущий статус (пе­ретаскивается ли объект в данный момент времени) и точную позицию объекта Ellipse.

// Переменная, содержащая статус эллипса

Private bool IsDragging = false;

// Переменная, содержащая позицию щелчка

private Point mouseOffset;

Ниже приведен код обработки события, создающий эллипс при щелчке на объек­те Canvas.

private void canvas_Click(object sender,

MouseButtonEventArgs e)

// Создание эллипса (если пользователь в данный момент // не перетаскивает другой эллипс)

if (Dragging) {

// Присвоение эллипсу диаметра в 50 пикселей

// и заливка красным цветом

Ellipse ellipse = new Ellipse ();

ellipse.Fill = new SolidColorBrush(Colors.Red);

ellipse.Width = 50;

ellipse.Height = 50;

// Применение позиции указателя в качестве // центра эллипса Point point = e.GetPosition(this) ; ellipse.SetValue(Canvas.TopProperty,

point.Y – ellipse.Height/2); ellipse.SetValue(Canvas.LeftProperty,

point.X – ellipse.Width/2);

// Подключение обработчика

ellipse.MouseLeftButtonDown += ellipse_MouseDown;

// Добавление эллипса на холст parentCanvas.Children.Add(ellipse);

}

}

Код не только создает очередной эллипс, но и подключает к нему обработчик ellipse MouseDown, реагирующий на щелчок на эллипсе. Обработчик изменяет цвет эллипса и реализует операцию перетаскивания.

private void ellipse_MouseDown(object sender,

MouseButtonEventArgs e)

{

// Начало режима перетаскивания

isDragging = true;

Ellipse ellipse = (Ellipse)sender;

// Получение позиции указателя при щелчке относительно // эллипса, т.е. левый верхний угол эллипса имеет / / координаты (0,0)

mouseOffset = е.GetPosition(ellipse); // Изменение цвета эллипса

ellipse.Fill = new SolidColorBrush(Colors.Green);

// Подключение к эллипсу событий мыши ellipse.MouseMove += ellipse_MouseMove; ellipse.MouseLeftButtonUp += ellipse_MouseUp;

// Захват мыши, позволяющий получать события мыши, // даже если пользователь резко вывел указатель ellipse.CaptureMouse ();

}

Эллипс не перемещается, пока не возникнет событие MouseMove. В момент его возникновения устанавливаются подключенные свойства Canvas.Left и Canvas.Тор, в результате чего эллипс рисуется в новой позиции. Координаты вычисляются на основе текущей позиции указателя с учетом того, в какой точке эллипса пользователь щелкнул мышью. Благодаря высокой частоте генерации событий MouseMove, эллипс плавно перемещается, пока пользователь не отпустит кнопку мыши. Ниже приведен код обработчика события MouseMove.

private void ellipse_MouseMove(object sender,

MouseEventArgs e)

{

if (isDragging)

(

Ellipse ellipse = (Ellipse)sender;

II Получение позиции эллипса относительно холста

Point point = е.GetPosition(this);

// Перемещение эллипса

ellipse. Set Value (Canvas .TopProperty,

point.Y – mouseOffset.Y); ellipse.SetValue(Canvas.LeftProperty, point.X – mouseOffset.X);

}

}

При отпускании левой кнопки мыши код изменяет цвет эллипса, отменяет захват мыши эллипсом и отключает обработчики событий MouseMove и MouseUp. После это­го пользователь может снова щелкнуть на этом же или другом эллипсе, чтобы начать выполнять описанные выше операции сначала. Ниже приведен код обработчика собы­тия MouseUp.

private void ellipse_MouseUp(object sender,

MouseButtonEventArgs e)

{

if (isDragging)

{

Ellipse ellipse = (Ellipse)sender; // Изменение цвета эллипса

ellipse.Fill = new SolidColorBrush(Colors.Orange);

II Отключение обработчиков и статуса перетаскивания ellipse.MouseMove -= ellipse_MouseMove; ellipse.MouseLeftButtonUp -= ellipse_MouseUp; ellipse.ReleaseMouseCapture(); isDragging = false;

)

)

Форма указателя

Обычно форма указателя изменяется, чтобы сообщить о том, что приложение занято, или просигнализировать о наведении указателя на элемент управления опреде­ленного типа. Изменить форму указателя при наведении на элемент можно с помощью свойства Cursor, наследуемого от класса FrameworkElement.

Каждая форма указателя представлена объектом System.Windows . Input .Cursor. Получить объект Cursor легче всего с помощью статических свойств класса Cursors, приведенного в пространстве имен System.Windows.Input. В класс Cursors включены все стандартные указатели Windows, такие как увеличительное стекло, песочные часы, рука, двухсторонняя стрелка и т.д. Ниже приведен оператор, придающий указателю форму песочных часов.

this.Cursor = Cursors.Wait;

Он вынуждает указатель при наведении на текущую страницу this принять форму песочных часов (в Windows ХР) или водоворота (в Windows Vista).

Примечание. Свойства класса Cursors выводят на экран указатели, определенные в компьютере. Если пользователь

настроил внешний вид стандартных указателей, приложение Silverlight будет выводить настроенные указатели.

Чтобы установить внешний вид указателя в разметке XAML, нужно применить не­посредственно класс Cursors. Это объясняется тем, что преобразователь типов свой­ства Cursor способен распознать имя свойства, а затем извлечь соответствующий объ­ект Cursor из класса Cursors. Ниже приведена разметка, вынуждающая указатель при наведении на кнопку принять форму специальной пиктограммы Help (т.е. вывести ука­затель в виде стрелки и вопросительного знака).

<Button Cursor="Help" Content="Cnpaвкa"></Button>

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

Примечание. В отличие от WPF, платформа Silverlight не поддерживает пользовательские указатели. Однако можно скрыть указатель (установив значение Cursors. None), а затем создать небольшое изображение, отслеживающее координаты скрытого указателя. Это можно сделать с помощью кода, аналогичного примененному в предыдущем примере (вместо эллипса должна перемещаться пиктограмма).

Нажатие клавиши

Как видно из табл. 4.1, для извещения о нажатии клавиш в элементах Silverlight ис­пользуются события KeyDown и KeyUp. Эти события могут подниматься от элемента, имеющего фокус, к элементам более высоких уровней.

Обработчик нажатия клавиши получает объект типа KeyEventArgs, содержащий свойства Key и PlatformKeyCode. Свойство Key обозначает конкретную нажатую кла­вишу с помощью перечисления System. Windows . Input. Key (например, значение Key.S обозначает клавишу <S>). Свойство PlatformKeyCone содержит целое число, которое должно интерпретироваться в зависимости от оборудования и операционной системы, установленных на клиентском компьютере. Например, нестандартная клавиша, кото­рую Silverlight не может распознать, возвращает в свойстве Key значение Key.Unknown, которое невозможно интерпретировать, а свойство PlatformKeyCode возвращает спец­ифичное для клавиши значение, пригодное для использования. Специфичной для ком­пьютеров Microsoft Windows является клавиша <Scroll Lock>.

Примечание. В общем случае рекомендуется избегать кодов, специфичных для конкретной платформы. Однако иногда все же возникает необходимость обработать нестандартную клавишу. Для этого можно применить класс Browserlnformation, содержащийся в пространстве имен System.Windows .Browser и включающий информацию о клиентском компьютере, на котором выполняется приложение.

Далее приведен пример приложения, иллюстрирующего поведение событий клавиа­туры (рис. 4.7). В этом приложении текстовый блок предоставляет три события (KeyDown, KeyUp и высокоуровневое событие TextChanged, генерируемые элементом управления TextBox). Для подключения указанных событий используется следующая разметка.

CTextBox KeyDown="txt_KeyDown" KeyUp="txt_KeyUp" TextChanged="txt_TextChanged"></TextBox>

Обработчики явно подключены в разметке к событиям KeyDown, KeyUp и TextChanged. Однако необходимо учитывать, что события KeyDown и KeyUp являются поднимающими­ся, что дает возможность обрабатывать их на более высоком уровне. Например, подклю­чить обработчики к событиям KeyDown и KeyUp можно через корневой контейнер Grid, чтобы получать события клавиатуры в любом месте страницы.

Ниже приведены коды обработчиков, реагирующих на указанные события.

private void txt_KeyUp(object sender, KeyEventArgs e) (

string message = "KeyUp " + " Key: " + e.Key; IstMessages.Items.Add(message);

}

private void txt_KeyDown(object sender, KeyEventArgs e) {

string message = "KeyDown " + " Key: " + e.Key; IstMessages.Items.Add(message);

)

private void txt_TextChanged (object sender,

TextChangedEventArgs e)

{

string message = "TextChanged"; IstMessages.Items.Add(message);

}

На рис. 4.7 показан результат ввода в текстовое поле буквы s в нижнем регистре.

Рис. 4.7. Отслеживание событий клавиатуры Для ввода одного символа иногда нужно нажать несколько клавиш. Например, что­бы ввести букву S в верхнем регистре, нужно сначала нажать клавишу <Shift>, а за­тем клавишу <S>. На большинстве компьютеров при удерживании клавиши дольше установленного промежутка времени генерируется последовательность событий нажа­тия. Поэтому при вводе буквы S в верхнем регистре можно наблюдать серию событий KeyDown клавиши <Shift>, как показано на рис. 4.8. Однако при этом произойдет толь­ко два события KeyUp (одно — для клавиши <S> и второе — для клавиши <Shift>) и одно событие TextChanged.

Рис. 4.8. При вводе буквы s в верхнем регистре генерируется ряд событий

Примечание. Элементы управления TextBox (и аналогичные им) не предназначены для обработки низкоуровневых событий клавиатуры. При работе с элементами ввода рекомендуется использовать только высокоуровневые события клавиатуры, такие как TextChanged.

Модификаторы клавиш

При нажатии клавиши иногда необходимо получить информацию не только о том, какая клавиша нажата, но и о том, какие еще клавиши в этот момент находятся в на­жатом состоянии. Особенно это относится к клавишам-модификаторам <Shift> и <Ctrl>, поддерживаемым на всех платформах. Конечно, можно подключить к ним обработчики и постоянно отслеживать их состояние, однако намного проще воспользоваться специ­ально для этого предназначенным свойством Modifiers класса Keyboard.

В перечислении Keyboard.Modifier применяется побитовая логика. Например, при­веденный ниже код проверяет, нажата ли в данный момент клавиша <Ctrl>.

if ((Keyboard.Modifiers & ModifierKeys.Control) = ModifierKeys.Control)

{

message += "Клавиша <Ctrl> сейчас нажата";

}

Примечание. Браузер может перехватывать нажатия клавиш. Например, в Internet Explorer невозможно получить событие KeyDown клавиши <Alt>, потому что его перехватывает браузер. Клавиша <Alt> открывает меню Internet Explorer (когда нажата только она) или подготавливает комбинацию клавиш (когда, кроме <Alt>, нажимается еще одна клавиша).

Фокус

В каждый момент времени пользователь работает только с одним элементом управ­ления. Нажатие клавиш обрабатывается только тем элементом управления, который в данный момент имеет фокус. Иногда элемент управления, имеющий фокус, отобра­жается на экране немного иначе, чем в обычном состоянии, чтобы пользователь ви­дел, какому элементу принадлежит фокус. Например, кнопка Silverlight при получении фокуса подсвечивается голубой заливкой.

Для передачи фокуса от текущего элемента к следующему пользователь может либо щелкнуть на следующем элементе, либо нажать клавишу <ТаЬ> (или одну из клавиш управления курсором). На предыдущих платформах разработки программист должен был вручную позаботиться о том, чтобы при нажатии клавиши <ТаЬ> фокус переходил в логичной последовательности (слева направо или сверху вниз, т.е. чтобы не прыгал беспорядочно по форме) и чтобы при открытии окна фокус присваивался определен­ному элементу управления. В Silverlight эта дополнительная работа необходима редко, потому что для реализации последовательности переходов в приложениях Silverlight ис­пользуется иерархическая структура элементов. При нажатии клавиши <ТаЬ> фокус пе­редается первому в разметке дочернему элементу текущего элемента или (если текущий элемент не имеет дочерних) следующему в разметке дочернему элементу, находящемуся на том же уровне вложенности. Например, при проходе по окну с двумя контейнерами StackPanel фокус проходит сначала по всем элементам, вложенным в первый контей­нер, а затем по всем элементам, вложенным во второй контейнер.

Изменить последовательность переходов при нажатии клавиши <ТаЬ> можно с по­мощью свойств Tablndex, принадлежащих элементам управления. Элемент управления, в котором свойство Tablndex имеет значение 0, получает фокус в первую очередь. Затем фокус передается элементу с большим значением Tablndex (например, 1, 2 и т.д.). Если несколько элементов имеют одинаковые значения Tablndex, применяется автоматиче­ская последовательность передачи фокуса, т.е. фокус переходит к следующему в размет­ке элементу, имеющему то же значение Tablndex.

Совет. По умолчанию свойства Tablndex всех элементов управления имеют значение 1. Следовательно, чтобы задать установку фокуса в некоторый элемент управления при открытии окна, достаточно присвоить его свойству Tablndex значение 0. Если не изменить значения Tablndex других элементов управления, переход фокуса по ним будет выполняться в той последовательности, в которой они определены в разметке.

Свойства Tablndex и IsTabStop определены в классе Control. Если присвоить свой­ству isTabStop значение false, элемент управления будет исключен из последователь­ности перехода фокуса. Такой элемент управления может получать фокус другим спо­собом, например программно путем вызова метода Focus () или при щелчке мышью на < элементе управления.

Невидимые и отключенные элементы (они выглядят затененными) исключены из по­следовательности перехода фокуса и не активизируются независимо от текущих значе­ний Tablndex и IsTabStop. Для сокрытия элемента управления можно применить свой­ство Visibility, а для отключения — свойство IsEnabled.

Резюме

Эта глава посвящена зависимым свойствам и маршрутизируемым событиям. Рассмотрены определение и регистрация зависимых свойств, а также их примене­ние для настройки пользовательского интерфейса Silverlight. Кроме того, рассмотрены подъем маршрутизируемых событий вверх по дереву иерархии элементов и базовый на­бор событий мыши и клавиатуры.

Совет. Для лучшего понимания принципов работы платформы Silverlight просмотрите коды базовых элементов интерфейса, таких как Button, UIElement и FrameworkElement. Для этого преобразуйте код IL в код С# с помощью программы Reflector (www. red-gate. com. products/reflector). В коде C# вы сможете увидеть определение зависимых свойств и маршрутизируемых событий, коды статических конструкторов и применение свойств и событий в кодах встроенных классов.

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

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