📄 valuemsgview.cpp
字号:
// ValueMsgView.cpp : implementation file
//
#include "stdafx.h"
#include "OpcClientSpy.h"
#include "ValueMsgView.h"
#include "AddItemDlg.h"
#include "ServerInfoView.h"
#include "MainFrm.h"
#include "ItemParamsDlg.h"
#include "WriteItemDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CValueMsgView *theMsgValue=NULL;
/////////////////////////////////////////////////////////////////////////////
// CValueMsgView
IMPLEMENT_DYNCREATE(CValueMsgView, CFormView)
CValueMsgView::CValueMsgView()
: CFormView(CValueMsgView::IDD)
{
//{{AFX_DATA_INIT(CValueMsgView)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
pCurrentItem = NULL;
transactionID = 0;
theMsgValue = this;
}
CValueMsgView::~CValueMsgView()
{
while( !m_items.IsEmpty() )
delete m_items.RemoveTail();
}
void CValueMsgView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CValueMsgView)
DDX_Control(pDX, IDC_LIST_INFO, m_value);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CValueMsgView, CFormView)
//{{AFX_MSG_MAP(CValueMsgView)
ON_MESSAGE(WM_OPCDATA, OnOPCDataChange)
ON_MESSAGE(WM_OPCWRITE, OnOPCWriteError)
ON_MESSAGE(WM_OPCSHUTDOWN, OnOPCShutdown)
//ON_MESSAGE(WM_OPCWRITE, OnOPCWriteError)
//ON_MESSAGE(WM_OPCSHUTDOWN, OnOPCShutdown)
ON_WM_SIZE()
ON_WM_CONTEXTMENU()
ON_COMMAND(IDT_ADD_ITEM, OnAddItem)
ON_UPDATE_COMMAND_UI(IDT_ADD_ITEM, OnUpdateAddItem)
ON_COMMAND(IDT_ITEM_PROPERTY, OnItemProperty)
ON_UPDATE_COMMAND_UI(IDT_ITEM_PROPERTY, OnUpdateItemProperty)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_INFO, OnItemchangedListInfo)
ON_COMMAND(IDT_WRITE_TOITEM, OnWriteToitem)
ON_UPDATE_COMMAND_UI(IDT_WRITE_TOITEM, OnUpdateWriteToitem)
ON_COMMAND(IDT_DELETE_ITEM, OnDeleteItem)
ON_UPDATE_COMMAND_UI(IDT_DELETE_ITEM, OnUpdateDeleteItem)
ON_COMMAND(IDT_REFRESH, OnRefresh)
ON_UPDATE_COMMAND_UI(IDT_REFRESH, OnUpdateRefresh)
ON_COMMAND(IDT_READ_VALUE, OnReadValue)
ON_UPDATE_COMMAND_UI(IDT_READ_VALUE, OnUpdateReadValue)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CValueMsgView diagnostics
#ifdef _DEBUG
void CValueMsgView::AssertValid() const
{
CFormView::AssertValid();
}
void CValueMsgView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CValueMsgView message handlers
//初始化列表的标题等。
void CValueMsgView::InitalListCtrl(void)
{
CRect rect;
m_value.DeleteAllItems();
m_value.InsertColumn(0, "条目", LVCFMT_LEFT,150,0);
m_value.InsertColumn(1, "值", LVCFMT_LEFT,100,1);
m_value.InsertColumn(2, "数据质量", LVCFMT_LEFT,100,2);
m_value.InsertColumn(3, "时间", LVCFMT_LEFT,100,3);
m_value.InsertColumn(4, "OPC服务", LVCFMT_LEFT,100,4);
m_value.InsertColumn(5, "描述信息", LVCFMT_LEFT,200,5);
}
void CValueMsgView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
//并初始化列标题
InitalListCtrl();
}
void CValueMsgView::OnSize(UINT nType, int cx, int cy)
{
CFormView::OnSize(nType, cx, cy);
CFormView::ShowScrollBar(SB_VERT,FALSE);
CFormView::ShowScrollBar(SB_HORZ,FALSE);
if (GetSafeHwnd())
{
if (m_value.GetSafeHwnd())
{
CRect rect(0,0,cx,cy);
m_value.MoveWindow(&rect);
}
}
}
//弹出菜单
void CValueMsgView::OnContextMenu(CWnd* pWnd, CPoint point)
{
CMenu popMenu;
if( popMenu.LoadMenu(IDR_MENU_LIST) )
{
popMenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
point.x,point.y,
AfxGetMainWnd());
}
}
//删除所有项
void CValueMsgView::DeleteAllItem(void)
{
while( !m_items.IsEmpty() )
delete m_items.RemoveTail();
pCurrentItem = NULL;
//重新画list
OnUpdate(NULL,0,NULL);
}
//ITEM参数对话框
void CValueMsgView::OnItemProperty()
{
// get an interface pointer
OPCItemMgt itemMgt;
HRESULT hr = itemMgt.Attach( m_pServerView->opcGroup );
if( FAILED(hr) )
return;
// test the item attributes enumerator
EnumOPCItemAttributes enumerator;
hr = itemMgt.CreateEnumerator( IID_IEnumOPCItemAttributes, enumerator );
while( hr==S_OK && enumerator.IsOk() )
{
OPCITEMATTRIBUTES* pAttributes = NULL;
ULONG count=0;
hr = enumerator.Next( 1, &pAttributes, &count );
if( hr == S_OK )
{
if( pAttributes->hClient == (OPCHANDLE)pCurrentItem )
{
// found the matching attributes for this item
ItemParamsDlg dlg;
dlg.pItemAttr = pAttributes;
if( dlg.DoModal() == IDOK )
{
HRESULT *pErrors;
hr = itemMgt.SetActiveState( 1, &pCurrentItem->hServerHandle, dlg.m_active, &pErrors);
if( SUCCEEDED(hr) )
CoTaskMemFree( pErrors );
}
}
VariantClear( &pAttributes->vEUInfo );
CoTaskMemFree( pAttributes->szAccessPath );
CoTaskMemFree( pAttributes->szItemID );
if( pAttributes->pBlob )
CoTaskMemFree( pAttributes->pBlob );
CoTaskMemFree( pAttributes );
}
else if( FAILED(hr) )
MessageBox( _T("EnumOPCItemAttributes: "));
}
}
void CValueMsgView::OnUpdateItemProperty(CCmdUI* pCmdUI)
{
pCmdUI->Enable( m_pServerView->opcServer.IsOk() && pCurrentItem );
}
void CValueMsgView::OnItemchangedListInfo(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
pCurrentItem = (Item*)pNMListView->lParam;
*pResult = 0;
}
//写值到ITEM
void CValueMsgView::OnWriteToitem()
{
WriteItemDlg dlg;
dlg.m_item = pCurrentItem->name;
if( dlg.DoModal() != IDOK ) return;
CWaitCursor wait;
HRESULT *pErrors = NULL;
if( dlg.m_async )
{
if( m_pServerView->usingCP )
{
OPCAsyncIO2 opcAsyncIO2;
if( opcAsyncIO2.Attach( m_pServerView->opcGroup ) == S_OK )
{
transactionID = 2; // any number the client wants
COleVariant vt( dlg.m_value ); // initialize as a string
vt.ChangeType( pCurrentItem->value.vt ); // let COleVariant convert!
HRESULT hr = opcAsyncIO2.Write(1, &pCurrentItem->hServerHandle,
vt, transactionID, &transactionID, &pErrors);
if( SUCCEEDED(hr) )
{
if( FAILED(pErrors[0]) )
MessageBox(_T("usingCP:pErrors[0]:ASync Write: "));
CoTaskMemFree( pErrors );
}
else
MessageBox(_T("usingCP:FAILED(hrt):ASync Write: "));
}
}
else//usingCP=FALSE
{
OPCAsyncIO opcAsyncIO;
if( opcAsyncIO.Attach( m_pServerView->opcGroup ) == S_OK )
{
COleVariant vt( dlg.m_value ); // initialize as a string
vt.ChangeType( pCurrentItem->value.vt ); // let COleVariant convert!
HRESULT hr = opcAsyncIO.Write(m_pServerView->dwConnection2, 1, &pCurrentItem->hServerHandle,
vt, &transactionID, &pErrors);
if( SUCCEEDED(hr) )
{
if( FAILED(pErrors[0]) )
MessageBox(_T("pErrors[0]:ASync Write: "));
CoTaskMemFree( pErrors );
}
else
MessageBox(_T("FAILED(hr):ASync Write: "));
}
}//end of "else
}
else//dlg.m_async=FALSE
{
OPCSyncIO opcSyncIO;
if( opcSyncIO.Attach( m_pServerView->opcGroup ) == S_OK )
{
COleVariant vt( dlg.m_value ); // initialize as a string
vt.ChangeType( pCurrentItem->value.vt ); // let COleVariant convert!
HRESULT hr = opcSyncIO.Write( 1, &pCurrentItem->hServerHandle, vt, &pErrors);
if( SUCCEEDED(hr) )
{
if( FAILED(pErrors[0]) )
MessageBox(_T("Sync Write: "));
CoTaskMemFree( pErrors );
}
else
MessageBox( _T("FAILED(hrt):Sync Write: "));
}
}//end of "else...
//强制显示新的数据
OnUpdate(NULL,0,NULL);
}
//是否允许写值到ITEM
void CValueMsgView::OnUpdateWriteToitem(CCmdUI* pCmdUI)
{
pCmdUI->Enable( m_pServerView->opcServer.IsOk() && pCurrentItem );
}
//删除项目
void CValueMsgView::OnDeleteItem()
{
OPCItemMgt itemMgt;
HRESULT hr = itemMgt.Attach( m_pServerView->opcGroup );
if( SUCCEEDED(hr) )
{
HRESULT *pErrors=0;
OPCHANDLE handle = pCurrentItem->hServerHandle;
hr = itemMgt.RemoveItems( 1, &handle, &pErrors );
if( SUCCEEDED(hr) )
CoTaskMemFree( pErrors );
POSITION pos = m_items.Find( pCurrentItem );
m_items.RemoveAt( pos );
delete pCurrentItem;
pCurrentItem = NULL;
OnUpdate(NULL,0,NULL);
}
}
//是否允许删除项目
void CValueMsgView::OnUpdateDeleteItem(CCmdUI* pCmdUI)
{
pCmdUI->Enable( m_pServerView->opcServer.IsOk() && pCurrentItem );
}
// Refresh causes all items to be advised immediately.
void CValueMsgView::OnRefresh()
{
CWaitCursor wait;
if( m_pServerView->usingCP )
{
OPCAsyncIO2 opcAsyncIO2;
if( opcAsyncIO2.Attach( m_pServerView->opcGroup ) == S_OK )
{
// test both Device and Cache data sources
// This should cause the server to queue a refresh while one is going on.
transactionID = 2; // any number the client wants
HRESULT hr = opcAsyncIO2.Refresh2(OPC_DS_DEVICE, transactionID, &transactionID);
if( FAILED(hr) )
{
MessageBox( _T("Refresh2:error"));
return;
}
}
}//end of "if(usingCP)...
else
{
OPCAsyncIO opcAsyncIO;
if( opcAsyncIO.Attach( m_pServerView->opcGroup ) == S_OK )
{
// test both Device and Cache data sources
// This should cause the server to queue a refresh while one is going on.
HRESULT hr = opcAsyncIO.Refresh(m_pServerView->dwConnection1, OPC_DS_DEVICE, &transactionID);
if( FAILED(hr) )
{
MessageBox( _T("!usingCP:Refresh: "));
return;
}
}
}//end of "else...
OnUpdate(NULL,0,NULL);
}
//是否允许刷新
void CValueMsgView::OnUpdateRefresh(CCmdUI* pCmdUI)
{
pCmdUI->Enable( m_pServerView->opcServer.IsOk() );
}
//Read value from OPC Server
void CValueMsgView::OnReadValue()
{
HRESULT *pErrors;
CWaitCursor wait;
// also test sync read since data is returned differently
OPCSyncIO opcSyncIO;
if( opcSyncIO.Attach( m_pServerView->opcGroup ) == S_OK )
{
OPCITEMSTATE* pItemState;
HRESULT hr = opcSyncIO.Read(OPC_DS_DEVICE, 1, &pCurrentItem->hServerHandle, &pItemState, &pErrors);
if( SUCCEEDED(hr) )
{
if( FAILED(pErrors[0]) )
MessageBox("Sync Read is error!");
else
{
pCurrentItem->quality = pItemState->wQuality;
pCurrentItem->value = pItemState->vDataValue;
}
VariantClear( &pItemState->vDataValue );
CoTaskMemFree( pItemState );
CoTaskMemFree( pErrors );
}
else//FAILED(hr)
MessageBox("Failed(hr),Sync Read.");
}
// Use AsyncIO2 here
if( m_pServerView->usingCP )
{
OPCAsyncIO2 opcAsyncIO2;
if( opcAsyncIO2.Attach( m_pServerView->opcGroup ) == S_OK )
{
transactionID = 3;
HRESULT hr = opcAsyncIO2.Read(1, &pCurrentItem->hServerHandle, transactionID, &transactionID, &pErrors);
if( SUCCEEDED(hr) )
{
if( FAILED(pErrors[0]) )
MessageBox(_T("Async Read: "));
CoTaskMemFree( pErrors );
}
else
MessageBox( _T("Async Read: "));
}
}//end of "if (usingCP)...
else
{
OPCAsyncIO opcAsyncIO;
if( opcAsyncIO.Attach( m_pServerView->opcGroup ) == S_OK )
{
HRESULT hr = opcAsyncIO.Read(m_pServerView->dwConnection1, OPC_DS_CACHE, 1, &pCurrentItem->hServerHandle, &transactionID, &pErrors);
if( SUCCEEDED(hr) )
{
if( FAILED(pErrors[0]) )
MessageBox( _T("Async Read: "));
CoTaskMemFree( pErrors );
}
else
MessageBox(_T("Async Read: "));
}
}//end of "else...
//重新显示新的数据
OnUpdate(NULL,0,NULL);
}
//是否允许读值
void CValueMsgView::OnUpdateReadValue(CCmdUI* pCmdUI)
{
pCmdUI->Enable( m_pServerView->opcServer.IsOk() && pCurrentItem );
}
//**************************************************************************
// An asynchronous data change callback triggers this message to
// update the values in the display
//
LONG CValueMsgView::OnOPCDataChange(UINT wParam,LONG lParam)
{
OnUpdate(NULL, 32, NULL);
return 0L;
}
//**************************************************************************
// An asynchronous write complete callback triggers this message
// if there is a message to display
//
LONG CValueMsgView::OnOPCWriteError(UINT wParam,LONG lParam)
{
MessageBox( _T("OPC Write错误信息:ASync Write error. "));
return 0L;
}
//**************************************************************************
// An asynchronous shutdown callback triggers this message
//
LONG CValueMsgView::OnOPCShutdown(UINT wParam,LONG lParam)
{
m_pServerView->DisconnectOPCServer(TRUE);
CString msg;
msg.Format(_T("Server shutting down."));
CString appName((LPCSTR)AFX_IDS_APP_TITLE);
MessageBox(msg, appName, MB_OK);
return 0L;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -