📄 iadvicesink.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 + -