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

📄 serverenumgroupsdlg.cpp

📁 VisualC OPC Client Example C 程序开发
💻 CPP
字号:
// **************************************************************************
// serverenumgroupsdlg.cpp
//
// Description:
//	Implements a dialog class for group enumerations.
//
// DISCLAIMER:
//	This programming example is provided "AS IS".  As such Kepware, Inc.
//	makes no claims to the worthiness of the code and does not warranty
//	the code to be error free.  It is provided freely and can be used in
//	your own projects.  If you do find this code useful, place a little
//	marketing plug for Kepware in your code.  While we would love to help
//	every one who is trying to write a great OPC client application, the 
//	uniqueness of every project and the limited number of hours in a day 
//	simply prevents us from doing so.  If you really find yourself in a
//	bind, please contact Kepware's technical support.  We will not be able
//	to assist you with server related problems unless you are using KepServer
//	or KepServerEx.
// **************************************************************************


#include "stdafx.h"
#include "opctestclient.h"
#include "serverenumgroupsdlg.h"

// Enumerate by scope defines, correspond to the scope combo-box list index:
#define SCOPE_PRIVATE	0
#define SCOPE_PUBLIC	1
#define SCOPE_ALL		2

// Enumerate by interface defines, correspond to the interface combo-box list
// index:
#define ITF_OBJECT		0
#define ITF_NAME		1


/////////////////////////////////////////////////////////////////////////////
// CKServerEnumerateGroupsDlg dialog
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
BEGIN_MESSAGE_MAP (CKServerEnumerateGroupsDlg, CDialog)
	//{{AFX_MSG_MAP(CKServerEnumerateGroupsDlg)
	ON_CBN_SELCHANGE (IDC_GROUPENUM_INTERFACE, OnChange)
	ON_BN_CLICKED (IDC_APPLY, OnApply)
	ON_CBN_SELCHANGE (IDC_GROUPENUM_SCOPE, OnChange)
	ON_NOTIFY (LVN_ITEMCHANGED, IDC_LIST, OnSelectItem)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP ()


// **************************************************************************
// CKServerEnumerateGroupsDlg ()
//
// Description:
//	Constructor.
//
// Parameters:
//  IOPCServer	*pIServer	Pointer to IOPCServer interface.
//	CWnd		*pParent	Pointer to parent window.
//
// Returns:
//  none
// **************************************************************************
CKServerEnumerateGroupsDlg::CKServerEnumerateGroupsDlg (IOPCServer *pIServer, CWnd *pParent /*=NULL*/)
	: CDialog (CKServerEnumerateGroupsDlg::IDD, pParent)
	{
	// Initialize member variables:
	ASSERT (pIServer != NULL);
	m_pIServer = pIServer;
	m_pEnumList = NULL;

	//{{AFX_DATA_INIT(CKServerEnumerateGroupsDlg)
	m_bActive = FALSE;
	m_nInterface = ITF_NAME;
	m_nScope = SCOPE_ALL;
	m_dwLanguageID = 0;
	m_strName = _T("");
	m_dwUpdateRate = 0;
	m_fDeadband = 0.0f;
	m_lBias = 0;
	//}}AFX_DATA_INIT
	}

// **************************************************************************
// DoDataExchange ()
//
// Description:
//	This method is called by the framework to exchange and validate dialog data.
//
// Parameters:
//  CDataExchange	*pDX	A pointer to a CDataExchange object.
//
// Returns:
//  void
// **************************************************************************
void CKServerEnumerateGroupsDlg::DoDataExchange (CDataExchange *pDX)
	{
	// Perform default processing:
	CDialog::DoDataExchange (pDX);

	// Exchange date between controls and associated member variables:
	//{{AFX_DATA_MAP(CKServerEnumerateGroupsDlg)
	DDX_Check (pDX, IDC_ACTIVE, m_bActive);
	DDX_CBIndex (pDX, IDC_GROUPENUM_INTERFACE, m_nInterface);
	DDX_CBIndex (pDX, IDC_GROUPENUM_SCOPE, m_nScope);
	DDX_Text (pDX, IDC_LANGUAGEID, m_dwLanguageID);
	DDX_Text (pDX, IDC_NAME, m_strName);
	DDX_Text (pDX, IDC_UPDATERATE, m_dwUpdateRate);
	DDX_Text (pDX, IDC_PERCENTDEADBAND, m_fDeadband);
	DDX_Text (pDX, IDC_TIMEBIAS, m_lBias);
	//}}AFX_DATA_MAP
	}

/////////////////////////////////////////////////////////////////////////////
// CKServerEnumerateGroupsDlg message handlers
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// OnInitDialog ()
//
// Description:
//	Called immediately before the dialog box is displayed.  Use opportunity
//	to initialize controls.
//
// Parameters:
//  none
//
// Returns:
//	BOOL - TRUE.
// **************************************************************************
BOOL CKServerEnumerateGroupsDlg::OnInitDialog () 
	{
	// Perform deafult processing:
	CDialog::OnInitDialog ();
	
	// Get pointer to our list control:
	m_pEnumList = (CListCtrl *) GetDlgItem (IDC_LIST);
	ASSERT (m_pEnumList != NULL);

	// Insert a blank column for our list control:
	CRect rc;
	m_pEnumList->GetClientRect (&rc);
	m_pEnumList->InsertColumn (0, _T(""), LVCFMT_LEFT, rc.Width ());	

	// Apply enumeration with default settings:
	OnApply ();

	// return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE	
	return (TRUE);  
	}

// **************************************************************************
// OnChange ()
//
// Description:
//	Default event handler for control change notifications.	
// 
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CKServerEnumerateGroupsDlg::OnChange () 
	{
	// Enable the apply button:
	((CButton *) GetDlgItem (IDC_APPLY))->EnableWindow (TRUE);
	}

// **************************************************************************
// OnApply ()
//
// Description:
//	Apply button event handler.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CKServerEnumerateGroupsDlg::OnApply () 
	{
	// Force an update data:
	UpdateData (true);

	// Enumerate the groups:
	EnumerateGroups ();

	// Disable the apply button:
	((CButton *) GetDlgItem (IDC_APPLY))->EnableWindow (FALSE);
	}

// **************************************************************************
// OnSelectItem ()
//
// Description:
//	Handles notification that a new item from list control has been selected.
//
// Parameters:
//  NMHDR		*pNMHDR			Contains information about a notification message.
//	LRESULT		*pResult		A 32-bit value returned from a window procedure 
//								  or callback function.
//
// Returns:
//  void
// **************************************************************************
void CKServerEnumerateGroupsDlg::OnSelectItem (NMHDR *pNMHDR, LRESULT *pResult) 
	{
	NM_LISTVIEW* pnmlv= (NM_LISTVIEW*)pNMHDR;
	
	// Wait for selection change then call UpdateState() to update all
	// controls:
	if (pnmlv->uNewState)
		UpdateState (m_pEnumList->GetItemText (pnmlv->iItem, pnmlv->iSubItem));
		
	*pResult = 0;
	}	


/////////////////////////////////////////////////////////////////////////////
// CKServerEnumerateGroupsDlg helpers
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// EnumerateGroups ()
//
// Description:
//	Performs the actual group enumeration.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CKServerEnumerateGroupsDlg::EnumerateGroups ()
	{
	HRESULT hr = E_FAIL;
	OPCENUMSCOPE eScope;
	TCHAR szBuffer [DEFBUFFSIZE];
	
	// Delete any items that are currently displayed:
	m_pEnumList->DeleteAllItems ();

	// Also re-initialize selected group properties to empty:
	m_bActive = FALSE;
	m_dwLanguageID = 0;
	m_strName = _T("");
	m_dwUpdateRate = 0;
	m_fDeadband = 0.0f;
	m_lBias = 0;

	// Update controls:
	UpdateData (false);
	
	// Convert scope combo-box index to true scope:
	switch (m_nScope)
		{
		case SCOPE_PRIVATE:
			eScope = OPC_ENUM_PRIVATE;
			break;

		case SCOPE_PUBLIC:
			eScope = OPC_ENUM_PUBLIC;
			break;

		case SCOPE_ALL:
			eScope = OPC_ENUM_ALL;
			break;

		default:
			break;
		}

	// If enumerate by object:
	if (m_nInterface == ITF_OBJECT)
		{
		// Ask server to create group enumerator interface:
		IEnumUnknown *pEnum = NULL;
		hr = m_pIServer->CreateGroupEnumerator (
			eScope,	IID_IEnumUnknown, (IUnknown**)&pEnum);

		// Process results if succeed:
		if (SUCCEEDED (hr) && pEnum != NULL)
			{
			IUnknown *pIUnknown;
			ULONG uFetched;
			IOPCGroupStateMgt *pIGroupStateMgt = NULL;
			
			// Loop over enumerated groups (call enemerator's next member to
			// reference next group and return its IUnknown interface):
			while ((hr = pEnum->Next (1, &pIUnknown, &uFetched)) == S_OK)
				{
				// Get group state management interface of current group:
				hr = pIUnknown->QueryInterface (IID_IOPCGroupStateMgt, (void**)&pIGroupStateMgt);

				if (SUCCEEDED (hr))
					{
					// Declare some variable needed to get the group name
					// from the server:
					OPCHANDLE hClient;
					OPCHANDLE hServer;
					WCHAR *pszName;

					// Get group state (we are only interested in the group name):
					hr = pIGroupStateMgt->GetState (
						&m_dwUpdateRate,
						&m_bActive,
						&pszName, 
						&m_lBias,
						&m_fDeadband,
						&m_dwLanguageID,
						&hClient,
						&hServer);

					// If succeed, process results:
					if (SUCCEEDED (hr))
						{
						// COM will return group name in UNICODE format.  Will have
						// to convert to ANSI format if ANSI build.  Copy result
						// to buffer:
#ifdef _UNICODE
						lstrcpyn (szBuffer, pszName, sizeof (szBuffer) / sizeof (TCHAR));
#else
						_wcstombsz (szBuffer, pszName, sizeof (szBuffer) / sizeof (TCHAR));
#endif

						// COM requires us to free memory allocated by server
						// for name string:
						if (pszName)
							CoTaskMemFree (pszName);

						// Insert group name into the list control:
						m_pEnumList->InsertItem (m_pEnumList->GetItemCount (), szBuffer);
						}

					// Release group state management interface:
					pIGroupStateMgt->Release ();
					}

				// Release the enumerated unknown interface:
				pIUnknown->Release ();
				}

			// Now release our enumerator:
			pEnum->Release ();
			}
		}

	// Else enumerate by name (generally faster):
	else
		{
		// Ask server to create group enumerator:
		ASSERT (m_nInterface == ITF_NAME);

		IEnumString *pEnum = NULL;
		hr = m_pIServer->CreateGroupEnumerator (
			eScope,	IID_IEnumString, (IUnknown**)&pEnum);

		// Process results if succeed:
		if (SUCCEEDED (hr) && pEnum != NULL)
			{
			LPOLESTR pString;
			ULONG uFetched;

			// Loop over enumerated groups (call enemerator's next member to
			// reference next group and return its name string):
			while ((hr = pEnum->Next (1, &pString, &uFetched)) == S_OK)
				{
				// COM will return group name in UNICODE format.  Will have
				// to convert to ANSI format if ANSI build.  Copy result
				// to buffer:
#ifdef _UNICODE
				lstrcpyn (szBuffer, pString, sizeof (szBuffer) / sizeof (TCHAR));
#else
				_wcstombsz (szBuffer, pString, sizeof (szBuffer) / sizeof (TCHAR));
#endif

				// Insert group name into the list control:
				m_pEnumList->InsertItem (m_pEnumList->GetItemCount (), szBuffer);

				// Free enumerator allocations:
				if (pString)
					CoTaskMemFree (pString);
				}

			// Now release our enumerator:
			pEnum->Release ();
			}
		}

	// Select the first item in the list:
	m_pEnumList->SetItemState (0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);

	// Force the list control to scroll if necessary to show 
	// selected item:
	m_pEnumList->EnsureVisible (0, TRUE);
	}

// **************************************************************************
// UpdateState ()
//
// Description:
//	Get state of OPC group and update controls accordingly.
//
// Parameters:
//  CString		&strName	Name of OPC Group.
//
// Returns:
//  void
// **************************************************************************
void CKServerEnumerateGroupsDlg::UpdateState (CString &strName) 
	{
	WCHAR *pszName;
	IOPCGroupStateMgt *pIGroupStateMgt;
	HRESULT hr = E_FAIL;

	// Allocate memory for name string:
	pszName = (WCHAR *) CoTaskMemAlloc ((strName.GetLength () + 1) * sizeof (WCHAR));

	// Copy name string into allocated memory.  COM requires all strings to 
	// be in UNICODE format.  Convert if this is an ANSI build:
#ifdef _UNICODE
	lstrcpyn (pszName, strName, strName.GetLength () + 1);
#else
	_mbstowcsz (pszName, strName, strName.GetLength () + 1);
#endif

	// Get group by name:
	hr = m_pIServer->GetGroupByName (
		pszName, IID_IOPCGroupStateMgt, (IUnknown**)&pIGroupStateMgt);

	// We are done with memory allocated for name string, so free it:
	CoTaskMemFree (pszName);

	// If request was successful, process results:
	if (SUCCEEDED (hr))
		{
		// Declare variables neede to get group state:
		OPCHANDLE hClient;
		OPCHANDLE hServer;

		// Get group state:
		hr = pIGroupStateMgt->GetState (
			&m_dwUpdateRate,
			&m_bActive,
			&pszName, 
			&m_lBias,
			&m_fDeadband,
			&m_dwLanguageID,
			&hClient,
			&hServer);

		// If succeeded, process results:
		if (SUCCEEDED (hr))
			{
			// Update group name:
			m_strName = strName;

			// Free memory server allocated for name string:
			if (pszName)
				CoTaskMemFree (pszName);
			}

		// Release our get group by name reference:
		pIGroupStateMgt->Release ();
		}

	// Update dilaog controls:
	UpdateData (false);
	}

⌨️ 快捷键说明

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