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

📄 group.cpp

📁 KepWare的OPC Client 示例.面向C
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			pItem->SetItemID (szFieldText);
			break;

		case CSV_AccessPath:
			// Item Access Path:
			pItem->SetAccessPath (szFieldText);
			break;

		case CSV_DataType:
			// Item Data Type.  (Need to convert string to variant type.)
			pItem->SetDataType (VartypeFromString (szFieldText));
			break;

		case CSV_Active:
			// Item Active state.  (Need to convert string to bool type.)
			if (lstrcmpi (szFieldText, _T("TRUE")) == 0)
				pItem->SetActive (true);
			else
				pItem->SetActive (false);
			break;
		
		default:
			// Unexpected field type ID.  Programmer error.
			ASSERT (FALSE);
			break;
		}
	}


/////////////////////////////////////////////////////////////////////////////
// CKGroup construction/destruction
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// CKGroup ()
//
// Description:
//	Constructor.
//
// Parameters:
//  CKServer	*pParent	Pointer to parent server object
//
// Returns:
//  none
// **************************************************************************
CKGroup::CKGroup (CKServer *pParent)
	{
	ASSERT (pParent != NULL);
	m_pServer = pParent;

	// Initialize member variables.

	// OPC Group properties:
	m_strName			= GROUP_DEFAULT_NAME;
	m_dwUpdateRate		= GROUP_DEFAULT_UPDATERATE;	
	m_dwLanguageID		= GROUP_DEFAULT_LANGUAGEID;	
	m_lBias				= GROUP_DEFAULT_TIMEBIAS;
	m_fDeadband			= GROUP_DEFAULT_DEADBAND;
	m_bActive			= GROUP_DEFAULT_ACTIVESTATE;
	m_dwUpdateMethod	= GROUP_DEFAULT_UPDATEMETHOD;

	m_hServer		= NULL;
	m_bValid		= FALSE;

	// Flags:
	ZeroMemory (&m_bfFlags, sizeof (m_bfFlags));

	// Item management:
	m_pPrev = NULL;
	m_pNext = NULL;

	m_pItemHead = NULL;
	m_cdwItems = 0;

	// GUI management:
	m_hTreeItem = NULL;

	// Interface pointers we will query and maintain:
	m_pIGroupState			= NULL;
	m_pIPublicGroupState	= NULL;
	m_pIItemMgt				= NULL;
	m_pISync				= NULL;
	m_pIAsync				= NULL;
	m_pIDataObject			= NULL;
	m_pIAsync2				= NULL;		
	m_pIConnPtContainer		= NULL;

	m_pIDataSink20			= NULL;
	m_dwCookieDataSink20	= 0;

	m_pIAdviseSink			= NULL;
	m_dwCookieRead			= 0;
	m_dwCookieWrite			= 0;
	}

// **************************************************************************
// // ~CKGroup ()
//
// Description:
//	Destructor
//
// Parameters:
//  none
//
// Returns:
//  none
// **************************************************************************
CKGroup::~CKGroup ()
	{
	// Assert that all interfaces and items have been properly released:
	ASSERT (m_cdwItems == 0);

	ASSERT (m_pIGroupState == NULL);
	ASSERT (m_pIPublicGroupState == NULL);
	ASSERT (m_pIItemMgt == NULL);
	ASSERT (m_pISync == NULL);
	ASSERT (m_pIAsync == NULL);
	ASSERT (m_pIDataObject == NULL);
	ASSERT (m_pIAsync2 == NULL);
	ASSERT (m_pIConnPtContainer == NULL);
	
	ASSERT (m_pIDataSink20 == NULL);
	ASSERT (m_dwCookieDataSink20 == 0);

	ASSERT (m_pIAdviseSink == NULL);
	ASSERT (m_dwCookieRead == 0);
	ASSERT (m_dwCookieWrite == 0);
	}


/////////////////////////////////////////////////////////////////////////////
// CKGroup item management
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// AddItemToList ()
//
// Description:
//	Add an item to this group.
//	
// Parameters:
//  CKItem		*pItem		Pointer to item object to add.
//
// Returns:
//  void
// **************************************************************************
void CKGroup::AddItemToList (CKItem *pItem)
	{
	// New items are added to the head of the linked list.

	// That means new the items's "next" item is old head of list,
	pItem->SetNext (m_pItemHead);

	// and the new item is the old head of list's "previous" item,
	if (m_pItemHead)	
		m_pItemHead->SetPrev (pItem);
		
	// and that new item is now the new "head" of list.
	m_pItemHead = pItem;

	// Don't forget to bump up our local item count,
	++m_cdwItems;

	// and the global item count.
	UpdateItemCount (+1);
	}

// **************************************************************************
// RemoveItemFromList ()
//
// Description:
//	Remove an item from this group.
//
// Parameters:
//  CKItem		*pItem		Pointer to item object to remove.  If NULL, all
//							  items will be removed.
//
// Returns:
//  void
// **************************************************************************
void CKGroup::RemoveItemFromList (CKItem *pItem)
	{
	// Remove all items:
	if (pItem == NULL)
		{
		// Start with head of linked list and work our way up:
		pItem = m_pItemHead;

		// Loop over items until we hit the end of the list (where
		// pItem will be NULL).
		while (pItem)
			{
			// Must save the next item before we delete item.  The next
			// item will become the new head of list.
			m_pItemHead = pItem->GetNext ();

			// Delete item:
			delete pItem;

			// Process next item (the new head of list):
			pItem = m_pItemHead;
			}

		// Update global item count,
		UpdateItemCount (-(int)m_cdwItems);

		// and reset our local count,
		m_cdwItems = 0;
		}

	// Remove a single item:
	else
		{
		// To remove a link, we must first get pointers to the adjacent links:
		CKItem *pPrev = pItem->GetPrev ();
		CKItem *pNext = pItem->GetNext ();
		
		// If there is a "previous" link, then its "next" is removed link's "next",
		if (pPrev)	
			pPrev->SetNext (pNext);

		// and if there is a "next" link, then its "previous" is removed link's "previous",
		if (pNext)
			pNext->SetPrev (pPrev);

		// and if removed link was the "head", then the new head is removed link's "next".
		if (pItem == m_pItemHead)
			m_pItemHead = pNext;

		// Decrement our local item count,
		--m_cdwItems;

		// and the global item count.
		UpdateItemCount (-1);
		}
	}

// **************************************************************************
// AddItems ()
//
// Description:
//	Called to add multiple OPC Items at one time.  A CKItem will be added to
//  this object if	needed and a request to add a corresponding OPC Item to
//  the OPC Group will be made.
//
// Parameters:
//  CObArray	&cItemList		Array of item objects to add.
//	DWORD		dwCount			Number of items in cItemList.
//	bool		bLoadingProject Set to true if call is made during project 
//								  load so item can be added to this object's
//								  imem list.  Otherwise we will assume item
//								  already exists in list, and only needs to
//								  added to OPC Group.
//
// Returns:
//  void
// **************************************************************************
void CKGroup::AddItems (CObArray &cItemList, DWORD dwCount, bool bLoadingProject /* = false */)
	{
	CKItem *pItem = NULL;
	DWORD dwIndex = 0;

	ASSERT (dwCount > 0);

	// If the item is new add it to our list:
	if (!bLoadingProject)
		{
		// Add the list of items to our project whether we they are valid or not:
		for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
			{
			// Get pointer to item in input array:
			pItem = (CKItem *) cItemList [dwIndex];
			ASSERT (pItem != NULL);

			// Add it to our list:
			AddItemToList (pItem);
			}
		}

	// If we are connected to an OPC Server, and have a pointer to its IOPCItemMgt
	// interface, then issue an "add items" request:
	if ((m_pServer->IsConnected ()) && (m_pIItemMgt != NULL))
		{
		HRESULT hr;
		OPCITEMDEF *pItemArray = NULL;
		OPCITEMRESULT *pResults = NULL;
		HRESULT *pErrors = NULL;
		DWORD dwLen;
		DWORD cdwSuccess = 0;

		// Allocate memory for item definition array:
		pItemArray = (OPCITEMDEF *) CoTaskMemAlloc (dwCount * sizeof (OPCITEMDEF));

		// Don't bother if memory allocation failed:
		if (pItemArray != NULL)
			{
			// Fill the item definition array:
			for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
				{
				// Get pointer to item in input array:
				pItem = (CKItem *) cItemList [dwIndex];
				ASSERT (pItem != NULL);

				// COM requires that all string be in wide character format.  The
				// access path and Item ID properties are strings, so we may have
				// to convert their format.

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

				if (dwLen)
					{
					// Allocate memory for string:
					pItemArray [dwIndex].szAccessPath = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR));

#ifdef _UNICODE
					// If Unicode build, string will already be in wide character
					// format, so copy into allocated memory as is:
					lstrcpyn (pItemArray [dwIndex].szAccessPath,  pItem->GetAccessPath (), dwLen + 1);
#else
					// If ANSI build, then string format needs to be converted.  Place 
					// result of conversion into allocated memory:
					MultiByteToWideChar (CP_ACP, 0, pItem->GetAccessPath (), -1, pItemArray [dwIndex].szAccessPath, dwLen + 1);
#endif
					}
				else
					{
					// Access path string length is zero, so set output to NULL: 
					pItemArray [dwIndex].szAccessPath = NULL;
					}

				// Multibyte to wide character conversion for Item ID:
				dwLen = lstrlen (pItem->GetItemID ()); // This can't be zero, so no test as above
				pItemArray [dwIndex].szItemID = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR));

#ifdef _UNICODE
				lstrcpyn (pItemArray [dwIndex].szItemID, pItem->GetItemID (), dwLen + 1);
#else
				MultiByteToWideChar (CP_ACP, 0, pItem->GetItemID (), -1, pItemArray [dwIndex].szItemID, dwLen + 1);
#endif

				// Set remaining structure members:
				// (If requested data type is NULL, the OPC Server should return
				// the default type.  The returned canonical data type may not be
				// the same as the requested data type.)
				pItemArray [dwIndex].bActive = pItem->IsActive ();	// active state
				pItemArray [dwIndex].hClient = (OPCHANDLE) pItem;	// our handle to item
				pItemArray [dwIndex].dwBlobSize = 0;				// no blob support
				pItemArray [dwIndex].pBlob = NULL;
				pItemArray [dwIndex].vtRequestedDataType = pItem->GetDataType (); // Requested data type
				}

			// Issue request add items request through IOPCItemMgt interface:
			hr = m_pIItemMgt->AddItems (
					dwCount,		// Item count
					pItemArray,		// Array of item definition structures
					&pResults,		// Result array
					&pErrors);		// Error array

			// Check results for each item:
			for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
				{
				// Get pointer to item in input array:
				pItem = (CKItem *) cItemList [dwIndex];
				ASSERT (pItem != NULL);

				// Everything looks good:
				if (SUCCEEDED (hr) && (pErrors && SUCCEEDED (pErrors [dwIndex])))
					{
					// Set CKItem valid:
					pItem->SetValid (TRUE);

					// Update CKItem properties:
					// (Note, the returned canonical data type may not be the same
					// as the requested data type.)
					pItem->SetServerHandle (pResults [dwIndex].hServer);
					pItem->SetDataType (pResults [dwIndex].vtCanonicalDataType);
					pItem->SetAccessRights (pResults [dwIndex].dwAccessRights);

					// If the server passed back a blob, it is our responsibilty
					// to free it.  (Wrap with exception handler in case they were
					// bad and did not initialize the blob pointer.)
					try
						{
						if (pResults [dwIndex].pBlob != NULL)
							CoTaskMemFree (pResults [dwIndex].pBlob);
						}
					
					catch (...)
						{
						// Probably hit a bad pointer.  Try to process next item.
						TRACE (_T("OTC: AddItems exception thrown from freeing invalid blob.\r\n"));
						}

					// Bump success count:
					++cdwSuccess;
					}
				
				// There were errors:
				else
					{
					// Log error message:
					if (pErrors && FAILED (pErrors [dwIndex]))
						{
						// We have a good error array, so use it's HRESULT value.
						// (We could use GetErrorString() to get use friendly text if 
						// we wish.)
						LogMsg (IDS_GROUP_ADD_ITEMS_FAILED, pItem->GetItemID (), GetName (),
							pErrors [dwIndex]);
						}
					else
						{
						// Error array does not look good.  Use HRESULT value returned by add
						// item call.  (Again we could use the GetErrorString() if we wish.)
						LogMsg (IDS_GROUP_ADD_ITEMS_FAILED, pItem->GetItemID (), GetName (), hr);
						}

					// Set item invalid:
					pItem->SetValid (FALSE);

					// Use NULL server handle for invalid items:
					pItem->SetServerHandle (NULL);
					}

				// COM requires us to free memory allocated for [out] and [in/out]
				// arguments (i.e. access path and item id strings):
				if (pItemArray [dwIndex].szAccessPath)
					CoTaskMemFree (pItemArray [dwIndex].szAccessPath);

⌨️ 快捷键说明

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