Поделиться через


Пример подключаемого модуля RealTimeStylus

Это приложение демонстрирует работу с классом RealTimeStylus . Подробный обзор API StylusInput, включая класс RealTimeStylus , см. в разделе Доступ к входным данным Stylus и управление ими. Сведения о синхронных и асинхронных подключаемых модулях см. в разделе Подключаемые модули и класс RealTimeStylus.

Обзор примера

Подключаемые модули, объекты, реализующие интерфейс IStylusSyncPlugin или IStylusAsyncPlugin , можно добавить в объект RealTimeStylus . В этом примере приложения используется несколько типов подключаемых модулей:

  • Подключаемый модуль фильтра пакетов: изменяет пакеты. Подключаемый модуль фильтра пакетов в этом примере изменяет сведения о пакетах, ограничивающие все данные пакетов (x,y) в прямоугольной области.
  • Подключаемый модуль пользовательского динамического отрисовщика: изменяет качества динамической отрисовки. Настраиваемый подключаемый модуль динамической отрисовки в этом примере изменяет способ отрисовки рукописного ввода, рисуя небольшой круг вокруг каждой точки (x,y) на росчерке.
  • Подключаемый модуль динамического отрисовщика: изменяет качества динамической отрисовки. В этом примере показано использование объекта DynamicRenderer в качестве подключаемого модуля для обработки динамической отрисовки рукописного ввода.
  • Подключаемый модуль Распознавателя жестов: распознает жесты приложения. В этом примере показано использование объекта GestureRecognizer в качестве подключаемого модуля для распознавания жестов приложения (при работе в системе с распознавателем жестов Майкрософт).

Кроме того, этот пример предоставляет пользовательский интерфейс, позволяющий пользователю добавлять, удалять и изменять порядок каждого подключаемого модуля в коллекции. Пример решения содержит два проекта: RealTimeStylusPluginApp и RealTimeStylusPlugins. RealTimeStylusPluginApp содержит пользовательский интерфейс для примера. RealTimeStylusPlugins содержит реализации подключаемых модулей. Проект RealTimeStylusPlugins определяет пространство имен RealTimeStylusPlugins, которое содержит фильтр пакетов и настраиваемые подключаемые модули динамического отрисовщика. На это пространство имен ссылается проект RealTimeStylusPluginApp. Проект RealTimeStylusPlugins использует пространства имен Microsoft.Ink, Microsoft.StylusInput и Microsoft.StylusInput.PluginData .

Общие сведения о пространствах имен Microsoft.StylusInput и Microsoft.StylusInput.PluginData см. в статье Архитектура API StylusInput.

Подключаемый модуль фильтрации пакетов

Подключаемый модуль фильтра пакетов — это синхронный подключаемый модуль, демонстрирующий изменение пакетов. В частности, он определяет прямоугольник формы. Все пакеты, отрисованные за пределами региона, отрисовываются внутри региона. Подключаемый класс PacketFilterPlugin, , регистрируется для уведомления о событиях StylusDownввода , StylusUpи Packets пера. Класс реализует методы StylusDown, StylusUp и Packets , определенные в классе IStylusSyncPlugin .

Для открытого конструктора для PacketFilterPlugin требуется структура Rectangle . Этот прямоугольник определяет прямоугольную область в координатах пространства рукописного ввода (.01mm = 1 единица HIMETRIC), в которой будут содержаться пакеты. Прямоугольник хранится в закрытом поле . rectangle

public class PacketFilterPlugin:IStylusSyncPlugin  
{
    private System.Drawing.Rectangle rectangle = System.Drawing.Rectangle.Empty;
    public PacketFilterPlugin(Rectangle r)
    {
        rectangle = r;
    }
    // ...

Класс PacketFilterPlugin регистрирует уведомления о событиях, реализуя метод доступа get для свойства DataInterest . В этом случае подключаемый модуль заинтересован в реагировании StylusDownна уведомления , Packets, StylusUpи Error . Пример возвращает эти значения, как определено в перечислении DataInterestMask . Метод StylusDown вызывается, когда кончик пера связывается с поверхностью дигитайзера. Метод StylusUp вызывается, когда кончик пера покидает поверхность дигитайзера. Метод Packets вызывается, когда объект RealTimeStylus получает пакеты. Метод Error вызывается, когда текущий подключаемый модуль или предыдущий подключаемый модуль создает исключение.

public DataInterestMask DataInterest
{
    get
    {
        return DataInterestMask.StylusDown | 
               DataInterestMask.Packets | 
               DataInterestMask.StylusUp | 
               DataInterestMask.Error;
    }
}           
    //...

Класс PacketFilterPlugin обрабатывает большинство этих уведомлений во вспомогательном методе ModifyPacketData. Метод ModifyPacketData получает значения x и y для каждого нового пакета из класса PacketsData . Если любое из значений находится за пределами прямоугольника, метод заменяет значение ближайшей точкой, которая по-прежнему находится в прямоугольнике. Это пример того, как подключаемый модуль может заменить данные пакетов по мере их получения из потока ввода пера.

private void ModifyPacketData(StylusDataBase data)
{
    for (int i = 0; i < data.Count ; i += data.PacketPropertyCount)
    {
        // packet data always has x followed by y followed by the rest
        int x = data[i];
        int y = data[i+1];

        // Constrain points to the input rectangle
        x = Math.Max(x, rectangle.Left);
        x = Math.Min(x, rectangle.Right);
        y = Math.Max(y, rectangle.Top);
        y = Math.Min(y, rectangle.Bottom);

        // If necessary, modify the x,y packet data
        if (x != data[i])
        {
            data[i] = x;
        }
        if (y != data[i+1])
        {
            data[i+1] = y;
        } 
    }
}

Подключаемый модуль пользовательского динамического отрисовщика

Класс CustomDynamicRenderer также реализует класс IStylusSyncPlugin для получения уведомлений ввода с помощью пера. Затем он обрабатывает уведомление, Packets чтобы нарисовать небольшой круг вокруг каждой новой точки пакета.

Класс содержит переменную Graphics , содержащую ссылку на графический объект, переданный в конструктор класса. Это графический объект, используемый для динамической отрисовки.

private Graphics myGraphics;

public CustomDynamicRendererPlugin(Graphics g)
{
    myGraphics = g;
}
        //...
            

Когда подключаемый модуль пользовательского динамического отрисовщика получает уведомление Пакеты, он извлекает данные (x,y) и рисует вокруг точки небольшой зеленый кружок. Это пример пользовательской отрисовки на основе потока ввода пера.

public void Packets(RealTimeStylus sender,  PacketsData data)
{           
    for (int i = 0; i < data.Count; i += data.PacketPropertyCount)
    {
        // Packet data always has x followed by y followed by the rest
        Point point = new Point(data[i], data[i+1]);

        // Since the packet data is in Ink Space coordinates, we need to convert to Pixels...
        point.X = (int)Math.Round((float)point.X * (float)myGraphics.DpiX/2540.0F);
        point.Y = (int)Math.Round((float)point.Y * (float)myGraphics.DpiY/2540.0F);

        // Draw a circle corresponding to the packet
        myGraphics.DrawEllipse(Pens.Green, point.X - 2, point.Y - 2, 4, 4);
    }
}

Проект RealTimeStylusPluginApp

Проект RealTimeStylusPluginApp демонстрирует описанные выше подключаемые модули, а также подключаемые модули GestureRecognizer и DynamicRenderer . Пользовательский интерфейс проекта состоит из следующих элементов:

  • Форма, содержащая элемент управления GroupBox , используемый для определения области ввода рукописного ввода.
  • Элемент управления CheckedListBox для перечисления и выбора доступных подключаемых модулей.
  • Пара объектов Button для включения переупорядочения подключаемых модулей.

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

Сам RealTimeStylusPluginApp класс реализует класс IStylusAsyncPlugin . Это необходимо, RealTimeStylusPluginApp чтобы класс можно было получать уведомления, когда подключаемый модуль GestureRecognizer добавляет данные жестов в очередь вывода. Приложение регистрируется для уведомления о CustomStylusDataAdded. При получении RealTimeStylusPluginApp данных жеста помещает их описание в строку состояния в нижней части формы.

public void CustomStylusDataAdded(RealTimeStylus sender, CustomStylusData data)
{
    if (data.CustomDataId == GestureRecognizer.GestureRecognitionDataGuid)
    {
        GestureRecognitionData grd = data.Data as GestureRecognitionData;
        if (grd != null)
        {
            if (grd.Count > 0)
            {
                GestureAlternate ga = grd[0];
                sbGesture.Text = "Gesture=" + ga.Id + ", Confidence=" + ga.Confidence;
            }
        }
    }
}

Примечание

В реализации CustomStylusDataAdded интересно, что данные пользовательских жестов в очереди вывода можно определить по guid (с помощью поля GestureRecognitionDataGuid ) или по типу (с помощью результата из инструкции as). В примере используются оба метода идентификации для демонстрационных целей. Также допустим любой из этих подходов.

 

В обработчике событий Load формы приложение создает экземпляры PacketFilter классов и и CustomDynamicRenderer добавляет их в список. Затем приложение пытается создать экземпляр класса GestureRecognizer и в случае успеха добавляет его в список. Эта ошибка завершается ошибкой, если распознаватель жестов отсутствует в системе. Затем приложение создает экземпляр объекта DynamicRenderer и добавляет его в список. Наконец, приложение включает каждый из подключаемых модулей и сам объект RealTimeStylus .

Еще одна важная вещь, которую следует отметить в примере, заключается в том, что во вспомогательных методах объект RealTimeStylus сначала отключается перед добавлением или удалением подключаемых модулей, а затем повторно включается после завершения добавления или удаления.

private void RemoveFromPluginCollection(int index)
{
    IStylusSyncPlugin plugin = ((PluginListItem)chklbPlugins.Items[index]).Plugin;

    bool rtsEnabled = myRealTimeStylus.Enabled;
    myRealTimeStylus.Enabled = false;
    myRealTimeStylus.SyncPluginCollection.Remove(plugin);
    myRealTimeStylus.Enabled = rtsEnabled;
}

Microsoft.StylusInput.DynamicRenderer

Microsoft.StylusInput.GestureRecognizer

Microsoft.StylusInput.RealTimeStylus

Microsoft.StylusInput.DataInterestMask

Microsoft.StylusInput.IStylusSyncPlugin

Microsoft.StylusInput.IStylusAsyncPlugin

Microsoft.StylusInput.PluginData.PacketsData

Доступ к входным данным пера и управление ими

Подключаемые модули и класс RealTimeStylus

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