Compartir a través de


Ejemplo de serialización de entrada de lápiz

En este ejemplo se muestra cómo serializar y des serializar la entrada de lápiz en varios formatos. La aplicación representa un formulario con campos para escribir el nombre, el apellido y la firma. El usuario puede guardar estos datos como formato serializado de lápiz puro (ISF), lenguaje de marcado extensible (XML) con ISF codificado en base64 o HTML, que hace referencia a la entrada de lápiz en una imagen codificada en formato de intercambio de gráficos (GIF) codificado en base64. La aplicación también permite al usuario abrir archivos guardados como formatos XML e ISF. El formato ISF usa propiedades extendidas para almacenar el nombre y apellidos, mientras que los formatos XML y HTML almacenan esta información en atributos personalizados.

Este ejemplo no admite la carga desde el formato HTML, ya que HTML no es adecuado para almacenar datos estructurados. Dado que los datos se separan en nombre, firma, etc., se requiere un formato que conserve esta separación, como XML u otro tipo de formato de base de datos.

HTML es muy útil en un entorno en el que el formato es importante, como en un documento de procesamiento de texto. El CÓDIGO HTML que guarda este ejemplo usa GIF fortificados. Estos GIF tienen ISF incrustados en ellos, lo que conserva la fidelidad completa de la entrada de lápiz. Una aplicación de procesamiento de texto puede guardar un documento que contenga varios tipos de datos, como imágenes, tablas, texto con formato y entrada de lápiz persistentes en un formato HTML. Este CÓDIGO HTML se representaría en exploradores que no reconocen la entrada de lápiz. Sin embargo, cuando se carga en una aplicación habilitada para entrada de lápiz, la fidelidad completa de la entrada de lápiz original está disponible y se puede representar, editar o usar para el reconocimiento.

En este ejemplo se usan las siguientes características:

Recopilación de entradas manuscritas

En primer lugar, haga referencia a la API de PC tablet, que se instala con el Kit de desarrollo de software (SDK) windows Vista y Windows XP Tablet PC Edition.

using Microsoft.Ink;

El constructor crea y habilita un control InkCollector, ic, para el formulario.

ic = new InkCollector(Signature.Handle);
ic.Enabled = true;

Guardar un archivo

El SaveAsMenu_Click método controla el cuadro de diálogo Guardar como, crea una secuencia de archivos en la que se guardan los datos de entrada de lápiz y llama al método save que corresponde a la elección del usuario.

Guardar en un archivo ISF

En el SaveISF método , los valores de nombre y apellido se agregan a la propiedad ExtendedProperties de la propiedad InkCollector del objeto Ink , antes de que la entrada de lápiz se serialice y escriba en el archivo. Después de serializar la entrada de lápiz, los valores de nombre y apellido se quitan de la propiedad ExtendedProperties del objeto Ink .

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);

Guardar en un archivo XML

En el SaveXML método , se usa un objeto XmlTextWriter para crear y escribir en un documento XML. Con el método Save del objeto Ink, la entrada de lápiz se convierte primero en una matriz de bytes de formato serializado de tinta codificada en base64 y, a continuación, la matriz de bytes se convierte en una cadena que se va a escribir en el archivo XML. Los datos de texto del formulario también se escriben en el archivo XML.

// 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);

Guardar en un archivo HTML

El método SaveHTML usa el cuadro de límite de la colección Strokes para probar la presencia de una firma. Si la firma existe, se convierte en el formato GIF fortificado mediante el método Save del objeto ink y se escribe en un archivo. A continuación, se hace referencia al GIF en el archivo HTML.

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);
    }

Carga de un archivo

El OpenMenu_Click método controla el cuadro de diálogo Abrir, abre el archivo y llama al método de carga que corresponde a la elección del usuario.

Carga de un archivo ISF

El LoadISF método lee el archivo creado anteriormente y convierte la matriz Byte en la entrada de lápiz con el método Load del objeto Ink. El recopilador de tintas está deshabilitado temporalmente para asignarle el objeto Ink. A LoadISF continuación, el método comprueba la propiedad ExtendedProperties del objeto Ink para las cadenas de nombre y apellido.

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;
}

Carga de un archivo XML

El LoadXML método carga un archivo XML creado anteriormente, recupera datos del nodo Ink y convierte los datos del nodo en la entrada de lápiz mediante el método Load del objeto Ink. InkCollector está deshabilitado temporalmente para asignarle el objeto Ink. El cuadro de firma se invalida y la información de nombre y apellidos se recupera del documento XML.

// 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;
}

Cerrar el formulario

El método Dispose del formulario elimina el objeto InkCollector .