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

📄 listviewctrlex.cpp

📁 beereader source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        break;

      case HDN_DIVIDERDBLCLICKW:
      case HDN_DIVIDERDBLCLICKA:
        if (m_bKeepLabelLeft &&
            (pNMHdr->iItem  > 0 && IndexToOrder(pNMHdr->iItem) == 0 ||
             pNMHdr->iItem == 0 && IndexToOrder(pNMHdr->iItem)  > 0))
        {
          // calculate needed column width
          int nOptWidth = 0;
          for (int nItem = m_pListCtrl->GetItemCount(); --nItem >= 0;)
          {
            int nWidth =
              m_pListCtrl->GetStringWidth(
                m_pListCtrl->GetItemText(nItem, pNMHdr->iItem));
            if (nWidth > nOptWidth) nOptWidth = nWidth;
          }

          if (pNMHdr->iItem > 0)
          {
            // add space for state icon and small icon
            CRect rcSubItem;
            if (GetRealSubItemRect(0, pNMHdr->iItem, LVIR_BOUNDS, rcSubItem))
            {
              CRect rcLabel;
              if (GetRealSubItemRect(0, pNMHdr->iItem, LVIR_LABEL, rcLabel))
                nOptWidth += rcLabel.left - rcSubItem.left;
            }

            // add left offset
            nOptWidth += m_nFirstColXOff;
          }
          else
            // add left offset
            nOptWidth += m_nNextColXOff;

          // add right offset
          nOptWidth += m_nNextColXOff;

          m_pListCtrl->SetColumnWidth(pNMHdr->iItem, nOptWidth);
          return true;
        }
        break;

      default:
        break;
    }

  return false;
}

/*** List control gains input focus ******************************************/
void CListBase::OnSetFocus() 
{
  ASSERT(m_pListCtrl);

	// manually set focus state so that custom drawing will function properly
  int nItem = m_pListCtrl->GetNextItem(-1, LVNI_SELECTED);
  if (nItem >= 0) m_pListCtrl->SetItemState(nItem, LVIS_FOCUSED, LVIS_FOCUSED);
}

/*** System colors have been changed *****************************************/
void CListBase::OnSysColorChange() 
{
  ASSERT(m_pListCtrl);
  ASSERT(m_pListCtrl->GetHeaderCtrl());

  // update color of sort icon
  m_imglstSortIcons.DeleteImageList         ();
  m_bmpUpArrow.DeleteObject                 ();
  m_bmpDownArrow.DeleteObject               ();
  CreateSortIcons                           ();
  m_pListCtrl->GetHeaderCtrl()->SetImageList(&m_imglstSortIcons);
  SetSortIcon                               ();

  // force update of column colors
  m_bColorSortColumn = !m_bColorSortColumn;
  ColorSortColumn(!m_bColorSortColumn);
}

/*** Assigns an image list to a list control *********************************/
CImageList* CListBase::SetImageList(CImageList* pImageList, int nImageList)
{
  ASSERT(m_pListCtrl);
  ASSERT(m_pListCtrl->GetHeaderCtrl());

  CImageList* pimglstPrev =
    m_pListCtrl->CListCtrl::SetImageList(pImageList, nImageList);

  if (nImageList == LVSIL_SMALL)
  {
    // restore image list with sort icons because default behavior is that the
    // header control shares its image list with the small icon list of the
    // list control
    m_pListCtrl->GetHeaderCtrl()->SetImageList(&m_imglstSortIcons);
  }

  return pimglstPrev;
}

/*** Private member functions ************************************************/

/*** Create image list with sort icons ***************************************/
void CListBase::CreateSortIcons()
{
  COLORMAP cm = {RGB(0, 0, 0), GetSysColor(COLOR_GRAYTEXT)};

  m_imglstSortIcons.Create     (9, 5, ILC_COLOR24 | ILC_MASK, 2, 0);
  m_bmpUpArrow.LoadMappedBitmap(IDB_HDRUP, 0, &cm, 1);
  m_nUpArrow = m_imglstSortIcons.Add(&m_bmpUpArrow, RGB(255, 255, 255));
  m_bmpDownArrow.LoadMappedBitmap(IDB_HDRDOWN, 0, &cm, 1);
  m_nDownArrow = m_imglstSortIcons.Add(&m_bmpDownArrow, RGB(255, 255, 255));
}

/*** Get all attributes of a given item or subitem ***************************/
LVITEM* CListBase::GetLVITEM(int nItem, int nSubItem) const
{
  ASSERT(m_pListCtrl);

  LVITEM* pItem = new LVITEM;

  pItem->mask      = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
  pItem->iItem     = nItem;
  pItem->iSubItem  = nSubItem;
  pItem->stateMask = ~0U;

  // enlarge text buffer gradually until it's large enough
  for (int nLen = 128; nLen += nLen;)
  {
    pItem->cchTextMax = nLen;
    pItem->pszText    = new TCHAR[nLen];
    if (!m_pListCtrl->GetItem(pItem))
    {
      delete[] pItem->pszText;
      delete pItem;
      return 0;
    }
    if (static_cast<int>(_tcslen(pItem->pszText)) < nLen-3) break;
    //                         ^
    // reserve extra space for two additional dots
    // to be added by "MakeShortString"
    delete[] pItem->pszText;
  }

  return pItem;
}

/*** Calculates the bounding rectangle of a subitem.                       ***/
/*** Difference to GetSubItemRect:                                         ***/
/*** If the bounding rectangle of subitem 0 is requested, the function     ***/
/*** returns the bounding rectangle of the label including the icons only, ***/
/*** not the bounding rectangle of the whole item.                         ***/
bool CListBase::GetRealSubItemRect(int iItem, int iSubItem, int nArea,
                                       CRect& ref)
{
  ASSERT(m_pListCtrl);
  ASSERT(iSubItem >= 0);

  switch (nArea)
  {
    case LVIR_BOUNDS:
      if (m_pListCtrl->GetSubItemRect(iItem, iSubItem, LVIR_BOUNDS, ref))
        if (iSubItem == 0)
        {
          CRect rcLabel;

          if (m_pListCtrl->GetSubItemRect(iItem, 0, LVIR_LABEL, rcLabel))
          {
            ref.right = rcLabel.right;

            int nOrder = IndexToOrder(0);
            if (nOrder > 0)
            {
              // The left edge of subitem 0 is identical with the right edge of
              // the subitem left of subitem 0.
              CRect rcSubItem;

              if (m_pListCtrl->GetSubItemRect(iItem, OrderToIndex(nOrder - 1),
                                              LVIR_BOUNDS, rcSubItem))
              {
                ref.left = rcSubItem.right;
                return true;
              }
            }
            else
              return true;
          }
        }
        else
          return true;
      break;

    case LVIR_ICON:
    {
      CRect rcIcon;           // rectangle bounding small icon of subitem 0  

      if (m_pListCtrl->GetSubItemRect(iItem, 0, LVIR_ICON, rcIcon))
      {
        CRect rcSubItem0;     // rectangle bounding subitem 0

        if (GetRealSubItemRect(iItem, 0, LVIR_BOUNDS, rcSubItem0))
          if (IndexToOrder(0) > 0 && m_bKeepLabelLeft)
          {
            int nIndex = OrderToIndex(0);

            if (GetRealSubItemRect(iItem, nIndex, LVIR_BOUNDS, ref))
            {
              int nSmallIconXOff = rcIcon.left - rcSubItem0.left;

              ref.left  += nSmallIconXOff;
              ref.right  = ref.left + rcIcon.Width();

              // clip rectangle at right edge if necessary
              int nWidth = m_pListCtrl->GetColumnWidth(nIndex);
              if (nSmallIconXOff + ref.Width() >= nWidth)
                ref.right = ref.left - nSmallIconXOff + nWidth - 1;
              return true;
            }
          }
          else
          {
            // clip rectangle at right edge if necessary
            if (rcIcon.right > rcSubItem0.right)
              rcIcon.right = rcSubItem0.right;
            ref = rcIcon;
            return true;
          }
      }
      break;
    }

    case LVIR_LABEL:
    {
      CRect rcLabel;          // rectangle bounding label of subitem 0

      if (m_pListCtrl->GetSubItemRect(iItem, 0, LVIR_LABEL, rcLabel))
      {
        CRect rcSubItem0;     // rectangle bounding subitem 0

        if (GetRealSubItemRect(iItem, 0, LVIR_BOUNDS, rcSubItem0))
          if (IndexToOrder(0) > 0 && m_bKeepLabelLeft)
          {
            if (GetRealSubItemRect(iItem, OrderToIndex(0), LVIR_BOUNDS, ref))
            {
              ref.left += rcLabel.left - rcSubItem0.left;
              return true;
            }
          }
          else
          {
            ref = rcLabel;
            return true;
          }
      }
      break;
    }

    default:
      ASSERT(false);
      break;
  }

  return false;
}

/*** Retrieves the bounding rectangle for the state icon of an item **********/
bool CListBase::GetStateIconRect(int nItem, LPRECT pRect)
{
  CRect rcSubItem;

  if (GetRealSubItemRect(nItem, m_bKeepLabelLeft ? OrderToIndex(0) : 0,
                         LVIR_BOUNDS, rcSubItem))
  {
    CRect rcSmallIcon;

    if (GetRealSubItemRect(nItem, 0, LVIR_ICON, rcSmallIcon))
    {
      *pRect       = rcSubItem;
      pRect->left += m_nIconXOff;
      pRect->right = rcSmallIcon.left - 1;

      // clip at right column border
      int nWidth = rcSubItem.Width();
      if (pRect->right >= rcSubItem.left + rcSubItem.Width())
        pRect->right = pRect->left + nWidth - 1;

      return true;
    }
  }

  return false;
}

/*** Invalidate client area not covered by list control items ****************/
void CListBase::InvalidateNonItemArea()
{
  ASSERT(m_pListCtrl);

  int nTopIndex = m_pListCtrl->GetTopIndex();

  if (nTopIndex >= 0)
  {
    // update coloring of sort column
    CRect rectHdrItem;
    ASSERT(m_pListCtrl->GetHeaderCtrl());
    if (m_pListCtrl->GetHeaderCtrl()->GetItemRect(
          abs(m_nSortColumn) - 1, rectHdrItem))
    {
      // erase area above top item
      CRect rectThis;
      m_pListCtrl->GetClientRect(rectThis);

      CRect rectItem;
      m_pListCtrl->GetItemRect(nTopIndex, rectItem, LVIR_BOUNDS);

      CRect rectToBeErased(rectThis.left, rectHdrItem.bottom,
                           rectThis.right, rectItem.top);
      m_pListCtrl->InvalidateRect(rectToBeErased);

      // erase area below bottom item
      m_pListCtrl->GetItemRect(m_pListCtrl->GetItemCount() - 1, rectItem,
                               LVIR_BOUNDS);
      if (rectItem.bottom < rectThis.bottom)
      {
        rectToBeErased.top    = rectItem.bottom;
        rectToBeErased.bottom = rectThis.bottom;
      }
      m_pListCtrl->InvalidateRect(rectToBeErased);
    }
  }
}

/*** Rejustify first column of listview control to enable a right- ***********/
/*** justified or centerd first column                             ***********/
void CListBase::JustifyFirstColumn(int nFormat)
{
  ASSERT(m_pListCtrl);

  if (m_pListCtrl->GetStyle()         & LVS_OWNERDRAWFIXED ||
      m_pListCtrl->GetExtendedStyle() & LVS_EX_FULLROWSELECT)
  {
    CHeaderCtrl* pHeaderCtrl = m_pListCtrl->GetHeaderCtrl();
    ASSERT(pHeaderCtrl);
    HDITEM hdrItem;

    hdrItem.mask = HDI_FORMAT;
    if (pHeaderCtrl->GetItem(0, &hdrItem))
    {
      hdrItem.fmt =
        hdrItem.fmt & ~HDF_JUSTIFYMASK | nFormat & HDF_JUSTIFYMASK;
      pHeaderCtrl->SetItem(0, &hdrItem);
    }
  }
}

/*** Truncate too long listview control entry and append three ***************/
void CListBase::MakeShortString(CDC* pDC, CString& strText, int nColumnLen)
  const
{
	LPCTSTR psz3Dots = _T("...");
  int     nTextLen = strText.GetLength();

	if (nTextLen > 0 && pDC->GetTextExtent(strText).cx > nColumnLen)
  {
	  const int nAddLen  = pDC->GetTextExtent(psz3Dots, 3).cx;
          int i;

	  for (i = nTextLen-1; i > 0; i--)
		  if (pDC->GetTextExtent(strText, i).cx + nAddLen <= nColumnLen) break;

    if (i > 0)
    {
      strText.Delete(i, nTextLen-i);
      strText += psz3Dots;
    }
    else
    {
      // if one character and three dots are to wide, decrease the dot count
      int n1stLen = pDC->GetTextExtent(strText, 1).cx;
      int i;
      for (i = 2; i > 0; i--)
		    if (n1stLen + pDC->GetTextExtent(psz3Dots, i).cx <= nColumnLen)
          break;
      strText.Delete(1, nTextLen-1);
      if (i > 0) strText += CString(psz3Dots, i);
    }
  }
}

/*** Return the index of a subitem, based in its order in the header control */
int CListBase::OrderToIndex(int nOrder)
{
  ASSERT(m_pListCtrl);
  ASSERT(m_pListCtrl->GetHeaderCtrl());

  return m_pListCtrl->GetHeaderCtrl()->OrderToIndex(nOrder);
}

/*** Display or hide sort icon on column to be sorted ************************/
void CListBase::SetSortIcon()
{
  ASSERT(m_pListCtrl);

  CHeaderCtrl* pHeaderCtrl = m_pListCtrl->GetHeaderCtrl();
  ASSERT(pHeaderCtrl);
  int nCols = pHeaderCtrl->GetItemCount();

  for (int col = 0; col < nCols; col++)
  {
    HDITEM hdrItem;

    hdrItem.mask = HDI_FORMAT | HDI_IMAGE;
    pHeaderCtrl->GetItem(col, &hdrItem);
    if (m_bSortIconEnabled && m_nSortColumn - 1 == col)
    {
      hdrItem.iImage = m_nUpArrow;
      hdrItem.fmt    = hdrItem.fmt & HDF_JUSTIFYMASK |
                       HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
    }
    else if (m_bSortIconEnabled && -m_nSortColumn - 1 == col)
    {
      hdrItem.iImage = m_nDownArrow;
      hdrItem.fmt    = hdrItem.fmt & HDF_JUSTIFYMASK |
                       HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
    }
    else
      hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_STRING;

    pHeaderCtrl->SetItem(col, &hdrItem);
  }
}

⌨️ 快捷键说明

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