このサンプルでは、インクをさまざまな形式でシリアル化および逆シリアル化する方法を示します。 アプリケーションは、名、姓、署名を入力するためのフィールドを含むフォームを表します。 ユーザーは、base64 でエンコードされた ISF を使用して純粋なインク シリアル化形式 (ISF)、拡張マークアップ言語 (XML)、または base64 でエンコードされた強化されたグラフィックス交換形式 (GIF) イメージ内のインクを参照する HTML としてこのデータを保存できます。 また、アプリケーションを使用すると、XML および ISF 形式として保存されたファイルを開くこともできます。 ISF 形式では、拡張プロパティを使用して名と姓が格納されますが、XML 形式と HTML 形式では、この情報がカスタム属性に格納されます。
HTML は構造化データを格納するのに適していないため、このサンプルでは HTML 形式からの読み込みはサポートされていません。 データは名前や署名などに分割されるため、XML や別の種類のデータベース形式など、この分離を保持する形式が必要です。
HTML は、ワープロ ドキュメントなど、書式設定が重要な環境で非常に便利です。 このサンプルによって保存される HTML では、強化された GIF が使用されます。 これらの GIF には ISF が埋め込まれており、インクの完全な忠実性が維持されます。 ワープロ アプリケーションでは、画像、テーブル、書式設定されたテキスト、HTML 形式で永続化されたインクなど、複数の種類のデータを含むドキュメントを保存できます。 この HTML は、インクを認識しないブラウザーでレンダリングされます。 ただし、インク対応のアプリケーションに読み込まれると、元のインクの完全な忠実性が利用でき、レンダリング、編集、または認識に使用できます。
このサンプルでは、次の機能を使用します。
インクの収集
まず、Windows Vista および Windows XP Tablet PC Edition ソフトウェア開発キット (SDK) と共にインストールされているタブレット PC API を参照します。
using Microsoft.Ink;
コンストラクターは、フォームの InkCollectoric
を作成して有効にします。
ic = new InkCollector(Signature.Handle);
ic.Enabled = true;
ファイルの保存
メソッドは SaveAsMenu_Click
、[名前を付けて保存] ダイアログ ボックスを処理し、インク データを保存するファイル ストリームを作成し、ユーザーの選択に対応する save メソッドを呼び出します。
ISF ファイルへの保存
SaveISF
メソッドでは、インクをシリアル化してファイルに書き込む前に、InkCollector オブジェクトの Ink プロパティの ExtendedProperties プロパティに姓と名の値が追加されます。 インクがシリアル化されると、 Ink オブジェクトの ExtendedProperties プロパティから姓と名の値が削除されます。
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);
XML ファイルへの保存
SaveXML
メソッドでは、XmlTextWriter オブジェクトを使用して XML ドキュメントを作成および書き込みます。
Ink オブジェクトの Save メソッドを使用して、インクは最初に base64 でエンコードされた Ink Serialized Format バイト配列に変換され、バイト配列は XML ファイルに書き出される文字列に変換されます。 フォームのテキスト データも 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);
HTML ファイルへの保存
SaveHTML メソッドは 、Strokes コレクションの境界ボックスを使用して、シグネチャの有無をテストします。 署名が存在する場合は、インク オブジェクトの Save メソッドを使用して強化された GIF 形式に変換され、ファイルに書き込まれます。 その後、GIF は 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 representation of the ink
fortifiedGif = ic.Ink.Save(PersistenceFormat.Gif);
// Write and close the gif file
gifFile.Write(fortifiedGif, 0, fortifiedGif.Length);
}
ファイルの読み込み
メソッドは OpenMenu_Click
、[開く] ダイアログ ボックスを処理し、ファイルを開き、ユーザーの選択に対応する読み込みメソッドを呼び出します。
ISF ファイルの読み込み
メソッドはLoadISF
、前に作成したファイルを読み取り、Ink オブジェクトの Load メソッドを使用して Byte 配列をインクに変換します。 インク コレクターは、Ink オブジェクトを割り当てるために一時的に無効になります。 次に、 メソッドは LoadISF
Ink オブジェクトの ExtendedProperties プロパティで姓と名の文字列を確認します。
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;
}
XML ファイルの読み込み
メソッドは LoadXML
、以前に作成した XML ファイルを読み込み、Ink ノードからデータを取得し、 Ink オブジェクトの Load メソッドを使用してノード内のデータをインクに変換します。
InkCollector は、Ink オブジェクトを割り当てるために一時的に無効になっています。 署名ボックスが無効になり、名と姓の情報が 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;
}
フォームを閉じる
フォームの Dispose メソッドは 、InkCollector オブジェクトを破棄します。