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

📄 serverpropertysheet.cpp

📁 KepWare的OPC Client 示例.面向C
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// **************************************************************************
// serverpropertysheet.cpp
//
// Description:
//	Implements a property sheet class and associated property page classes for
//	OPC server properties.
//
// 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 "serverpropertysheet.h"
#include "server.h"

static LPCTSTR lpszDataAccessServers10 = _T("OPC Data Access Servers Version 1.0");
static LPCTSTR lpszDataAccessServers20 = _T("OPC Data Access Servers Version 2.0");
static LPCTSTR lpszOPCServers = _T("OPC General");

static const CATID CATID_OPCDAServer10 = 
{ 0x63d5f430, 0xcfe4, 0x11d1, { 0xb2, 0xc8, 0x0, 0x60, 0x8, 0x3b, 0xa1, 0xfb } };
// {63D5F430-CFE4-11d1-B2C8-0060083BA1FB}

static const CATID CATID_OPCDAServer20 = 
{ 0x63d5f432, 0xcfe4, 0x11d1, { 0xb2, 0xc8, 0x0, 0x60, 0x8, 0x3b, 0xa1, 0xfb } };
// {63D5F432-CFE4-11d1-B2C8-0060083BA1FB}

// image list indices
#define ILI_CATAGORY	0
#define ILI_COMPONENT	1
#define ILI_INTERFACE	2


/////////////////////////////////////////////////////////////////////////////
// CKServerGeneralPage property page
/////////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE (CKServerGeneralPage, CPropertyPage)

// **************************************************************************
BEGIN_MESSAGE_MAP (CKServerGeneralPage, CDialog)
	//{{AFX_MSG_MAP(CKServerGeneralPage)
	ON_NOTIFY (TVN_SELCHANGED, IDC_SERVERLIST, OnSelChanged)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP ()


// **************************************************************************
// CKServerGeneralPage ()
//
// Description:
//	Constructor.
//
// Parameters:
//  none
//
// Returns:
//  none
// **************************************************************************
CKServerGeneralPage::CKServerGeneralPage ()
	: CPropertyPage (CKServerGeneralPage::IDD)
	{
	// Initialize member variables:
	m_strProgID = cApp.GetDefConnectProgID ();
	m_strRemoteMachine.Empty ();

	m_pServerList = NULL;
	}

// **************************************************************************
// 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 CKServerGeneralPage::DoDataExchange (CDataExchange *pDX)
	{
	// Perform default processing:
	CDialog::DoDataExchange (pDX);

	// Exchange data between controls and associated member variables:
	//{{AFX_DATA_MAP(CKServerGeneralPage)
	DDX_Text (pDX, IDC_MACHINENAME, m_strRemoteMachine);
	DDV_MaxChars (pDX, m_strRemoteMachine, 256);
	DDX_Text (pDX, IDC_PROGID, m_strProgID);
	DDV_MaxChars (pDX, m_strProgID, 256);
	//}}AFX_DATA_MAP
	}


/////////////////////////////////////////////////////////////////////////////
// CKServerGeneralPage message handlers
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// OnInitDialog ()
//
// Description:
//	Called immediately before the dialog box is displayed.  Use opportunity
//	to initialize controls.
//
// Parameters:
//  none
//
// Returns:
//	BOOL - TRUE.
// **************************************************************************
BOOL CKServerGeneralPage::OnInitDialog () 
	{
	// Create a wait cursor object.  This will cause the wait cursor, 
	// usually an hourglass, to be displayed.  When this object goes
	// out of scope, its destructor will restore the previous cursor
	// type.
	CWaitCursor wc;
	CDialog::OnInitDialog ();

	// Initialize the tree control:
	m_pServerList = (CTreeCtrl *) GetDlgItem (IDC_SERVERLIST);
	ASSERT (m_pServerList != NULL);

	// Initialize the image list for the interfaces. The bitmap must use a 
	// purple background color, RGB (255, 0, 255), so that the CImageList
	// object can construct a mask.  The images are 16x16 pixels.  Set the
	// image list background color to CLR_NONE so masked pixels will be
	// transparent. 
	// Image number		Use
	//	0				not used
	//	1				not used
	//	2				Interface
	m_cImageList.Create (IDB_COMPONENTS, 16, 4, RGB (255, 0, 255));
	m_cImageList.SetBkColor (CLR_NONE);
	m_pServerList->SetImageList (&m_cImageList, TVSIL_NORMAL);

	HTREEITEM hParent;

	// Insert data access 1.0 servers:
	hParent = m_pServerList->InsertItem (lpszDataAccessServers10, ILI_CATAGORY, ILI_CATAGORY);
	DisplayComponentCatList (hParent, CATID_OPCDAServer10);

	// Insert data access 2.0 servers:
	hParent = m_pServerList->InsertItem (lpszDataAccessServers20, ILI_CATAGORY, ILI_CATAGORY);
	DisplayComponentCatList (hParent, CATID_OPCDAServer20);

	// Insert general OPC registered servers:
	hParent = m_pServerList->InsertItem (lpszOPCServers, ILI_CATAGORY, ILI_CATAGORY);
	DisplayGeneralOPCServers (hParent);

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

// **************************************************************************
// OnSelChanged ()
//
// Description:
//	Handles notification that a new item in tree 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 CKServerGeneralPage::OnSelChanged (NMHDR *pNMHDR, LRESULT *pResult) 
	{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	// see if it was a server selection (i.e, has a parent item)

	// Update page is server was selected (non-NULL parent item):
	if (m_pServerList->GetParentItem (pNMTreeView->itemNew.hItem) != NULL)
		{
		// Transfer selection to ProgID edit control:
		m_strProgID = m_pServerList->GetItemText (pNMTreeView->itemNew.hItem);

		// Update controls:
		UpdateData (FALSE);

		// Make sure selected server is visible:
		m_pServerList->EnsureVisible (pNMTreeView->itemNew.hItem); 
		}

	*pResult = 0;
	}


/////////////////////////////////////////////////////////////////////////////
// CKServerGeneralPage helpers
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// DisplayComponentCatList ()
//
// Description:
//	Construct a list of installed 1.0 and 2.0 OPC servers and insert into 
//	tree control.
//
// Parameters:
//  HTREEITEM	hParent		Handle of parent tree control item.
//	CATID		catid		Catagory ID (CATID_OPCDAServer10 or
//							  CATID_OPCDAServer20).
//
// Returns:
//  void
// **************************************************************************
void CKServerGeneralPage::DisplayComponentCatList (HTREEITEM hParent, CATID catid)
	{
	HRESULT hr;
	
	// Make sure COM is initialized:
	hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);

	if (SUCCEEDED (hr))
		{
		ICatInformation *pCat = NULL;

		// Get component category manager:
		hr = CoCreateInstance (CLSID_StdComponentCategoriesMgr, 
			NULL,
			CLSCTX_SERVER, 
			IID_ICatInformation,
			(void **)&pCat);

		// If succeeded, enumerate registered components:
		if (SUCCEEDED (hr))
			{
			IEnumCLSID *pEnum = NULL;

			CATID arrcatid [1];
			arrcatid [0] = catid;

			// Enumerate registered components based on clsid:
			hr = pCat->EnumClassesOfCategories (
				sizeof (arrcatid) / sizeof (CATID),	// number of catids in the array that follows
				arrcatid,							// catid array
				0, 
				NULL,
				&pEnum);							// clsid enumerator for registered components under this category

			// If succeeded, process results:
			if (SUCCEEDED (hr))
				{
				GUID guid;
				ULONG fetched;

				// Loop over enumerated components.  Call enemerator's next
				// member function to reference next component and get its
				// guid:
				while ((hr = pEnum->Next (1, &guid, &fetched)) == S_OK)
					{
					// Get the ProgID from the guid:
					WCHAR *wszProgID;
					hr = ProgIDFromCLSID (guid, &wszProgID);

					// If succeeded, add component to list:
					if (SUCCEEDED (hr))
						{
						// ProgID string will be in UNICODE format.  Convert to 
						// ANSI format if this is and ANSI build.  Insert component
						// into list:
#ifdef _UNICODE
						m_pServerList->InsertItem (wszProgID, ILI_COMPONENT, ILI_COMPONENT, hParent);
#else
						TCHAR szProgID [DEFBUFFSIZE];

						_wcstombsz (szProgID, wszProgID, sizeof (szProgID) / sizeof (TCHAR));
						m_pServerList->InsertItem (szProgID, ILI_COMPONENT, ILI_COMPONENT, hParent);
#endif
						// It is up to us to free the Prog ID string memory:
						CoTaskMemFree (wszProgID);
						}
					}

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

			// release our category mamager
			pCat->Release ();
			}

		// Uninitialize COM:
		CoUninitialize ();
		}
	}

// **************************************************************************
// DisplayGeneralOPCServers ()
//
// Description:
//	Construct a list of installed general OPC servers and insert into tree
//	control.
//
// Parameters:
//  HTREEITEM	hParent		Handle of parent tree control item.
//
// Returns:
//  void
// **************************************************************************
void CKServerGeneralPage::DisplayGeneralOPCServers (HTREEITEM hParent)
	{
	HKEY hKey = HKEY_CLASSES_ROOT;		// search under this key
	TCHAR szKey [DEFBUFFSIZE];			// allocate key buffer
	DWORD dwLength = DEFBUFFSIZE;

	// Search the registry for installed OPC Servers:
	for (DWORD dwIndex = 0; 
		 RegEnumKey (hKey, dwIndex, szKey, dwLength) == ERROR_SUCCESS; 
		 ++dwIndex)
		{
		HKEY hSubKey;

		// Open the registry key:
		if (RegOpenKey (hKey, szKey, &hSubKey) == ERROR_SUCCESS)
			{
			// Search for OPC subkey:
			if (RegQueryValue (hSubKey, _T("OPC"), NULL, NULL) == ERROR_SUCCESS)
				{
				// Display the prog ID for this server:
				m_pServerList->InsertItem (szKey, ILI_COMPONENT, ILI_COMPONENT, hParent);
				}

			// Close the registry key:
			RegCloseKey (hSubKey);
			}

		// Re-initialize length:
		dwLength = DEFBUFFSIZE;
		}
	}


/////////////////////////////////////////////////////////////////////////////
// CKServerStatusPage property page
/////////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE (CKServerStatusPage, CPropertyPage)

// **************************************************************************
BEGIN_MESSAGE_MAP (CKServerStatusPage, CPropertyPage)
	//{{AFX_MSG_MAP(CKServerStatusPage)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP ()


// **************************************************************************
// CKServerStatusPage ()
//
// Description:
//	Constructor.
//
// Parameters:
//  none
//
// Returns:
//  none
// **************************************************************************
CKServerStatusPage::CKServerStatusPage () : CPropertyPage (CKServerStatusPage::IDD)
	{
	// Initialize member variables:

	//{{AFX_DATA_INIT(CKServerStatusPage)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	
	m_pServer = NULL;
	}

// **************************************************************************
// ~CKServerStatusPage ()
//
// Description:
//	Destructor.
//
// Parameters:
//  none
//
// Returns:
//  none
// **************************************************************************
CKServerStatusPage::~CKServerStatusPage ()
	{
	}

// **************************************************************************
// 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 CKServerStatusPage::DoDataExchange (CDataExchange *pDX)
	{
	// Perform default processing:
	CPropertyPage::DoDataExchange (pDX);

	// Exchange data between controls and associated member variables:
	//{{AFX_DATA_MAP(CKServerStatusPage)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
	}


/////////////////////////////////////////////////////////////////////////////
// CKServerStatusPage message handlers
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// OnInitDialog ()
//
// Description:
//	Called immediately before the dialog box is displayed.  Use opportunity
//	to initialize controls.
//
// Parameters:
//  none
//
// Returns:
//	BOOL - TRUE.
// **************************************************************************
BOOL CKServerStatusPage::OnInitDialog () 
	{
	IOPCServer *pIServer = NULL;
	OPCSERVERSTATUS *pServerStatus;
	CString strLoader;
	CString strStatus;
	CString strTemp;

	// Perform default processing:
	CPropertyPage::OnInitDialog ();

	// Get IServer interface:
	ASSERT (m_pServer != NULL);
	pIServer = m_pServer->GetIServer ();

	// Add server name to status string:
	strLoader.FormatMessage (IDS_PROGID, m_pServer->GetProgID ());
	strStatus += strLoader;

	// Add remote machine (if applicable) to status string:
	if (m_pServer->GetRemoteMachine ())
		{
		strLoader.FormatMessage (IDS_REMOTEMACHINE, m_pServer->GetRemoteMachine ());
		strStatus += strLoader;
		}

	// Get the server status:
	if (pIServer && SUCCEEDED (pIServer->GetStatus (&pServerStatus)) && pServerStatus)
		{
		FILETIME ftLocal;
		TCHAR szBuffer [DEFBUFFSIZE];

		// Add vendor name to status string:
		if (pServerStatus->szVendorInfo)
			{
			// Convert venter name from UNICODE if needed:
#ifdef _UNICODE
			lstrcpyn (szBuffer, pServerStatus->szVendorInfo, sizeof (szBuffer) / sizeof (TCHAR));
#else
			_wcstombsz (szBuffer, pServerStatus->szVendorInfo, sizeof (szBuffer) / sizeof (TCHAR));
#endif
			// Add vender name:

⌨️ 快捷键说明

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