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

📄 iadvsink.cpp

📁 用visual c++编写的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 "resource.h"
#include <afxadv.h>

#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<pHeader->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<pHeader->dwItemCount; index++, offset += sizeof(OPCITEMHEADER1) )
    {
      const OPCITEMHEADER1* pItemHeader = (OPCITEMHEADER1*)&buffer[offset];
#else
      for( DWORD index=0; index<pHeader->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;
    }

⌨️ 快捷键说明

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