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) FRDocument IFRDocumentEvents (DIFRDocumentEvents)FRPages IFRPagesEvents (DIFRPagesEvents)FRPage IFRPageEvents (DIFRPageEvents)ImageDocument IImageDocumentEvents (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 物件作為範例。
實作 IFRDocumentEvents 介面。由於其衍生自 IUnknown 介面,客戶端物件也應實作 IUnknown 方法:
然後,CFRDocumentCallback 類別可用來從 FRDocument 物件接收通知。將此物件註冊至通知來源 (省略錯誤處理) :
Linux 使用者也可以參閱 EventsHandling 範例。 本主題其餘部分適用於 Windows 版 FRE 使用者。
適用於 Windows:
只需使用 WithEvents 宣告可連接物件,並實作對應回呼介面的方法。您還需要明確指定與事件關聯的事件處理常式。 對於 FRDocument 物件,程序將如下:
使用 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 ()
在類似下列的 Sub 中實作 DIFRDocumentEvents dispinterface 的必要方法。
如果您想在程式執行期間的任何時間啟動和停止事件處理 (使用 AddHandler 和 RemoveHandler 陳述式) : 或者只需指定此程序處理特定事件 (在定義時使用 Handles 關鍵字) :
將實作的事件處理常式連接到事件來源,使用 FRDocument 物件進行處理,然後斷開處理常式:
在 C++ 中,您需要實作必要的介面、取得連接點,並將實作該介面的物件「Advise」至對應的可連接的物件。我們將以 FRDocument 物件為例。
實作 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);
接著,CFRDocumentEventsListener 類別即可用來接收來自 FRDocument 物件的通知。將此物件 Advise 至通知來源 (省略錯誤處理) :
C# 的程序與 Visual Basic .NET 類似。您需要實作 callback 介面的必要方法,並將實作好的事件處理常式連接到事件來源。我們將以 FRDocument 物件為例。
實作 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 ;
將事件處理常式連接至事件來源,使用 FRDocument 物件進行處理,然後再中斷處理常式的連線:
Windows 使用者應參閱 COM 文件,以取得可連接的物件更詳細的說明。
您也可以參考 FRE for Linux 提供給 C++ 使用,以及 Windows 提供給 C#、具備 Native COM Support 的 C++、raw C++ 和 Visual Basic .NET 使用的 EventsHandling 範例。