⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iadvsink.cpp

📁 一个opc服务器
💻 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 "OPC ClientDoc.h"
extern OPCClientDoc* pDoc;
/*
 * 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)
   {
   // Verify the format follows the OPC spec
   if( TYMED_HGLOBAL != pFE->tymed )
      return;
   if( pSTM->hGlobal == 0 )
      return;
#ifdef DATATIMEFORMAT
   if( OPCSTMFORMATDATATIME != pFE->cfFormat )
#else
   if( OPCSTMFORMATDATA != pFE->cfFormat )
#endif // DATATIMEFORMAT
   {
      OnWriteComplete(pFE, pSTM);
      return;
   }

   // 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 quality
#ifdef DATATIMEFORMAT
   for( DWORD index=0; index<pHeader->dwItemCount; index++, offset += sizeof(OPCITEMHEADER1) )
      {
      const OPCITEMHEADER1* pItemHeader = (OPCITEMHEADER1*)&buffer[offset];
      Item* pItem = (Item*)pItemHeader->hClient;
      pItem->timestamp = pItemHeader->ftTimeStampItem;
#else
   for( DWORD index=0; index<pHeader->dwItemCount; index++, offset += sizeof(OPCITEMHEADER2) )
      {
      const OPCITEMHEADER2* pItemHeader = (OPCITEMHEADER2*)&buffer[offset];
      Item* pItem = (Item*)pItemHeader->hClient;
#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));
        }
      pItem->value = pValue;
      pItem->quality = pItemHeader->wQuality;
      }

   GlobalUnlock( pSTM->hGlobal );
   if(PostMessage(pDoc->hView, WM_OPCDATA, 0, 0))	   
   return;
   }



STDMETHODIMP_(void) CAdviseSink::OnWriteComplete(LPFORMATETC pFE
    , LPSTGMEDIUM pSTM)
   {
   const BYTE* buffer = (BYTE*)GlobalLock( pSTM->hGlobal );
   if( !buffer )
      return;

   const OPCGROUPHEADERWRITE* pHeader = (OPCGROUPHEADERWRITE*)buffer;
   if( FAILED(pHeader->hrStatus) )
      PostMessage(pDoc->hView, WM_OPCWRITE, pHeader->hrStatus, 0);
   else
   {
      int offset = sizeof(OPCGROUPHEADERWRITE);
      // for each item in the data stream, access its data
      for( DWORD index=0; index<pHeader->dwItemCount; index++, offset += sizeof(OPCITEMHEADERWRITE) )
      {
         const OPCITEMHEADERWRITE* pItemHeader = (OPCITEMHEADERWRITE*)&buffer[offset];
         if( FAILED(pItemHeader->dwError) )
         {
            PostMessage(pDoc->hView, WM_OPCWRITE, pItemHeader->dwError, 0);
         }
      }
   }
   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;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -