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

📄 itemadddlg.cpp

📁 PC客户和opc通信的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//  none
//
// Returns:
//  bool - true if success.
// **************************************************************************
bool CKItemAddDlg::OnApplyChange ()
	{
	// No need to apply changes unless we are modified:
	if (m_bModified)
		{
		CKItem *pItem = NULL;

		// Make sure member variables have values currently displayed in
		// associated controls:
		UpdateData (true);

		// If auto validating, validate item before applying changes.
		if (m_bAutoValidate)
			{
			// Validate currently selected item:
			HRESULT hr = Validate ();

			// If item is invalid, then inform user of problem and give him
			// option of continuing:
			if (FAILED (hr))
				{
				// Define a string format for the validation return code:
				CString strHR;
				strHR.Format (_T("0x%08X"), hr);

				// Define a string format for the validation return code:
				CString strFailure;
				strFailure.FormatMessage (IDS_VALIDATE_ITEM_FAILED_CONTINUE, m_strItemID, strHR);

				// Show message bow with error string.  Give user of option of
				// continuing.  If user clicks "NO", return now without applying
				// changes:
				if (AfxMessageBox (strFailure, MB_YESNO | MB_ICONQUESTION) == IDNO)
					return (false);
				}
			}

		// If we make it here, it is OK to apply changes.
		
		// If selected index is the same as list control index, then we
		// need to create a new item and add to the list:
		if (m_nSelIndex == m_nListIndex)
			{
			try 
				{
				// Create a new item object and add it to the list:
				pItem = new CKItem (m_pGroup);
				m_cItemList.SetAtGrow (m_nListIndex++, pItem);
				}
			
			catch (...)
				{
				ASSERT (FALSE);
				}
			}
		
		// else we are modifying an item already in list:
		else
			{
			pItem = (CKItem *) m_cItemList.GetAt (m_nSelIndex);
			ASSERT (pItem != NULL);
			}

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

		// Set modified flag:
		m_bModified = false;
		}

	// Return true to indicate success:
	return (true);
	}

// **************************************************************************
// 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 CKItemAddDlg::AutoIncrementID (bool bDotBitAddress)
	{
	static TCHAR szBuffer [DEFBUFFSIZE];
	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 [DEFBUFFSIZE - 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 CKItemAddDlg::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:
	m_cNext.EnableWindow (m_nSelIndex < m_nListIndex - 1);

	// Enable the previous button if the selected item has a previous button:
	m_cPrev.EnableWindow (m_nSelIndex > 0);

	// Enable the new button if there is a valid item ID entered
	// (otherwise they are already editting a new item):
	m_cNew.EnableWindow (!m_strItemID.IsEmpty ());

	// Duplicate any item that has an item ID:
	m_cDuplicate.EnableWindow (!m_strItemID.IsEmpty ());

	// Enable the delete button if the item selected is not the one we 
	// are adding to the list:
	m_cDelete.EnableWindow (m_nSelIndex < m_nListIndex);

	// Enable validate item:
	m_cValidate.EnableWindow (m_pIItemMgt && !m_strItemID.IsEmpty ());

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

	GetDlgItem (IDC_ADD_LEAVES)->EnableWindow (m_pIBrowse != NULL);
	GetDlgItem (IDC_FILTERACCESS)->EnableWindow (m_pIBrowse != NULL);
	GetDlgItem (IDC_FILTERLEAF)->EnableWindow (m_pIBrowse != NULL);
	GetDlgItem (IDC_FILTERTYPE)->EnableWindow (m_pIBrowse != NULL);
	GetDlgItem (IDC_FILTERBRANCH)->EnableWindow (m_pIBrowse != NULL);

	// Update the item count display:
	CString strItemCount;
	strItemCount.Format (_T("Item Count: %d"), m_nListIndex);
	((CStatic *) GetDlgItem (IDC_ITEM_COUNT))->SetWindowText (strItemCount);

	// 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 CKItemAddDlg::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);

	// Initialize the image list for the branch control.  These are the 
	// images that show up to the left of each item in list.  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-7				not used
	//	8				Branch
	//	9				Self branch
	m_cBranchImageList.Create (IDB_GROUPIMAGES, 16, 3, RGB (255, 0, 255));
	m_cBranchImageList.SetBkColor (CLR_NONE);
	m_pBranchList->SetImageList (&m_cBranchImageList, TVSIL_NORMAL);

	// Initialize the image list for the leaf control.  These are the images
	// that show up to the left of each item in list.  The bitmap must use a 
	// purple background color, RGB (255, 0, 255), so that the CImageList
	// object can construct a mask.  The images are 14x14 pixels.  Set the
	// image list background color to CLR_NONE so masked pixels will be
	// transparent. 
	//
	// Image number		Use
	//	0-2				not used
	//	3				Leaf
	m_cLeafImageList.Create (IDB_ITEMIMAGES, 14, 2, RGB (255, 0, 255));
	m_cLeafImageList.SetBkColor (CLR_NONE);
	m_pLeafList->SetImageList (&m_cLeafImageList, LVSIL_SMALL);

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

	// Initialize filters:
	m_strFilterBranch = "*";
	((CEdit *) GetDlgItem (IDC_FILTERBRANCH))->SetWindowText (m_strFilterBranch);

	m_strFilterLeaf = "*";
	((CEdit *) GetDlgItem (IDC_FILTERLEAF))->SetWindowText (m_strFilterLeaf);

	m_vtFilterType = VT_EMPTY;
	((CComboBox *) GetDlgItem (IDC_FILTERTYPE))->SetCurSel (0);

	m_dwFilterAccessRights = CB_ACCESS_ANY;
	((CComboBox *) GetDlgItem (IDC_FILTERACCESS))->SetCurSel (CB_ACCESS_ANY);

	// 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 CKItemAddDlg::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 ())->GetProgID (), 
				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 ())->GetProgID (), 
				ILI_BRANCH, ILI_SELBRANCH, TVI_ROOT);
			}

		// Select root item:
		if (hItem)
			m_pBranchList->SelectItem (hItem);
		}
	
	catch (...)
		{
		m_pIBrowse = NULL;
		UpdateStatus ();
		}
	}

⌨️ 快捷键说明

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