將文字筆跡物件轉換為 Ink
從文字筆跡物件 (tInk) 轉換成筆跡的實作。
若要從文字筆跡物件轉換成筆跡
- 使用 IPersistStream 介面,將文字筆跡物件的內容寫入資料流程。 文字筆跡物件會使用筆跡序列化格式寫入至資料流程。
- 將資料流程的內容讀入 BYTE 陣列。
- 使用 InkDisp 物件的 Load 方法,將資料流程的內容載入 InkDisp 物件。
將 Ink 物件文字寫入 Ink 物件範例
下列程式碼片段會將文字筆跡物件轉換成筆跡。
首先,程式碼會取得文字筆跡物件。
/* Create a variable to hold the text ink object */
CComPtr<IInkObject *> spITextInk;
/* Obtain the text ink object */
然後,程式碼會為保存文字筆跡物件內容的資料流程建立指標。
// Create a Stream pointer to hold the saved object
CComPtr<IStream *> spStream = NULL;
然後,程式碼會從文字筆跡物件取得 IPersistStream 介面。
// Declare the IPersistStream to be used for retrieving the saved data from the text ink
CComPtr<IPersistStream *> spIPersistStream = NULL;
// Get the actual IPersistStream interface off of the TextInk
HRESULT hr = pITextInk->QueryInterface(IID_IPersistStream, (void **)&spIPersistStream);
ASSERT(SUCCEEDED(hr) && spIPersistStream);
然後,程式碼會使用 IPersistStream 介面,將文字筆跡物件的內容儲存至資料流程。
if( SUCCEEDED(hr) && pIPersistStream )
{
// Create the stream
if( SUCCEEDED(hr=CreateStreamOnHGlobal(NULL, TRUE, &spStream)) && spStream )
{
// Save the TextInk through IPersistStream Interface to the IStream
hr = spIPersistStream->Save(spStream, FALSE);
}
}
然後,程式碼會建立InkCollector物件、建立InkCollector的InkDisp物件、將InkCollector附加至應用程式視窗,並在InkCollector上啟用筆跡集合。
// Now create an InkCollector object along with InkDisp Object
if( SUCCEEDED(hr) && spStream)
{
CComPtr<IInkCollector *> spIInkCollector;
CComPtr<IInkDisp *> spIInkDisp = NULL;
// Create the InkCollector object.
hr = CoCreateInstance(CLSID_InkCollector,
NULL, CLSCTX_INPROC_SERVER,
IID_IInkCollector,
(void **) &spIInkCollector);
if (FAILED(hr))
return -1;
// Get a pointer to the Ink object
hr = spIInkCollector->get_Ink(&spIInkDisp);
if (FAILED(hr))
return -1;
// Tell InkCollector the window to collect ink in
hr = spIInkCollector->put_hWnd((long)hwnd);
if (FAILED(hr))
return -1;
// Enable ink input in the window
hr = spIInkCollector->put_Enabled(VARIANT_TRUE);
if (FAILED(hr))
return -1;
然後,程式碼會擷取資料流程的大小,並建立安全陣列來保存資料流程的內容。
// Now create a variant data type based on the IStream data
const LARGE_INTEGER li0 = {0, 0};
ULARGE_INTEGER uli = {0,0};
// Find the size of the stream
hr = spStream->Seek(li0, STREAM_SEEK_END, &uli);
ASSERT(0 == uli.HighPart);
DWORD dwSize = uli.LowPart;
// Set uli to point to the beginning of the stream.
hr=spStream->Seek(li0, STREAM_SEEK_SET, &uli);
ASSERT(SUCCEEDED(hr));
// Create a safe array to hold the stream contents
if( SUCCEEDED(hr) )
{
VARIANT vtData;
VariantInit(&vtData);
vtData.vt = VT_ARRAY | VT_UI1;
vtData.parray = ::SafeArrayCreateVector(VT_UI1, 0, dwSize);
if (vtData.parray)
{
最後,程式碼會存取安全陣列,並使用 InkDisp 物件的 Load 方法從陣列載入筆跡。
DWORD dwRead = 0;
LPBYTE pbData = NULL;
if (SUCCEEDED(::SafeArrayAccessData(vtData.parray, (void**)&pbData)))
{
// Read the data from the stream to the varian data and load that into an InkDisp object
if (TRUE == spStream->Read(pbData, uli.LowPart, &dwRead)
&& SUCCEEDED(spIInkDisp->Load(vtData)))
{
hr = S_OK;
}
::SafeArrayUnaccessData(vtData.parray);
}
::SafeArrayDestroy(vtData.parray);
}
}
}