catlistbox.cpp

来自「vc++的部分比较经典的源码」· C++ 代码 · 共 996 行 · 第 1/3 页

CPP
996
字号
         if ((*iter).first.CompareNoCase( pCategory ) > 0) {
            if ((UINT)pCatInfo->iListIndex > (UINT)pTempInfo->iListIndex)
               pCatInfo->iListIndex = pTempInfo->iListIndex;
            pTempInfo->iListIndex++;      // Increment index of all following categories.
         }
      }
   }
   m_bDoDraw = false;      // Disables listbox drawing.
   pCatInfo->iListIndex = InsertString( pCatInfo->iListIndex, pCategory );
   SetItemData( pCatInfo->iListIndex, (DWORD)pCatInfo );
   m_bDoDraw = true;       // Enables listbox drawing. Must wait for SetItemData() to be called.
   Invalidate();

   return S_OK;
}

// Adds an item under the specified category. Creates category if it hasn't already been added.
// Also sets the item's state. 0 = Unchecked checkbox. 1 = Checked checkbox. 2 = No checkbox.
// Returns the category item index to the new string or LB_ERR if the add failed.
int CCatListBox::AddCategoryItem( LPCTSTR pCategory, LPCTSTR pItem, int iState /*=2*/ )
{
   CatListBoxCatInfo*      pCatInfo;
   CatListBoxItemInfo      ItemInfo;
   CatListBoxStlListIter   iter;
   int                     iItemIndex = 0;
   int                     iListIndex;

   // Validate argument.
   if (!pCategory)
      return LB_ERR;

   // Get category
   pCatInfo = GetCategoryInfo( pCategory );
   if (!pCatInfo) {
      // Category not found. Add it to map.
      if (S_OK != AddCategory( pCategory ))
         return LB_ERR;
      pCatInfo = GetCategoryInfo( pCategory );
      if (!pCatInfo)
         return LB_ERR;
   }

   // Add string to category's STL list.
   if (LBS_SORT & GetStyle()) {
      iItemIndex = 0;
      for (iter = pCatInfo->lstItems.begin(); iter != pCatInfo->lstItems.end(); iter++) {
         if ((*iter).sItem.CompareNoCase( pItem ) > 0)
            break;
         iItemIndex++;
      }
   }
   else {
      iter       = pCatInfo->lstItems.end();
      iItemIndex = pCatInfo->lstItems.size();
   }
   ItemInfo.dwValue = 0;
   ItemInfo.iState  = iState;
   ItemInfo.sItem   = pItem;
   pCatInfo->lstItems.insert( iter, ItemInfo );

   // Add string to listbox if its category is open.
   if (pCatInfo->bIsOpen) {
      // Add string.
      m_bDoDraw = false;      // Disables listbox drawing.
      iListIndex = pCatInfo->iListIndex + iItemIndex + 1;
      iListIndex = InsertString( iListIndex, pItem );
      if (iListIndex >= 0) {
         SetItemData( iListIndex, (DWORD)pCatInfo );
         UpdateCategoryIndexes( pCatInfo->iListIndex, 1 );
      }
      m_bDoDraw = true;       // Enables listbox drawing. Wait for SetItemData() to be called.
      Invalidate();
   }

   return iItemIndex;
}

// Overloaded and made protected to prevent this function from being called from outside.
// Must use AddCategoryItem(pCategory,pItem) instead.
int CCatListBox::AddString( LPCTSTR pString )
{
   return CListBox::AddString( pString );
}

// Overloaded and made protected to prevent this function from being called from outside.
int CCatListBox::InsertString( int iListIndex, LPCTSTR pString )
{
   return CListBox::InsertString( iListIndex, pString );
}


//////////////////////////////////////////////////////////////////////
// Delete functions.
//////////////////////////////////////////////////////////////////////

// Deletes the indexed listbox item.
// If the index points to a category's item, then only that item is deleted.
// If the index points to a category, then that category and all of its items are deleted.
HRESULT CCatListBox::Delete( int iListIndex )
{
   CatListBoxCatInfo*   pInfo;
   CString              sCategory;
   HRESULT              hr = E_FAIL;

   // Validate argument.
   if ((iListIndex < 0) || (iListIndex >= GetCount()))
      return E_INVALIDARG;

   // Get category's info.
   pInfo = (CatListBoxCatInfo*)GetItemData( iListIndex );
   if (!pInfo)
      return E_FAIL;

   // Delete indexed listbox item.
   GetText( pInfo->iListIndex, sCategory );
   if (iListIndex == pInfo->iListIndex)
      hr = DeleteCategory( (LPCTSTR)sCategory );
   else
      hr = DeleteCategoryItem( (LPCTSTR)sCategory, (iListIndex - pInfo->iListIndex) - 1 );
   return hr;
}

// Deletes specified category and all of its items.
HRESULT CCatListBox::DeleteCategory( LPCTSTR pCategory )
{
   CatListBoxCatInfo*      pInfo;
   CatListBoxStlMapIter    iter;
   int                     iCount = 0;

   // Validate argument.
   if (!pCategory)
      return E_POINTER;

   // Get category's info.
   iter = m_mapCat.find( CString( pCategory ) );
   if (iter == m_mapCat.end())
      return E_INVALIDARG;
   pInfo = (*iter).second;
   if (!pInfo)
      return E_INVALIDARG;

   // Delete category and its items from listbox.
   m_bDoDraw = false;      // Disables listbox drawing.
   while ((CatListBoxCatInfo*)GetItemData( pInfo->iListIndex ) == pInfo) {
      DeleteString( pInfo->iListIndex );
      iCount++;
   }
   UpdateCategoryIndexes( pInfo->iListIndex, 0 - iCount );
   m_bDoDraw = true;       // Enables listbox drawing. Clears listbox strings all at once.
   Invalidate();

   // Delete category from STL map.
   delete pInfo;
   (*iter).second = NULL;
   m_mapCat.erase( iter );
   return S_OK;
}

// Deletes indexed category item.
HRESULT CCatListBox::DeleteCategoryItem( LPCTSTR pCategory, int iItemIndex )
{
   CatListBoxCatInfo*      pInfo;
   CatListBoxStlListIter   iter;
   int                     iValue;

   // Validate argument.
   if (!pCategory)
      return E_POINTER;

   // Get category's info.
   pInfo = GetCategoryInfo( pCategory );
   if (!pInfo)
      return E_INVALIDARG;

   // Do not continue if "iItemIndex" exceeds list's bounds.
   if ((iItemIndex < 0) || (iItemIndex >= pInfo->lstItems.size()))
      return E_INVALIDARG;

   // Delete string in listbox if its category is open.
   if (pInfo->bIsOpen) {
      m_bDoDraw = false;   // Disables listbox drawing.
      iValue = pInfo->iListIndex + iItemIndex + 1;
      DeleteString( iValue );
      UpdateCategoryIndexes( iValue, -1 );
      m_bDoDraw = true;    // Enables listbox drawing. Wait for category index update.
      Invalidate();
   }

   // Find item in category's list.
   // Delete item from category's list.
   iValue = 0;
   for (iter = pInfo->lstItems.begin(); iter != pInfo->lstItems.end(); iter++) {
      if (iValue == iItemIndex)
         break;
      iValue++;
   }
   pInfo->lstItems.erase( iter );
   return S_OK;
}

// Overloaded and made protected to prevent this function from being called from outside.
// Must use DeleteCategoryItem(pCategory,pItem) instead.
int CCatListBox::DeleteString( UINT iListIndex )
{
   return CListBox::DeleteString( iListIndex );
}


//////////////////////////////////////////////////////////////////////
// Reset functions.
//////////////////////////////////////////////////////////////////////

// Empties listbox.
void CCatListBox::ResetContent()
{
   // Empty listbox.
   CListBox::ResetContent();

   // Empty STL map.
   ResetCategoryInfo();
}

// Empties category STL map.
void CCatListBox::ResetCategoryInfo()
{
   CatListBoxStlMapIter    iter;
   CatListBoxCatInfo*      pCatInfo;

   for (iter = m_mapCat.begin(); iter != m_mapCat.end(); iter++) {
      if (pCatInfo = (*iter).second) {
         delete pCatInfo;
         (*iter).second = NULL;
      }
   }
   m_mapCat.clear();
}


//////////////////////////////////////////////////////////////////////
// Find functions.
//////////////////////////////////////////////////////////////////////

// Returns specified category's listbox index or -1 if not found.
int CCatListBox::FindCategory( LPCTSTR pCategory )
{
   CatListBoxCatInfo* pInfo = GetCategoryInfo( pCategory );
   return (pInfo) ? pInfo->iListIndex : -1;
}

// Finds the first item string exactly matching "pItem" in the category's list.
// Will search after index "iStartAfter" in list. Set "iStartAfter" to -1 to search entire list.
// Returns the category item's index or -1 if not found. (Does not return listbox index!)
int CCatListBox::FindCategoryItem( LPCTSTR pCategory, int iStartAfter, LPCTSTR pItem )
{
   CatListBoxCatInfo*      pInfo;
   CatListBoxStlListIter   iter;
   int                     iCount = 0;

   // Validate arguments.
   if (!pCategory || !pItem)
      return -1;

   // Get category's info.
   pInfo = GetCategoryInfo( pCategory );
   if (!pInfo)
      return -1;

   // Find item in category's list.
   for (iter = pInfo->lstItems.begin(); iter != pInfo->lstItems.end(); iter++) {
      if (iCount > iStartAfter) {
         if (0 == (*iter).sItem.Compare( pItem )) {
            return iCount;
         }
      }
      iCount++;
   }
   return -1;
}


//////////////////////////////////////////////////////////////////////
// Is functions.
//////////////////////////////////////////////////////////////////////

// Returns TRUE if listbox index references a category.
bool CCatListBox::IsCategory( int iListIndex )
{
   CatListBoxCatInfo* pInfo = (CatListBoxCatInfo*)GetItemData( iListIndex );
   if (pInfo && (LB_ERR != (int)pInfo)) {
      if (iListIndex == pInfo->iListIndex) {
         return true;
      }
   }
   return false;
}

// Returns TRUE if specified string is a category name.
bool CCatListBox::IsCategory( LPCTSTR pString )
{
   return (FindCategory( pString ) >= 0) ? true : false;
}

// Returns TRUE if the specified category is open.
// Returns FALSE if closed or if category does not exist.
bool CCatListBox::IsCategoryOpen( LPCTSTR pCategory )
{
   CatListBoxCatInfo* pInfo = GetCategoryInfo( pCategory );
   if (pInfo) {
      if (pInfo->bIsOpen) {
         return true;
      }
   }
   return false;
}


//////////////////////////////////////////////////////////////////////
// Get functions.
//////////////////////////////////////////////////////////////////////

// Returns the number of categories stored in this listbox.
int CCatListBox::GetCategoryCount()
{
   return m_mapCat.size();
}

// Returns the category's name specified by the given index.
// If "bIsListIndex" = TRUE, then "iIndex" references the listbox.
// If "bIsListIndex" = FALSE, then "iIndex" references the category list.
// (The total number of categories can be retrieved via GetCategoryCount().)
LPCTSTR CCatListBox::GetCategoryName( int iIndex, bool bIsListIndex /*=true*/ )
{

⌨️ 快捷键说明

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