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

📄 tyopcclientview.cpp

📁 OPC Client 源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	int nColumnCount = cListCtrl.GetHeaderCtrl()->GetItemCount();

	int nItem=0;
	CString strText;
      cListCtrl.InsertItem(LVIF_TEXT|LVIF_STATE, nItem, strText, 
      LVIS_SELECTED , LVIS_SELECTED,
      0, 0);

	  int nIndex=1;
	// Item ID
	cListCtrl.SetItemText (nItem,nIndex++,pItem->GetItemID ());
	// Data Type
	cListCtrl.SetItemText (nItem,nIndex++,pItem->GetDataType());
	// Value
	cListCtrl.SetItemText (nItem,nIndex++,pItem->GetValue(pItem->GetValue()));
	// Timestamp
	cListCtrl.SetItemText (nItem,nIndex++,pItem->GetTimeStamp ());
	// Quality
	cListCtrl.SetItemText (nItem,nIndex++,pItem->GetQuality ());
	// Update Count
	cListCtrl.SetItemText (nItem,nIndex++,pItem->GetUpdateCount ());


//*/
	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csSortedList);

	// Make sure item pointer was set (debuf only):
	ASSERT (pItem != NULL);

	// If sorted item list is full, we need to allocate another block of
	// memory big enough for current list plus room for more items and
	// transfer current list to it:
	if (m_nSortedItems == m_nSortedListSize)
	{
		DWORD *pSortList = NULL;

		// Be prepared to deal with allocation problems (p will be NULL in
		// this event):
		try
		{
			// Allocate the next largest size:
			pSortList = new DWORD [m_nSortedListSize + GROWLIST];

			// Initialize new memory:
			ZeroMemory (pSortList, sizeof (sm_pSortedItems [0]) * (m_nSortedListSize + GROWLIST));

			// Transfer existing items to the new memory:
			if (0<m_nSortedItems)	//存在COPCItem数据
			{
				// Copy old to new:
				memcpy (pSortList, sm_pSortedItems, m_nSortedItems * sizeof (sm_pSortedItems [0]));

				// Free old memory:
				delete [] sm_pSortedItems;
				sm_pSortedItems=NULL;
			}

			// Point to new list:
			sm_pSortedItems = pSortList;

			// Increment allocated list size:
			m_nSortedListSize += GROWLIST;
			}
		
		catch (...)
		{
			pSortList = NULL;
		}
	}

	// Add the item to the sorted list:
	sm_pSortedItems [m_nSortedItems++] = (DWORD)pItem;
//*/
}



void CViewOPCItem::OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult) 
{
//	HD_NOTIFY * phdn = (HD_NOTIFY *) pHNMHDR;
	// TODO: Add your control notification handler code here

	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csSortedList);

	// Cast generic notification message pointer to list view notification
	// message pointer:
	LV_DISPINFO *plvdi = (LV_DISPINFO *)pNMHDR;

	// Get pointer to list view item information structure from message
	// notification structure:
	LV_ITEM *plvItem = &plvdi->item;

	// If there are no items in the sorted item list, then there is no
	// work to be done here.
	if (sm_pSortedItems == NULL	//数据项地址数组
		|| m_nSortedItems == 0		//数据项地址数组中无数组
		)
		return;

	// If index of item we are being ased to supply information for is 
	// greater than the number of items in our sorted item list, then
	// there is something wrong.  Return immediately.
	if (plvItem->iItem >= m_nSortedItems)
	{	//存在一个错误----可能程序计算错误
		return;
	}

	// Get pointer to COPCItem object from sorted item list:
	COPCItem *pItem = (COPCItem *)sm_pSortedItems [plvItem->iItem];
	ASSERT (pItem != NULL);

	// If we are being asked to supply item text:
	if (plvItem->mask & LVIF_TEXT)
		{
		// See what subitem (column) text is needed for.  Copy requested
		// text to output structure:
		switch (plvItem->iSubItem)
			{
			case 0:	// Item Alias
				{
//				TRACE("CViewOPCItem::OnGetDispInfo()--%s\n",pItem->GetItemID ());
 				lstrcpyn (plvItem->pszText, pItem->GetAlias (), plvItem->cchTextMax);
				break;
				}
			case 1:	// Item ID
				{
//				TRACE("CViewOPCItem::OnGetDispInfo()--%s\n",pItem->GetItemID ());
 				lstrcpyn (plvItem->pszText, pItem->GetItemID (), plvItem->cchTextMax);
				break;
				}
			case 2:	// Data Type
				{
				// Convert data type to string:
				static CString strDataType;
				pItem->GetDataType (strDataType);

				lstrcpyn (plvItem->pszText, strDataType, plvItem->cchTextMax);
				break;
				}
			case 3:	// Value
				{
				static CString strValue;
				pItem->GetValue (strValue);

				lstrcpyn (plvItem->pszText, strValue, plvItem->cchTextMax);
				break;
				}
			case 4:	// Timestamp
				{
				static CString strTimeStamp;
				pItem->GetTimeStamp (strTimeStamp);
				lstrcpyn (plvItem->pszText, strTimeStamp, plvItem->cchTextMax);
				break;
				}
			case 5: // Quality
				{
				static CString strQuality;
				pItem->GetQuality (strQuality);
				lstrcpyn (plvItem->pszText, strQuality, plvItem->cchTextMax);
				break;
				}
			case 6: // Active
				{
				static CString strActive;

				if(pItem->IsActive ())
					strActive=_T("√");
				else
					strActive=_T("×");

				lstrcpyn (plvItem->pszText, strActive, plvItem->cchTextMax);
				break;
				}
			case 7:	// Update Count
				{
				// Format numerical value as string:
				TCHAR szNum [64];
				wsprintf (szNum, _T("%u"), pItem->GetUpdateCount ());
				
				lstrcpyn (plvItem->pszText, szNum, plvItem->cchTextMax);
				break;
				}
			default:
				break;
			}
		}

	// If we are being asked to supply item image.  Return index into
	// list control's image list:
	if (plvItem->mask & LVIF_IMAGE)
	{
		// If item is valid, specify active or inactive item image
		// as the case may be.
//		if (pItem->IsValid ())
			plvItem->iImage = pItem->IsActive () ? 0 : 1;
//		else		// Else specify invalid item image:
//			plvItem->iImage = 2;
	}

	*pResult = 0;
}

void CViewOPCItem::SortItems()
{
	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csSortedList);

	// Get reference to out list control:
	CListCtrl &cList = GetListCtrl ();

	// If there are no items in the list, then there is nothing to do:
	if (0>=m_nSortedItems)	
		return;

	// Get number of selected items:
	int cnSelections = cList.GetSelectedCount ();

	// Initialize a variable to contain the index of item with focus:
	int nFocus = -1;

	// Save off selected items so we can restore them after sort:
	CMemFile cMem (cnSelections * sizeof (DWORD));
	
	// Don't bother looking for selected items if there are none:
	if (cnSelections)
		{
		// Find the first selected item:
		int nSel = cList.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);

		// Save the items index if it has the focus:
		if (cList.GetItemState (nSel, LVIS_FOCUSED) == LVIS_FOCUSED)
			nFocus = sm_pSortedItems [nSel];

		// Clear the selection and store off the array element (pointer
		// to COPCItem object):
		cList.SetItemState (nSel, 0, LVIS_SELECTED | LVIS_FOCUSED);
		cMem.Write (&sm_pSortedItems [nSel], sizeof (DWORD));
		
		// Store off remaining selections:
		int n = cnSelections;
		
		while (--n)
			{
			// Get index of next selected item:
			nSel = cList.GetNextItem (nSel, LVNI_BELOW | LVNI_SELECTED);
			ASSERT (nSel != -1);
	
			// Store it's index if it has the focus:
			if (nFocus == -1 && cList.GetItemState (nSel, LVIS_FOCUSED) == LVIS_FOCUSED)
				nFocus = sm_pSortedItems [nSel];

			// Clear the selection and store off the index:
			cList.SetItemState (nSel, 0, LVIS_SELECTED | LVIS_FOCUSED);
			cMem.Write (&sm_pSortedItems [nSel], sizeof (DWORD));
			}
		}

	// Sort the list.  qsort function requires us to define a function to
	// compare items.
	qsort ((void *)sm_pSortedItems, m_nSortedItems, 
		sizeof (sm_pSortedItems [0]), CompareItems);

	// Now restore original selections:
	if (cnSelections)
		{
		// Reset file pointer to beginning:
		cMem.SeekToBegin ();

		// There is one unsorted index in the memory file for each 
		// selection detected above:
		for (int i = 0; i < cnSelections; i++)
			{
			// Read the index (actually pointer to COPCItem object cast as DWORD)
			// of first selected item:
			DWORD dwIndex;
			cMem.Read (&dwIndex, sizeof (DWORD));

			// Find the item's location in the sorted array.  Look at each
			// element in array until we find the item:
			for (int j = 0; j < m_nSortedItems; j++)
				{
				// We have found the item if the array element is the original index:
				if (sm_pSortedItems [j] == dwIndex)
					{
					// Make sure the focused item is visible:
					if (dwIndex == (DWORD)nFocus)
						{
						cList.EnsureVisible (j, false);
						cList.SetItemState (j, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
						}
					
					// Restore selection:
					else
						cList.SetItemState (j, LVIS_SELECTED, LVIS_SELECTED);
					
					// If we are here, we found the item.  No need to continue
					// searching so break out of loop.
					break;
					}
				}
			}
		}

	// Force the list control to repaint itself:
	GetListCtrl ().Invalidate (true);
}

// **************************************************************************
// CompareItems ()
//
// Description:
//	Compares the order of items when sorting by values in one of the list
//	control columns.  Used by the qsort function, so we need to declare
//	parameters as void pointers.
//
// Parameters:
//  const void	*arg1		Pointer to the first items.
//	const void	*arg2		Pointer to the second item.
//
// Returns:
//  int - Returns a negative number if the arg1 comes first, 0 if arg1 and
//	arg2 are the same, or a positive value if arg2 comes first.
// **************************************************************************
int CViewOPCItem::CompareItems(const void *arg1, const void *arg2)
{
	// Initialize a variable to contain comparison result:
	int nRC = 0;

	// Cast arguments to COPCItem pointers (this what the calling routine
	// is really comparing).
	COPCItem *pItem1 = (COPCItem *)(*(DWORD *)arg1);
	COPCItem *pItem2 = (COPCItem *)(*(DWORD *)arg2);

	// Sort based on the column parameter passed to SortItems():
	switch (sm_wSortColumn)
		{
		case 0: // Item Alias
			// Item Alias is a string, so do a simple string compare:
			nRC = lstrcmp (pItem1->GetAlias (), pItem2->GetAlias ());
			break;

		case 1: // Item ID
			// Item ID is a string, so do a simple string compare:
			nRC = lstrcmp (pItem1->GetItemID (), pItem2->GetItemID ());
			break;

		case 2:	// Data Type
			{
			// Must get data types and convert them to strings:
			static CString strType1;
			static CString strType2;
			
			pItem1->GetDataType (strType1);
			pItem2->GetDataType (strType2);

			// Now compare strings:
			nRC = lstrcmp (strType1, strType2);
			}
			break;

		case 3:	// Value
			{
			// Get string representation of values:
			static CString strValue1;
			static CString strValue2;
			
			pItem1->GetValue (strValue1);
			pItem2->GetValue (strValue2);

			// Compare strings:
			nRC = lstrcmp (strValue1, strValue2);
			}
			break;

		case 4:	// Timestamp
			{
			// Get string representation of timestamp:
			static CString strTimeStamp1;
			static CString strTimeStamp2;
			
			pItem1->GetTimeStamp (strTimeStamp1);
			pItem2->GetTimeStamp (strTimeStamp2);

			// Compare strings:
			nRC = lstrcmp (strTimeStamp1, strTimeStamp2);
			}
			break;

		case 5: // Quality
			{
			// Quality is a string, so do string compare:
			static CString strQuality1;
			static CString strQuality2;
			pItem1->GetQuality (strQuality1);
			pItem2->GetQuality (strQuality2);
			nRC = lstrcmp (strQuality1, strQuality2);
			break;
			}
		case 6: // Active
			{
			// Quality is a string, so do string compare:
			static BOOL bActive1;
			static BOOL bActive2;
			bActive1=pItem1->IsActive ();
			bActive2=pItem2->IsActive ();
			// Compare numerical update counts:
			if (bActive1 == bActive2)
				nRC = 0;
			else if (bActive1 > bActive2)
				nRC = -1;
			else
				nRC = 1;

			break;
			}
		case 7:	// Update Count
			{
			// Get update counts:
			DWORD dwUpdates1 = pItem1->GetUpdateCount ();
			DWORD dwUpdates2 = pItem2->GetUpdateCount ();

			// Compare numerical update counts:
			if (dwUpdates1 == dwUpdates2)
				nRC = 0;
			else if (dwUpdates1 > dwUpdates2)
				nRC = -1;
			else
				nRC = 1;
			}
			break;

		// Unexpected column index:
		default:
			ASSERT (FALSE);
			break;
		}

	// Equal items should be sorted by item ID:
	if (sm_wSortColumn && nRC == 0)
		nRC = lstrcmp (pItem1->GetItemID (), pItem2->GetItemID ());

	// If the order is descending, reverse the result:
	if (LOWORD (sm_wSortOrder) == DESCENDING)
		nRC = -nRC;

	// Return the result:
	return (nRC);
}

void CViewOPCItem::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	
	// Process according to timer event type:
	switch (nIDEvent)
		{
		// Update the item pane.  This will cause the items' value,
		// quality, timestamp, etc. to get refreshed.
		case UPDATE_ITEMPANE_EVENT:
			{
			// Get reference to our list control:
			CListCtrl &cList = GetListCtrl ();

			// If there are items in the list control, update the view:
			if (cList.GetItemCount () > 0)
				{
				int nTopIndex;
				CRect rc;
				CRect rcitem;
				
				// Get index of the first visible item:
				nTopIndex = cList.GetTopIndex ();

				// Get client area rectangle.  We will modify this rectangle to 
				// only include the area of the view we wish to refresh.
				cList.GetClientRect (&rc);

				// Get rectangel that bounds top visible item:
				cList.GetItemRect (nTopIndex, &rcitem, LVIR_BOUNDS);

				// Reset left bound of rc to exclude first column.  There 
				// is no need to refresh this (item ID and image).  We are 
				// interested in refreshing all other properties/columns.
				rc.left = cList.GetColumnWidth (0);

				// No need to refresh anything above top of uppermost item:

⌨️ 快捷键说明

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