Beispiel für die Freihandserialisierung
In diesem Beispiel wird veranschaulicht, wie Freihand in verschiedenen Formaten serialisiert und deserialisiert wird. Die Anwendung stellt ein Formular mit Feldern für die Eingabe von Vornamen, Nachnamen und Signatur dar. Der Benutzer kann diese Daten als reines Serialisiertes Freihandformat (Ink Serialized Format, ISF), Extensible Markup Language (XML) mit base64-codiertem ISF oder HTML speichern, der auf Freihand in einem base64-codierten GIF-Bild (Fortified Graphics Interchange Format) verweist. Die Anwendung ermöglicht es dem Benutzer auch, Dateien zu öffnen, die im XML- und ISF-Format gespeichert wurden. Das ISF-Format verwendet erweiterte Eigenschaften, um den Vor- und Nachnamen zu speichern, während die XML- und HTML-Formate diese Informationen in benutzerdefinierten Attributen speichern.
In diesem Beispiel wird das Laden aus dem HTML-Format nicht unterstützt, da HTML nicht zum Speichern strukturierter Daten geeignet ist. Da die Daten in Name, Signatur usw. getrennt sind, ist ein Format erforderlich, das diese Trennung beibehalten wird, z. B. XML oder ein anderes Datenbankformat.
HTML ist sehr nützlich in einer Umgebung, in der Formatierung wichtig ist, z. B. in einem Textverarbeitungsdokument. Der HTML-Code, der in diesem Beispiel gespeichert wird, verwendet angereicherte GIFs. Diese GIFs haben ISF eingebettet, wodurch die volle Genauigkeit der Freihand beibehalten wird. Eine Textverarbeitungsanwendung kann ein Dokument speichern, das mehrere Datentypen enthält, z. B. Bilder, Tabellen, formatierten Text und Freihandeingaben, die in einem HTML-Format beibehalten werden. Dieser HTML-Code würde in Browsern gerendert, die Freihandeingaben nicht erkennen. Wenn sie jedoch in eine Anwendung geladen wird, die freihandfähig ist, ist die vollständige Genauigkeit der ursprünglichen Freihandeingabe verfügbar und kann gerendert, bearbeitet oder zur Erkennung verwendet werden.
In diesem Beispiel werden die folgenden Features verwendet:
- Load-Methode desInk-Objekts
- Save-Methode des Freihandobjekts
- Die ExtendedProperties-Eigenschaft des Freihandobjekts
Erfassen von Freihandeingaben
Verweisen Sie zunächst auf die Tablet-PC-API, die mit dem Software Development Kit (SDK) für Windows Vista und Windows XP Tablet PC Edition installiert sind.
using Microsoft.Ink;
Der Konstruktor erstellt und aktiviert einen InkCollector ( ic
) für das Formular.
ic = new InkCollector(Signature.Handle);
ic.Enabled = true;
Speichern einer Datei
Die SaveAsMenu_Click
-Methode verarbeitet das Dialogfeld Speichern unter, erstellt einen Dateidatenstrom, in dem die Freihanddaten gespeichert werden sollen, und ruft die Save-Methode auf, die der Auswahl des Benutzers entspricht.
Speichern in einer ISF-Datei
In der SaveISF
-Methode werden der Vor- und Nachname der ExtendedProperties-Eigenschaft der InkCollector-Eigenschaft des InkCollector-Objekts hinzugefügt, bevor die Freihandeingabe serialisiert und in die Datei geschrieben wird. Nach der Serialisierung der Freihandeingabe werden die Werte für Vor- und Nachname aus der ExtendedProperties-Eigenschaft des Ink-Objekts entfernt.
byte[] isf;
// This is the ink object which is serialized
ExtendedProperties inkProperties = ic.Ink.ExtendedProperties;
// Store the name fields in the ink object
// These fields roundtrip through the ISF format
// Ignore empty fields since strictly empty strings
// cannot be stored in ExtendedProperties.
if (FirstNameBox.Text.Length > 0)
{
inkProperties.Add(FirstName, FirstNameBox.Text);
}
if (LastNameBox.Text.Length > 0)
{
inkProperties.Add(LastName, LastNameBox.Text);
}
// Perform the serialization
isf = ic.Ink.Save(PersistenceFormat.InkSerializedFormat);
// If the first and last names were added as extended
// properties to the ink, remove them - these properties
// are only used for the save and there is no need to
// keep them around on the ink object.
if (inkProperties.DoesPropertyExist(FirstName))
{
inkProperties.Remove(FirstName);
}
if (inkProperties.DoesPropertyExist(LastName))
{
inkProperties.Remove(LastName);
}
// Write the ISF to the stream
s.Write(isf,0,isf.Length);
Speichern in einer XML-Datei
In der SaveXML
-Methode wird ein XmlTextWriter-Objekt verwendet, um ein XML-Dokument zu erstellen und in ein XML-Dokument zu schreiben. Mithilfe der Save-Methode des Ink-Objekts wird die Freihandeingabe zunächst in ein Base64-codiertes Bytearray im serialisierten Freihandformat konvertiert, und dann wird das Bytearray in eine Zeichenfolge konvertiert, die in die XML-Datei geschrieben werden soll. Die Textdaten aus dem Formular werden auch in die XML-Datei geschrieben.
// Get the base64 encoded ISF
base64ISF_bytes = ic.Ink.Save(PersistenceFormat.Base64InkSerializedFormat);
// Convert it to a String
base64ISF_string = utf8.GetString(base64ISF_bytes);
// Write the ISF containing node to the XML
xwriter.WriteElementString("Ink", base64ISF_string);
// Write the text data from the form
// Note that the names are stored as XML fields, rather
// than custom properties, so that these properties can
// be most easily accessible if the XML is saved in a database.
xwriter.WriteElementString("FirstName",FirstNameBox.Text);
xwriter.WriteElementString("LastName",LastNameBox.Text);
Speichern in einer HTML-Datei
Die SaveHTML-Methode verwendet das Begrenzungsfeld der Strokes-Auflistung , um zu testen, ob eine Signatur vorhanden ist. Wenn die Signatur vorhanden ist, wird sie mithilfe der Save-Methode des Freihandobjekts in das angereicherte GIF-Format konvertiert und in eine Datei geschrieben. Anschließend wird in der HTML-Datei auf das GIF verwiesen.
if (ic.Ink.Strokes.GetBoundingBox().IsEmpty)
{
MessageBox.Show("Unable to save empty ink in HTML persistence format.");
}
else
{
FileStream gifFile;
byte[] fortifiedGif = null;
...
// Create a directory to store the fortified GIF which also contains ISF
// and open the file for writing
Directory.CreateDirectory(nameBase + "_files");
using (FileStream gifFile = File.OpenWrite(nameBase + "_files\\signature.gif"))
{
// Generate the fortified GIF represenation of the ink
fortifiedGif = ic.Ink.Save(PersistenceFormat.Gif);
// Write and close the gif file
gifFile.Write(fortifiedGif, 0, fortifiedGif.Length);
}
Laden einer Datei
Die OpenMenu_Click
-Methode verarbeitet das Dialogfeld Öffnen, öffnet die Datei und ruft die Lademethode auf, die der Auswahl des Benutzers entspricht.
Laden einer ISF-Datei
Die LoadISF
-Methode liest die zuvor erstellte Datei und konvertiert das Byte-Array mit der Load-Methode des Ink-Objekts in Freihand. Der Freihandsammler wird vorübergehend deaktiviert, um ihm das Ink-Objekt zuzuweisen. Die LoadISF
-Methode überprüft dann die ExtendedProperties-Eigenschaft des Ink-Objekts auf die Vor- und Nachnamenzeichenfolgen.
Ink loadedInk = new Ink();
byte[] isfBytes = new byte[s.Length];
// read in the ISF
s.Read(isfBytes, 0, (int) s.Length);
// load the ink into a new ink object
// After an ink object has been "dirtied" it can never load ink again
loadedInk.Load(isfBytes);
// temporarily disable the ink collector and swap ink objects
ic.Enabled = false;
ic.Ink = loadedInk;
ic.Enabled = true;
// Repaint the inkable region
Signature.Invalidate();
ExtendedProperties inkProperties = ic.Ink.ExtendedProperties;
// Get the raw data out of this stroke's extended
// properties list, using the previously defined
// Guid as a key to the extended property.
// Since the save method stored the first and last
// name information as extended properties, this
// information can be remove now that the load is complete.
if (inkProperties.DoesPropertyExist(FirstName))
{
FirstNameBox.Text = (String) inkProperties[FirstName].Data;
inkProperties.Remove(FirstName);
}
else
{
FirstNameBox.Text = String.Empty;
}
if (inkProperties.DoesPropertyExist(LastName))
{
LastNameBox.Text = (String) inkProperties[LastName].Data;
inkProperties.Remove(LastName);
}
else
{
LastNameBox.Text = String.Empty;
}
Laden einer XML-Datei
Die LoadXML
-Methode lädt eine zuvor erstellte XML-Datei, ruft Daten vom Ink-Knoten ab und konvertiert die Daten im Knoten mithilfe der Load-Methode des Ink-Objekts in Freihand. Der InkCollector ist vorübergehend deaktiviert, um ihm das Ink-Objekt zuzuweisen. Das Signaturfeld wird ungültig, und die Vor- und Nachnameninformationen werden aus dem XML-Dokument abgerufen.
// This object encodes our byte data to a UTF8 string
UTF8Encoding utf8 = new UTF8Encoding();
XmlDocument xd = new XmlDocument();
XmlNodeList nodes;
Ink loadedInk = new Ink();
// Load the XML data into a DOM
xd.Load(s);
// Get the data in the ink node
nodes = xd.GetElementsByTagName("Ink");
// load the ink into a new ink object
// After an ink object has been "dirtied" it can never load ink again
if (0 != nodes.Count)
loadedInk.Load(utf8.GetBytes(nodes[0].InnerXml));
// temporarily disable the ink collector and swap ink objects
ic.Enabled = false;
ic.Ink = loadedInk;
ic.Enabled = true;
// Repaint the inkable region
Signature.Invalidate();
// Get the data in the FirstName node
nodes = xd.GetElementsByTagName("FirstName");
if (0 != nodes.Count)
{
FirstNameBox.Text = nodes[0].InnerXml;
}
else
{
FirstNameBox.Text = String.Empty;
}
// Get the data in the LastName node
nodes = xd.GetElementsByTagName("LastName");
if (0 != nodes.Count)
{
LastNameBox.Text = nodes[0].InnerXml;
}
else
{
LastNameBox.Text = String.Empty;
}
Schließen des Formulars
Die Dispose-Methode des Formulars verwirf das InkCollector-Objekt .