📄 opcadvisesink.~pas
字号:
unit OPCAdviseSink;
//***************异步读写类**************//
//
//
//
//***************************************//
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,ComObj,OPCtypes,OPCDA, OPCutils,ActiveX;
type
// class to receive IDataObject data change advises
TOPCAdviseSink = class(TInterfacedObject, IAdviseSink)
public
procedure OnDataChange(const formatetc: TFormatEtc;
const stgmed: TStgMedium); stdcall;
procedure OnViewChange(dwAspect: Longint; lindex: Longint); stdcall;
procedure OnRename(const mk: IMoniker); stdcall;
procedure OnSave; stdcall;
procedure OnClose; stdcall;
end;
implementation
// TOPCAdviseSink methods
// OPC standard says this is the only method we need to fill in
procedure TOPCAdviseSink.OnDataChange(const formatetc: TFormatEtc;
const stgmed: TStgMedium);
var
PG: POPCGROUPHEADER;
PI1: POPCITEMHEADER1ARRAY;
PI2: POPCITEMHEADER2ARRAY;
PV: POleVariant;
I: Integer;
PStr: PWideChar;
NewValue: string;
WithTime: Boolean;
ClientHandle: OPCHANDLE;
Quality: Word;
begin
// the rest of this method assumes that the item header array uses
// OPCITEMHEADER1 or OPCITEMHEADER2 records,
// so check this first to be defensive
if (formatetc.cfFormat <> OPCSTMFORMATDATA) and
(formatetc.cfFormat <> OPCSTMFORMATDATATIME) then Exit;
// does the data stream provide timestamps with each value?
WithTime := formatetc.cfFormat = OPCSTMFORMATDATATIME;
PG := GlobalLock(stgmed.hGlobal);
if PG <> nil then
begin
// we will only use one of these two values, according to whether
// WithTime is set:
PI1 := Pointer(PChar(PG) + SizeOf(OPCGROUPHEADER));
PI2 := Pointer(PI1);
if Succeeded(PG.hrStatus) then
begin
for I := 0 to PG.dwItemCount - 1 do
begin
if WithTime then
begin
PV := POleVariant(PChar(PG) + PI1[I].dwValueOffset);
ClientHandle := PI1[I].hClient;
Quality := (PI1[I].wQuality and OPC_QUALITY_MASK);
end
else begin
PV := POleVariant(PChar(PG) + PI2[I].dwValueOffset);
ClientHandle := PI2[I].hClient;
Quality := (PI2[I].wQuality and OPC_QUALITY_MASK);
end;
if Quality = OPC_QUALITY_GOOD then
begin
// this test assumes we're not dealing with array data
if TVarData(PV^).VType <> VT_BSTR then
begin
NewValue := VarToStr(PV^);
end
else begin
// for BSTR data, the BSTR image follows immediately in the data
// stream after the variant union; the BSTR begins with a DWORD
// character count, which we skip over as the BSTR is also
// NULL-terminated
PStr := PWideChar(PChar(PV) + SizeOf(OleVariant) + 4);
NewValue := WideString(PStr);
end;
if WithTime then
begin
Writeln('New value for item ', ClientHandle, ' advised: ',
NewValue, ' (with timestamp)');
end
else begin
Writeln('New value for item ', ClientHandle, ' advised: ',
NewValue);
end;
end
else begin
Writeln('Advise received for item ', ClientHandle,
' , but quality not good');
end;
end;
end;
GlobalUnlock(stgmed.hGlobal);
end;
end;
procedure TOPCAdviseSink.OnViewChange(dwAspect: Longint; lindex: Longint);
begin
end;
procedure TOPCAdviseSink.OnRename(const mk: IMoniker);
begin
end;
procedure TOPCAdviseSink.OnSave;
begin
end;
procedure TOPCAdviseSink.OnClose;
begin
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -