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

📄 listviewctrlex.cpp

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

$Author$
  
$Modtime$
$Revision$

Description: Implementation of class "CListBase"
             (list control with sort icons and colored sort column)

$Log$

******************************************************************************/

#include "stdafx.h"
#include "ListViewCtrlEx.h"
#include "Resource.h"

/*** Definition of class "CListCtrlEx" ***************************************/

IMPLEMENT_DYNCREATE(CListCtrlEx, CListCtrl)

/*** Public member functions *************************************************/
/*** A column header has been clicked ****************************************/
BOOL CListCtrlEx::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
  return CListBase::OnColumnclick(pNMHDR, pResult);
}

/*** Protected member functions **********************************************/

/*** A list view (sub)item will be drawn *************************************/
void CListCtrlEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) 
{
  CListBase::OnCustomDraw(pNMHDR, pResult);
}

/*** The background will be erased *******************************************/
BOOL CListCtrlEx::OnEraseBkgnd(CDC* pDC) 
{
  if (CListBase::OnEraseBkgnd(pDC))
    return TRUE;
  else
    return CListCtrl::OnEraseBkgnd(pDC);
}

/*** List control has been scrolled horizontally *****************************/
void CListCtrlEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
  CListCtrl::OnHScroll (nSBCode, nPos, pScrollBar);
  InvalidateNonItemArea();
}

/*** A key has been pressed  *************************************************/
void CListCtrlEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
  if (!CListBase::OnKeyDown(nChar))
    CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}

/*** A key has been released *************************************************/
void CListCtrlEx::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
  CListBase::OnKeyUp(nChar);
  CListCtrl::OnKeyUp(nChar, nRepCnt, nFlags);
}

/*** List control loses input focus ******************************************/
void CListCtrlEx::OnKillFocus(CWnd* pNewWnd) 
{
  CListCtrl::OnKillFocus(pNewWnd);
  CListBase::OnKillFocus();
}

/*** The user double-clicks the left mouse button ****************************/
void CListCtrlEx::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
  if (!CListBase::OnLButtonDblClk(point))
    CListCtrl::OnLButtonDblClk(nFlags, point);
}

/*** The user presses the left mouse button **********************************/
void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point) 
{
  if (!CListBase::OnLButtonDown(point))
    CListCtrl::OnLButtonDown(nFlags, point);
}

/*** Divider in header control has been dragged ******************************/
BOOL CListCtrlEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
  BOOL bRet = CListCtrl::OnNotify(wParam, lParam, pResult);

  if (CListBase::OnNotify(lParam)) return TRUE; else return bRet;
}

/*** List control gains input focus ******************************************/
void CListCtrlEx::OnSetFocus(CWnd* pOldWnd) 
{
  CListCtrl::OnSetFocus(pOldWnd);
  CListBase::OnSetFocus();
}

/*** System colors have been changed *****************************************/
void CListCtrlEx::OnSysColorChange()
{
  CListCtrl::OnSysColorChange();
  CListBase::OnSysColorChange();
}

/*** Table of message handlers ***********************************************/
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
	//{{AFX_MSG_MAP(CListCtrlEx)
	ON_WM_SYSCOLORCHANGE()
	ON_WM_ERASEBKGND()
	ON_WM_HSCROLL()
	ON_WM_KILLFOCUS()
	ON_WM_SETFOCUS()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	//}}AFX_MSG_MAP
	ON_NOTIFY_REFLECT_EX(LVN_COLUMNCLICK, OnColumnclick)
  ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
END_MESSAGE_MAP()


/*** Definition of class "CListViewEx" ***************************************/

IMPLEMENT_DYNCREATE(CListViewEx, CListView)

/*** Protected member functions **********************************************/

/*** A column header has been clicked ****************************************/
BOOL CListViewEx::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
  return CListBase::OnColumnclick(pNMHDR, pResult);
}

/*** A list view (sub)item will be drawn *************************************/
void CListViewEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) 
{
  CListBase::OnCustomDraw(pNMHDR, pResult);
}

/*** The background will be erased *******************************************/
BOOL CListViewEx::OnEraseBkgnd(CDC* pDC) 
{
  if (CListBase::OnEraseBkgnd(pDC))
    return TRUE;
  else
    return CListView::OnEraseBkgnd(pDC);
}

/*** List control has been scrolled horizontally *****************************/
void CListViewEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
  CListView::OnHScroll (nSBCode, nPos, pScrollBar);
  InvalidateNonItemArea();
}

/*** A key has been pressed  *************************************************/
void CListViewEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
  if (!CListBase::OnKeyDown(nChar))
    CListView::OnKeyDown(nChar, nRepCnt, nFlags);
}

/*** A key has been released *************************************************/
void CListViewEx::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
  CListBase::OnKeyUp(nChar);
  CListView::OnKeyUp(nChar, nRepCnt, nFlags);
}

/*** List control loses input focus ******************************************/
void CListViewEx::OnKillFocus(CWnd* pNewWnd) 
{
  CListView::OnKillFocus(pNewWnd);
  CListBase::OnKillFocus();
}

/*** The user double-clicks the left mouse button ****************************/
void CListViewEx::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
  if (!CListBase::OnLButtonDblClk(point))
    CListView::OnLButtonDblClk(nFlags, point);
}

/*** The user presses the left mouse button **********************************/
void CListViewEx::OnLButtonDown(UINT nFlags, CPoint point) 
{
  if (!CListBase::OnLButtonDown(point))
    CListView::OnLButtonDown(nFlags, point);
}

/*** Divider in header control has been dragged ******************************/
BOOL CListViewEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
  BOOL bRet = CListView::OnNotify(wParam, lParam, pResult);

  if (CListBase::OnNotify(lParam)) return TRUE; else return bRet;
}

/*** List control gains input focus ******************************************/
void CListViewEx::OnSetFocus(CWnd* pOldWnd) 
{
  CListView::OnSetFocus(pOldWnd);
  CListBase::OnSetFocus();
}

/*** System colors have been changed *****************************************/
void CListViewEx::OnSysColorChange()
{
  CListView::OnSysColorChange();
  CListBase::OnSysColorChange();
}

/*** Table of message handlers ***********************************************/
BEGIN_MESSAGE_MAP(CListViewEx, CListView)
	//{{AFX_MSG_MAP(CListViewEx)
	ON_WM_SYSCOLORCHANGE()
	ON_WM_ERASEBKGND()
	ON_WM_HSCROLL()
	ON_WM_KILLFOCUS()
	ON_WM_SETFOCUS()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	//}}AFX_MSG_MAP
	ON_NOTIFY_REFLECT_EX(LVN_COLUMNCLICK, OnColumnclick)
  ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
END_MESSAGE_MAP()


/*** Definition of "workhorse" class "CListBase" *****************************/

const int CListBase::m_nFirstColXOff = 2;   // x-offset of first column
const int CListBase::m_nNextColXOff  = 6;   // x-offset of other columns
const int CListBase::m_nIconXOff     = 4;   // x-offset of icon

/*** Public member functions *************************************************/

/*** Enable or disable coloring of sort column *******************************/
#if _MSC_VER == 1300
#pragma runtime_checks("c", off)  // due to a flaw in the definition of
#endif                            // Get[R|G|B]Value
void CListBase::ColorSortColumn(bool bEnable)
{
  
ASSERT(m_pListCtrl);

  if (bEnable == m_bColorSortColumn) return;

  m_bColorSortColumn = bEnable;
  if (bEnable) //开启排序列颜色模式.
  {
    DWORD dwColNormalColor = m_pListCtrl->GetBkColor(); 

    // emulate sort column coloring of Windows XP explorer
	//根据当前控件背景色的RGB值,调整排序列颜色值.
    UINT nRed   = GetRValue(dwColNormalColor);
    UINT nGreen = GetGValue(dwColNormalColor);
    UINT nBlue  = GetBValue(dwColNormalColor);
/*
    if (nRed > 240 && nGreen > 240 && nBlue > 240)
    {
      nRed   -= 8;
      nGreen -= 8;
      nBlue  -= 8;
    }
    else
    {
      if (nRed   < 232) nRed   += nRed   / 10; else nRed   = 255;
      if (nGreen < 232) nGreen += nGreen / 10; else nGreen = 255;
      if (nBlue  < 232) nBlue  += nBlue  / 10; else nBlue  = 255;
    }
*/
    m_dwColSortColor = RGB(nRed, nGreen, nBlue);
  }
}
#if _MSC_VER == 1300
#pragma runtime_checks("c", restore)
#endif

/*** Draw the entire item (called if window has style LVS_OWNERDRAWFIXED) ****/
void CListBase::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  ASSERT(m_pListCtrl);

  LVITEM* pItem = GetLVITEM(lpDrawItemStruct->itemID);

  bool bAlwaysSelected  = pItem->state & LVIS_SELECTED &&
                          (m_pListCtrl->GetStyle() & LVS_SHOWSELALWAYS) != 0;
  bool bLVHasFocus      = m_pListCtrl->GetFocus() == m_pListCtrl;
  bool bItemHasFocus    = pItem->state & LVIS_FOCUSED  && bLVHasFocus;
	bool bSelected        = pItem->state & LVIS_SELECTED && bLVHasFocus;
  bool bFullRowSelected =
    (m_pListCtrl->GetExtendedStyle() & LVS_EX_FULLROWSELECT) != 0;
  
  
  CRect rcItem;                   // rectangle bounding complete item
  m_pListCtrl->GetItemRect(pItem->iItem, rcItem, LVIR_BOUNDS);

  CRect rcSubItem0;               // rectangle bounding subitem 0
  GetRealSubItemRect(pItem->iItem, 0, LVIR_BOUNDS, rcSubItem0);

  CRect rcLabel;                  // rectangle bounding item label
  GetRealSubItemRect(pItem->iItem, 0, LVIR_LABEL, rcLabel);

	CRect rcSelection;              // rectangle bounding selection
  if (bFullRowSelected)
  {
	  rcSelection = rcItem;
    if (IndexToOrder(0) == 0 || m_bKeepLabelLeft)
    {
      rcSelection.left = rcLabel.left;
      int nWidthOfCol0 = m_pListCtrl->GetColumnWidth(OrderToIndex(0));
      if (rcSelection.left > nWidthOfCol0) rcSelection.left = nWidthOfCol0;
    }
  }

	CDC*   pDC          = CDC::FromHandle(lpDrawItemStruct->hDC);
  CBrush brushHiLite;
  DWORD  dwNormalText = GetSysColor(COLOR_WINDOWTEXT);
  DWORD  dwHiLiteBk   = 0;

	if (bSelected)
	{
    dwHiLiteBk = GetSysColor(COLOR_HIGHLIGHT);
    brushHiLite.CreateSolidBrush(dwHiLiteBk);
	}
	else if (bAlwaysSelected)
  {
    dwHiLiteBk = GetSysColor(COLOR_3DFACE);
    brushHiLite.CreateSolidBrush(dwHiLiteBk);
  }

  LVCOLUMN lvc;
	lvc.mask = LVCF_FMT | LVCF_WIDTH;

  // display all subitems
  int nIndex;
	for (int nColumn = 0;
       m_pListCtrl->GetColumn(nIndex = OrderToIndex(nColumn), &lvc);
       nColumn++)
  {
    LVITEM* pSubItem  = nIndex > 0 ? GetLVITEM(pItem->iItem, nIndex) : pItem;
    CRect   rcSubItem;                  // rectangle bounding subitem
	  CRect   rcText;                     // output rectangle
    DWORD   dwBkColor =                 // background color of curremt column
      nIndex+1 == abs(m_nSortColumn) ?
      m_dwColSortColor : m_pListCtrl->GetBkColor();
    CBrush  brushBk(dwBkColor);

    // consider column margins
    if (nColumn > 0)
    {
      // move output rectangle over next column
      rcSubItem.left   = rcSubItem.right;
      rcSubItem.right += lvc.cx;
    }
    else
    {
      rcSubItem       = rcItem;
      rcSubItem.right = rcSubItem.left + lvc.cx;
    }

    if (nIndex == 0 && !m_bKeepLabelLeft || nColumn == 0 && m_bKeepLabelLeft)
    {
      rcText        = rcLabel;
      rcText.left  += m_nFirstColXOff;
      rcText.right -= nIndex > 0 ? m_nNextColXOff : m_nFirstColXOff;
    }
    else
    {
      rcText        = rcSubItem;
      rcText.left  += m_nNextColXOff;
      rcText.right -= m_nNextColXOff;
    }

    int  nLabelWidth = GetLabelWidth(pDC, pSubItem, rcText.Width());
    bool bHiLite     = false;

    if (bSelected || bAlwaysSelected || bItemHasFocus && !bFullRowSelected)
      if (nIndex == 0 && nColumn != 0 && !m_bKeepLabelLeft && !bFullRowSelected
          ||
          nColumn == 0 && (m_bKeepLabelLeft || nIndex == 0))
      {
        // calculate selection area
        CRect rcSubItemSelection(rcLabel);

        if (!bFullRowSelected)
        {
          int nFormat = nIndex == 0 && nColumn == 0 || !m_bKeepLabelLeft ?
                        m_nFormatOfSubItem0 : lvc.fmt & LVCFMT_JUSTIFYMASK;

          switch (nFormat)
          {
            case LVCFMT_LEFT:
              rcSubItemSelection.right =
                rcSubItemSelection.left +
                  m_nFirstColXOff + nLabelWidth + m_nNextColXOff;
              break;

            case LVCFMT_RIGHT:
              rcSubItemSelection.left =
                rcSubItemSelection.right -
                  m_nFirstColXOff - nLabelWidth - m_nNextColXOff;
              break;

            case LVCFMT_CENTER:
            {
              int nSelectionWidth =
                m_nNextColXOff + nLabelWidth + m_nNextColXOff;
              rcSubItemSelection.left  =
                rcLabel.left + (rcLabel.Width() - nSelectionWidth) / 2;
              rcSubItemSelection.right =
                rcSubItemSelection.left + nSelectionWidth;
              break;
            }

            default:
              ASSERT(false);
              break;
          }
          if (rcSubItemSelection.left < rcLabel.left)
            rcSubItemSelection.left = rcLabel.left;
          if (rcSubItemSelection.right > rcLabel.right)
            rcSubItemSelection.right = rcLabel.right;

          rcSelection = rcSubItemSelection;

⌨️ 快捷键说明

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