📄 opcsample_cppdlg.cpp
字号:
// OPCSample_cppDlg.cpp : implementation file
//
#include "stdafx.h"
#include "OPCSample_cppDlg.h"
#include "OPCSample_cpp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COPCSample_cppDlg dialog
COPCSample_cppDlg::COPCSample_cppDlg(COPCSample_cppApp *p, CWnd* pParent /*=NULL*/)
: CDialog(COPCSample_cppDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(COPCSample_cppDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
pcApp = p;
pcBrowse=NULL;
pdwServerHandles=NULL;
pcApp->pcServer->QueryInterface(IID_IOPCBrowseServerAddressSpace,(LPVOID*)&pcBrowse);
pcApp->pcGroup->QueryInterface(IID_IOPCItemMgt, (LPVOID*)&pcItemMgt);
}
void COPCSample_cppDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COPCSample_cppDlg)
DDX_Control(pDX, IDC_TREE, m_Tree);
DDX_Control(pDX, IDC_LIST, m_List);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COPCSample_cppDlg, CDialog)
//{{AFX_MSG_MAP(COPCSample_cppDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_NOTIFY(TVN_SELCHANGED, IDC_TREE, OnSelchangedTree)
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COPCSample_cppDlg message handlers
#define DLG_TIMER_ID WM_TIMER + 2
BOOL COPCSample_cppDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
m_List.InsertColumn(0, "ItemID", LVCFMT_LEFT, 150);
m_List.InsertColumn(1, "Quality", LVCFMT_LEFT, 80);
m_List.InsertColumn(2, "Type", LVCFMT_LEFT, 50);
m_List.InsertColumn(3, "Value", LVCFMT_LEFT, 150);
InitializeTree();
SetTimer(DLG_TIMER_ID, 250, NULL );
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void COPCSample_cppDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR COPCSample_cppDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void COPCSample_cppDlg::InitializeTree()
{
// Fill the tree with the server's hierarchy
m_Tree.SetRedraw(FALSE);
m_List.SetRedraw(FALSE);
HTREEITEM first=0;
UpdateData();
m_Tree.DeleteAllItems();
if( pcBrowse )
{
IEnumString* pEnumString = NULL;
CString csAdd;
HRESULT hr = pcBrowse->BrowseOPCItemIDs(OPC_BRANCH,
csAdd.AllocSysString(),
VT_EMPTY,
OPC_READABLE | OPC_WRITEABLE,
&pEnumString);
if( hr == S_OK )
{
LPWSTR pName = NULL;
ULONG count = 0;
while( (hr = pEnumString->Next(1, &pName, &count)) == S_OK )
{
// CString does translation from UNICODE to native type
// (depends on the way the application is built)
CString name( pName );
HTREEITEM item = m_Tree.InsertItem( name );
if( first == 0 )
first = item;
InsertChildren( pName, item );
CoTaskMemFree( pName );
}
pEnumString->Release();
}
}
m_Tree.SelectItem( first );
m_Tree.SetRedraw(TRUE);
m_List.SetRedraw(TRUE);
}
void COPCSample_cppDlg::InsertChildren( LPWSTR child, HTREEITEM hParent )
{
HRESULT hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_DOWN, (LPCWSTR)child );
if( FAILED(hr) )
return;
IEnumString* pEnumString = NULL;
CString csAdd;
hr = pcBrowse->BrowseOPCItemIDs( OPC_BRANCH,
csAdd.AllocSysString(),
VT_EMPTY,
OPC_READABLE|OPC_WRITEABLE,
&pEnumString);
if( hr == S_OK )
{
LPWSTR pName = NULL;
ULONG count = 0;
while( (hr = pEnumString->Next(1, &pName, &count)) == S_OK )
{
CString name( pName ); // translation
HTREEITEM item = m_Tree.InsertItem( name, hParent );
InsertChildren( pName, item );
CoTaskMemFree( pName );
}
pEnumString->Release();
}
hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_UP, L"" );
}
void COPCSample_cppDlg::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)
{
//set the group to inactive to avoid callbacks
HRESULT hr;
BOOL boActive=FALSE;
DWORD dwRate;
hr = pcApp->pcGroup->SetState( NULL,&dwRate,&boActive,NULL,NULL,NULL,NULL);
if (!SUCCEEDED(hr))
{
AfxMessageBox("Call of SetState failed");
}
//remove all Tags from the group
HRESULT *pOPCErrors=NULL;
if (pdwServerHandles)
{
m_List.SetRedraw(FALSE);
DWORD count = m_List.GetItemCount();
pcItemMgt->RemoveItems( count,//number
pdwServerHandles,//server handles
&pOPCErrors//errors
);
if (pOPCErrors)
CoTaskMemFree( pOPCErrors );
pOPCErrors=NULL;
delete [] pdwServerHandles;
pdwServerHandles=NULL;
m_List.DeleteAllItems();
}
//get all tags of this branch
HTREEITEM item = m_Tree.GetSelectedItem( );
hr = BrowseHere( item ); // move browse position here
if( SUCCEEDED(hr) )
{
// get the tags
IEnumString* pEnumString = NULL;
CString csAdd;
hr = pcBrowse->BrowseOPCItemIDs(OPC_LEAF,
csAdd.AllocSysString(),
VT_EMPTY,
OPC_READABLE|OPC_WRITEABLE,
&pEnumString);
if( hr == S_OK )
{
LPWSTR *pName = new LPWSTR[500];
LPWSTR pItemID = NULL;
DWORD count = 0;
hr = pEnumString->Next(500, pName, &count);
if (count)
{
Item* pcItem;
OPCITEMDEF *pidef = new OPCITEMDEF[count] ;
CString csItemID;
for ( int i = 0; i<(int)count; i++ )
{
// CString does translation from UNICODE to native type
// (depends on the way the application is built)
pcItem = new Item;
pcItem->quality = QUAL_BAD;
pcBrowse->GetItemID(pName[i],&pItemID);
pcItem->name = pItemID;
pidef[i].szItemID = pcItem->name.AllocSysString();
pidef[i].dwBlobSize = 0;
pidef[i].pBlob = NULL;
pidef[i].bActive = TRUE;
pidef[i].hClient = (OPCHANDLE)pcItem; // pointer to item is its "handle"
pidef[i].szAccessPath = pcItem->cAccessPath.AllocSysString();
pidef[i].vtRequestedDataType = VT_EMPTY;
CoTaskMemFree( pItemID );
CoTaskMemFree( pName[i] );
}
OPCITEMRESULT * pOPCResults=NULL;
hr = pcItemMgt->AddItems(count, pidef, &pOPCResults, &pOPCErrors);
if( SUCCEEDED( hr ) )
{
CString csOut;
csOut.Empty();
int item=0;
pdwServerHandles = new DWORD[count];
for (i=0; i<(int)count;i++)
{
if (pOPCErrors[i]==S_OK)
{
pdwServerHandles[i] = pOPCResults[i].hServer; // save the server handle
//insert the tag in the list
CString cs;
cs = pidef[i].szItemID;
m_List.InsertItem(item, (LPCSTR)cs);
cs = "no update";
m_List.SetItem(item, 1, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 );
cs.Format("%u",pOPCResults[i].vtCanonicalDataType);
m_List.SetItem(item, 2, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 );
cs = "no update";
m_List.SetItem(item, 3, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 );
m_List.SetItemData(item, (DWORD)pidef[i].hClient);
item++;
} else
{
CString cs;
cs.Format("Result <%lu> from AddItems for Item <%s>\n",
pOPCErrors[i],
(LPCTSTR)pidef[i].szItemID);
csOut += cs;
}
SysFreeString( pidef[i].szItemID );
SysFreeString( pidef[i].szAccessPath );
}
}
if (pOPCErrors)
CoTaskMemFree( pOPCErrors );
pOPCErrors=NULL;
if (pOPCResults)
CoTaskMemFree( pOPCResults );
pOPCResults=NULL;
delete [] pidef;
}
pEnumString->Release();
if (pResult)
*pResult = 1;
delete [] pName;
}
}
hr = S_OK;
while(hr==S_OK)
hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_UP, L"" );
if( pResult )
*pResult = 0;
m_List.SetRedraw(TRUE);
//set the group to active to get changed data
boActive=TRUE;
hr = pcApp->pcGroup->SetState( NULL,&dwRate,&boActive,NULL,NULL,NULL,NULL);
if (!SUCCEEDED(hr))
{
AfxMessageBox("Call of SetState failed");
}
}
//**************************************************************************
// Recursive function that moves the browse position to this tree item
HRESULT COPCSample_cppDlg::BrowseHere( HTREEITEM item )
{
HRESULT hr = S_OK;
if( item != NULL )
{
HTREEITEM parent = m_Tree.GetParentItem( item );
hr = BrowseHere( parent );
if( SUCCEEDED( hr ) )
{
CString name( m_Tree.GetItemText( item ) );
hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_DOWN, name.AllocSysString() );
}
}
return hr;
}
void COPCSample_cppDlg::OnTimer(UINT nIDEvent)
{
DWORD count = m_List.GetItemCount();
VARIANT Value;
CString cs, cs1, cs2;
Value.vt = VT_EMPTY;
if (count)
{
int foundItem = m_List.GetNextItem( -1, LVNI_ALL );
while( foundItem != -1 )
{
Item* pcItem = (Item*)m_List.GetItemData( foundItem );
if (pcItem->boActual)
{
if (pcItem->quality==QUAL_BAD)
{
cs1 = "Bad";
} else if (pcItem->quality==QUAL_UNCERTAIN)
{
cs1 = "Uncertain";
} else if (pcItem->quality==QUAL_GOOD)
{
cs1 = "Good";
}
cs2.Format(" (%u)",pcItem->quality);
cs = cs1 + cs2;
m_List.SetItem(foundItem, 1, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 );
HRESULT hr = VariantChangeType(&Value, &pcItem->value, 0, VT_BSTR);
if (hr==S_OK)
{
cs = Value.bstrVal;
} else
{
cs.Format("Variant error 0x(%x)", hr);
}
m_List.SetItem(foundItem, 3, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 );
pcItem->boActual=FALSE;
}
foundItem = m_List.GetNextItem( foundItem, LVNI_ALL );
}
}
CDialog::OnTimer(nIDEvent);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -