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

📄 itempropertiesdlg.cpp

📁 PC客户和opc通信的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// **************************************************************************
// itempropertiesdlg.cpp
//
// Description:
//	Implements a dialog class for assigning OPC item 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 "itempropertiesdlg.h"
#include "item.h"
#include "server.h"
#include "mainwnd.h"

#define NUMCOLUMNS			4


/////////////////////////////////////////////////////////////////////////////
// CKItemPropertiesDlg dialog
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
BEGIN_MESSAGE_MAP (CKItemPropertiesDlg, CDialog)
	//{{AFX_MSG_MAP(CKItemPropertiesDlg)
	ON_BN_CLICKED (IDC_NEXT, OnNext)
	ON_BN_CLICKED (IDC_PREVIOUS, OnPrevious)
	ON_BN_CLICKED (IDC_ACTIVE, OnActive)
	ON_CBN_SELCHANGE (IDC_DATATYPE, OnChangeDataType)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP ()


// **************************************************************************
// CKItemPropertiesDlg ()
//
// Description:
//	Constructor.
//
// Parameters:
//  CObArray	&cItemList	Array of items objects that can be viewed and 
//							  modified with this dialog.
//	DWORD		cdwItems	Number of items in cItemList.
//	IOPCItemMgt	*pIItemMgt	Pointer to IOPCItemMgt interface.
//	CKServer	*pServer	Pointer to server items belong to.
//	CWnd		*pParent	Pointer to parent window.
//
// Returns:
//  none
// **************************************************************************
CKItemPropertiesDlg::CKItemPropertiesDlg (CObArray &cItemList, 
										  DWORD cdwItems, 
										  IOPCItemMgt *pIItemMgt,
										  CKServer *pServer,
										  CWnd *pParent /*=NULL*/)
	: CDialog (CKItemPropertiesDlg::IDD, pParent)
	{
	ASSERT (cdwItems > 0);
	ASSERT (pServer);

	// Intialize members:
	m_pItemList = &cItemList;
	m_cnItems = (int) cdwItems;
	m_pIItemMgt = pIItemMgt;
	m_pIItemProps = pServer->GetIItemProps ();
	m_pServer = pServer;

	m_nSelIndex = 0;
	m_bModified = false;

	// Initialize bitmap buttons:
	m_cNext.Initialize (IDB_NEXT, IDB_NEXTGRAY);
	m_cPrev.Initialize (IDB_PREVIOUS, IDB_PREVIOUSGRAY);
	}

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

	// Exchange data between controls and associated member variables:
	//{{AFX_DATA_MAP(CKItemPropertiesDlg)
	DDX_Text (pDX, IDC_ACCESSPATH, m_strAccessPath);
	DDX_Check (pDX, IDC_ACTIVE, m_bActive);
	DDX_Text (pDX, IDC_ITEMID, m_strItemID);
	//}}AFX_DATA_MAP

	// Get pointer to data type combo box:
	CComboBox *pCombo = (CComboBox *)GetDlgItem (IDC_DATATYPE);
	CString strType;

	// If not save and validate, use member vaiable value to make
	// data type combo box selection:
	if (!pDX->m_bSaveAndValidate)
		{
		CString strType;

		switch (m_vtDataType & ~VT_ARRAY)
			{
			case VT_BOOL:	strType = _T("Boolean");	break;
			case VT_UI1:	strType = _T("Byte");		break;
			case VT_I1:		strType = _T("Char");		break;
			case VT_UI2:	strType = _T("Word");		break;
			case VT_I2:		strType = _T("Short");		break;
			case VT_UI4:	strType = _T("DWord");		break;
			case VT_I4:		strType = _T("Long");		break;
			case VT_R4:		strType = _T("Float");		break;
			case VT_R8:		strType = _T("Double");		break;
			case VT_BSTR:	strType = _T("String");		break;
			default:		strType = _T("Native");		break;
			}

		// Update array flag data:
		if ((m_vtDataType & VT_ARRAY) != 0)
			strType += _T(" Array");
		
		// Select data type:
		pCombo->SelectString (-1, strType);
		}

	// else transfer data type combo box index to vartype member variable:
	else
		{
		pCombo->GetLBText (pCombo->GetCurSel (), strType);
		m_vtDataType = VartypeFromString (strType);
		}
	}	


/////////////////////////////////////////////////////////////////////////////
// CKItemPropertiesDlg message handlers
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// OnInitDialog ()
//
// Description:
//	Called immediately before the dialog box is displayed.  Use opportunity
//	to initialize controls.
//
// Parameters:
//  none
//
// Returns:
//	BOOL - Result of base class processing.
// **************************************************************************
BOOL CKItemPropertiesDlg::OnInitDialog () 
	{
	CString strText;

	// Limit the access path to 255 chars:
	((CEdit *)GetDlgItem (IDC_ACCESSPATH))->LimitText (255);
	
	// Allow 10 levels of 32 character names plus a tag name of 31 characters:
	((CEdit *)GetDlgItem (IDC_ITEMID))->LimitText (10*32 + 31);

	// Subclass image buttons:
	m_cNext.SubclassDlgItem (IDC_NEXT, this);
	m_cPrev.SubclassDlgItem (IDC_PREVIOUS, this);

	// Create tool tips for image buttons:
	m_cToolTip.Create (this);
	m_cToolTip.AddWindowTool (&m_cNext);
	m_cToolTip.AddWindowTool (&m_cPrev);

	// Intialize IItemProperties 2.0 list control headings:
	CListCtrl *pList = (CListCtrl *) GetDlgItem (IDC_LIST);
	ASSERT (pList != NULL);

	// Get rectangle that bounds list control:
	CRect rc;
	pList->GetWindowRect (&rc);

	// Calculate the width of the list control:
	int nTotalWidth;
	nTotalWidth = rc.right - rc.left;
	
	// Create the list control columns.  Headers will be loaded from
	// string resources and widths will be a function of total width
	// of list control:
	for (int i = 0; i < NUMCOLUMNS; i++)
		{
		int nWidth;

		switch (i)
			{
			case 0:	// ID
				strText.LoadString (IDS_ID);
				nWidth = nTotalWidth / 8;
				break;

			case 1: // Description
				strText.LoadString (IDS_DESCRIPTION);
				nWidth = nTotalWidth / 3;
				break;

			case 2:	// Value
				strText.LoadString (IDS_VALUE);
				nWidth = nTotalWidth / 6;
				break;

			case 3: // Item ID
				strText.LoadString (IDS_ITEMID);
				nWidth = nTotalWidth / 3;
				break;

			default:
				ASSERT (FALSE);
				break;
			}

		// Insert the column:
		pList->InsertColumn (i, strText, LVCFMT_LEFT, nWidth);
		}

	// Enable/disable the window based on whether or not the 2.0 
	// functionality is available. (If m_pIItemProps interface
	// pointer is NULL, we can assume functionality is not available.)
	pList->EnableWindow (m_pIItemProps != NULL);

	// Select the first item:
	SelectItem (0);

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

// **************************************************************************
// OnNext ()
//
// Description:
//	Next button event handler.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CKItemPropertiesDlg::OnNext () 
	{
	// Select the next item:
	if (m_nSelIndex < m_cnItems)
		SelectItem (m_nSelIndex + 1);

#ifdef _DEBUG
	// Button should be disabled in this case:
	else
		ASSERT (FALSE);
#endif
	}

// **************************************************************************
// OnPrevious ()
//
// Description:
//	Previous button event handler.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CKItemPropertiesDlg::OnPrevious () 
	{
	// Select the previous item:
	if (m_nSelIndex > 0)
		SelectItem (m_nSelIndex - 1);

#ifdef _DEBUG
	// Button should be disabled in this case:
	else
		ASSERT (FALSE);
#endif
	}

// **************************************************************************
// OnApply ()
//
// Description:
//	Called to apply changes to currently selected item.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CKItemPropertiesDlg::OnApply ()
	{
	// Only apply changes if Item ID control is enabled.  This will be the
	// case if the item is invalid to begin with:
	if (GetDlgItem (IDC_ITEMID)->IsWindowEnabled ())
		{
		try
			{
			// Transfer dialog contents to member vairables:
			UpdateData (true);

			// Define an array OPC Item Def structures to make property change
			// request:
			OPCITEMDEF *pItemArray = NULL;

			// Get selected item:
			CKItem *pItem = GetSelectedItem ();
			ASSERT (pItem);

			// Update item object:
			pItem->SetAccessPath (m_strAccessPath);
			pItem->SetItemID (m_strItemID);
			pItem->SetActive (m_bActive);
			pItem->SetDataType (m_vtDataType);

			// Attempt to add the item to the OPC server:
			if (m_pIItemMgt)
				{
				// Allocate memory for item definition:
				pItemArray = (OPCITEMDEF *) CoTaskMemAlloc (sizeof (OPCITEMDEF));

				// If allocation succeeds, fill in definition structure:
				if (pItemArray)
					{
					OPCITEMRESULT *pResults = NULL;
					HRESULT *pErrors = NULL;
					HRESULT hr;
					DWORD dwLen;

					// COM requires all strings be in UNICODE format.  We may have
					// to convert format before copying into request structure.

					// First process the access path string:
					dwLen = lstrlen (pItem->GetAccessPath ());

					// Access path is optional.  If it is not defined, i.e. it's length
					// is zero, just set pointer to string to NULL:
					if (dwLen)
						{
						// Allocate memory for the string:
						pItemArray->szAccessPath = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR));

#ifdef _UNICODE
						// This is a UNICODE build, so copy the string into allocated
						// memory as is:
						lstrcpyn (pItemArray->szAccessPath, pItem->GetAccessPath (), dwLen + 1);
#else
						// This is an ANSI build, so convert format an copy result into
						// allocated memory:
						MultiByteToWideChar (CP_ACP, 0, pItem->GetAccessPath (), -1, pItemArray->szAccessPath, dwLen + 1);
#endif
						}
					else
						pItemArray->szAccessPath = NULL;

					// Next process the item ID string the same way.  This string is 
					// required so we don't expect its length to be zero:

⌨️ 快捷键说明

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