Опубликован: 24.03.2009 | Доступ: свободный | Студентов: 2283 / 115 | Оценка: 4.24 / 3.93 | Длительность: 17:47:00
Лекция 11:

Мультимедиа, рукописный ввод и Deep Zoom

Программирование для рукописного ввода в Silverlight

При написании приложений инструментами Microsoft под термином рукописный ввод (Ink) обычно подразумевается надпись или рисунок от руки, создаваемый пользователем с помощью описанных ранее устройств рукописного ввода, таких как цифровое перо, сенсорный экран или мышь. При использовании в приложении Silverlight эти устройства обеспечивают заполнение объекта StrokeCollec-tion отдельными объектами Stroke. В свою очередь, Stroke выполняет запись действий устройства, например пера, к которым относятся действия: перо опускается (pen-down), перо перемещается (pen-move) и перо поднимается (pen-up). Stroke может представлять точку, прямую линию или кривую. Это осуществляется с помощью объекта StylusPointCollection, который содержит объекты StylusPoint, создаваемые преобразователем графической информации, связанным с пером, сенсорным экраном или мышью. Атрибуты рукописного ввода содержаться в классе DrawingAttributes.

Как говорилось, Silverlight принимает элементы рукописного ввода с помощью класса InkPresenter. Это подкласс элемента Canvas, который также содержит коллекцию обводок в StrokeCollection. При добавлении обводок в StrokeCollection, InkPresenter автоматически формирует их визуальное представление, используя соответствующие DrawingAttributes.

Обычно InkPresenter добавляется в XAML приложения во время разработки дизайна, но объекты Stroke, составляющие StrokeCollection, будут добавляться во время выполнения с помощью JavaScript.

Далее представлен пример использования перекрывающего изображение InkPresenter на странице:

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml">
  <Image Source="sushi.jpg" Width="600" Height="400"></Image>
  <InkPresenter x:Name="inkEl" Background="transparent" 
                Width="600" Height="400" 
                MouseLeftButtonDown="inkMouseDown" 
                MouseMove="inkMouseMove" 
                MouseLeftButtonUp="inkMouseUp"/>
</Canvas>

InkPresenter определяет обработчики событий MouseLeftButtonDown, MouseMove и MouseUp. Мы рассмотрим, как это делается в JavaScript, для чего создадим простое приложение для рукописного ввода. Затем далее в этом разделе то же самое будет сделано на C#. Сходство необыкновенное! Для этих событий понадобятся функции-обработчики действий "начало рукописного ввода", "рукописный ввод" и "прекращение рукописного ввода".

Примечание Хотя рукописный ввод может быть выполнен пером, с помощью сенсорного экрана или мыши, в документации API используется термин "Мышь".

Прежде чем перейти к функциям-обработчикам событий JavaScript, требуется выполнить некоторые вспомогательные операции по объявлению глобальных переменных, необходимых для поддержки этих действий:

var theInk;       // Ссылка на модуль отображения рукописного ввода
var newStroke;  // Ссылка на обводку
var theControl;  // Ссылка на элемент управления Silverlight
function handleLoad(control, userContext, rootElement)
{
 // Событие Load возвращает ссылку на элемент управления,
 // но другие обработчики событий нет. Поэтому мы собираемся
 // создать ссылку на элемент управления здесь
 theControl = control;
 // Здесь мы создадим ссылку на элемент рукописного ввода 
 theInk = control.content. findName("inkEl"); 
}

Эти вспомогательные переменные для InkPresenter, текущей обводки и самого элемента управления Silverlight будут использоваться функциями, поддерживающими описанные выше действия рукописного ввода. При загрузке элемент управления Silverlight запускает функцию handleLoad. В качестве параметра она принимает ссылку на элемент управления Silverlight, но поскольку реализованные нами обработчики событий мыши не делают этого, данную ссылку необходимо сохранить в handleLoad. В ходе выполнения handleLoad можно также получить ссылку на InkPresenter, проведя его поиск по имени ( in-kEl ). Тогда не придется вызывать getHost для получения ссылки на родительский элемент UI, чтобы найти InkPresenter, при каждом выполнении обработчика событий.

Теперь можно приступать к рассмотрению обработчиков событий. Сначала разберемся, что происходит при формировании события MouseLeftButtonDown, результатом чего является выполнение функции inkMouseDown (Нажатие кнопки мыши при рукописном вводе). Мы будем отслеживать перемещения мыши аналогично тому, как это происходило при обработке перемещения методом "drag-and-drop", что рассматривалось в "Элемент управления браузера Silverlight" . При получении входных данных от мыши создается новый объект Stroke, содержащий объект DrawingAttributes, который определяет визуальные характеристики этой обводки. В представленном здесь примере DrawingAttributes будет обеспечивать следующие параметры обводки: Width - 2, Height-2, цвет заливки - White (Белый), и цвет контура - White. Тип MouseEven-tArgs в Silverlight поддерживает метод getStylusPoints, как было показано ранее в этой лекции, который принимает InkPresenter в качестве единственного параметра. Этот метод возвращает тип StylusPointCol-lection, который используется в методе AddStylusPoints обводки. Теперь можно добавить обводку в StrokesCollection InkPresenter. Посмотрим на код:

function inkMouseDown(sender,args) 
{
 // Перехватываем событие мыши. 
 theInk.CaptureMouse();
 // Создаем новую обводку.
 newStroke = theControl.content.createFromXaml('<Stroke/>');
 // Задаем новый элемент атрибутов рисования для обводки. 
 // Он, как следует из его имени, определяет внешний вид обводки 
 var da =    theControl.content.CreateFromXaml('<DrawingAttributes/>'); 
 newStroke.DrawingAttributes = da;
 // Теперь, когда обводка имеет атрибуты рисования, 
 // зададим их значения... 
 newStroke.DrawingAttributes.Width = 2; 
 newStroke.DrawingAttributes.Height = 2; 
 newStroke.DrawingAttributes.Color = "White"; 
 newStroke.DrawingAttributes.OutlineColor = "White";
 newStroke.StylusPoints.Add StylusPoints(args.GetS tylusPoints(theInk)); 
 theInk.Strokes.Add (newStroke); 
}

Теперь перемещение курсора мыши по холсту в состоянии отрисовки обводки (т.е. когда newStroke не null ) означает добавление новых штрихов в эту обводку и отображается в виде следа, оставляемого мышью. Вот код, реализующий это:

// Добавляем новые штрихи в Stroke, с которым работаем в данный момент.
function inkMouseMove(sender,args)
{
 if (newStroke != null)
 { 
  newStroke.StylusPoints.AddStylusPoints(args.GetStylusPoints(theInk));
 }
}

Наконец, по завершении отрисовки обводки, когда вы отпускаете кнопку мыши (или отрываете перо от экрана), формируется событие MouseLeftButtonUp. После этого требуется очистить обводку и прекратить отслеживание мыши. После того, как переменной newStroke задается значение null, движение мыши (или пера) по экрану больше не будет обеспечивать добавление штрихов в обводку, и, следовательно, обводка не будет отрисовываться. Рассмотрим код:

function inkMouseUp(sender,args) 
{
 // Задаем newStroke значение null
 newStroke = null;
 // Прекращаем отслеживать перемещения мыши 
 theInk.releaseMouseCapture(); 
}

На рис. 11.16 показан пример приложения до добавления в него рукописного примечания. На рис. 11ly представлено то же приложение с рукописным примечанием, которое было отрисовано с помощью мыши или пера.

 Выполнение приложения Silverlightc возможностью рукописного ввода

Рис. 11.16. Выполнение приложения Silverlightc возможностью рукописного ввода
 Приложение Silverlight с возможностью рукописного ввода с рукописным примечанием

Рис. 11.17. Приложение Silverlight с возможностью рукописного ввода с рукописным примечанием

В предыдущем примере было продемонстрировано, как программировать рукописный ввод, используя Silverlight и JavaScript. Конечно же, то же самое можно сделать с помощью управляемого кода. Вот полный выделенный код на C#, обеспечивающий создание такого же приложения:

using System;
using System. Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Ink;
namespace NetInkSample 
{
 public partial class Page : UserControl 
 {
  Stroke newStroke; public Page() 
  {
   InitializeComponent(); 
  }
  private void inkEl  MouseLeftButtonDown( object sender, MouseButtonEventArgs e) 
  {
  inkEl.CaptureMouse();
  // Создаем новую обводку.
  newStroke = new Stroke();
  DrawingAttributes da = new DrawingAttributes();
  newStroke.DrawingAttributes = da;
  newStroke.DrawingAttributes.Width=2;
  newStroke.DrawingAttributes.Height=2;
  newStroke.DrawingAttributes.Color= Colors.White;
  newStroke.DrawingAttributes.OutlineColor= Colors. White;
  newStroke. StylusPoints.Add(e.Sty lusDevice.GetStylusPoints(inkEl));
  inkEl.Strokes.Add (newStroke); }
  private void inkEl  MouseMove(object sender, MouseEventArgs e) {
  if (newStroke != null) {
   newStroke.StylusPoints.Add ( e.Sty lusDevice. GetS tylusPoints(inkEl));
   }
  }
  private void inkEl  MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
  {
   newStroke = null; inkEl.ReleaseMouseCapture(); 
  } 
 } 
}

И в XAML-коде, соответственно, необходимо сделать изменения:

<Image Source="sushi.jpg" Width="600" Height="400">
</Image> 
<InkPresenter x:Name="inkEl" Background="transparent" 
           Width="600" Height="400" 
           MouseLeftButtonDown="inkEl   MouseLeftButtonDown" 
           MouseMove="inkEl  MouseMove" 
           MouseLeftButtonUp="inkEl   MouseLeftButtonUp"/>

Кроме демонстрации гибкости Silverlight, который позволяет разрабатывать приложения как на языке сценариев JavaScript, так и на компилируемых языках программирования .NET, это также показывает простоту перехода от JavaScript к .NET, что позволяет без труда обновить существующие Silverlight-приложения на JavaScript до Silverlight 2 и перейти к управляемому коду.