Przykład wtyczki RealTimeStylus
Ta aplikacja demonstruje pracę z klasą RealTimeStylus. Aby zapoznać się ze szczegółowym omówieniem interfejsów API StylusInput, w tym klasy RealTimeStylus, zobacz Uzyskiwanie dostępu do danych wejściowych Stylus i manipulowanie nimi. Aby uzyskać informacje na temat wtyczek synchronicznych i asynchronicznych, zobacz Plug-ins and the RealTimeStylus Class.
Omówienie przykładu
Wtyczki, obiekty implementujące interfejs IStylusSyncPlugin lub IStylusAsyncPlugin interfejsu można dodać do obiektu RealTimeStylus. Ta przykładowa aplikacja używa kilku typów wtyczek:
- Wtyczka filtru pakietów: modyfikuje pakiety. Wtyczka filtru pakietów w tym przykładzie modyfikuje informacje o pakiecie przez ograniczenie wszystkich danych pakietów (x,y) w prostokątnym obszarze.
- Niestandardowa wtyczka dynamicznego modułu renderowania: modyfikuje dynamiczne cechy renderowania. Niestandardowa dynamiczna wtyczka renderowania w tym przykładzie modyfikuje sposób renderowania tuszu, rysując małe okręgi wokół każdego punktu (x,y) na pociągnięciu.
- Wtyczka dynamicznego modułu renderowania: modyfikuje dynamiczne cechy renderowania. W tym przykładzie pokazano użycie obiektu DynamicRenderer jako dodatku do obsługi dynamicznego renderowania tuszu.
- Wtyczka rozpoznawania gestów: rozpoznaje gesty aplikacji. W tym przykładzie pokazano użycie obiektu GestureRecognizer jako dodatku rozszerzającego do rozpoznawania gestów aplikacji (gdy uruchamiany jest na systemie z rozpoznawaniem gestów Microsoft).
Ponadto ten przykład udostępnia interfejs użytkownika, który umożliwia użytkownikowi dodawanie, usuwanie i zmienianie kolejności każdej wtyczki w kolekcji. Przykładowe rozwiązanie zawiera dwa projekty: RealTimeStylusPluginApp i RealTimeStylusPlugins. Aplikacja RealTimeStylusPluginApp zawiera interfejs użytkownika dla przykładu. Funkcja RealTimeStylusPlugins zawiera implementacje wtyczek. Projekt RealTimeStylusPlugins definiuje przestrzeń nazw RealTimeStylusPlugins, która zawiera filtr pakietów i niestandardowe wtyczki modułu renderowania dynamicznego. Ta przestrzeń nazw jest przywołyana przez projekt RealTimeStylusPluginApp. Projekt RealTimeStylusPlugins używa Microsoft.Ink, Microsoft.StylusInputi Microsoft.StylusInput.PluginData przestrzeni nazw.
Aby zapoznać się z omówieniem przestrzeni nazw Microsoft.StylusInput i Microsoft.StylusInput.PluginData, zobacz Architektura interfejsów API StylusInput.
Wtyczka filtru pakietów
Wtyczka filtru pakietów jest wtyczką synchroniczną, która demonstruje modyfikację pakietów. W szczególności definiuje prostokąt w formularzu. Wszystkie pakiety pobierane poza regionem są renderowane wewnątrz regionu. Klasa wtyczki, PacketFilterPlugin
, rejestruje się w celu powiadomienia o StylusDown
, StylusUp
i Packets
zdarzeniach wprowadzania pióra. Klasa implementuje metody StylusDown, StylusUpi Pakiety zdefiniowane w klasie IStylusSyncPlugin.
Publiczny konstruktor dla PacketFilterPlugin
wymaga struktury prostokąta . Ten prostokąt definiuje prostokątny obszar w współrzędnych przestrzeni tuszu (.01 mm = 1 jednostka HIMETRIC), w którym będą zawierane pakiety. Prostokąt jest przechowywany w polu prywatnym, rectangle
.
public class PacketFilterPlugin:IStylusSyncPlugin
{
private System.Drawing.Rectangle rectangle = System.Drawing.Rectangle.Empty;
public PacketFilterPlugin(Rectangle r)
{
rectangle = r;
}
// ...
Klasa PacketFilterPlugin
rejestruje powiadomienia o zdarzeniach, implementując metodę get dla właściwości DataInterest. W tym przypadku wtyczka jest zainteresowana odpowiadaniem na powiadomienia StylusDown
, Packets
, StylusUp
i Error
. Przykład zwraca te wartości, jak określono w enumeracji DataInterestMask. Metoda StylusDown jest wywoływana, gdy czubek pióra kontaktuje się z powierzchnią digitalizatora. Metoda StylusUp jest wywoływana, gdy końcówka pióra opuszcza powierzchnię cyfryzatora. Metoda pakietów jest wywoływana, gdy obiekt RealTimeStylus odbiera pakiety. Metoda Error jest wywoływana, gdy bieżąca wtyczka lub poprzednia wtyczka zgłasza wyjątek.
public DataInterestMask DataInterest
{
get
{
return DataInterestMask.StylusDown |
DataInterestMask.Packets |
DataInterestMask.StylusUp |
DataInterestMask.Error;
}
}
//...
Klasa PacketFilterPlugin
obsługuje większość tych powiadomień w metodzie pomocniczej, ModifyPacketData
. Metoda ModifyPacketData
pobiera wartości x i y dla każdego nowego pakietu z klasy PacketsData. Jeśli którakolwiek wartość znajduje się poza prostokątem, metoda zastępuje wartość najbliższym punktem, który nadal znajduje się w prostokątze. Jest to przykład sposobu, w jaki wtyczka może zastąpić dane pakietu w miarę jak są odbierane ze strumienia wejściowego pióra.
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;
}
}
}
Niestandardowa wtyczka modułu renderowania dynamicznego
Klasa CustomDynamicRenderer
implementuje również klasę IStylusSyncPlugin w celu odbierania powiadomień wejściowych piórem. Następnie obsługuje powiadomienie Packets
, aby narysować mały okrąg wokół każdego nowego punktu pakietu.
Klasa zawiera zmienną Graphics, która zawiera odwołanie do obiektu graficznego przekazanego do konstruktora klasy. Jest to obiekt graficzny używany do renderowania dynamicznego.
private Graphics myGraphics;
public CustomDynamicRendererPlugin(Graphics g)
{
myGraphics = g;
}
//...
Gdy niestandardowa wtyczka renderowania dynamicznego odbiera powiadomienie o pakietach, wyodrębnia dane (x, y) i rysuje zielony mały okrąg wokół punktu. Jest to przykład renderowania niestandardowego na podstawie strumienia danych wejściowych pióra.
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);
}
}
Projekt RealTimeStylusPluginApp
Projekt RealTimeStylusPluginApp demonstruje wcześniej opisane wtyczki, a także wtyczki GestureRecognizer i DynamicRenderer. Interfejs użytkownika projektu składa się z następujących elementów:
- Formularz zawierający kontrolkę GroupBox służącą do definiowania obszaru wprowadzania tuszu.
- Kontrolka typu CheckedListBox do wyświetlania listy i wyboru dostępnych wtyczek.
- Para obiektów typu Button, aby umożliwić zmianę kolejności wtyczek.
Projekt definiuje strukturę, PlugInListItem
, aby ułatwić zarządzanie wtyczkami używanymi w projekcie. Struktura PlugInListItem
zawiera wtyczkę i opis.
Klasa RealTimeStylusPluginApp
implementuje klasę IStylusAsyncPlugin. Jest to konieczne, aby można było powiadomić klasę RealTimeStylusPluginApp
, gdy wtyczka GestureRecognizer dodaje dane gestów do kolejki wyjściowej. Aplikacja rejestruje się do otrzymywania powiadomień o CustomStylusDataAdded. Po odebraniu danych gestów RealTimeStylusPluginApp
umieszcza opis na pasku stanu w dolnej części formularza.
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;
}
}
}
}
Notatka
W implementacji CustomStylusDataAdded jest interesujące, że można zidentyfikować niestandardowe dane gestów w kolejce wyjściowej albo za pomocą identyfikatora GUID (przy użyciu pola GestureRecognitionDataGuid), albo według typu (przy użyciu wyniku z instrukcji as). W przykładzie użyto obu technik identyfikacji do celów demonstracyjnych. Każde z podejść jest również prawidłowe samodzielnie.
W procedurze obsługi zdarzenia ładowania formularza aplikacja tworzy wystąpienia klas PacketFilter
i CustomDynamicRenderer
i dodaje je do listy. Następnie aplikacja próbuje utworzyć wystąpienie klasy GestureRecognizer i, jeśli się powiedzie, doda je do pola listy. Nie powiedzie się, jeśli rozpoznawanie gestów nie jest obecne w systemie. Następnie aplikacja tworzy wystąpienie obiektu DynamicRenderer i dodaje go do pola listy. Na koniec aplikacja włącza każdą z wtyczek oraz sam obiekt RealTimeStylus.
Należy pamiętać o tym, że w metodach pomocniczych obiekt RealTimeStylus jest najpierw wyłączony przed dodaniem lub usunięciem wtyczek, a następnie jest ponownie włączony po zakończeniu dodawania lub usuwania.
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;
}
Tematy pokrewne
-
przykład kolekcji RealTimeStylus Ink Collection