www.pudn.com > OPC_VC++.rar > IADVSINK.CPP
/* * IADVSINK.CPP * Data Object User Chapter 10 * * Implementation of an object with IAdviseSink. * * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved * * Kraig Brockschmidt, Microsoft * Internet : kraigb@microsoft.com * Compuserve: >INTERNET:kraigb@microsoft.com */ #include "stdafx.h" #include "resource.h" #include#include "OPCSample_cppDlg.h" #define PRINT_MESSAGE {CString cs, cs1;\ cs1.Format("%s",__LINE__);\ AfxFormatString2(cs, IDS_ERROR_MESSAGE, (LPCSTR)cs1, __FILE__);\ MessageBox(NULL, "", cs, MB_OK);} extern COPCSample_cppDlg* theDlg; /* * CAdviseSink::CAdviseSink * CAdviseSink::~CAdviseSink * * Parameters (Constructor): * pApp PAPP to the application * */ CAdviseSink::CAdviseSink() { m_cRef=0; return; } CAdviseSink::~CAdviseSink(void) { return; } /* * CAdviseSink::QueryInterface * CAdviseSink::AddRef * CAdviseSink::Release * * Purpose: * IUnknown members for CAdviseSink object. */ STDMETHODIMP CAdviseSink::QueryInterface(REFIID riid, void** ppv) { *ppv=NULL; if (IID_IUnknown==riid || IID_IAdviseSink==riid) *ppv=this; if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CAdviseSink::AddRef(void) { return ++m_cRef; } STDMETHODIMP_(ULONG) CAdviseSink::Release(void) { if (0!=--m_cRef) return m_cRef; delete this; return 0; } /* * CAdviseSink::OnDataChange * * Purpose: * Notifes the advise sink that data changed in a data object. * On this message you may request a new data rendering and update * your displays as necessary. Any data sent to this function is * owned by the caller, not by this advise sink. * * All Advise Sink methods are asynchronous and therefore we * should attempt no synchronous calls from within them to an EXE * object. If we do, we'll get RPC_E_CALLREJECTED. * * Parameters: * pFEIn LPFORMATETC describing format that changed * pSTM LPSTGMEDIUM providing the medium in which the * data is provided. * * Return Value: * None */ STDMETHODIMP_(void) CAdviseSink::OnDataChange(LPFORMATETC pFE , LPSTGMEDIUM pSTM) { int iMode=0; // Verify the format follows the OPC spec if( TYMED_HGLOBAL != pFE->tymed ) { return; } if( pSTM->hGlobal == 0 ) { return; } if( OPCSTMFORMATWRITECOMPLETE != pFE->cfFormat ) // ignore write status notification { #ifdef DATATIMEFORMAT if( OPCSTMFORMATDATATIME != pFE->cfFormat ) // ignore write status notification #else if( OPCSTMFORMATDATA != pFE->cfFormat ) // ignore write status notification #endif // DATATIMEFORMAT { return; } } else { iMode=OPCSTMFORMATWRITECOMPLETE; } // It must be a data advise const BYTE* buffer = (BYTE*)GlobalLock( pSTM->hGlobal ); if( !buffer ) { return; } const OPCGROUPHEADER* pHeader = (OPCGROUPHEADER*)buffer; // check pHeader->hClientGroup // pHeader->dwTransactionID // pHeader->hrStatus int offset = sizeof(OPCGROUPHEADER); // for each item in the data stream, get the value and if (iMode==(int)OPCSTMFORMATWRITECOMPLETE) { if (!pHeader->dwTransactionID) { //error } if (pHeader->dwItemCount>200) { //error } for( DWORD index=0; index dwItemCount; index++, offset += sizeof(OPCITEMHEADERWRITE) ) { const OPCITEMHEADERWRITE* pItemHeader = (OPCITEMHEADERWRITE*)&buffer[offset]; if ( pItemHeader->dwError != S_OK) { Item* pItem = (Item*)pItemHeader->hClient; if (pItem) { pItem->dwLastError = pItemHeader->dwError; pItem->boActual = TRUE; } else { // DEBUG BREAK pItem=pItem; } }// else // pItem->boActual = TRUE; } } else { #ifdef DATATIMEFORMAT for( DWORD index=0; index dwItemCount; index++, offset += sizeof(OPCITEMHEADER1) ) { const OPCITEMHEADER1* pItemHeader = (OPCITEMHEADER1*)&buffer[offset]; #else for( DWORD index=0; index dwItemCount; index++, offset += sizeof(OPCITEMHEADER2) ) { const OPCITEMHEADER2* pItemHeader = (OPCITEMHEADER2*)&buffer[offset]; #endif // DATATIMEFORMAT VARIANT* pValue = (VARIANT*)&buffer[pItemHeader->dwValueOffset]; // Strings and arrays are packed in the stream // requiring unpacking if( pValue->vt == VT_BSTR ) { pValue->bstrVal = (BSTR)((BYTE*)pValue + sizeof(VARIANT) + sizeof(DWORD)); } else if( (pValue->vt & VT_ARRAY) == VT_ARRAY ) { pValue->parray = (SAFEARRAY*)((BYTE*)pValue + sizeof(VARIANT)); pValue->parray->pvData = ((BYTE*)pValue->parray + sizeof(SAFEARRAY)); } Item* pItem = (Item*)pItemHeader->hClient; pItem->value = pValue; pItem->quality = pItemHeader->wQuality; pItem->boActual = TRUE; } } GlobalUnlock( pSTM->hGlobal ); return; } /* * CAdviseSink::OnViewChange * CAdviseSink::OnRename * CAdviseSink::OnSave * CAdviseSink::OnClose * * Unimplemented members */ STDMETHODIMP_(void) CAdviseSink::OnViewChange(DWORD dwAspect , LONG lindex) { return; } STDMETHODIMP_(void) CAdviseSink::OnRename(LPMONIKER pmk) { return; } STDMETHODIMP_(void) CAdviseSink::OnSave(void) { return; } STDMETHODIMP_(void) CAdviseSink::OnClose(void) { return; }