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

📄 listviewctrlex.cpp

📁 与LCD1602配套的上位机程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }
        else
          nPhysicalOrder++;
        break;
      }

  ASSERT(false);
  return -1;
}

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

  LVITEM* pItem = new LVITEM;

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

  // enlarge text buffer gradually until it's large enough
  for (int nLen = 128;; nLen += nLen)
  {
    LPTSTR pszText = new TCHAR[nLen];

    pItem->cchTextMax = nLen;
    pItem->pszText    = pszText;
    if (m_pListCtrl->DefWindowProc(LVM_GETITEM, 0,
                                   reinterpret_cast<LPARAM>(pItem)))
    {
      if (pItem->pszText != pszText)
      {
        // Windows hasn't used our buffer!
        _tcsncpy(pszText, pItem->pszText, nLen-1);
        pszText[nLen-1] = _T('\0');
        pItem->pszText  = pszText;
      }
    }
    else
    {
      delete[] pszText;
      delete pItem;
      return 0;
    }
    if (static_cast<int>(_tcslen(pItem->pszText)) < nLen-1) break;
    delete[] pItem->pszText;
  }

  return pItem;
}

/*** Returns the physical index of a given column index **********************/
int CListBase::GetPhysicalIndex(int nColumnIndex) const
{
  int nIndex = 0;

  for (int i = 0; i < nColumnIndex; i++)
    if (m_aColumnData[i]->m_bVisible) nIndex++;

  return nIndex;
}

/*** Returns the physical order of a given column order **********************/
int CListBase::GetPhysicalOrder(int nColumnOrder) const
{
  int nOrder = 0;

  for (int i = 0; i < nColumnOrder; i++)
    for (INT_PTR j = m_aColumnData.GetUpperBound(); j >= 0; j--)
      if (m_aColumnData[j]->m_nOrder == i)
      {
        if (m_aColumnData[j]->m_bVisible) nOrder++;
        break;
      }

  return nOrder;
}

/*** 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

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

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

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

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

              // clip rectangle at right edge if necessary
              INT_PTR nWidth =
                m_pListCtrl->DefWindowProc(LVM_GETCOLUMNWIDTH, nIndex, 0);
              if (nSmallIconXOff + ref.Width() >= nWidth)
                ref.right = ref.left - nSmallIconXOff + nWidth - 1;
              return true;
            }
          }
          else if ( m_bKeepLabelLeft && iSubItem == 0 ||
                   !m_bKeepLabelLeft && iSubItem >= 0)
          {
            // clip rectangle at right edge if necessary
            if (rcIcon.right > rcSubItem.right)
              rcIcon.right = rcSubItem.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->right = rcSmallIcon.left;
      if (rcSmallIcon.right > rcSmallIcon.left) pRect->right--;

      // calculate x-offset of state icon
      if (!m_bIconXOffCalculated)
      {
        ASSERT(m_pListCtrl);
        CImageList* pImageList = m_pListCtrl->GetImageList(LVSIL_STATE);

        if (pImageList)
        {
          // retrieve width of state icon
          IMAGEINFO ii = {0, 0, 0, 0};

          if (pImageList->GetImageInfo(0, &ii))
          {
            int nXOff = pRect->right - (ii.rcImage.right - ii.rcImage.left) -
                        pRect->left;

            if (nXOff < 0)
              m_nIconXOff = 0;
            else if (nXOff < 4)
              m_nIconXOff = nXOff;
            else
              m_nIconXOff = 4;
          }
          else
            m_nIconXOff = 4;
        }
        else
          m_nIconXOff = 4;

        m_bIconXOffCalculated = true;
      }

      pRect->left += m_nIconXOff;

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

      return true;
    }
  }

  return false;
}

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

  HDITEM headerItem = {HDI_ORDER};
  return m_pListCtrl->GetHeaderCtrl()->GetItem(nIndex, &headerItem) ?
         headerItem.iOrder : -1;

}

/*** 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);

  m_nFormatOfSubItem0 = nFormat;

  if (m_pListCtrl->GetStyle() & LVS_OWNERDRAWFIXED ||
      m_dwExtendedStyle       & 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);
    }
  }
}

/*** A column header has been clicked ****************************************/
BOOL CListBase::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NMLISTVIEW* pNMListView    = reinterpret_cast<NMLISTVIEW*>(pNMHDR);
  int         nAbsSortColumn = abs(m_nSortColumn);

  pNMListView->iSubItem = GetLogicalIndex(pNMListView->iSubItem);
  if (nAbsSortColumn > 0)
    if (pNMListView->iSubItem == nAbsSortColumn-1)
      m_nSortColumn = -m_nSortColumn;
    else
      m_nSortColumn = pNMListView->iSubItem + 1;
  else
    m_nSortColumn = pNMListView->iSubItem + 1;
  SetSortIcon();

	*pResult = 0;
  return FALSE;
}

/*** An item in the column selection menu has been selected ******************/
BOOL CListBase::OnCommand(WPARAM wParam)
{
  if (HIWORD(wParam) == 0)
    ShowColumn(static_cast<int>(wParam), !m_aColumnData[wParam]->m_bVisible);
  return TRUE;
}

/*** The user has right clicked the mouse ************************************/
void CListBase::OnContextMenu(CWnd* pWnd)
{
  ASSERT(m_pListCtrl);

  if (pWnd == m_pListCtrl->GetHeaderCtrl())
    if (m_nColumnHidingAllowed)
    {
      CMenu menu;

      if (menu.CreatePopupMenu())
      {
        for (INT_PTR i = m_aColumnData.GetUpperBound(); i >= 0; i--)
          menu.InsertMenu(0,
            MF_BYPOSITION                                              |
            (m_aColumnData[i]->m_bVisible ? MF_CHECKED : MF_UNCHECKED) |
            (m_aColumnData[i]->m_bHidingAllowed ? 0 : MF_GRAYED)       |
            MF_STRING, i, m_aColumnData[i]->m_pLVColumn->pszText);

        CPoint pt(0, 0);
        GetCursorPos       (&pt);
        menu.TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, m_pListCtrl, 0);
      }
    }
}

/*** A list view (sub)item will be drawn *************************************/
void CListBase::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) 
{
  ASSERT(m_pListCtrl);
  ASSERT(m_pListCtrl->GetHeaderCtrl());

  NMLVCUSTOMDRAW* pNMLVCustomDraw = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);

  switch (pNMLVCustomDraw->nmcd.dwDrawStage)
  {
    case CDDS_PREPAINT:
      *pResult = CDRF_NOTIFYITEMDRAW;
      break;

    case CDDS_ITEMPREPAINT:
      *pResult = CDRF_NOTIFYSUBITEMDRAW;
      break;

    case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
   

⌨️ 快捷键说明

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