ABBYY FineReader Engine 中的某些对象被称为”可连接对象”。这意味着它们实现了 IConnectionPointContainer 接口。可连接对象支持 ABBYY FineReader Engine 与其客户端之间的通信。
在 Linux 中,以进程外服务器方式加载的 Engine 对象不支持使用回调。
对于 Windows 用户,每个 FRE 可连接对象提供两种类型的连接点——一种使用调度接口,另一种使用派生自 IUnknown 的接口。调度接口专为在 Visual Basic 及类似环境中自动调用而设计,而基于 vtbl 的接口则适合在 C++ 中使用。
下表列出了 ABBYY FineReader Engine 中的可连接对象及其对应的回调接口 (调度接口) :
调度接口 (Dispinterface) 为 Windows 专用。
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 示例。 本主题的其余内容适用于 FRE for Windows 的用户。
适用于 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
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 ()
在 Sub 中实现 DIFRDocumentEvents 调度接口的必要方法,示例如下。
如果您希望在程序执行期间随时启动和停止事件处理 (使用 AddHandler 和 RemoveHandler 语句) : 或者直接指定该过程处理特定事件 (在定义时使用 Handles 关键字) :
将已实现的事件处理程序连接到事件源,使用 FRDocument 对象执行处理,然后断开处理程序:
在 C++ 中,您需要实现必要的接口,获取连接点,并将实现该接口的对象”注册”到相应的可连接对象。以下以 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);
// 将监听器注册到通知源
DWORD cookie; // 用于存储 IConnectionPoint::Advise 方法返回的 cookie 的变量
pPoint -> Advise (listenerUnknown, & cookie);
// 处理文档
...
// 通知完成后,监听器不再需要,应取消注册
pPoint -> Unadvise (cookie);
随后,CFRDocumentEventsListener 类可用于接收来自 FRDocument 对象的通知。将此对象注册到通知源 (省略错误处理) :
C# 的操作流程与 Visual Basic .NET 类似。您需要实现回调接口的必要方法,并将已实现的事件处理程序连接到事件源。以下以 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#、支持原生 COM 的 C++、原始 C++、Visual Basic .NET) 中提供的 EventsHandling 示例。