📄 opc_data.cpp
字号:
// opc_data.cpp - IDataObject test code
//
//
// (c) Copyright 1998 The OPC Foundation
// ALL RIGHTS RESERVED.
//
// DISCLAIMER:
// This sample code is provided by the OPC Foundation solely to assist
// in understanding the OPC Specifications and may be used
// as set forth in the License Grant section of the OPC Specification.
// This code is provided as-is and without warranty or support of any sort
// and is subject to the Warranty and Liability Disclaimers which appear
// in the printed OPC Specification.
//
// CREDITS:
// This code was generously provided to the OPC Foundation by
// Al Chisholm, Intellution Inc.
//
// CONTENTS:
//
//
// Modification Log:
// Vers Date By Notes
// ---- -------- --- -----
// 0.90 04/03/97 acc
// 05/20/97 ACC HandleWrite should use GROUPHEADERWRITE, not GROUPHEADER
// 01/14/98 acc update per final spec
//
//
#include <stdio.h>
#include <conio.h>
#include "opcda.h"
#include "OLECTL.h"
#include "OPC_PACK.h"
void HandleData(STGMEDIUM *pSTM);
void HandleDataTime(STGMEDIUM *pSTM);
void HandleWrite(STGMEDIUM *pSTM);
// Define an actual implementation of the IAdviseSink interface
//
class IXXXAS : public IAdviseSink
{
public:
IXXXAS( void );
~IXXXAS( void );
// the IUnknown Functions
STDMETHODIMP QueryInterface( REFIID iid, LPVOID* ppInterface);
STDMETHODIMP_(ULONG) AddRef( void);
STDMETHODIMP_(ULONG) Release( void);
// Member Functions
STDMETHODIMP_(void) OnDataChange(
FORMATETC *pFmt,
STGMEDIUM *pStg
);
STDMETHODIMP_(void) OnViewChange(
DWORD dwA,
LONG lindex
);
STDMETHODIMP_(void) OnRename(IMoniker* m);
STDMETHODIMP_(void) OnSave(void);
STDMETHODIMP_(void) OnClose(void);
private:
DWORD mRefCount;
UINT m_data;
UINT m_datatime;
UINT m_write;
};
///////////////////////////////////////
// The first section of this file contains the
// Client specific impementation of
// his IOPCCallback Methods
//
///////////////////////////////////////
//
///////////////////////////////////////
IXXXAS:: IXXXAS()
{
mRefCount = 0;
m_data = RegisterClipboardFormat("OPCSTMFORMATDATA");
m_datatime = RegisterClipboardFormat("OPCSTMFORMATDATATIME");
m_write = RegisterClipboardFormat("OPCSTMFORMATWRITECOMPLETE");
}
///////////////////////////////////////
//
///////////////////////////////////////
IXXXAS:: ~IXXXAS()
{
}
///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP_(ULONG) IXXXAS:: AddRef( void)
{
return ++mRefCount;
}
///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP_(ULONG) IXXXAS:: Release( void)
{
ULONG currentCount = --mRefCount;
// If no references left for this object
if ( currentCount == 0)
{
// Then delete this group.
delete this;
}
return currentCount;
}
///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP IXXXAS:: QueryInterface( REFIID iid, LPVOID* ppInterface)
{
if ( ppInterface == NULL)
return E_INVALIDARG;
if ( iid == IID_IUnknown )
*ppInterface = (IUnknown*) this;
else if ( iid == IID_IAdviseSink)
{
*ppInterface = (IUnknown*) this;
}
else
{
*ppInterface = NULL;
}
if ( *ppInterface == NULL)
return E_NOINTERFACE;
AddRef();
return S_OK;
}
///////////////////////////////////////
//
///////////////////////////////////////
void IXXXAS::OnDataChange(LPFORMATETC pFE
, LPSTGMEDIUM pSTM)
{
printf("IAdviseSink::OnDataChange...\n");
// Sanity checks...
// If wrong storage medium or null pointer
// we can't handle it
//
if( TYMED_HGLOBAL != pFE->tymed )
{
printf("ERROR:Bad tymed (not HGLOBAL)\n");
return;
}
if( pSTM->hGlobal == 0 )
{
printf("ERROR:Bad hGlobal\n");
return;
}
if(pFE->cfFormat == m_data)
{
printf("\tFormat:data...\n");
HandleData(pSTM);
} else if(pFE->cfFormat == m_datatime)
{
printf("\tFormat:data with time...\n");
HandleDataTime(pSTM);
} else if(pFE->cfFormat == m_write)
{
printf("\tFormat:WriteComplete...\n");
HandleWrite(pSTM);
} else
{
printf("\tERROR: Format unknown\n");
return;
}
}
///////////////////////////////////////
//
///////////////////////////////////////
void IXXXAS::OnViewChange(
DWORD dwA,
LONG lindex
)
{
printf("OnViewChange...\n");
}
///////////////////////////////////////
//
///////////////////////////////////////
void IXXXAS::OnSave(void)
{
printf("OnSave...\n");
}
///////////////////////////////////////
//
///////////////////////////////////////
void IXXXAS::OnRename(IMoniker*)
{
printf("OnRename...\n");
}
///////////////////////////////////////
//
///////////////////////////////////////
void IXXXAS::OnClose(void)
{
printf("OnClose...\n");
}
///////////////////////////////////////
// The rest of this file contains the
// test program
//
///////////////////////////////////////
void OnDataChange(
DWORD Transid,
OPCHANDLE grphandle,
DWORD count,
OPCHANDLE * clienthandles,
VARIANT * value,
BOOL masterquality,
WORD * quality,
FILETIME * time
);
void OnWriteComplete(
DWORD Transid,
OPCHANDLE grphandle,
DWORD count,
OPCHANDLE * clienthandles,
HRESULT * hrs,
BOOL masterhr
);
extern IMalloc *pIMalloc;
void TryDataObject(IOPCGroupStateMgt * pGRP, int nItem, OPCHANDLE *sh);
static void flip_mode(OPCDATASOURCE *mode);
static void DumpValue(int i, VARIANT *v, WORD q, OPCHANDLE h);
extern void DumpVariant(VARIANT *v);
//---------------------------------------------------------
// TryDataObject
// Function to exercise the DataObject logic for a group
//
//void TryDataObject(IOPCGroupStateMgt * pGRP)
void TryDataObject(IOPCGroupStateMgt * pGRP, int nItem, OPCHANDLE *sh)
{
IDataObject *pDO;
OPCDATASOURCE mode = OPC_DS_CACHE;
IOPCAsyncIO *pASIO = 0;
DWORD MyCookie = 0L;
DWORD MyCookiew = 0L;
IXXXAS *MyCallback;
HRESULT r1;
BOOL Active = 1;
BOOL InActive = 0;
DWORD RequestedRate = 2123;
DWORD Rate;
DWORD tid;
cputs("Hit Enter to Try OnDataChange...\n");
getch();
// Create a callback instance
//
MyCallback = new IXXXAS;
MyCallback -> AddRef();
// Establish a connection
//
r1 = pGRP->QueryInterface(IID_IDataObject, (void**)&pDO);
if (FAILED(r1))
{
printf("No DataObject:(%lx)\n", r1);
return;
}
r1 = pGRP->QueryInterface(IID_IOPCAsyncIO, (void**)&pASIO);
if (FAILED(r1))
{
printf("No AsyncIO interface:(%lx)\n", r1);
pDO->Release();
return;
}
// todo: add test for data without timestamp zzz
// (Note the callback handler is already here -
// I just never subscribe to it)
FORMATETC fe;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.cfFormat = RegisterClipboardFormat("OPCSTMFORMATDATATIME");
r1 = pDO->DAdvise(&fe, ADVF_PRIMEFIRST, MyCallback, &MyCookie);
if (FAILED(r1))
{
printf("Data/Time Advise Failed:(%lx)\n", r1);
pASIO->Release();
pDO->Release();
return;
}
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.cfFormat = RegisterClipboardFormat("OPCSTMFORMATWRITECOMPLETE");
r1 = pDO->DAdvise(&fe, ADVF_PRIMEFIRST, MyCallback, &MyCookiew);
if (FAILED(r1))
{
pDO->DUnadvise(MyCookie);
printf("WriteComplete Advise Failed:(%lx)\n", r1);
pASIO->Release();
pDO->Release();
return;
}
printf("Callback is Connected - monitoring for activity...\n");
printf("Mode = DEVICE\n");
printf("Press 'a' to set active, f to Refresh, c to cancel, i to set inactive\n");
printf("'m' to change mode, 'x' to disconnect\n");
// Run test until terminated by user.
// We must dispatch messages (in single apartment model)
// for callbacks to work!
//
pGRP->SetState(&RequestedRate, &Rate, &Active,0,0,0,0);
printf("Requested rate: %ld, Revised rate: %ld\n", RequestedRate, Rate);
while(1)
{
if(kbhit())
{
char c;
c = getch();
if (c == 'x')
break;
if (c == 'a')
pGRP->SetState(0, &Rate, &Active, 0,0,0,0);
if (c == 'i')
pGRP->SetState(0, &Rate, &InActive, 0,0,0,0);
if (c == 'f')
{
r1= pASIO->Refresh(MyCookie, mode, &tid);
if (FAILED(r1)) printf("Refresh Error:%lx\n", r1);
else printf("RefreshTID=%lx\n", tid);
}
if (c == 'c')
{
r1 = pASIO->Cancel(tid);
if(FAILED(r1)) printf("Cancel Error=%lx\n", r1);
}
if (c == 'm')
flip_mode(&mode);
}else
{
MSG msg;
while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
// Done - set group Inactive to stop ondatachange
//
pGRP->SetState(0, &Rate, &InActive, 0,0,0,0);
// Next, test Async Read/Write
//
cputs("Hit Enter to Try AsyncRead/Write...\n");
getch();
mode = OPC_DS_DEVICE;
printf("Mode = DEVICE\n");
printf("Press 'r' to read, 'w' to write\n");
printf("'f' to Refresh, 'c' to Cancel\n");
printf("'m' to change mode, 'x' to disconnect\n");
while(1)
{
HRESULT *hr;
if(kbhit())
{
char c;
c = getch();
if (c == 'x')
break;
if (c == 'r')
{
r1 = pASIO->Read(MyCookie, mode, nItem,
sh, &tid, &hr);
// check r1 and hr array and also free hr
if(r1 != S_OK)
{
printf("Async ReadFailed:(%lx)\n", r1);
}
if(hr) pIMalloc->Free(hr);
}
if (c == 'w')
{
VARIANT v[2];
v[0].vt = VT_R4;
v[0].fltVal = (float)12.34;
v[1].vt = VT_R4;
v[1].fltVal = (float)56.78;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -