Vai al contenuto principale
Alcuni degli oggetti in ABBYY FineReader Engine sono i cosiddetti “oggetti connettibili”. Ciò significa che implementano l’interfaccia IConnectionPointContainer. Gli oggetti connettibili consentono la comunicazione tra ABBYY FineReader Engine e i relativi client.
In Linux, l’oggetto Engine caricato come server out-of-process non supporta l’uso dei callback.
Per gli utenti Windows, ciascuno degli oggetti connettibili di FRE fornisce punti di connessione di due tipi: uno che utilizza un’interfaccia dispatch e uno che utilizza l’interfaccia derivata da IUnknown. L’interfaccia dispatch è progettata per l’uso automatico in Visual Basic e ambienti simili, mentre l’interfaccia basata su vtbl è adatta all’uso in C++.
Nella tabella seguente è riportato l’elenco degli oggetti connettibili in ABBYY FineReader Engine e delle corrispondenti interfacce callback (dispinterface):
Le dispinterface sono specifiche di Windows.
OggettoInterfaccia callback (Dispinterface)
FRDocumentIFRDocumentEvents (DIFRDocumentEvents)
FRPagesIFRPagesEvents (DIFRPagesEvents)
FRPageIFRPageEvents (DIFRPageEvents)
ImageDocumentIImageDocumentEvents (DIImageDocumentEvents)
Visual Components per Windows L’applicazione client di ABBYY FineReader Engine che desidera ricevere notifiche di determinati eventi in ABBYY FineReader Engine deve implementare interfacce di un tipo specifico e “advise” gli oggetti che implementano tali interfacce ai corrispondenti oggetti connettibili.
Esistono due metodi globali usati per collegarsi e scollegarsi dalla sorgente delle notifiche:
HRESULT AdviseFREngineObject( IUnknown* object, IUnknown* callback, DWORD* cookie );
HRESULT UnAdviseFREngineObject( IUnknown* object, DWORD cookie );
class CFRDocumentCallback: public IFRDocumentEvents {
public:
...
    // Fornire una semplice implementazione dei metodi IUnknown
    ULONG STDMETHODCALLTYPE AddRef() { return 1; }
    ULONG STDMETHODCALLTYPE Release() { return 1; }
    HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppObject )
    {
        if( ppObject == 0 ) {
            return E_POINTER;
        }
    *ppObject = 0;
    if( riid == IID_IUnknown || riid == IID_IFRDocumentEvents )
    {
        *ppObject = this;
        AddRef();
        return S_OK;
    } else {
        return E_NOINTERFACE;
    }
}
// Fornire l'implementazione dei metodi IFRDocumentEvents
HRESULT STDMETHODCALLTYPE OnProgress(
IFRDocument* sender, int percentage, VARIANT_BOOL* cancel );
HRESULT STDMETHODCALLTYPE OnWarning(
IFRDocument* sender, int index, BSTR tip, VARIANT_BOOL* cancel );
HRESULT STDMETHODCALLTYPE OnPageProcessed(
    IFRDocument* sender, int index, PageProcessingStageEnum stage ) { return S_OK; }
};
// Supponiamo di avere già ottenuto l'oggetto FRDocument
IFRDocument* document;
// Creare l'oggetto callback
CFRDocumentCallback callbackObject;
// Collegare il listener alla sorgente delle notifiche
DWORD cookie; // Variabile per memorizzare il cookie restituito dal metodo Advise
AdviseFREngineObject( frDocument, &callbackObject, &cookie );
// Elaborare il documento
...
// Dopo la notifica, il listener non è più necessario e deve essere scollegato
UnadviseFREngineObject( frDocument, cookie );
Questi metodi devono ricevere uno degli oggetti connettibili come argomento object e la corrispondente interfaccia callback come argomento callback.È necessario implementare l’interfaccia richiesta e usare “advise” per collegare l’oggetto che implementa l’interfaccia ai corrispondenti oggetti connettibili. Useremo l’oggetto FRDocument come esempio.
  1. Implementare l’interfaccia IFRDocumentEvents. Poiché deriva dall’interfaccia IUnknown, l’oggetto client deve implementare anche i metodi IUnknown:
  2. La classe CFRDocumentCallback può quindi essere usata per ricevere notifiche dall’oggetto FRDocument. Collegare questo oggetto alla sorgente delle notifiche tramite advise (la gestione degli errori è omessa):
Gli utenti Linux possono anche fare riferimento all’esempio EventsHandling.
Il resto di questo argomento si applica agli utenti di FRE per Windows.
Per Windows:
È sufficiente dichiarare l’oggetto connettibile con WithEvents e implementare i metodi della corrispondente interfaccia callback. Sarà inoltre necessario specificare esplicitamente il gestore eventi associato all’evento.Per l’oggetto FRDocument, la procedura sarà la seguente:
  1. Dichiarare l’oggetto FRDocument con WithEvents:
Private WithEvents document As FREngine.FRDocument
Private Sub document_RecognitionOnProgress(ByVal sender As FREngine.FRDocument, _
                                           ByVal Percentage As Integer, _
                                           ByRef cancel As Boolean)
...
End Sub
Private Sub document_RecognitionOnProgress(ByVal sender As FREngine.FRDocument, _
                                           ByVal Percentage As Integer, _
                                           ByRef cancel As Boolean) Handles document.OnProgress
...
End Sub
document = Engine.CreateFRDocument
document.AddImageFile("D:\Demo.tif")
AddHandler document.OnProgress, AddressOf Me.document_RecognitionOnProgress
document.Process()
RemoveHandler document.OnProgress, AddressOf Me.document_RecognitionOnProgress
or simply use the FRDocument object for processing if you define the event handling methods with Handles keyword:
document = Engine.CreateFRDocument
document.AddImageFile("D:\Demo.tif")
document.Process()
  1. Implementare i metodi necessari della dispinterface DIFRDocumentEvents in una Sub simile alla seguente.
Se si desidera avviare e interrompere la gestione degli eventi in qualsiasi momento durante l’esecuzione del programma (usando le istruzioni AddHandler e RemoveHandler):oppure specificare semplicemente che questa procedura gestisce un evento specifico (usando la parola chiave Handles durante la definizione):
  1. Collegare il gestore eventi implementato all’origine eventi, usare l’oggetto FRDocument per l’elaborazione, quindi scollegare il gestore:
In C++, è necessario implementare l’interfaccia richiesta, ottenere un connection point ed eseguire l‘“advise” dell’oggetto che implementa l’interfaccia sugli oggetti connettibili corrispondenti. Useremo l’oggetto FRDocument come esempio.
  1. Implementare l’interfaccia IFRDocumentEvents. Poiché deriva dall’interfaccia IUnknown, anche l’oggetto client deve implementare i metodi IUnknown:
class CFRDocumentEventsListener : public IFRDocumentEvents {
public:
...
    // Fornisce una semplice implementazione dei metodi IUnknown. Possono anche essere
    // implementati tramite ereditarietà da una classe standard con supporto COM
    ULONG AddRef();
    ULONG Release();
    HRESULT QueryInterface(REFIID riid, void** ppvObject)
    {
        if( ppvObject == 0 )
            return E_INVALIDARG;
        if( riid == __uuidof(IFRDocumentEvents) ) {
            *ppvObject = static_cast<IFRDocumentEvents*>( this );
        } else if( riid == IID_IUnknown ) {
            *ppvObject = static_cast<IUnknown*>( this );
        } else {
            *ppvObject = 0;
            return E_NOINTERFACE;
        }
        AddRef();
        return S_OK;
    }
    // Fornisce l'implementazione dei metodi IFRDocumentEvents
 HRESULT STDMETHODCALLTYPE OnProgress(
  IFRDocument* sender, int percentage, VARIANT_BOOL* cancel );
 HRESULT STDMETHODCALLTYPE OnWarning(
  IFRDocument* sender, int index, BSTR tip, VARIANT_BOOL* cancel );
 HRESULT STDMETHODCALLTYPE OnPageProcessed(
  IFRDocument* sender, int index, PageProcessingStageEnum stage ) { return S_OK; }
};
// Supponiamo di avere già ricevuto l'oggetto FRDocument
IFRDocument* document;
// Esegue la query di IConnectionPointContainer sull'oggetto FRDocument
IConnectionPointContainer* pContainer=0;
document->QueryInterface(IID_IConnectionPointContainer, (void**)&pContainer);
// Ottiene un puntatore all'interfaccia IConnectionPoint su un connection point all'interno dell'oggetto connettibile
IConnectionPoint* pPoint=0;
pContainer->FindConnectionPoint(__uuidof(IFRDocumentEvents),
                                &pPoint);
// Stabilisce una connessione tra la classe CFRDocumentEventsListener e il connection point
CFRDocumentEventsListener listener;
IUnknown* listenerUnknown=0;
listener.QueryInterface(IID_IUnknown, (void**)&listenerUnknown);
// Esegue l'advise di listener sulla sorgente delle notifiche
DWORD cookie; // Una variabile per memorizzare il cookie restituito dal metodo IConnectionPoint::Advise
pPoint->Advise(listenerUnknown, &cookie);
// Elabora il documento
...
// Dopo la notifica, listener non è più necessario e l'advise deve essere annullato
pPoint->Unadvise(cookie);
  1. La classe CFRDocumentEventsListener può quindi essere utilizzata per ricevere notifiche dall’oggetto FRDocument. Eseguire l’advise di questo oggetto sulla sorgente delle notifiche (la gestione degli errori è omessa):
La procedura in C# è simile a quella di Visual Basic .NET. È necessario implementare i metodi richiesti dell’interfaccia callback e collegare i gestori eventi implementati alla sorgente degli eventi. Useremo l’oggetto FRDocument come esempio.
  1. Implementare i metodi necessari dell’interfaccia IFRDocumentEvents:
private void document_RecognitionOnProgress(FREngine.IFRDocument sender, int Percentage, ref bool cancel)
{
 ...
}
FREngine.DIFRDocumentEvents_OnProgressEventHandler recognizeOnProgressHandler =
 new FREngine.DIFRDocumentEvents_OnProgressEventHandler(
 document_RecognitionOnProgress );
document.OnProgress += recognizeOnProgressHandler;
document.Process( null, null, null );
document.OnProgress -= recognizeOnProgressHandler;
  1. Collegare il gestore eventi alla sorgente degli eventi, usare l’oggetto FRDocument per l’elaborazione, quindi scollegare il gestore:
Gli utenti Windows dovrebbero fare riferimento alla documentazione su COM per una descrizione più dettagliata degli oggetti connettibili. Puoi anche fare riferimento all’esempio EventsHandling fornito in FRE per Linux per C++ e Windows per C#, C++ con Native COM Support, raw C++ e Visual Basic .NET.