Żądanie rozpoznawania tekstu
Aplikacja wywołuje funkcję MappingRecognizeText w celu żądania rozpoznawania tekstu z określonej usługi ELS. Usługa musiała zostać odnaleziona w poprzednim wywołaniu MappingGetServices, zgodnie z opisem w Wyliczanie i zwalnianie usług.
Notatka
Platforma może przetwarzać MappingRecognizeText wywołania synchronicznie lub asynchronicznie.
MappingRecognizeText obsługuje następujące typy tekstu:
- Wykrywanie języka firmy Microsoft. UTF-16, normalizacja formularza C, tekst, dla którego należy określić język.
- Wykrywanie skryptów firmy Microsoft. Tekst UTF-16, dla którego należy określić zakresy skryptów.
- Usługi transliteracji. Tekst UTF-16 napisany w skrypcie źródłowym (system zapisu).
Korzystanie z synchronicznego rozpoznawania tekstu
Ta sekcja zawiera instrukcje dotyczące kilku sposobów przeprowadzania synchronicznego rozpoznawania tekstu.
synchroniczne rozpoznawanie tekstu za pomocą usługi wykrywania języka firmy Microsoft
W poniższym przykładzie pokazano użycie MappingRecognizeText z usługą wykrywania języka firmy Microsoft i wyświetla wszystkie wyniki pobrane przez usługę. Format danych wyjściowych tej usługi to pojedyncza struktura MAPPING_DATA_RANGE z elementem pData wskazującym na tablicę ciągów formatu rejestru w Unicode, która jest zakończona podwójnym znakiem null. Każdy ciąg tablicy jest zakończony wartością null, a pusty ciąg służy do określania końca tablicy. Zawartość tablicy to nazwy języków posortowane według pewności.
#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);
}
}
synchroniczne rozpoznawanie tekstu za pomocą usługi wykrywania skryptów firmy Microsoft
W następnym przykładzie pokazano użycie MappingRecognizeText z usługą wykrywania skryptów firmy Microsoft i wyświetla wszystkie pobrane wyniki. Format danych wyjściowych tej usługi to tablica struktur MAPPING_DATA_RANGE, z których każdy określa tekst napisany w tym samym skrygcie. Typowe znaki (Zyyy) są dodawane do poprzedniego zakresu lub do następnego zakresu, jeśli poprzedni zakres nie istnieje. Składowa pData każdej struktury wskazuje ciąg znaków Unicode zakończony wartością null, zawierający standardową nazwę skryptu dla określonego zakresu.
Notatka
Od systemu Windows 7 usługa wykrywania skryptów firmy Microsoft jest zgodna z standardem 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);
}
}
synchroniczne rozpoznawanie tekstu z usługą transliteracji z cyrylicy na łacinę firmy Microsoft
W poniższym przykładzie pokazano użycie MappingRecognizeText z usługą transliteracji Microsoft z cyrylicy na łaciński, gdzie wyświetla pobrane wyniki. Zwróć uwagę na dwa różne sposoby wyliczania tej usługi przez identyfikator GUID lub według kategorii i skryptu wejściowego.
Format danych wyjściowych jest taki sam dla wszystkich dostępnych usług transliteracji. Jest to pojedyncza struktura MAPPING_DATA_RANGE ze swoim elementem członkowskim pData wskazującym tablicę znaków Unicode reprezentujących oryginalny tekst transliterowany do skryptu wyjściowego, przy zastosowaniu wyłącznie reguł określonych przez konkretną usługę transliteracji. Ta usługa nie dodaje końcowego znaku null do swoich danych wyjściowych, jeśli dane wejściowe nie zawierają znaku zakończenia null.
#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);
}
synchroniczne rozpoznawanie tekstu z wywołaniem wszystkich dostępnych usług
Poniższy przykład przedstawia użycie MappingRecognizeText ze wszystkimi dostępnymi usługami i wyświetla pobrane wyniki dla wszystkich usług. W tym przykładzie przedstawiono dobrą ilustrację działania każdej usługi. Patrząc na dane wyjściowe przykładowej aplikacji, łatwo jest dowiedzieć się, co dzieje się wewnętrznie z usługami. W tym przykładzie pokazano również, że prawie cały kod używany do wywoływania dowolnej z usług ELS jest taki sam.
#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;
}
Używanie asynchronicznego rozpoznawania tekstu
W poniższym przykładzie pokazano użycie MappingRecognizeText do asynchronicznego rozpoznawania tekstu. Gdy jest używane wywołanie zwrotne, aplikacja musi upewnić się, że torba właściwości, tekst wejściowy, opcje i usługa są prawidłowe do momentu zakończenia wykonywania wywołania zwrotnego.
Aplikacja musi wywołać MappingFreePropertyBag natychmiast po użyciu torby przez funkcję wywołania zwrotnego. Aby uzyskać więcej informacji, zobacz Zapewnianie wywołań zwrotnych dla usług 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);
}
Tematy pokrewne
-
Mapowanie FreePropertyBag