这是Delphi XE3探索:Winapi.Functiondiscovery系列到第三篇文章。
思路分析
Discovery API 不仅仅可以用来枚举设备信息,还可以接收设备通知;例如设备的添加、移除或者设备的属性被修改。为了接收这些设备改变的通知就需要实现 IFunctionDiscoveryNotification接口。AddQueryConstraint 的PROVIDERPNP_QUERYCONSTRAINT_NOTIFICATIONSONLY值用于设置是否仅接收设备通知,最后调用 IFunctionInstanceCollectionQuery.Execute方法。
实现IFunctionDiscoveryNotification 接口
IFunctionDiscoveryNotification 有三个方法用于接收 IFunctionInstanceCollectionQuery.Execute 异步查询的结果。
接口方法
OnError : Receives errors that occur during asynchronous query processing.
OnEvent : Receives any add, remove, or update events.
OnUpdate : Indicates that a function instance has been added, removed, or changed.
IFunctionDiscoveryNotification 接口声明:
IFunctionDiscoveryNotification = interface(IUnknown) [SID_IFunctionDiscoveryNotification] function OnUpdate(enumQueryUpdateAction: QueryUpdateAction; fdqcQueryContext: FDQUERYCONTEXT; pIFunctionInstance: IFunctionInstance): HRESULT; stdcall; function OnError(hr: HRESULT; fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR): HRESULT; stdcall; function OnEvent(dwEventID: DWORD; fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR): HRESULT; stdcall; end;
接口实现代码
type
TFunctionDiscoveryOnUpdate = procedure(enumQueryUpdateAction: QueryUpdateAction; fdqcQueryContext: FDQUERYCONTEXT;
pIFunctionInstance: IFunctionInstance) of object;
TFunctionDiscoveryOnError = procedure(hr: HRESULT; fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR) of object;
TFunctionDiscoveryOnEvent = procedure(dwEventID: DWORD; fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR) of object;
TFunctionDiscoveryNotificationSync=class(TInterfacedObject, IFunctionDiscoveryNotification)
private
FAction : QueryUpdateAction;
FEventAdd : TEvent;
FEventRemove : TEvent;
FEventChange : TEvent;
FOnUpdateEvent : TFunctionDiscoveryOnUpdate;
FOnErrorEvent : TFunctionDiscoveryOnError;
FOnEventEvent : TFunctionDiscoveryOnEvent;
function OnUpdate(enumQueryUpdateAction: QueryUpdateAction; fdqcQueryContext: FDQUERYCONTEXT;
pIFunctionInstance: IFunctionInstance): HRESULT; stdcall;
function OnError(hr: HRESULT; fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR): HRESULT; stdcall;
function OnEvent(dwEventID: DWORD; fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR): HRESULT; stdcall;
public
constructor Create;
destructor Destroy; override;
function WaitFor(dwTimeout : DWORD; pszCategory: PWCHAR; eAction : QueryUpdateAction) : HRESULT;
property OnUpdateEvent: TFunctionDiscoveryOnUpdate read FOnUpdateEvent write FOnUpdateEvent;
property OnErrorEvent : TFunctionDiscoveryOnError read FOnErrorEvent write FOnErrorEvent;
property OnEventEvent : TFunctionDiscoveryOnEvent read FOnEventEvent write FOnEventEvent;
end;
{TFunctionDiscoveryNotificationSync}
constructor TFunctionDiscoveryNotificationSync.Create;
begin
inherited;
FOnUpdateEvent:=nil;
//create the events objects
FEventAdd := TEvent.Create(nil, False, False, '', true);
FEventRemove := TEvent.Create(nil, False, False, '', true);
FEventChange := TEvent.Create(nil, False, False, '', true);
end;
destructor TFunctionDiscoveryNotificationSync.Destroy;
begin
//release the event objects
FEventAdd.Free;
FEventRemove.Free;
FEventChange.Free;
inherited;
end;
function TFunctionDiscoveryNotificationSync.OnError(hr: HRESULT;
fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR): HRESULT;
begin
//send the error notification if a callback method was defined
if @FOnErrorEvent<>nil then
FOnErrorEvent(hr, fdqcQueryContext, pszProvider);
Exit(S_OK);
end;
function TFunctionDiscoveryNotificationSync.OnEvent(dwEventID: DWORD;
fdqcQueryContext: FDQUERYCONTEXT; pszProvider: PWCHAR): HRESULT;
begin
//send the OnEvent notification if a callback method was defined
if @FOnEventEvent<>nil then
FOnEventEvent(dwEventID, fdqcQueryContext, pszProvider);
Exit(S_OK);
end;
function TFunctionDiscoveryNotificationSync.OnUpdate(
enumQueryUpdateAction: QueryUpdateAction; fdqcQueryContext: FDQUERYCONTEXT;
pIFunctionInstance: IFunctionInstance): HRESULT;
begin
//signal the event object
case enumQueryUpdateAction of
QUA_ADD : FEventAdd.SetEvent;
QUA_REMOVE : FEventRemove.SetEvent;
QUA_CHANGE : FEventChange.SetEvent;
end;
//send the OnEvent notification if a callback method was defined
if (@FOnUpdateEvent<>nil) and (FAction=enumQueryUpdateAction) then
FOnUpdateEvent(enumQueryUpdateAction, fdqcQueryContext, pIFunctionInstance);
Exit(S_OK);
end;
function TFunctionDiscoveryNotificationSync.WaitFor(dwTimeout : DWORD; pszCategory: PWCHAR; eAction : QueryUpdateAction) : HRESULT;
var
hr : HRESULT;
LEvent : TEvent;
LWaitResult : TWaitResult;
FFunctionDiscovery : IFunctionDiscovery;
ppIFunctionInstanceCollection: IFunctionInstanceCollection;
ppIFunctionInstanceCollectionQuery: IFunctionInstanceCollectionQuery;
begin
FAction:=eAction;
//reset the event objects
FEventAdd.ResetEvent;
FEventRemove.ResetEvent;
FEventChange.ResetEvent;
//create a instance to the IFunctionDiscovery
FFunctionDiscovery := CreateComObject(CLSID_FunctionDiscovery) as IFunctionDiscovery;
//create a new query passing the current class as callback
hr := FFunctionDiscovery.CreateInstanceCollectionQuery(FCTN_CATEGORY_PNP, nil, true, Self, nil, ppIFunctionInstanceCollectionQuery);
//instruct to the query to only receive notifications
if hr=S_OK then
hr := ppIFunctionInstanceCollectionQuery.AddQueryConstraint(PROVIDERPNP_QUERYCONSTRAINT_NOTIFICATIONSONLY,'TRUE');
//execute the query
if hr=S_OK then
hr := ppIFunctionInstanceCollectionQuery.Execute(ppIFunctionInstanceCollection);
if( hr=E_PENDING) then hr := S_OK;
case eAction of
QUA_ADD : LEvent:=FEventAdd;
QUA_REMOVE : LEvent:=FEventRemove;
QUA_CHANGE : LEvent:=FEventChange;
else
LEvent := nil;
end;
if (hr=S_OK) and (LEvent<>nil) then
LWaitResult:= LEvent.WaitFor(dwTimeout);
// One device may correspond to multiple function instances
// This sleep allows the OnUpdate call to output information
// about each Function Instance.
// THIS SLEEP IS MERELY FOR DISPLAY PURPOSES
Sleep(1000);
Exit(hr);
end;
1 2
转载需保留链接来源:软件玩家 » Delphi XE3探索:Winapi.Functiondiscovery (三)
微软Edge浏览器如何分享网页到手机上查看?
迅雷下载磁力链接提示“种子下载失败”解决办法!
Microsoft Edge浏览器隐藏网页标题栏文字
Edge浏览器怎样网页整页全部截图?