跳轉到主要內容
ABBYY FineReader Engine 中有些物件屬於所謂的「可連接的物件」。這表示它們實作了 IConnectionPointContainer 介面。可連接的物件支援 ABBYY FineReader Engine 與其客戶端之間的通訊。
在 Linux 中,以處理序外伺服器形式載入的 Engine 物件不支援使用回呼。
對 Windows 使用者而言,每個 FRE 可連接物件都提供兩種類型的連接點——一種使用 dispatch 介面,另一種使用衍生自 IUnknown 的介面。dispatch 介面是為了在 Visual Basic 及類似環境中自動使用而設計,而以 vtbl 為基礎的介面則適合在 C++ 中使用。
在下表中,您可以找到 ABBYY FineReader Engine 中可連接物件及其對應回呼介面 (dispinterface) 的清單:
Dispinterface 僅適用於 Windows。
物件回呼介面 (Dispinterface)
FRDocumentIFRDocumentEvents (DIFRDocumentEvents)
FRPagesIFRPagesEvents (DIFRPagesEvents)
FRPageIFRPageEvents (DIFRPageEvents)
ImageDocumentIImageDocumentEvents (DIImageDocumentEvents)
Windows Visual Components 想要接收 ABBYY FineReader Engine 中特定事件通知的 ABBYY FineReader Engine 客戶端應用程式,應實作特定類型的介面,並將實作這些介面的物件註冊到對應的可連接物件。
有兩個全域方法用於連接到通知來源並斷開連接:
HRESULT AdviseFREngineObject( IUnknown* object, IUnknown* callback, DWORD* cookie );
HRESULT UnAdviseFREngineObject( IUnknown* object, DWORD cookie );
class CFRDocumentCallback: public IFRDocumentEvents {
public:
...
    // 提供 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;
    }
}
// 提供 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; }
};
// 假設我們已經取得 FRDocument 物件
IFRDocument* document;
// 建立回呼物件
CFRDocumentCallback callbackObject;
// 將接聽器註冊至通知來源
DWORD cookie; // 用於儲存來自 Advise 方法的 cookie 的變數
AdviseFREngineObject( frDocument, &callbackObject, &cookie );
// 處理文件
...
// 處理完成後,不再需要接聽器,因此應取消註冊
UnadviseFREngineObject( frDocument, cookie );
這些方法應以其中一個可連接物件作為 object 參數,並以對應的回呼介面作為 callback 參數。您需要實作必要的介面,並將實作該介面的物件註冊至對應的可連接物件。我們將以 FRDocument 物件作為範例。
  1. 實作 IFRDocumentEvents 介面。由於其衍生自 IUnknown 介面,客戶端物件也應實作 IUnknown 方法:
  2. 然後,CFRDocumentCallback 類別可用來從 FRDocument 物件接收通知。將此物件註冊至通知來源 (省略錯誤處理) :
Linux 使用者也可以參閱 EventsHandling 範例。
本主題其餘部分適用於 Windows 版 FRE 使用者。
適用於 Windows:
只需使用 WithEvents 宣告可連接物件,並實作對應回呼介面的方法。您還需要明確指定與事件關聯的事件處理常式。對於 FRDocument 物件,程序將如下:
  1. 使用 WithEvents 宣告 FRDocument 物件:
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
或者,如果您使用 Handles 關鍵字定義事件處理方法,則可直接使用 FRDocument 物件進行處理:
document = Engine.CreateFRDocument
document.AddImageFile("D:\Demo.tif")
document.Process()
  1. 在類似下列的 Sub 中實作 DIFRDocumentEvents dispinterface 的必要方法。
如果您想在程式執行期間的任何時間啟動和停止事件處理 (使用 AddHandler 和 RemoveHandler 陳述式) :或者只需指定此程序處理特定事件 (在定義時使用 Handles 關鍵字) :
  1. 將實作的事件處理常式連接到事件來源,使用 FRDocument 物件進行處理,然後斷開處理常式:
在 C++ 中,您需要實作必要的介面、取得連接點,並將實作該介面的物件「Advise」至對應的可連接的物件。我們將以 FRDocument 物件為例。
  1. 實作 IFRDocumentEvents 介面。由於它衍生自 IUnknown 介面,因此客戶端物件也應實作 IUnknown 的方法:
class CFRDocumentEventsListener : public IFRDocumentEvents {
public:
...
    // 提供 IUnknown 方法的簡單實作。這些方法也可以
    // 透過繼承某個支援 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;
    }
    // 提供 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; }
};
// 假設我們已經取得 FRDocument 物件
IFRDocument* document;
// 在 FRDocument 物件上查詢 IConnectionPointContainer
IConnectionPointContainer* pContainer=0;
document->QueryInterface(IID_IConnectionPointContainer, (void**)&pContainer);
// 取得可連接物件中某個連接點上的 IConnectionPoint 介面指標
IConnectionPoint* pPoint=0;
pContainer->FindConnectionPoint(__uuidof(IFRDocumentEvents),
                                &pPoint);
// 在 CFRDocumentEventsListener 類別與連接點之間建立連線
CFRDocumentEventsListener listener;
IUnknown* listenerUnknown=0;
listener.QueryInterface(IID_IUnknown, (void**)&listenerUnknown);
// 將 listener Advise 至通知來源
DWORD cookie; // 用來儲存 IConnectionPoint::Advise 方法所傳回 cookie 的變數
pPoint->Advise(listenerUnknown, &cookie);
// 處理文件
...
// 通知完成後,listener 就不再需要,應取消 Advise
pPoint->Unadvise(cookie);
  1. 接著,CFRDocumentEventsListener 類別即可用來接收來自 FRDocument 物件的通知。將此物件 Advise 至通知來源 (省略錯誤處理) :
C# 的程序與 Visual Basic .NET 類似。您需要實作 callback 介面的必要方法,並將實作好的事件處理常式連接到事件來源。我們將以 FRDocument 物件為例。
  1. 實作 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. 將事件處理常式連接至事件來源,使用 FRDocument 物件進行處理,然後再中斷處理常式的連線:
Windows 使用者應參閱 COM 文件,以取得可連接的物件更詳細的說明。 您也可以參考 FRE for Linux 提供給 C++ 使用,以及 Windows 提供給 C#、具備 Native COM Support 的 C++、raw C++ 和 Visual Basic .NET 使用的 EventsHandling 範例。