Pular para o conteúdo principal
Alguns dos objetos no ABBYY FineReader Engine são os chamados “objetos conectáveis”. Isso significa que eles implementam a interface IConnectionPointContainer. Os objetos conectáveis dão suporte à comunicação entre o ABBYY FineReader Engine e seus clientes.
No Linux, o objeto Engine, carregado como um servidor fora do processo, não oferece suporte ao uso de callbacks.
Para usuários do Windows, cada um dos objetos conectáveis do FRE fornece pontos de conexão de dois tipos — um que usa uma interface de despacho e outro que usa a interface derivada de IUnknown. A interface de despacho foi projetada para uso automático no Visual Basic e em ambientes semelhantes, enquanto a interface baseada em vtbl é adequada para uso em C++.
Na tabela abaixo, é possível encontrar a lista de objetos conectáveis no ABBYY FineReader Engine e as interfaces de callback correspondentes (dispinterfaces):
Dispinterfaces são específicas do Windows.
ObjetoInterface de Callback (Dispinterface)
FRDocumentIFRDocumentEvents (DIFRDocumentEvents)
FRPagesIFRPagesEvents (DIFRPagesEvents)
FRPageIFRPageEvents (DIFRPageEvents)
ImageDocumentIImageDocumentEvents (DIImageDocumentEvents)
Visual Components do Windows O aplicativo cliente do ABBYY FineReader Engine que quiser receber notificações sobre determinados eventos no ABBYY FineReader Engine deve implementar interfaces de um tipo específico e “associar” aos objetos conectáveis correspondentes os objetos que implementam essas interfaces.
Há dois métodos globais usados para conectar-se e desconectar-se da fonte de notificações:
HRESULT AdviseFREngineObject( IUnknown* object, IUnknown* callback, DWORD* cookie );
HRESULT UnAdviseFREngineObject( IUnknown* object, DWORD cookie );
class CFRDocumentCallback: public IFRDocumentEvents {
public:
...
    // Fornece uma implementação simples dos métodos de 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;
    }
}
// Fornece a implementação dos métodos de 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; }
};
// Suponha que já tenhamos recebido o objeto FRDocument
IFRDocument* document;
// Cria o objeto de callback
CFRDocumentCallback callbackObject;
// Registra o listener na fonte de notificações
DWORD cookie; // Variável para armazenar o cookie retornado pelo método Advise
AdviseFREngineObject( frDocument, &callbackObject, &cookie );
// Processa o documento
...
// Após a notificação, o listener deixa de ser necessário e seu registro deve ser removido
UnadviseFREngineObject( frDocument, cookie );
Esses métodos devem receber um dos objetos conectáveis como argumento object e a interface de callback correspondente como argumento callback.Você precisa implementar a interface necessária e “registrar” o objeto que a implementa nos objetos conectáveis correspondentes. Usaremos o objeto FRDocument como exemplo.
  1. Implemente a interface IFRDocumentEvents. Como ela deriva da interface IUnknown, o objeto cliente também deve implementar os métodos de IUnknown:
  2. Em seguida, a classe CFRDocumentCallback poderá ser usada para receber notificações do objeto FRDocument. Registre esse objeto na fonte de notificações (o tratamento de erros foi omitido):
Os usuários do Linux também podem consultar o exemplo EventsHandling.
O restante deste tópico se aplica aos usuários do FRE para Windows.
Para Windows:
Basta declarar o objeto conectável com WithEvents e implementar os métodos da interface de callback correspondente. Você também precisará especificar explicitamente o manipulador de eventos associado ao evento.Para o objeto FRDocument, o procedimento será o seguinte:
  1. Declare o objeto FRDocument com 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
ou simplesmente use o objeto FRDocument para processamento se você definir os métodos de tratamento de eventos com a palavra-chave Handles:
document = Engine.CreateFRDocument
document.AddImageFile("D:\Demo.tif")
document.Process()
  1. Implemente os métodos necessários da dispinterface DIFRDocumentEvents em um Sub, de forma semelhante ao exemplo a seguir.
Se quiser iniciar e interromper o tratamento de eventos a qualquer momento durante a execução do programa (usando as instruções AddHandler e RemoveHandler):ou simplesmente especifique que esse procedimento trata um evento específico (use a palavra-chave Handles ao defini-lo):
  1. Conecte o manipulador de eventos implementado à fonte de eventos, use o objeto FRDocument para processamento e, em seguida, desconecte o manipulador:
Em C++, você precisa implementar a interface necessária, obter um ponto de conexão e usar “registrar” para associar o objeto que implementa a interface aos objetos conectáveis correspondentes. Usaremos o objeto FRDocument como exemplo.
  1. Implemente a interface IFRDocumentEvents. Como ela deriva da interface IUnknown, o objeto cliente também deve implementar os métodos de IUnknown:
class CFRDocumentEventsListener : public IFRDocumentEvents {
public:
...
    // Forneça uma implementação simples dos métodos de IUnknown. Eles também podem ser
    // implementados por herança a partir de alguma classe padrão com suporte a 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;
    }
    // Forneça a implementação dos métodos de 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; }
};
// Suponha que já tenhamos recebido o objeto FRDocument
IFRDocument* document;
// Consulte IConnectionPointContainer no objeto FRDocument
IConnectionPointContainer* pContainer=0;
document->QueryInterface(IID_IConnectionPointContainer, (void**)&pContainer);
// Obtenha um ponteiro para a interface IConnectionPoint em um ponto de conexão dentro do objeto conectável
IConnectionPoint* pPoint=0;
pContainer->FindConnectionPoint(__uuidof(IFRDocumentEvents),
                                &pPoint);
// Estabeleça uma conexão entre a classe CFRDocumentEventsListener e o ponto de conexão
CFRDocumentEventsListener listener;
IUnknown* listenerUnknown=0;
listener.QueryInterface(IID_IUnknown, (void**)&listenerUnknown);
// Registre o listener na fonte de notificações com Advise
DWORD cookie; // Uma variável para armazenar o cookie retornado pelo método IConnectionPoint::Advise
pPoint->Advise(listenerUnknown, &cookie);
// Processe o documento
...
// Depois disso, o listener não será mais necessário e o registro deverá ser desfeito com Unadvise
pPoint->Unadvise(cookie);
  1. Em seguida, a classe CFRDocumentEventsListener pode ser usada para receber notificações do objeto FRDocument. Registre esse objeto na fonte de notificações com Advise (o tratamento de erros foi omitido):
O procedimento em C# é semelhante ao do Visual Basic .NET. Você precisa implementar os métodos necessários da interface de callback e conectar os manipuladores de eventos implementados à fonte de eventos. Usaremos o objeto FRDocument como exemplo.
  1. Implemente os métodos necessários da interface 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. Conecte o manipulador de eventos à fonte de eventos, use o objeto FRDocument para processamento e, em seguida, desconecte o manipulador:
Os usuários do Windows devem consultar a documentação sobre COM para obter uma descrição mais detalhada dos objetos conectáveis. Você também pode consultar o exemplo EventsHandling fornecido no FRE para Linux, no caso de C++, e para Windows, no caso de C#, C++ com Native COM Support, raw C++ e Visual Basic .NET.