Partilhar via


Exemplo de serialização de tinta

Este exemplo demonstra como serializar e des serializar a tinta em vários formatos. O aplicativo representa um formulário com campos para inserir o nome, o sobrenome e a assinatura. O usuário pode salvar esses dados como ISF (formato serializado de tinta pura), XML (Linguagem de Marcação Extensível) usando ISF codificado em base64 ou HTML, que faz referência à tinta em uma imagem GIF (Formato de Intercâmbio gráfico fortificado) codificada em base64. O aplicativo também permite que o usuário abra arquivos que foram salvos como formatos XML e ISF. O formato ISF usa propriedades estendidas para armazenar o nome e o sobrenome, enquanto os formatos XML e HTML armazenam essas informações em atributos personalizados.

Este exemplo não dá suporte ao carregamento do formato HTML, pois HTML não é adequado para armazenar dados estruturados. Como os dados são separados em nome, assinatura e assim por diante, é necessário um formato que preserva essa separação, como XML ou outro tipo de formato de banco de dados.

HTML é muito útil em um ambiente no qual a formatação é importante, como em um documento de processamento de palavras. O HTML salvo por este exemplo usa GIFs fortificados. Esses GIFs têm ISF inserido neles, o que preserva a fidelidade total da tinta. Um aplicativo de processamento de palavras pode salvar um documento que contém vários tipos de dados, como imagens, tabelas, texto formatado e tinta persistentes em um formato HTML. Esse HTML seria renderizado em navegadores que não reconhecem tinta. No entanto, quando carregado em um aplicativo habilitado para tinta, a fidelidade total da tinta original está disponível e pode ser renderizada, editada ou usada para reconhecimento.

Os seguintes recursos são usados neste exemplo:

Coletando tinta

Primeiro, faça referência à API do Tablet PC, que são instaladas com o Windows Vista e o SDK (Software Development Kit) do Windows XP Tablet PC Edition.

using Microsoft.Ink;

O construtor cria e habilita um InkCollector, ic, para o formulário.

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

Salvando um arquivo

O SaveAsMenu_Click método manipula a caixa de diálogo Salvar como, cria um fluxo de arquivos no qual salvar os dados de tinta e chama o método save que corresponde à escolha do usuário.

Salvando em um arquivo ISF

SaveISF No método , os valores de nome e sobrenome são adicionados à propriedade ExtendedProperties da propriedade Ink do objeto InkCollector, antes que a tinta seja serializada e gravada no arquivo. Depois que a tinta for serializada, os valores de nome e sobrenome serão removidos da propriedade ExtendedProperties do 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);

Salvando em um arquivo XML

SaveXML No método , um objeto XmlTextWriter é usado para criar e gravar em um documento XML. Usando o método Save do objeto Ink, a tinta é convertida primeiro em uma matriz de bytes ink serialized format codificada em base64 e, em seguida, a matriz de bytes é convertida em uma cadeia de caracteres a ser gravada no arquivo XML. Os dados de texto do formulário também são gravados no arquivo 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);

Salvando em um arquivo HTML

O método SaveHTML usa a caixa delimitadora da coleção Strokes para testar a presença de uma assinatura. Se a assinatura existir, ela será convertida no formato GIF fortificado usando o método Save do objeto de tinta e gravada em um arquivo. O GIF é referenciado no arquivo 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);
    }

Carregando um arquivo

O OpenMenu_Click método manipula a caixa de diálogo Abrir, abre o arquivo e chama o método de carregamento que corresponde à escolha do usuário.

Carregando um arquivo ISF

O LoadISF método lê o arquivo criado anteriormente e converte a matriz Byte em tinta com o método Load do objeto Ink. O coletor de tinta está temporariamente desabilitado para atribuir o objeto Ink a ele. Em LoadISF seguida, o método verifica a propriedade ExtendedProperties do objeto Ink para as cadeias de caracteres de nome e sobrenome.

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

Carregando um arquivo XML

O LoadXML método carrega um arquivo XML criado anteriormente, recupera dados do nó Ink e converte os dados no nó em tinta usando o método Load do objeto Ink. O InkCollector está temporariamente desabilitado para atribuir o objeto Ink a ele. A caixa de assinatura é invalidada e as informações de nome e sobrenome são recuperadas do 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;
}

Fechando o formulário

O método Dispose do formulário descarta o objeto InkCollector .