📄 itemview.cpp
字号:
// Add a separator if we have already added menu items:
if (cMenu.GetMenuItemCount () > 0)
cMenu.AppendMenu (MF_SEPARATOR);
// Add Cut menu item:
pMainMenu->GetMenuString (ID_EDIT_CUT, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_EDIT_CUT, strMenuText);
// Add Copy menu item:
pMainMenu->GetMenuString (ID_EDIT_COPY, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_EDIT_COPY, strMenuText);
// Add Paste menu item:
pMainMenu->GetMenuString (ID_EDIT_PASTE, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_EDIT_PASTE, strMenuText);
// Add Delete menu item:
pMainMenu->GetMenuString (ID_EDIT_DELETE, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_EDIT_DELETE, strMenuText);
// Add separator:
cMenu.AppendMenu (MF_SEPARATOR);
// Add Properties menu item:
pMainMenu->GetMenuString (ID_EDIT_PROPERTIES, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_EDIT_PROPERTIES, strMenuText);
}
// If popup menu is not empty, display it at hit point:
if (cMenu.GetMenuItemCount () > 0)
cMenu.TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd ());
}
}
/////////////////////////////////////////////////////////////////////////////
// CKItemView list handlers
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// Insert ()
//
// Description:
// Insert an item into view.
//
// Parameters:
// CKItem *pItem Pointer to item object to add.
//
// Returns:
// void
// **************************************************************************
void CKItemView::Insert (CKItem *pItem)
{
// 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_cnSortedItems == m_nSortedListSize)
{
DWORD *p = NULL;
// Be prepared to deal with allocation problems (p will be NULL in
// this event):
try
{
// Allocate the next largest size:
p = new DWORD [m_nSortedListSize + GROWLIST];
// Initialize new memory:
ZeroMemory (p, sizeof (sm_pSortedItemList [0]) * (m_nSortedListSize + GROWLIST));
// Transfer existing items to the new memory:
if (m_cnSortedItems)
{
// Copy old to new:
memcpy (p, sm_pSortedItemList, m_cnSortedItems * sizeof (sm_pSortedItemList [0]));
// Free old memory:
delete [] sm_pSortedItemList;
}
// Point to new list:
sm_pSortedItemList = p;
// Increment allocated list size:
m_nSortedListSize += GROWLIST;
}
catch (...)
{
p = NULL;
}
}
// Add the item to the sorted list:
sm_pSortedItemList [m_cnSortedItems++] = (DWORD)pItem;
}
// **************************************************************************
// DeleteAllItems ()
//
// Description:
// Delete all items.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemView::DeleteAllItems ()
{
// 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 our list control:
CListCtrl &cList = GetListCtrl ();
// Reset sorted item list:
ZeroMemory (sm_pSortedItemList,
sizeof (sm_pSortedItemList[0]) * (m_nSortedListSize));
// Reset sorted item counter:
m_cnSortedItems = 0;
// Set the list control item count to zero. (This is how it must
// be done for virtual list view style. See comments in PreCreateWindow ()).
cList.SetItemCountEx (0, LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
// Force a repaint of the view:
cList.Invalidate (true);
cList.UpdateWindow ();
}
// **************************************************************************
// OnGetDispInfo ()
//
// Description:
// Handle notification to fill item information for display.
//
// Parameters:
// NMHDR *pNMHDR Contains information about a notification message.
// LRESULT *pResult A 32-bit value returned from a window procedure
// or callback function.
//
// Returns:
// void
// **************************************************************************
void CKItemView::OnGetDispInfo (NMHDR *pNMHDR, LRESULT *pResult)
{
// 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_pSortedItemList == NULL || m_cnSortedItems == 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_cnSortedItems)
return;
// Get pointer to CKItem object from sorted item list:
CKItem *pItem = (CKItem *)sm_pSortedItemList [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 ID
lstrcpyn (plvItem->pszText, pItem->GetItemID (), plvItem->cchTextMax);
break;
case 1: // Data Type
{
// Convert data type to string:
static CString strDataType;
StringFromVartype (pItem->GetDataType (), strDataType);
lstrcpyn (plvItem->pszText, strDataType, plvItem->cchTextMax);
}
break;
case 2: // Value
{
static CString strValue;
pItem->GetValue (strValue);
lstrcpyn (plvItem->pszText, strValue, plvItem->cchTextMax);
}
break;
case 3: // Timestamp
{
static CString strTimestamp;
pItem->GetTimeStamp (strTimestamp);
lstrcpyn (plvItem->pszText, strTimestamp, plvItem->cchTextMax);
}
break;
case 4: // Quality
lstrcpyn (plvItem->pszText, pItem->GetQuality (), plvItem->cchTextMax);
break;
case 5: // 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 specify invalid item image:
else
plvItem->iImage = 2;
}
}
// **************************************************************************
// OnToolTipText
//
// Description:
// Called by framework when tool tip text needs to be defined.
//
// Parameters:
// UINT uID Identifier of the control that sent the notification.
// NMHDR *pNMHDR Contains information about a notification message.
// LRESULT *pResult A 32-bit value returned from a window procedure
// or callback function.
//
// Returns:
// BOOL - FALSE.
// **************************************************************************
BOOL CKItemView::OnToolTipText (UINT uID, NMHDR *pNMHDR, LRESULT *pResult)
{
// Get pointers for output text:
TOOLTIPTEXTA *pTTTA = (TOOLTIPTEXTA *) pNMHDR;
TOOLTIPTEXTW *pTTTW = (TOOLTIPTEXTW *) pNMHDR;
CString strText;
int nRow = 0;
int nCol = 0;
// Get ID of cell tool tip is needed for:
UINT nID = pNMHDR->idFrom;
// Get reference to our list control:
CListCtrl &cList = GetListCtrl ();
// Filter automatically created tip with ID 0:
if (nID == 0)
return (FALSE);
// Decode the row and column from the ID we created earlier in OnToolHitTest():
nRow = ((nID - 1) >> 10) & 0x3FFFFFF;
nCol = (nID - 1) & 0x3FF;
// Get the text from this cell:
strText = cList.GetItemText (nRow, nCol);
// Whether or not this application has been built for unicode or ansi is
// irrelevant. We need to pass the tootip text based on the request from
// the OS.
// Set the text:
#ifndef _UNICODE
// This is an ANSI build.
// If request is for ANSI, just copy string:
if (pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn (pTTTA->szText, strText, sizeof (pTTTA->szText) / sizeof (char));
// Else request is for UNICODE, so convert from ANSI:
else
_mbstowcsz (pTTTW->szText, strText, sizeof (pTTTW->szText) / sizeof (WCHAR));
#else
// This is a UNICODE build.
// If request is for ANSI, convert from UNICODE:
if (pNMHDR->code == TTN_NEEDTEXTA)
_wcstombsz (pTTTA->szText, strText, sizeof (pTTTA->szText) / sizeof (char));
// Else request is for UNICODE, so just copy string:
else
lstrcpyn (pTTTW->szText, strText, sizeof (pTTTW->szText) / sizeof (WCHAR));
#endif
*pResult = 0;
return (FALSE);
}
// **************************************************************************
// OnColumnClick ()
//
// Description:
// List control column header click event handler. Sort the items based
// on values in column.
//
// Parameters:
// NMHDR *pNMHDR Contains information about a notification message.
// LRESULT *pResult A 32-bit value returned from a window procedure
// or callback function.
//
// Returns:
// void
// **************************************************************************
void CKItemView::OnColumnClick (NMHDR *pNMHDR, LRESULT *pResult)
{
// 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;
// Get column index from message notification structure:
WORD wColumn = ((NM_LISTVIEW *)pNMHDR)->iSubItem;
// Record change in sorting parameters:
// If same sort column selected, toggle the sort order:
if (wColumn == sm_wSortColumn)
sm_wSortOrder = !sm_wSortOrder;
// Else sort using data in new sort column:
else
sm_wSortColumn = wColumn;
// Sort the list using new column and order settings:
SortList ();
}
// **************************************************************************
// 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 CKItemView::CompareItems (const void *arg1, const void *arg2)
{
// Initialize a variable to contain comparison result:
int nRC = 0;
// Cast arguments to CKItem pointers (this what the calling routine
// is really comparing).
CKItem *pItem1 = (CKItem *)(*(DWORD *)arg1);
CKItem *pItem2 = (CKItem *)(*(DWORD *)arg2);
// Sort based on the column parameter passed to SortItems():
switch (sm_wSortColumn)
{
case 0: // Item ID
// Item ID is a string, so do a simple string compare:
nRC = lstrcmp (pItem1->GetItemID (), pItem2->GetItemID ());
break;
case 1: // Data Type
{
// Must get data types and convert them to strings:
static CString strType1;
static CString strType2;
StringFromVartype (pItem1->GetDataType (), strType1);
StringFromVartype (pItem2->GetDataType (), strType2);
// Now compare strings:
nRC = lstrcmp (strType1, strType2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -