Solicitando reconhecimento de texto
O aplicativo chama a função MappingRecognizeText para solicitar o reconhecimento de texto de um serviço ELS específico. O serviço deve ter sido descoberto em uma chamada anterior para MappingGetServices, conforme descrito em Enumerando e Liberando Serviços.
Observação
A plataforma pode processar chamadas MappingRecognizeText de forma síncrona ou assíncrona.
MappingRecognizeText manipula os seguintes tipos de texto:
- Detecção de idioma da Microsoft. UTF-16, forma de normalização C, texto para o qual determinar o idioma.
- Detecção de script da Microsoft. Texto UTF-16 para o qual determinar intervalos de script.
- Serviços de transliteração. Texto UTF-16 escrito no script de origem (sistema de gravação).
Usar o Reconhecimento de Texto Síncrono
Esta seção fornece instruções para várias maneiras de executar o reconhecimento de texto síncrono.
Reconhecimento de texto síncrono com o Serviço de Detecção de Idiomas da Microsoft
O exemplo a seguir ilustra o uso de MappingRecognizeText com o serviço de Detecção de Idioma da Microsoft e imprime todos os resultados recuperados pelo serviço. O formato de saída desse serviço é uma única estrutura MAPPING_DATA_RANGE com seu membro pData apontando para uma matriz de cadeias de caracteres com terminação dupla nula unicode formatada no registro. Cada cadeia de caracteres da matriz é terminada em nulo e uma cadeia de caracteres vazia é usada para especificar o final da matriz. O conteúdo da matriz são nomes de idioma classificados por confiança.
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Using the Language Auto-Detection GUID to enumerate LAD only:
EnumOptions.pGuid = (GUID *)&ELS_GUID_LANGUAGE_DETECTION;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
WCHAR * p;
// The return format of the Language Auto-Detection is a
// double null-terminated registry-formatted array of strings.
// Every string of the array is null-terminated and there's an
// empty string specifying the end of the array.
for (p = (WCHAR *)pBag->prgResultRanges[0].pData; *p; p += wcslen(p) + 1)
{
printf("%ws\n", p);
}
}
Reconhecimento de texto síncrono com o Serviço de Detecção de Scripts da Microsoft
O exemplo a seguir ilustra o uso de MappingRecognizeText com o serviço de Detecção de Scripts da Microsoft e imprime todos os resultados recuperados. O formato de saída desse serviço é uma matriz de estruturas MAPPING_DATA_RANGE , cada uma especificando o texto escrito no mesmo script. Caracteres comuns (Zyyy) são adicionados ao intervalo anterior ou ao próximo intervalo se o intervalo anterior não existir. O membro pData de cada estrutura aponta para uma cadeia de caracteres terminada em nulo Unicode que contém o nome Unicode padrão do script para o intervalo específico.
Observação
A partir do Windows 7, o serviço de Detecção de Scripts da Microsoft está em conformidade com o Unicode 5.1.
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Using the Script Detection GUID to enumerate SD only:
EnumOptions.pGuid = (GUID *)&ELS_GUID_SCRIPT_DETECTION;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
DWORD dwRangeIndex;
for (dwRangeIndex = 0; dwRangeIndex < pBag->dwRangesCount; ++dwRangeIndex)
{
if (dwRangeIndex > 0)
{
printf(" ----\n");
}
printf("Range from %u to %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwStartIndex,
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwEndIndex);
printf("Data size in WCHARs: %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwDataSize / 2);
printf("\"%ws\"\n", (WCHAR *)pBag->prgResultRanges[dwRangeIndex].pData);
}
}
Reconhecimento de Texto Síncrono com o Serviço de Transliteração Do Microsoft Cirílico para Latino
O exemplo a seguir ilustra o uso de MappingRecognizeText com o serviço de transliteração Microsoft Cyrillic to Latin e imprime os resultados recuperados. Observe as duas maneiras diferentes de enumerar esse serviço, por GUID ou por categoria e script de entrada.
O formato de saída é o mesmo para todos os serviços de transliteração disponíveis. É uma única estrutura MAPPING_DATA_RANGE com seu membro pData apontando para uma matriz de caracteres Unicode que representa o texto original transliterado no script de saída aplicando apenas as regras do serviço de transliteração específico. Esse serviço não termina em nulo sua saída se a entrada não contiver o caractere nulo de terminação.
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT (L"Skip The russian word for 'yes' is transliterated to Latin as '\x0434\x0430'.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices;
DWORD dwServicesCount;
HRESULT hResult;
// 1. Enumerate by GUID:
prgServices = NULL;
dwServicesCount = 0;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Use the Cyrl->Latn Transliteration GUID to enumerate only this service:
EnumOptions.pGuid = (GUID *)&ELS_GUID_TRANSLITERATION_CYRILLIC_TO_LATIN;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
printf("--\n");
// 2. Enumerate by input script and category:
prgServices = NULL;
dwServicesCount = 0;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
EnumOptions.pszCategory = L"Transliteration";
EnumOptions.pszInputScript = L"Cyrl";
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
// We want the result to be null-terminated for display.
// That's why we will also pass the input null terminator:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT) + 1, USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
printf("\"%ws\"\n", (WCHAR *)pBag->prgResultRanges[0].pData);
}
Reconhecimento de texto síncrono com uma chamada para todos os serviços disponíveis
O exemplo a seguir mostra o uso de MappingRecognizeText com todos os serviços disponíveis e imprime os resultados recuperados para todos os serviços. Este exemplo fornece uma boa ilustração da operação de cada serviço. Ao examinar a saída do aplicativo de exemplo, é fácil descobrir o que está acontecendo internamente com os serviços. Este exemplo também mostra que quase todo o código usado para chamar qualquer um dos serviços ELS é o mesmo.
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
DWORD i;
// Get all installed ELS services:
hResult = MappingGetServices(NULL, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
for (i = 0; i < dwServicesCount; ++i)
{
// Do something with each service:
// ... prgServices[i] ...
if (i > 0)
{
printf("--\n");
}
hResult = CallMappingRecognizeText(&prgServices[i]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[i].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[i].pszDescription, hResult);
}
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
DWORD dwRangeIndex;
DWORD dwDataIndex;
WCHAR c;
for (dwRangeIndex = 0; dwRangeIndex < pBag->dwRangesCount; ++dwRangeIndex)
{
if (dwRangeIndex > 0)
{
printf(" ----\n");
}
printf("Range from %u to %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwStartIndex,
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwEndIndex);
// Currently, we can treat all results as arrays of unicode WCHAR
// characters, but there can be services in the future
// that use different formatting, i.e. XML, HTML, etc.
printf("Data size in WCHARs: %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwDataSize / 2);
printf("\"");
for (dwDataIndex = 0; dwDataIndex < pBag->prgResultRanges[dwRangeIndex].dwDataSize / 2; ++dwDataIndex)
{
c = ((WCHAR *)pBag->prgResultRanges[dwRangeIndex].pData)[dwDataIndex];
if (c >= 32 && c < 128 && c != '"') printf("%wc", c);
else printf("#%x", (unsigned)c);
}
printf("\"\n");
}
}
void CallRecognizeText(LPCWSTR Category, LPCWSTR Text)
{
HRESULT Result;
PMAPPING_SERVICE_INFO rgServices;
DWORD ServicesCount;
MAPPING_ENUM_OPTIONS options = {sizeof(MAPPING_ENUM_OPTIONS), (LPWSTR) Category, 0};
Result = MappingGetServices(&options, &rgServices, &ServicesCount);
if (Result == S_OK && ServicesCount > 0)
{
MAPPING_PROPERTY_BAG bag = { sizeof(MAPPING_PROPERTY_BAG), 0};
Result = MappingRecognizeText(&rgServices[0], Text, wcslen(Text), 0, NULL, &bag);
if (Result == S_OK)
{
MappingFreePropertyBag(&bag);
}
MappingFreeServices(rgServices);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
CallRecognizeText(L"Language Detection", L"Text to be recognized");
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
return 0;
}
Usar o Reconhecimento de Texto Assíncrono
O exemplo a seguir mostra o uso de MappingRecognizeText para reconhecimento de texto assíncrono. Quando o retorno de chamada é usado, o aplicativo deve garantir que o recipiente de propriedades, o texto de entrada, as opções e o serviço sejam válidos até que o retorno de chamada tenha terminado de ser executado.
O aplicativo deve chamar MappingFreePropertyBag imediatamente após o recipiente ser consumido pela função de retorno de chamada. Para obter mais informações, consulte Fornecendo retornos de chamada para serviços ELS.
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void RecognizeCallback(PMAPPING_PROPERTY_BAG pBag, LPVOID data, DWORD dwDataSize, HRESULT Result);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Using the Language Auto-Detection GUID to enumerate LAD only:
EnumOptions.pGuid = (GUID *)&ELS_GUID_LANGUAGE_DETECTION;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
MAPPING_OPTIONS Options;
HRESULT hResult;
HANDLE SyncEvent;
DWORD dwWaitResult;
SyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (SyncEvent == NULL)
{
hResult = E_FAIL;
}
else
{
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
ZeroMemory(&Options, sizeof (MAPPING_OPTIONS));
Options.Size = sizeof (MAPPING_OPTIONS);
Options.pfnRecognizeCallback = (PFN_MAPPINGCALLBACKPROC)RecognizeCallback;
Options.pRecognizeCallerData = &SyncEvent;
Options.dwRecognizeCallerDataSize = sizeof (HANDLE);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, &Options, &bag);
if (SUCCEEDED(hResult))
{
// We are using an event to synchronize our waiting for the call to end,
// because some objects have to be valid till the end of the callback call:
// - the input text
// - the property bag
// - the options
// - the service
dwWaitResult = WaitForSingleObject(SyncEvent, INFINITE);
if (dwWaitResult != WAIT_OBJECT_0)
{
hResult = E_FAIL;
}
}
CloseHandle(SyncEvent);
}
return hResult;
}
void RecognizeCallback(PMAPPING_PROPERTY_BAG pBag, LPVOID data, DWORD dwDataSize, HRESULT Result)
{
HANDLE SyncEvent;
WCHAR * p;
UNREFERENCED_PARAMETER(dwDataSize);
if (SUCCEEDED(Result))
{
for (p = (WCHAR *)pBag->prgResultRanges[0].pData; *p; p += wcslen(p) + 1)
{
printf("%ws\n", p);
}
MappingFreePropertyBag(pBag);
}
SyncEvent = *((HANDLE *)data);
SetEvent(SyncEvent);
}
Tópicos relacionados