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

📄 iadvicesink.cpp

📁 此为Insight opc client InfoServerExplorer源程序
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////
//
//  OPC DataAccess VC++ Client:	IAdviceSink.CPP
//								(Source File)
//
/////////////////////////////////////////////////////////////////////////////
//
//          Author: Raphael Imhof
//    Initial Date: 11/04/98
//       $Workfile: IAdviceSink.cpp $
//       $Revision: 1 $
//           $Date: 7/27/99 5:22p $
//   Target System: Microsoft Windows NT 4.0
//     Environment: Visual C++ 5.0 / OPC DataAccess 1.0
//         Remarks: 
//
/////////////////////////////////////////////////////////////////////////////
//
//     Description: implementation of the CIAdviseSink class.
//					IAdviceSink wrapper.
//					
//
/////////////////////////////////////////////////////////////////////////////
//
//  History of Changes     (Please remove very old comments and blank lines!)
//            $Log: /IDK/OPCServer/clients/VC++/InfoServerExplorer/IAdviceSink.cpp $
// 
// 1     7/27/99 5:22p Imhof
// 
// 1     7/27/99 5:18p Imhof
// 
// 8     2/12/99 2:38p Imhof
// Changed variable name, plus corrected comment
// 
// 7     1/15/99 6:43p Imhof
// Updated legal notice.
// 
// 6     1/06/99 10:34a Imhof
// Added a changed attribute to the CItem class which is used to optimize
// the content view update.
// 
// 5     12/14/98 4:46p Imhof
// Modifications for OPC 2.0
// 
// 4     12/11/98 5:58p Imhof
// Made modifications for OPC 2.0.
// 
// 3     11/10/98 2:20p Imhof
// Added file header's.
// 
// 
//  $Nokeywords:$ (To avoid useless search while checking in.)
/////////////////////////////////////////////////////////////////////////////
//  Copyright (C) 1998, Siemens Building Technologies, Inc. Landis Division
//
// SIEMENS BUILDING TECHNOLOGIES, INC. IS PROVIDING THE FOLLOWING
// EXAMPLES OF CODE AS SAMPLE ONLY.
//
// SIEMENS BUILDING TECHNOLOGIES, INC.  MAKES NO REPRESENTATIONS
// OR WARRANTIES OF ANY KIND  WITH RESPECT TO THE VALIDTY OF THE 
// CODES   OR   DESIRED   RESULTS   AND   DISCLAIMS   ALL   SUCH 
// REPRESENTATIONS   AND   WARRANTIES,  INCLUDING  FOR  EXAMPLE, 
// WARRANTIES  OF  MERCHANTABILITY  AND FITNESS FOR A PARTICULAR 
// PURPOSE.    SIEMENS  BUILIDNG  TECHNOLOGIES,  INC.  DOES  NOT 
// REPRESENT  OR  WARRANT  THAT  THE  FOLLOWING CODE SAMPLES ARE 
// ACCURATE, VALID, COMPLETE OR CURRENT.
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "infoserverexplorer.h"
#include "IAdviceSink.h"
#include "MainFrm.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CIAdviseSink::CIAdviseSink()
{
	m_FormatData = RegisterClipboardFormat(TEXT("OPCSTMFORMATDATA"));
	m_FormatDataTime = RegisterClipboardFormat(TEXT("OPCSTMFORMATDATATIME"));
	m_FormatWrite = RegisterClipboardFormat(TEXT("OPCSTMFORMATWRITECOMPLETE"));

	mRefCount = 0;
}

CIAdviseSink::~CIAdviseSink()
{

}

STDMETHODIMP_(ULONG) CIAdviseSink:: AddRef()
{
	return ++mRefCount;
}

STDMETHODIMP_(ULONG) CIAdviseSink:: Release()
{
	ULONG newCount = --mRefCount; 

	// no references => delete
	if ( newCount == 0)
	{
		// Then delete this group.  //OK ?
		delete this;
	}
	return newCount;
}

STDMETHODIMP CIAdviseSink:: 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;
}

STDMETHODIMP_(void) CIAdviseSink::OnDataChange(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
{
	TRACE("IAdviseSink::OnDataChange...\n");

	//correct format ?
	if(TYMED_HGLOBAL != pFE->tymed)
	{
		TRACE("ERROR:Bad tymed (not HGLOBAL)\n");
		return;
	}
	if(pSTM->hGlobal == NULL)
	{
		TRACE("ERROR:Bad hGlobal\n");
		return;
	}

	//which format ?
	if(pFE->cfFormat == m_FormatData)
	{
		HandleDataChange(pSTM);		
	} 
	else if(pFE->cfFormat == m_FormatDataTime)
	{
		HandleDataTimeChange(pSTM);
	} 
	else if(pFE->cfFormat == m_FormatWrite)
	{
		HandleWriteComplete(pSTM);
	} 
	else
	{
		((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("Unknown format received in CIAdviseSink::OnDataChange()"));
	}
}

BOOL CIAdviseSink::HandleWriteComplete(LPSTGMEDIUM pSTM)
{
	const BYTE* buffer = (BYTE*)GlobalLock(pSTM->hGlobal);
	if(!buffer) return FALSE;

	const OPCGROUPHEADERWRITE* pHeader = (OPCGROUPHEADERWRITE*)buffer;
	
	if(FAILED(pHeader->hrStatus))
		((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("Async Write:"), pHeader->hrStatus);
	else
	{
		int offset = sizeof(OPCGROUPHEADERWRITE);
		CGroup* pGroup = NULL;

		for(DWORD index=0; index < pHeader->dwItemCount; index++, offset += sizeof(OPCITEMHEADERWRITE))
		{
			const OPCITEMHEADERWRITE* pItemHeader = (OPCITEMHEADERWRITE*)&buffer[offset];
			CItem* pItem = (CItem*)pItemHeader->hClient;

			if(pGroup == NULL) pGroup = pItem->GetGroup();

			if(FAILED(pItemHeader->dwError))
			{
				CString sMsg;
				sMsg.Format(_T("Async Write Item[%d]:"),index);
				((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(sMsg, pItemHeader->dwError);
			}
		}

		if(pGroup != NULL)
		{
			pGroup->SetCurrentTransactionID(0);
			pGroup->SetCurrentCancelID(0);
		}
	}
	GlobalUnlock( pSTM->hGlobal );

	return TRUE;
}

BOOL CIAdviseSink::HandleDataChange(LPSTGMEDIUM pSTM)
{
	const BYTE* buffer = (BYTE*)GlobalLock( pSTM->hGlobal );
	if( !buffer ) return FALSE;

	const OPCGROUPHEADER* pHeader = (OPCGROUPHEADER*)buffer;

	// check pHeader->hClientGroup
	// pHeader->dwTransactionID
	// pHeader->hrStatus

	// If Transid != 0, this is a refresh or read, otherwise a datachange 
	// from an item in an active group
	BOOL bRefresh_Read = FALSE;
	if(pHeader->dwTransactionID != 0) bRefresh_Read = TRUE;

	int offset = sizeof(OPCGROUPHEADER);
	CGroup* pGroup = NULL;

	for( DWORD index=0; index < pHeader->dwItemCount; index++, offset += sizeof(OPCITEMHEADER2) )
    {
		const OPCITEMHEADER2* pItemHeader = (OPCITEMHEADER2*)&buffer[offset];
		CItem* pItem = (CItem*)pItemHeader->hClient;
		
		if(pGroup == NULL) pGroup = pItem->GetGroup();

		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->SetValue(*pValue);
		pItem->SetQuality(pItemHeader->wQuality);

		//item changed for content view update
		pItem->SetChanged(TRUE);
	}

	GlobalUnlock(pSTM->hGlobal);

	if(bRefresh_Read && (pGroup != NULL))
	{
		pGroup->SetCurrentTransactionID(0);
		pGroup->SetCurrentCancelID(0);
	}

	//notify the content view
	CInfoServerExplorerApp* pApp = (CInfoServerExplorerApp*) AfxGetApp();
	CMainFrame* pMainFrame = (CMainFrame*) AfxGetMainWnd();
	if(NULL != pMainFrame)
	{
		CContentView* pView = pMainFrame->GetContentView();
		if(NULL != pView)
			pView->PostMessage(WM_CONTENTVIEW_UPDATE, CONTENT_UPDATE_ONLY, 0);
	}

	return TRUE;
}

BOOL CIAdviseSink::HandleDataTimeChange(LPSTGMEDIUM pSTM)
{
	const BYTE* buffer = (BYTE*)GlobalLock(pSTM->hGlobal);
	if(!buffer) return FALSE;

	const OPCGROUPHEADER* pHeader = (OPCGROUPHEADER*)buffer;

	// check pHeader->hClientGroup
	// pHeader->dwTransactionID
	// pHeader->hrStatus

	// If Transid != 0, this is a refresh or read, otherwise a datachange 
	// from an item in an active group
	BOOL bRefresh_Read = FALSE;
	if(pHeader->dwTransactionID != 0) bRefresh_Read = TRUE;

	int offset = sizeof(OPCGROUPHEADER);
	CGroup* pGroup = NULL;

	for(DWORD index=0; index < pHeader->dwItemCount; index++, offset += sizeof(OPCITEMHEADER1))
    {
		const OPCITEMHEADER1* pItemHeader = (OPCITEMHEADER1*)&buffer[offset];
		CItem* pItem = (CItem*)pItemHeader->hClient;

		if(pGroup == NULL) pGroup = pItem->GetGroup();

		pItem->SetTimeStamp(pItemHeader->ftTimeStampItem);
		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->SetValue(*pValue);
		pItem->SetQuality(pItemHeader->wQuality);

		//item changed for content view update
		pItem->SetChanged(TRUE);
	}

	GlobalUnlock( pSTM->hGlobal );

	if(bRefresh_Read && (pGroup != NULL))
	{
		pGroup->SetCurrentTransactionID(0);
		pGroup->SetCurrentCancelID(0);
	}

	//notify the content view
	CInfoServerExplorerApp* pApp = (CInfoServerExplorerApp*) AfxGetApp();
	CMainFrame* pMainFrame = (CMainFrame*) AfxGetMainWnd();
	if(NULL != pMainFrame)
	{
		CContentView* pView = pMainFrame->GetContentView();
		if(NULL != pView)
			pView->PostMessage(WM_CONTENTVIEW_UPDATE, CONTENT_UPDATE_ONLY, 0);
	}

	return TRUE;
}

/*
 * CAdviseSink::OnViewChange
 * CAdviseSink::OnRename
 * CAdviseSink::OnSave
 * CAdviseSink::OnClose
 *
 * Unimplemented members
 */

STDMETHODIMP_(void) CIAdviseSink::OnViewChange(DWORD dwAspect, LONG lindex)
{
	return;
}

STDMETHODIMP_(void) CIAdviseSink::OnRename(LPMONIKER pmk)
{
	return;
}

STDMETHODIMP_(void) CIAdviseSink::OnSave(void)
{
	return;
}

STDMETHODIMP_(void) CIAdviseSink::OnClose(void)
{
	return;
}

⌨️ 快捷键说明

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