다음을 통해 공유


잉크 직렬화 샘플

이 샘플에서는 다양한 형식으로 잉크를 직렬화 및 직렬화 해제하는 방법을 보여 줍니다. 애플리케이션은 이름, 성 및 서명을 입력하기 위한 필드가 있는 양식을 나타냅니다. 사용자는 base64로 인코딩된 ISF를 사용하여 순수 잉크 직렬화된 형식(ISF), XML(Extensible Markup Language) 또는 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 메서드는 다른 이름으로 저장 대화 상자를 처리하고, 잉크 데이터를 저장할 파일 스트림을 만들고, 사용자의 선택에 해당하는 저장 메서드를 호출합니다.

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로 인코딩된 잉크 직렬화된 형식 바이트 배열로 변환된 다음, 바이트 배열을 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 형식으로 변환되고 파일에 기록됩니다. 그런 다음 HTML 파일에서 GIF를 참조합니다.

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 배열을 잉크로 변환합니다. 잉크 수집기가 일시적으로 비활성화되어 잉크 개체를 할당할 수 없습니다. 그런 다음 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 개체의 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 개체를 삭제합니다.