Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este exemplo demonstra os recursos avançados da API (interface de programação de aplicativo) da Automação de COMPUTADORES MicrosoftTablet usada para reconhecimento de manuscrito .
Isso inclui o seguinte:
- Enumerando os reconhecedores instalados
- Criando um contexto de reconhecedor com um reconhecedor de idioma específico
- Serializando resultados de reconhecimento com uma coleção de traços
- Organizando coleções de traços em uma coleção personalizada dentro do objeto InkDisp
- Serializando objetos de tinta para e recuperando-os de um arquivo ISF (formato serializado à tinta)
- Guias de entrada do reconhecedor de configuração
- Usando o reconhecimento síncrono e assíncrono
Cabeçalhos de tinta
Primeiro, inclua os cabeçalhos para interfaces de Automação de TABLET PC. Eles são instalados com o SDK (Software Development Kit) do Microsoft Windows XP Tablet PC Edition.
#include <msinkaut.h>
#include <msinkaut_i.c>
O arquivo EventSinks.h define as interfaces IInkEventsImpl e IInkRecognitionEventsImpl.
#include "EventSinks.h"
Enumerando os Reconhecedores Instalados
O método LoadMenu do aplicativo preenche o menu Criar Novos Traços com os reconhecedores disponíveis. Um InkRecognizers é criado. Se a propriedade Languages de um objeto InkRecognizers não estiver vazia, o reconhecedor será um reconhecedor de texto e o valor de sua propriedade Name será adicionado ao 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)))
...
}
}
Criando um coletor de tinta
O método OnCreate do aplicativo cria um objeto InkCollector , conecta-o à origem do evento e habilita a coleção de tinta.
// 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);
Criando um contexto de reconhecedor
O método CreateRecoContext do aplicativo cria e inicializa um novo contexto de reconhecedor e configura os guias compatíveis com a linguagem associada. O método CreateRecognizerContext do objeto IInkRecognizer cria um objeto IInkRecognizerContext2 para a linguagem. Se necessário, o contexto do reconhecedor antigo será substituído. O contexto está conectado à origem do evento. Por fim, a propriedade Capabilities do contexto do reconhecedor é verificada para qual guia o contexto do reconhecedor dá suporte.
// 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)))
...
Coletando traços e exibindo resultados de reconhecimento
O método OnStroke do aplicativo atualiza os InkStrokes do coletor de tinta, cancela as solicitações de reconhecimento assíncronas existentes e cria uma solicitação de reconhecimento no contexto do reconhecedor.
// 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);
}
O método do OnRecognition aplicativo envia os resultados da solicitação de reconhecimento para o método da janela de UpdateString saída.
// Update the output window with the new results
m_wndResults.UpdateString(bstrRecognizedString);
Excluindo traços e resultados de reconhecimento
O método OnClear do aplicativo exclui todos os traços e os resultados de reconhecimento do objeto InkDisp e limpa as janelas. A associação do contexto do reconhecedor com sua coleção InkStrokes é removida.
// 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)))
...
}
Alterando contextos do reconhecedor
O método OnNewStrokes do aplicativo é chamado quando o usuário seleciona um reconhecedor no menu Criar Novos Traços. Os InkStrokes atuais são salvos . Se um reconhecedor de idioma diferente tiver sido selecionado, um novo contexto de reconhecedor será criado. Em seguida, um novo InkStrokes é anexado ao novo contexto do reconhecedor.
// 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;
}
Em seguida, ele chama StartNewStrokeCollection, que cria um InkStrokes vazio e o anexa ao contexto do reconhecedor.
Salvando a coleção Strokes para um contexto de reconhecedor
O método do SaveStrokeCollection aplicativo verifica um contexto de reconhecedor existente e finaliza o reconhecimento da coleção de traços atual. Em seguida, a coleção InkStrokes é adicionada aos CustomStrokes do objeto de tinta.
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)))
...