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

📄 additemdlg.cpp

📁 VC 编写的OPC客户端
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		{
			do
			{
				hr = m_pIBrowse->ChangeBrowsePosition (OPC_BROWSE_UP, L"\0");
			} while (SUCCEEDED (hr));
		}
	}

	catch (...)
	{
	}
}
void CAddItemDlg::OnTvnItemexpandingBranchlist(NMHDR *pNMHDR, LRESULT *pResult)
{
	// Cast notification header to tree view notification header:
	NM_TREEVIEW* pnmtv = (NM_TREEVIEW*) pNMHDR;

	// Expand branch:
	if (pnmtv->action & TVE_EXPAND)
	{
		ExpandBranch (pnmtv->itemNew.hItem);
	}

	// else delete child branches on collapse:
	else if (pnmtv->action & TVE_COLLAPSE)
	{
		DeleteChildBranches (pnmtv->itemNew.hItem);
	}

	*pResult = 0;
}

void CAddItemDlg::OnTvnSelchangedBranchlist(NMHDR *pNMHDR, LRESULT *pResult)
{
	NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;

	// Select the branch:
	SelectBranch (pnmtv->itemNew.hItem);
	*pResult = 0;
}

void CAddItemDlg::OnCancel()
{
	for (int nIndex = 0; nIndex < m_nListIndex; nIndex++)
	{
		// Get next element in list:
		CHotOpcItem *pItem = (CHotOpcItem *) m_cItemList.GetAt (nIndex);
		ASSERT (pItem != NULL);

		// Delete it:
		delete pItem;
	}


	CDialog::OnCancel();
}

void CAddItemDlg::OnCbnSelchangeDatatype()
{
	UpdateData (true);

	// We will consider ourselves modified if there is an item ID defined:
	m_bModified = !m_strItemID.IsEmpty ();

	// Update control status:
	UpdateStatus ();
}

void CAddItemDlg::OnEnChangeAccesspath()
{
	// TODO:  如果该控件是 RICHEDIT 控件,则它将不会
	// 发送该通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	UpdateData (true);

	// We will consider ourselves modified if there is an item ID defined:
	m_bModified = !m_strItemID.IsEmpty ();

	// Update control status:
	UpdateStatus ();
}

void CAddItemDlg::OnEnChangeItemid()
{
	UpdateData (true);

	// We will consider ourselves modified if there is an item ID defined:
	m_bModified = !m_strItemID.IsEmpty ();

	// Update control status:
	UpdateStatus ();
}

void CAddItemDlg::OnOK()
{
	if (OnApplyChange ())
	{
		// Terminate the list.  Will allow us to process list using
		// "while (element)" loop if we want:
		if (m_nListIndex > 0)
			m_cItemList.SetAtGrow (m_nListIndex, NULL);


		CDialog::OnOK();
	}
}

void CAddItemDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
	CDialog::OnShowWindow(bShow, nStatus);

	// If showing dialog, set focus to item ID edit box:
	if (bShow)
		GetDlgItem (IDC_ITEMID)->SetFocus ();
}

void CAddItemDlg::OnNMDblclkLeaflist(NMHDR *pNMHDR, LRESULT *pResult)
{
	int nSelItem;

	// Get selected item index:
	nSelItem = m_pLeafList->GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);

	// If index looks good, get properties of selected item and
	// update all other controls accordingly:
	if (nSelItem >= 0)
	{
		HRESULT hr;
		WCHAR szItemID [MAX_PATH];
		LPWSTR lpszQualifiedID;

		// COM requires all strings to be in UNICODE format. Convert
		// item ID if needed, then copy to allocated buffer:
#ifdef _UNICODE
		lstrcpyn (szItemID, m_pLeafList->GetItemText (nSelItem, 0), sizeof (szItemID) / sizeof (WCHAR));
#else
		_mbstowcsz (szItemID, m_pLeafList->GetItemText (nSelItem, 0), sizeof (szItemID) / sizeof (WCHAR));
#endif

		try
		{
			// If we are using a flat browse space, then we need to browse to
			// root first:
			if (m_bBrowseFlat)
				BrowseToRoot ();

			// User browser to get item's fully qualified ID:
			hr = m_pIBrowse->GetItemID (szItemID, &lpszQualifiedID);

			// If we succeeded, update controls:
			if (SUCCEEDED (hr) && lpszQualifiedID)
			{
				// Update selector to end of the list:
				m_nSelIndex = m_nListIndex;

				// Re-initialize for new item:
				m_strItemID = lpszQualifiedID;
				m_strAccessPath.Empty ();
				UpdateData (false);

				// Apply new dataset:
				m_bModified = true;
				OnApplyChange ();

				// Update control state:
				UpdateStatus ();

				// Free server allocation for qualified item id:
				CoTaskMemFree (lpszQualifiedID);
			}

			// If we didn't get qualified ID, issue a trace statement for debugging:
			else
			{
				TRACE (_T("OTC: Unable to get the qualified item id for %s\r\n"), 
					m_pLeafList->GetItemText (nSelItem, 0));
			}
		}

		// Catch exceptions:
		catch (...)
		{
			m_pIBrowse = NULL;
			UpdateStatus ();
		}
	}

	*pResult = 0;
}

bool CAddItemDlg::OnApplyChange ()
{
	// No need to apply changes unless we are modified:
	if (m_bModified)
	{
		CHotOpcItem *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 %s %s", 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 CHotOpcItem (m_pGroup);
				m_cItemList.SetAtGrow (m_nListIndex++, pItem);
			}

			catch (...)
			{
				ASSERT (FALSE);
			}
		}

		// else we are modifying an item already in list:
		else
		{
			pItem = (CHotOpcItem *) m_cItemList.GetAt (m_nSelIndex);
			ASSERT (pItem != NULL);
		}

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

		// Set modified flag:
		m_bModified = false;
	}

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

HRESULT CAddItemDlg::Validate (bool *pbDotBitAddress /*= NULL */)
{
	// Assume invalid until proven otherwisw:
	HRESULT hr = E_FAIL;

	// Make sure data in member variables represents current control settings:
	UpdateData (true);

	// Allocate memory for our item definition:
	OPCITEMDEF *pItems = (OPCITEMDEF *) CoTaskMemAlloc (sizeof (OPCITEMDEF));

	// If allocation succeeds, perform validation:
	if (pItems)
	{
		// Initialize some variables:
		HRESULT *pErrors = NULL;
		OPCITEMRESULT *pResults = NULL;
		WCHAR *pszItemID = NULL;
		WCHAR *pszAccessPath = NULL;

		// Check to make sure we have an item ID (debug only):
		ASSERT (!m_strItemID.IsEmpty ());

		// Allocate memory for item ID string:
		pszItemID = (WCHAR *) CoTaskMemAlloc ((m_strItemID.GetLength () + 1) * sizeof (WCHAR));

		// COM requires us to put strings in UNICODE format.
#ifdef _UNICODE
		// This is a UNICODE build so just copy item ID string "as is"
		// to allocated memory:
		lstrcpyn (pszItemID, m_strItemID, m_strItemID.GetLength () + 1);
#else
		// This is an ANSI build so convert item ID string to UNICODE and
		// place result in allocated memory:
		_mbstowcsz (pszItemID, m_strItemID, m_strItemID.GetLength () + 1);
#endif

		// If an access path is specified, then convert its string to UNICODE
		// and copy it to allocated memory:
		if (!m_strAccessPath.IsEmpty ())
		{
			// First allocate memory for the access path string:
			pszAccessPath = (WCHAR *) CoTaskMemAlloc ((m_strAccessPath.GetLength () + 1) * sizeof (WCHAR));

			// Convert if necessary and copy result to allocated memory:
#ifdef _UNICODE
			lstrcpyn (pszAccessPath, m_strAccessPath, m_strAccessPath.GetLength () + 1);
#else
			_mbstowcsz (pszAccessPath, m_strAccessPath, m_strAccessPath.GetLength () + 1);
#endif
		}

		// Fill in item def structure:
		pItems->bActive = true;
		pItems->dwBlobSize = 0;
		pItems->hClient = NULL;
		pItems->pBlob = NULL;
		pItems->szAccessPath = pszAccessPath;
		pItems->szItemID = pszItemID;
		pItems->vtRequestedDataType = m_vtDataType;

		// Validate the single item, (no blob requested):
		try
		{
			// Request server to validate item described initem def structure
			// through the group's item management interface:
			hr = m_pIItemMgt->ValidateItems (1, pItems, FALSE, &pResults, &pErrors);

			// If server reports that item is valid, we may still have to modify
			// the data type.  We will also validate "dot bit address" format.
			if (hr == S_OK)
			{
				// Modify the data type to what the server will use:
				m_vtDataType = pResults->vtCanonicalDataType;

				// Update the dialog controls to reflect data type change:
				UpdateData (false);

				// Flag as modified:
				m_bModified = true;

				// Verify dot bit address setting:
				if (pbDotBitAddress)
				{
					// Assume false until proven otherwise:
					*pbDotBitAddress = false;

					// Data type must be VT_BOOL for dot bit address,  It it's not,
					// fall through with flag set to false:
					if (m_vtDataType == VT_BOOL)
					{
						// To determine if truly a dot bit address, strip off
						// bit number and see if its still valid.

						// First free previous results,
						if (pResults)
						{
							CoTaskMemFree (pResults);
							pResults = NULL;
						}

						// and previous errors:
						if (pErrors)
						{
							CoTaskMemFree (pErrors);
							pErrors = NULL;
						}

						// Get position of "dot" character:
						WCHAR *pwch = wcsrchr (pItems->szItemID, L'.');

						if (pwch)
						{
							// Replace "dot" with NULL terminator, effectively stripping
							// off the whole "dot bit number" portion of the address:
							*pwch = L'\0';

							// Reset the requested data type to VT_EMPTY.  We are only
							// interested in seeing if the address is valid for some
							// unspecified data type.
							pItems->vtRequestedDataType = VT_EMPTY;

							// Request server to validate the "stripped" address:
							if (SUCCEEDED (m_pIItemMgt->ValidateItems (1, pItems, FALSE, &pResults, &pErrors)))
							{
								// If the server reports that the "stipped" address is valid, and
								// that it corresponds to some data type other than VT_BOOL, 
								// then the original address is truely a "dot bit" address:
								if (pResults->vtCanonicalDataType != VT_EMPTY && pResults->vtCanonicalDataType != VT_BOOL)
									*pbDotBitAddress = true;
							}
						}
					}
				}
			}

			// else if server reports that item is not valid.  Assign item
			// error for return:
			else
			{
				hr = pErrors [0];
			}
		}

		// Catch exceptions:
		catch (...)
		{
			// Probably something wrong with interface pointer, so invalidate it:
			m_pIItemMgt = NULL;

			// Update dialog control status:
			UpdateStatus ();
		}

		// Free allocations (COM requires us to do this):
		CoTaskMemFree (pItems);

		if (pszItemID)
			CoTaskMemFree (pszItemID);

		if (pszAccessPath)
			CoTaskMemFree (pszAccessPath);

		if (pResults)
			CoTaskMemFree (pResults);

		if (pErrors)
			CoTaskMemFree (pErrors);
	}

	// Return validation return code:
	return (hr);
}

⌨️ 快捷键说明

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