Главная » C#, Windows Runtime, XAML, Разработка для Windows 8 » Взаимодействие Metro с пользователем

0

ОС Windows 8 одинаково хорошо работает с мышью, пером и  жестами. Это дает дополнительные преимущества для пользователей, но требует серьезных изменений в модели событий, на которые отвечает код разработчика в ответ на действия пользователей.

Отметим, что событий мыши в  WinRT нет. Ведь если рассматривать  события мыши отдельно от событий, связанных с прикосновениями, то разработчик будет вынужден писать  дополнительных код,  обрабатывающий оба типа  событий. Выделено три типа существующих событий:

·                   События, связанные с нажатиями (пальцем, мышью или пером);

·                   События, связанные с жестами (поворот, перемещение, масштабирование);

·                   События, связанные с перемещениями указателя (мышь, палец или перо).

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

Начнем  наш  обзор с  событий,  связанных с  нажатиями.  Существует  четыре события:

·                   Tapped — позволяет определить щелчок. В случае работы с мышью это щелчок левой кнопки мыши, а в  случае работы с  пальцем — простое касание (с отпусканием пальца);

·                   DoubleTapped — событие, аналогичное предыдущему, но  определяет двойной щелчок. В Platform Preview подобного события не было, но уже в бета-версию платформы его решили добавить, хотя необходимость в нем и неочевидна;

·                   Holding  —  позволяет определить  событие,  связанное с  удержанием правой кнопки мыши или пальца на одном месте экрана. Теоретически именно в ответ на это событие можно отображать контекстное меню, но в большинстве случаев это делается в ответ на следующее событие;

·                   RightTapped  —  позволяет обработать  событие,  которое  для   мыши ассоциируется с  щелчком  правой кнопкой  мыши,  а  в  случае работы с пальцем или пером — отход пальца или пера от экрана после удержания. Иными словами, событие RightTapped может быть сгенерировано после события Holding в момент освобождения пальца или другого устройства ввода.

Следует  отметить,   что   для   генерации   этих   событий   необходимо,   чтобы элемент  имел   установленные в    true   такие   свойства, как   IsTapEnabled, IsDoubleTapEnabled,   IsHoldingEnabled,   IsRightTapEnabled   соответственно. Но  поскольку  в   основе  интерфейса  Windows 8  лежит  его  отзывчивость  на взаимодействие с пользователем, то по умолчанию все эти свойства установлены в true.

Все перечисленные выше события передают в обработчик параметр, одним из свойств которого является PointerDeviceType. Это свойство  может принимать одно из трех значений: Mouse, Touch, Pen. То есть Вы всегда можете определить, с чем работает пользователь.

Самым сложным является событие Holding, так как оно подразумевает работы с несколькими  состояниями. Ниже приведен небольшой блок  кода, который демонстрирует обработку всех состояний:

private void Grid_Holding(object sender, HoldingRoutedEventArgs e)

{

switch (e.HoldingState)

{

case Windows.UI.Input.HoldingState.Started:

. . . . .

break;

case Windows.UI.Input.HoldingState.Completed:

. . . . .

break;

case Windows.UI.Input.HoldingState.Canceled:

. . . . .

break;

}

}

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

Вторая группа событий позволяет реагировать на жесты. Вот эти события:

·                   ManipulationStarting  —  это  событие  позволяет что-то   сделать  до начала манипуляции. Обычно речь идет об инициализации переменных, необходимых для манипуляции;

·                   ManipulationStarted — событие позволяет сигнализировать  о  том, что пользователь начал выполнять манипуляцию с объектом;

·                   ManipulationDelta    —    основное   событие,    которое     приходится обрабатывать. Позволяет  определить   все   необходимые   параметры манипуляции (поворот, перемещение, масштабирование) и применить их к текущему объекту;

·                   ManipulationCompleted   —   событие   сигнализирует   о    завершении манипуляции;

·                   ManipulationInertiaStarting — это событие полезно, если мы планируем добавить некоторую  инерцию  к  действиям  пользователя. Тут  можно установить необходимые параметры.

Итак, если с событиями все ясно, пока непонятно, как определить тот или иной жест. Очевидно, информация скрыта в  параметрах обработчиков событий. Но прежде чем обрабатывать  то или иное  событие, необходимо указать, какой из  типов манипуляций  мы  хотим  обрабатывать. Базируясь  на  инструкциях разработчика, система будет собирать ту или иную информацию, предоставляя ее  только для интересующих объектов  (чтобы избежать лишних  вычислений). Указать тип обрабатываемой манипуляции (режим) можно с помощью свойства ManipulationMode. Тут можно отключить сбор параметров, указать конкретный вид манипуляции (с инерцией или без нее) или обрабатывать  все типы. Режим можно  задать  и  при   обработке  события  ManipulationStarting.  Для  этого в параметре обработчика этого события есть специальное свойство Mode.

Задав режим, можно переходить к определению жестов. Информацию о жестах можно получить с помощью параметра обработчика события ManipulationDelta. Второй  параметр  этого  обработчика  имеет   замечательное  свойство   Delta, которое, в свою  очередь, содержит несколько полезных свойств:

·                   Rotation — задает угол поворота (в подсказке написано, что в градусах,

а на самом деле в радианах);

·                   Expansion — определяет изменение расстояния между двумя  точками касания в пикселях. Данное свойство можно использовать для организации масштабирования;

·                   Translation — задает изменения координат X и Y. Позволяет реализовать перемещение объекта;

·                   Scale — определяет изменение расстояния между двумя точками касания в процентах.

Зная значения перечисленных выше  свойств, мы можем применить к объекту все необходимые трансформации.

Ниже   показан   пример   кода,   который   позволяет  выполнять    вращение изображения  вокруг его  центральной точки.  Вот  как  выглядит содержимое страницы XAML:

<Canvas Background="{StaticResource ApplicationPageBackgroundBrush}">

<Image Source="DSC01707.JPG" Height="300" Width="400" Name="img" ManipulationMode="Rotate" " ManipulationDelta="Image_ManipulationDelta">

</Image>

</Canvas>

А вот  и сам код, который создает необходимую трансформацию и  изменяет ее всякий раз, когда происходит изменение параметра Rotation (мы включили только режим Rotation в нашем коде XAML):

public BlankPage()

{

this.InitializeComponent();

RotateTransform tr = new RotateTransform()

{

Angle = 0,

CenterX = img.ActualWidth / 2, CenterY = img.ActualHeight / 2

};

img.RenderTransform = tr;

}

private void Image_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)

{

RotateTransform rt = img.RenderTransform as RotateTransform; rt.Angle += e.Delta.Rotation * 180 / Math.PI;

e.Handled = true;

}

Последняя группа событий связана с указателем и самая большая:

·                   PointerPressed — определяет момент нажатия указателя;

·                   PointerReleased — определяет момент освобождений указателя;

·                   PointerWheelChanged — реагирует на изменение позиции,  связанной с прокруткой (обычно колесика мыши);

·                   PointerMoved  —  позволяет реагировать на  перемещение   указателя

(в нажатом состоянии);

·                   PointerEntered — позволяет определить, что указатель попал в границы объекта;

·                   PointerExited — позволяет определить, что указатель покинул  границы объекта;

·                   PointerCaptureLost — происходит в том случае, когда указатель перешел в другое окно (например, одно окно находится в прикрепленном режиме, а другое — в режиме Filled);

·                   PointerCanceled — показывает, что указатель вышел за пределы экрана.

Рассмотрим небольшой пример, который позволяет рисовать на экране прямые линии. Внутри XAML мы объявим простой элемент Canvas:

<Canvas Name="LayoutRoot"

Background="{StaticResource ApplicationPageBackgroundBrush}" PointerPressed="Canvas_PointerPressed_1" PointerMoved="Canvas_PointerMoved_1" PointerReleased="LayoutRoot_PointerReleased">

</Canvas>

А   код   позволит устанавливать начальную  точку   для   прорисовки   линий и добавлять новые линии по мере продвижения указателя:

Point? startPoint = null;

private void Canvas_PointerPressed_1(object sender, PointerEventArgs e)

{

startPoint = e.GetCurrentPoint(LayoutRoot).Position;

}

private void Canvas_PointerMoved_1(object sender, PointerEventArgs e)

{

if (startPoint != null)

{

Line l = new Line();

l.X1 = ((Point)startPoint).X; l.Y1 = ((Point)startPoint).Y;

startPoint = e.GetCurrentPoint(LayoutRoot).Position; l.X2 = ((Point)startPoint).X;

l.Y2 = ((Point)startPoint).Y;

l.Stroke = new SolidColorBrush(Colors.Red);

LayoutRoot.Children.Add(l);

}

}

private void LayoutRoot_PointerReleased(object sender, PointerEventArgs e)

{

startPoint = null;

}

Сергей Лутай, Сергей Байдачный, Windows 8 для C# разработчиков

По теме:

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