Condividi tramite


Esempio di riconoscimento multiplo

Questo esempio illustra le funzionalità avanzate dell'interfaccia di programmazione dell'applicazione di Automazione PC di MicrosoftTablet (API) usata per il riconoscimento della grafia .

Include quanto segue:

  • Enumerazione dei riconoscimento installati
  • Creazione di un contesto di riconoscimento con un riconoscimento linguistico specifico
  • Serializzazione dei risultati del riconoscimento con una raccolta di tratti
  • Organizzazione di raccolte di tratti in una raccolta personalizzata all'interno dell'oggetto InkDisp
  • Serializzazione di oggetti input penna in e recupero da un file ISF (Serialized Format) in input penna
  • Impostazione delle guide di input del riconoscimento
  • Uso del riconoscimento sincrono e asincrono

Intestazioni input penna

In primo luogo, includere le intestazioni per le interfacce di Automazione pc tablet. Questi sono installati con Microsoft Windows XP Tablet PC Edition Software Development Kit (SDK).

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

Il file EventSinks.h definisce le interfacce IInkEventsImpl e IInkRecognitionEventsImpl.

#include "EventSinks.h"

Enumerazione dei riconoscimento installati

Il metodo LoadMenu dell'applicazione popola il menu Create New Strokes con i riconoscimento disponibili. Viene creato un oggetto InkRecognizers . Se la proprietà Languages di un oggetto InkRecognizers non è vuota, il riconoscimento è un riconoscimento del testo e il valore della proprietà Name viene aggiunto al menu.

// 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)))
                ...
        }
    }

Creazione di un agente di raccolta input penna

Il metodo OnCreate dell'applicazione crea un oggetto InkCollector , lo connette all'origine evento e abilita l'insieme input penna.

// 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);

Creazione di un contesto di riconoscimento

Il metodo CreateRecoContext dell'applicazione crea e inizializza un nuovo contesto di riconoscimento e configura le guide supportate dal linguaggio associato. Il metodo CreateRecognizer dell'oggetto IInkRecognizerContext crea un oggetto IInkRecognizerContext2 per la lingua. Se necessario, il contesto del riconoscimento precedente viene sostituito. Il contesto è connesso alla relativa origine eventi. Infine, la proprietà Capabilities del contesto di riconoscimento viene verificata per quali guide il contesto di riconoscimento supporta.

// 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)))
    ...

Raccolta di tratti e visualizzazione dei risultati del riconoscimento

Il metodo OnStroke dell'applicazione aggiorna gli inkStroke dell'agente di raccolta input penna, annulla le richieste di riconoscimento asincrone esistenti e crea una richiesta di riconoscimento nel contesto del riconoscimento.

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

Il metodo dell'applicazione OnRecognition invia i risultati della richiesta di riconoscimento al metodo della finestra di UpdateString output.

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

Eliminazione di tratti e risultati di riconoscimento

Il metodo OnClear dell'applicazione elimina tutti i tratti e i risultati del riconoscimento dall'oggetto InkDisp e cancella le finestre. L'associazione del contesto di riconoscimento con la relativa raccolta InkStrokes viene rimossa.

// 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)))
        ...
}

Modifica dei contesti di riconoscimento

Il metodo OnNewStrokes dell'applicazione viene chiamato quando l'utente seleziona un riconoscimento nel menu Crea nuovi tratti. Viene salvato InkStrokes corrente. Se è stato selezionato un riconoscimento della lingua diverso, viene creato un nuovo contesto di riconoscimento. Viene quindi collegato un nuovo oggetto InkStrokes al nuovo contesto di riconoscimento.

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

Chiama quindi StartNewStrokeCollection, che crea un inkStroke vuoto e lo collega al contesto di riconoscimento.

Salvataggio dell'insieme Strokes per un contesto di riconoscimento

Il metodo dell'applicazione SaveStrokeCollection controlla un contesto di riconoscimento esistente e finalizza il riconoscimento della raccolta tratti correnti. L'insieme InkStrokes viene quindi aggiunto agli oggetti CustomStrokes dell'oggetto input penna.

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)))
            ...