次の方法で共有


複数の認識エンジンのサンプル

このサンプルでは、 手書き 認識に使用される MicrosoftTablet PC Automation アプリケーション プログラミング インターフェイス (API) の高度な機能を示します。

含まれる内容は次のとおりです。

  • インストールされている認識エンジンの列挙
  • 特定の言語 認識エンジン を使用して認識エンジン コンテキストを作成する
  • ストローク コレクションを使用した認識結果のシリアル化
  • InkDisp オブジェクト内のカスタム コレクションにストローク コレクションを整理する
  • インク オブジェクトをシリアル化し、インク シリアル化形式 (ISF) ファイルから取得する
  • 認識エンジン入力ガイドの設定
  • 同期認識と非同期認識の使用

インク ヘッダー

最初に、タブレット PC オートメーション インターフェイスのヘッダーを含めます。 これらは、Microsoft Windows XP Tablet PC Edition Software Development Kit (SDK) と共にインストールされます。

#include <msinkaut.h>
#include <msinkaut_i.c>

EventSinks.h ファイルは、IInkEventsImpl インターフェイスと IInkRecognitionEventsImpl インターフェイスを定義します。

#include "EventSinks.h"

インストールされている認識エンジンの列挙

アプリケーションの LoadMenu メソッドは、[新しいストロークの作成] メニューに使用可能な認識エンジンを設定します。 InkRecognizers が作成されます。 InkRecognizers オブジェクトの Languages プロパティが空でない場合、認識エンジンはテキスト認識エンジンであり、Name プロパティの値がメニューに追加されます。

// Create the enumerator for the installed recognizers
hr = m_spIInkRecognizers.CoCreateInstance(CLSID_InkRecognizers);
...
    // Filter out non-language recognizers by checking for
    // the languages supported by the recognizer - there is not
    // any if it is a gesture or object recognizer.
    CComVariant vLanguages;
    if (SUCCEEDED(spIInkRecognizer->get_Languages(&vLanguages)))
    {
        if ((VT_ARRAY == (VT_ARRAY & vLanguages.vt))           // it should be an array
            && (NULL != vLanguages.parray)
            && (0 < vLanguages.parray->rgsabound[0].cElements)) // with at least one element
        {
            // This is a language recognizer. Add its name to the menu.
            CComBSTR bstrName;
            if (SUCCEEDED(spIInkRecognizer->get_Name(&bstrName)))
                ...
        }
    }

インク コレクターの作成

アプリケーションの OnCreate メソッドは InkCollector オブジェクトを作成し、それをそのイベント ソースに接続し、インクコレクションを有効にします。

// Create an ink collector object.
hr = m_spIInkCollector.CoCreateInstance(CLSID_InkCollector);

// Establish a connection to the collector's event source.
hr = IInkCollectorEventsImpl<CMultiRecoApp>::DispEventAdvise(m_spIInkCollector);

// Enable ink input in the m_wndInput window
hr = m_spIInkCollector->put_hWnd((long)m_wndInput.m_hWnd);
hr = m_spIInkCollector->put_Enabled(VARIANT_TRUE);

認識エンジン コンテキストの作成

アプリケーションの CreateRecoContext メソッドは、新しい認識エンジン コンテキストを作成して初期化し、関連付けられている言語でサポートされているガイドを設定します。 IInkRecognizer オブジェクトの CreateRecognizerContext メソッドは、言語の IInkRecognizerContext2 オブジェクトを作成します。 必要に応じて、古い認識エンジン コンテキストが置き換えられます。 コンテキストは、そのイベント ソースに接続されています。 最後に、認識エンジン コンテキストの Capabilities プロパティがチェックされ、認識エンジン コンテキストがサポートするガイドが表示されます。

// Create a recognizer context
CComPtr<IInkRecognizerContext2> spNewContext;
if (FAILED(pIInkRecognizer2->CreateRecognizerContext(&spNewContext)))
    return false;

// Replace the current context with the new one
if (m_spIInkRecoContext != NULL)
{
    // Close the connection to the recognition events source
    IInkRecognitionEventsImpl<CMultiRecoApp>::DispEventUnadvise(m_spIInkRecoContext);
}
m_spIInkRecoContext.Attach(spNewContext.Detach());

// Establish a connection with the recognizer context's event source
if (FAILED(IInkRecognitionEventsImpl<CMultiRecoApp>::DispEventAdvise(m_spIInkRecoContext)))
    ...

// Set the guide if it's supported by the recognizer and has been created 
int cRows = 0, cColumns = 0;
InkRecognizerCapabilities dwCapabilities = IRC_DontCare;
if (SUCCEEDED(pIInkRecognizer->get_Capabilities(&dwCapabilities)))
    ...

ストロークの収集と認識結果の表示

アプリケーションの OnStroke メソッドは、インク コレクターの InkStrokes を更新し、既存の非同期認識要求を取り消し、認識エンジン コンテキストで認識要求を作成します。

// Add the new stroke to the current collection
hr = m_spIInkStrokes->Add(pIInkStroke);

if (SUCCEEDED(hr))
{
    // Cancel the previous background recognition requests
    // which have not been processed yet
    m_spIInkRecoContext->StopBackgroundRecognition();

    // Ask the context to update the recognition results with newly added strokes
    // When the results are ready, the recognizer context returns them
    // through the corresponding event RecognitionWithAlternates
    CComVariant vCustomData;
    m_spIInkRecoContext->BackgroundRecognize(vCustomData);
}

アプリケーションの OnRecognition メソッドは、認識要求の結果を出力ウィンドウの UpdateString メソッドに送信します。

// Update the output window with the new results
m_wndResults.UpdateString(bstrRecognizedString);

ストロークと認識結果の削除

アプリケーションの OnClear メソッドは、 InkDisp オブジェクトからすべてのストロークと認識結果を削除し、ウィンドウをクリアします。 認識エンジン コンテキストと InkStrokes コレクションの 関連付けが削除されます。

// Detach the current stroke collection from the recognizer context and release it
if (m_spIInkRecoContext != NULL)
    m_spIInkRecoContext->putref_Strokes(NULL);

m_spIInkStrokes.Release();

// Clear the custom strokes collection
if (m_spIInkCustomStrokes != NULL)
    m_spIInkCustomStrokes->Clear();

// Delete all strokes from the Ink object
// Passing NULL as a stroke collection pointer means asking to delete all strokes
m_spIInkDisp->DeleteStrokes(NULL);

// Get a new stroke collection from the ink object
...
// Ask for an empty collection by passing an empty variant 
if (SUCCEEDED(m_spIInkDisp->CreateStrokes(v, &m_spIInkStrokes)))
{
    // Attach it to the recognizer context
    if (FAILED(m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes)))
        ...
}

認識エンジン コンテキストの変更

アプリケーションの OnNewStrokes メソッドは、ユーザーが [新しいストロークの作成] メニューで認識エンジンを選択すると呼び出されます。 現在の InkStrokes が保存されます。 別の言語認識エンジンが選択されている場合は、新しい認識エンジン コンテキストが作成されます。 次に、新しい InkStrokes が新しい認識エンジン コンテキストにアタッチされます。

// Save the current stroke collection if there is any
if (m_spIInkRecoContext != NULL)
{
    // Cancel the previous background recognition requests
    // which have not been processed yet
    m_spIInkRecoContext->StopBackgroundRecognition();
    
    // Let the context know that there'll be no more input 
    // for the attached stroke collection
    m_spIInkRecoContext->EndInkInput();

    // Add the stroke collection to the Ink object's CustomStrokes collection
    SaveStrokeCollection();
}
...
// If a different recognizer was selected, create a new recognizer context
// Else, reuse the same recognizer context
if (wID != m_nCmdRecognizer)
{
    // Get a pointer to the recognizer object from the recognizer collection  
    CComPtr<IInkRecognizer> spIInkRecognizer;
    if ((m_spIInkRecognizers == NULL)
        || FAILED(m_spIInkRecognizers->Item(wID - ID_RECOGNIZER_FIRST,
                                             &spIInkRecognizer))
        || (false == CreateRecoContext(spIInkRecognizer)))
    {
        // restore the cursor
        ::SetCursor(hCursor);
        return 0;
    }

    // Update the status bar
    m_bstrCurRecoName.Empty();
    spIInkRecognizer->get_Name(&m_bstrCurRecoName);
    UpdateStatusBar();

    // Store the selected recognizer's command id
    m_nCmdRecognizer = wID;
}

次に、StartNewStrokeCollection を呼び出します。これにより、空の InkStrokes が作成され、認識エンジン コンテキストにアタッチされます。

認識エンジン コンテキストの Strokes コレクションを保存する

アプリケーションの メソッドは、既存の SaveStrokeCollection 認識エンジン コンテキストをチェックし、現在の strokes コレクションの認識を終了します。 次に、 InkStrokes コレクションが Ink オブジェクトの CustomStrokes に追加されます。

if (m_spIInkRecoContext != NULL)
{
    if (SUCCEEDED(m_spIInkStrokes->get_Count(&lCount)) && 0 != lCount)
    {
        CComPtr<IInkRecognitionResult> spIInkRecoResult;
        InkRecognitionStatus RecognitionStatus;
        if (SUCCEEDED(m_spIInkRecoContext->Recognize(&RecognitionStatus, &spIInkRecoResult)))
        {
            if (SUCCEEDED(spIInkRecoResult->SetResultOnStrokes()))
            {
                CComBSTR bstr;
                spIInkRecoResult->get_TopString(&bstr);
                m_wndResults.UpdateString(bstr);
            }
            ...
        }
    }
    // Detach the stroke collection from the old recognizer context
    m_spIInkRecoContext->putref_Strokes(NULL);
}

// Now add it to the ink's custom strokes collection
// Each item (stroke collection) of the custom strokes must be identified
// by a unique string. Here we generate a GUID for this.
if ((0 != lCount) && (m_spIInkCustomStrokes != NULL))
{
    GUID guid;
    WCHAR szGuid[40]; // format: "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
    if (SUCCEEDED(::CoCreateGuid(&guid)) 
        && (::StringFromGUID2(guid, szGuid, countof(szGuid)) != 0))
    {
        CComBSTR bstrGuid(szGuid);
        if (FAILED(m_spIInkCustomStrokes->Add(bstrGuid, m_spIInkStrokes)))
            ...