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

📄 additemdlg.cpp

📁 VC 编写的OPC客户端
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// AddItemDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "SuperOPC.h"
#include "AddItemDlg.h"
#include ".\additemdlg.h"
// Registry sections;
static LPCTSTR lpszRegSection	= _T("Add Items");
static LPCTSTR lpszAutoValidate	= _T("Auto Validate");
static LPCTSTR lpszBrowseFlat	= _T("Browse Flat");

// Default add item list size:
#define DEF_ITEM_LIST_SIZE		16

// Branch dummy item data:
#define NULL_ITEM_NAME			_T("_QCNULL_DUMMY")
#define NULL_ITEM_DATA			0xFFFFFFFF

// Image list indices:
#define ILI_BRANCH				8
#define ILI_SELBRANCH			9
#define ILI_LEAF				3

// Access rights filter combo box indices:
#define CB_ACCESS_ANY			0
#define CB_ACCESS_READONLY		1
#define CB_ACCESS_WRITEONLY		2
#define CB_ACCESS_READWRITE		4

// CAddItemDlg 对话框

IMPLEMENT_DYNAMIC(CAddItemDlg, CDialog)
CAddItemDlg::CAddItemDlg(CHotOpcGroup *pGroup, IOPCBrowseServerAddressSpace *pIBrowse, CWnd* pParent /*=NULL*/)
: CDialog(CAddItemDlg::IDD, pParent)
, m_strItemID(_T(""))
{
	ASSERT (pGroup != NULL);
	m_pGroup = pGroup;
	m_pIBrowse = pIBrowse;
	m_vtDataType = VT_EMPTY;
	m_nListIndex = 0;
	m_nSelIndex = 0;
	m_bModified = false;
	m_pIItemMgt = NULL;

	// Load registry settings.  These are settings we may want to use each time
	// we add some items:
	m_bAutoValidate = FALSE;
	m_bBrowseFlat = FALSE;

	// Allocate memory for add item list:
	try
	{
		m_cItemList.SetSize (DEF_ITEM_LIST_SIZE, DEF_ITEM_LIST_SIZE);
	}
	catch (...)
	{
		ASSERT (FALSE);
	}
}

CAddItemDlg::~CAddItemDlg()
{
}

void CAddItemDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	// Transfer data type combo box index to vartype:
	CComboBox *pCombo = (CComboBox *)GetDlgItem (IDC_DATATYPE);
	CListCtrl *pList  = (CListCtrl *)GetDlgItem(IDC_LEAFLIST);
	pList->ModifyStyle(NULL, LVS_REPORT | LVS_SORTASCENDING ,0);
	pList->SetExtendedStyle(LVS_EX_FULLROWSELECT);

	// If save and validate, transfer data type combo box index to
	// vartype member variable:
	if (pDX->m_bSaveAndValidate)
	{
		CString strType;
		pCombo->GetLBText (pCombo->GetCurSel (), strType);
		m_vtDataType = VartypeFromString (strType);
	}

	// else use current member variable value to make combo box selection:
	else
	{
		CString strType;

		// Convert data type to combo box entry string:
		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 combo box entry:
		pCombo->SelectString (-1, strType);
	}
	DDX_Text(pDX, IDC_ACCESSPATH, m_strAccessPath);
	DDX_Text(pDX, IDC_ITEMID, m_strItemID);
}


BEGIN_MESSAGE_MAP(CAddItemDlg, CDialog)
	ON_NOTIFY(TVN_ITEMEXPANDING, IDC_BRANCHLIST, OnTvnItemexpandingBranchlist)
	ON_NOTIFY(TVN_SELCHANGED, IDC_BRANCHLIST, OnTvnSelchangedBranchlist)
	ON_CBN_SELCHANGE(IDC_DATATYPE, OnCbnSelchangeDatatype)
	ON_EN_CHANGE(IDC_ACCESSPATH, OnEnChangeAccesspath)
	ON_EN_CHANGE(IDC_ITEMID, OnEnChangeItemid)
	ON_WM_SHOWWINDOW()
	ON_NOTIFY(NM_DBLCLK, IDC_LEAFLIST, OnNMDblclkLeaflist)
END_MESSAGE_MAP()


// CAddItemDlg 消息处理程序

BOOL CAddItemDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 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);
	// Get our group's item management interface pointer for the group:
	m_pIItemMgt = m_pGroup->GetIItemMgt ();

	// Intialize our item browser:
	InitializeBrowser ();

	// Intialize control status:
	UpdateStatus ();


	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}
// **************************************************************************
// AutoIncrementID ()
//
// Description:
//	Create a new item ID by incrementing current ID.
//
// Parameters:
//  bool		bDotBitAddress	Set to true if item has "dot bit number"
//								  address format.
//
// Returns:
//  void
// **************************************************************************
void CAddItemDlg::AutoIncrementID (bool bDotBitAddress)
{
	static TCHAR szBuffer [MAX_PATH];
	static TCHAR *pch = NULL;

	// If the item ID is defined, we will modify it by incrementing:
	if (!m_strItemID.IsEmpty ())
	{
		// Make a local copy of the current item ID:
		lstrcpyn (szBuffer, m_strItemID, sizeof (szBuffer) / sizeof (TCHAR));

		// Ensure it is null terminated:
		szBuffer [MAX_PATH - 1] = '\0';

		// Get a pointer to the last character of the string (search for 
		// NULL terminator, then back up a character):
		pch = _tcschr (szBuffer, _T('\0'));
		pch--;

		// If it is a digit we can simply increment this address:
		if (_istdigit (*pch))
		{
			int nNumber;

			// Scan backwards from last character until we encounter
			// a non-digit:
			while (_istdigit (*pch) && pch != szBuffer)
				pch--;

			// Obtain the number we are peeling off (go to next character
			// which will be the first digit, then convert text to right
			// to an integer):
			pch++;
			nNumber = _ttol (pch);

			// Increment the number:
			nNumber++;

			// If we are dealing with a "dot bit number" address,
			// make sure we do not increment bit number beyond 15.
			// Increment bit numbers to 15, then increment offset
			// and make bit number 0.

			// If bDotBitAddress is set, then character to the left
			// of current pointer should be the "dot".
			if (bDotBitAddress && *(pch - 1) == _T('.'))
			{
				// Assume dot specifier is a bit and increment 0 - 15.

				// If nNumber is greater than 15, determine offset, and
				// increment that instead of the bit number:
				if (nNumber > 15)
				{
					// Roll offset ahead:
					pch = _tcsrchr (szBuffer, _T('.'));
					pch--;

					// Peel back looking for the first non-digit:
					while (_istdigit (*pch) && pch != szBuffer)
						pch--;

					// Go to next character and convert to integer.  This will
					// be the offset since _ttol will not use any characters to 
					// the right of the dot.  Increment the result by one.  This
					// will be our new offset.
					pch++;
					nNumber = _ttol (pch) + 1;

					// Replace old offset and bit number with incremented
					// offset and bit number "00".
					_stprintf (pch, _T("%d.00"), nNumber);
				}

				// Otherwise just replace the bit number with incremeted
				// bit number:
				else
					_stprintf (pch, _T("%02d"), nNumber);
			}

			// If not a dot bit number address, make sure we do not lose
			// any leading zeros (as in modbus addresses):
			else
			{
				// We should currently be pointing at first character of 
				// trailing digit portion of address.  Check to see if
				// this is a zero.
				if (*pch == _T('0'))
				{
					// We found a leading zero.
					TCHAR *pZeros = pch;
					int cnDigits = 0;

					// Scan forwared until we find a non-zero character.
					// Count each zero along the way:
					while (*pZeros++ != _T('\0'))
						cnDigits++;

					// Replace the trailing digits of the adress with
					// the new incremented number, keeping the same
					// number of leading zeros:
					_stprintf (pch, _T("%0*d"), cnDigits, nNumber);
				}

				// Else if no leading zeros, just replace the trailing 
				// digits with the new incremented number:
				else
					_stprintf (pch, _T("%d"), nNumber);
			}
		}

		// else if last character is not a digit, append a good starting offset:
		else
			*(pch + 1) = '0';

		// Update item ID:
		m_strItemID = szBuffer;

		// Update controls:
		UpdateData (false);

		// Set modifed flag:
		m_bModified = true;		
	}
}

// **************************************************************************
// UpdateStatus ()
//
// Description:
//	Update status of dialog controls based on current item selected.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CAddItemDlg::UpdateStatus ()
{
	// Determine the focus so that if we disable the focused control
	// we can move it.
	HWND hWnd = ::GetFocus ();

	// Enable the next button if the selected item has an item ID defined:


	// Update the browse controls:
	m_pBranchList->EnableWindow (m_pIBrowse != NULL);
	m_pLeafList->EnableWindow (m_pIBrowse != NULL);


	// Set the focus to the first control if the previous control with the
	// focus just lost it:
	if (hWnd && !::IsWindowEnabled (hWnd))
		GetDlgItem (IDC_ITEMID)->SetFocus ();
}

// **************************************************************************
// InitializeBrowser ()
//
// Description:
//	Initialize things related to the browser.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CAddItemDlg::InitializeBrowser ()
{
	// Get pointers to our browse controls for easy access:
	m_pBranchList = (CTreeCtrl *) GetDlgItem (IDC_BRANCHLIST);
	ASSERT (m_pBranchList != NULL);

	m_pLeafList = (CListCtrl *) GetDlgItem (IDC_LEAFLIST);
	ASSERT (m_pLeafList != NULL);



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


	// Intialize browse controls if browsing is supported, otherwise
	// just disable the controls:
	if (m_pIBrowse != NULL)
	{
		// 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;
		HRESULT hr;

		// Query the server name space:
		hr = m_pIBrowse->QueryOrganization (&m_cOpcNameSpace);

		if (SUCCEEDED (hr))
		{
			// Browse root level:
			switch (m_cOpcNameSpace)
			{
			case OPC_NS_HIERARCHIAL:
			case OPC_NS_FLAT:
				BrowseRootLevel ();
				break;

				// Did the foundation add a new type?
			default:
				ASSERT (FALSE);
				break;
			}
		}

		// We will assume a hierarchial search if the server fails this request:
		// (This allows us to work with any server that uses the ICONICS toolkit.)
		else
		{
			TRACE (_T("OTC: Attempting agressive browsing since the server failed on QueryOrganization ()\r\n"));

			m_cOpcNameSpace = OPC_NS_HIERARCHIAL;
			BrowseRootLevel ();
		}
	}
}

// **************************************************************************
// BrowseRootLevel ()
//
// Description:
//	Reset the browser to the root object.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CAddItemDlg::BrowseRootLevel ()
{
	HRESULT hr = E_FAIL;
	HTREEITEM hItem = NULL;

	try
	{
		// If hierarchial namespace:
		if (m_cOpcNameSpace == OPC_NS_HIERARCHIAL)
		{
			// Re-initialize server's browse position to the root:
			do
			{
				// Use the OPC_BROWSE_UP rather than the OPC_BROWSE_TO which
				// is only supported in OOPC version 2.0.  We will have to 
				// browse up to root one level at a time.  Function will
				// fail when we are at root.
				hr = m_pIBrowse->ChangeBrowsePosition (OPC_BROWSE_UP, L"\0");
			} while (SUCCEEDED (hr));

			// Insert our root level item:
			hItem = m_pBranchList->InsertItem ((m_pGroup->GetParentServer ())->GetServerName(), 
				ILI_BRANCH, ILI_SELBRANCH, TVI_ROOT);

			// Set the item data and add a dummy child branch:
			m_pBranchList->SetItemData (hItem, DWORD (-1));
			AddDummyBranch (hItem);
		}

		// Else flat namespace:
		else
		{
			ASSERT (m_cOpcNameSpace == OPC_NS_FLAT);

			// Insert our root level item (there is no need to add any dummy
			// branches since a flat space will only have one level of leaves)
			hItem = m_pBranchList->InsertItem ((m_pGroup->GetParentServer ())->GetServerName (), 
				ILI_BRANCH, ILI_SELBRANCH, TVI_ROOT);

⌨️ 快捷键说明

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