不同的编程语言以不同的方式创建 ADO 事件实例。如下所有范例均创建 ConnectComplete 事件处理程序。
Dim WithEvent connEvent as Connection Dim conn as New Connection set connEvent = conn '打开事件支持。 conn.Open(...) ... set connEvent = Nothing '关闭事件支持。 ... Private Sub connEvent_ConnectComplete(ByVal err as ADODB.Error, & _ adStatus as ADODB.EventStatus, ByVal pConnectionas ADODB.Connection) '仅当 adStatus 等于 adStatusErrorsOccurred 时检查错误对象。 ... End Sub
这是关于在 VC++ 中如何实例化事件的示意性说明。
创建在 adoint.h 文件中由 ConnectionEventsVt 和 RecordsetEventsVt 接口所派生的类。
class CConnEvent : public ConnectionEventsVt { public: STDMETHODIMP InfoMessage( ADOError *pError, EventStatusEnum *adStatus, _ADOConnection *pConnection); ... }class CRstEvent : public RecordsetEventsVt { public: STDMETHODIMP WillChangeField( LONG cFields, VARIANT Fields, EventStatusEnum *adStatus, _ADORecordset *pRecordset); ... }
在两个类中执行每个事件处理程序方法。每个方法只返回一个 HRESULT of S_OK 就够了。但是,一旦事件处理程序有效,这些事件处理程序就会在默认状态下被连续调用。为改变这种情况,您可通过将 adStatus 设置为 adStatusUnwantedEvent,以便在第一次调用之后不再请求其他通知。
STDMETHODIMP CConnEvent::ConnectComplete( ADOError *pError, EventStatusEnum *adStatus, _ADOConnection *pConnection) { *adStatus = adStatusUnwantedEvent; return S_OK; }
事件类继承了 Iunknown,所以也必须执行 QueryInterface、AddRef 和 Release 方法。如要执行类构造函数和析构函数,请选择最易于使用并能简化这部分任务的 VC++ 工具。
通过在 Recordset 和 Connection 对象上向 IConnectionPointContainer 和 IConnectionPoint 接口发出 QueryInterface,通知事件处理程序现在已可以使用,然后向各类发出 IConnectionPoint::Advise。
例如,假设您正在使用布尔型函数,该函数在成功地向 Recordset 对象发出可以使用事件处理程序的通知时返回“真”值。
HRESULT hr; DWORD dwEvtClass; IConnectionPointContainer *pCPC = NULL; IConnectionPoint *pCP = NULL; CRstEvent *pRStEvent = NULL; ... _RecordsetPtr pRs(); pRs.CreateInstance(__uuidof(Recordset)); pRStEvent = New CRstEvent(); if (pRStEvent == NULL) return FALSE; ... hr = pRs->QueryInterface(IID_IConnectionPointContainer, &pCPC); if (FAILED(hr)) return FALSE; hr = pCPC->FindConnectionPoint(IID_ADORecordsetEvents, &pCP); pCPC->Release(); // Always Release now, even before checking. if (FAILED(hr)) return FALSE; hr = pCP->Advise(pRstEvent, &dwEvtClass); //Turn on event support. pCP->Release(); if (FAILED(hr)) return FALSE; ... return TRUE; ...
在此,RecordsetEvent 类的事件会被打开并且在 Recordset 事件出现时方法将被调用。
此后,如果您想使事件处理程序无效,可以再次获取连接点并发出 IConnectionPoint::UnAdvise 方法。
... hr = pCP->UnAdvise(dwEvtClass); //Turn off event support. pCP->Release(); if (FAILED(hr)) return FALSE; ...
当然,必须在适当的时候释放接口并毁掉类的对象。
import wfc.data.*; public class MyClass { ConnectionEventHandler handler = new ConnectionEventHandler(this,"onConnectComplete");public void onConnectComplete(Object sender,ConnectionEvent e) { if (e.adStatus == AdoEnums.EventStatus.ERRORSOCCURRED) System.out.println("Connection failed"); else System.out.println("Connection completed"); return; }void main( void ) { Connection conn = new Connection(); conn.addOnConnectComplete(handler); //打开事件支持。 conn.open("DSN=pubs"); conn.close(); conn.removeOnConnectComplete(handler); //关闭事件支持。 } }
VBScript 不支持事件。