home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / ROWLST.PAK / LISTVWEX.CPP next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  10.4 KB  |  434 lines

  1. // ListVwEx.cpp : implementation of the CListViewEx class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1996 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "ListVwEx.h"
  15.  
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CListViewEx
  24.  
  25. IMPLEMENT_DYNCREATE(CListViewEx, CListView)
  26.  
  27. BEGIN_MESSAGE_MAP(CListViewEx, CListView)
  28.     //{{AFX_MSG_MAP(CListViewEx)
  29.     ON_WM_SIZE()
  30.     ON_WM_PAINT()
  31.     ON_WM_SETFOCUS()
  32.     ON_WM_KILLFOCUS()
  33.     //}}AFX_MSG_MAP
  34.     ON_MESSAGE(LVM_SETIMAGELIST, OnSetImageList)
  35.     ON_MESSAGE(LVM_SETTEXTCOLOR, OnSetTextColor)
  36.     ON_MESSAGE(LVM_SETTEXTBKCOLOR, OnSetTextBkColor)
  37.     ON_MESSAGE(LVM_SETBKCOLOR, OnSetBkColor)
  38. END_MESSAGE_MAP()
  39.  
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CListViewEx construction/destruction
  42.  
  43. CListViewEx::CListViewEx()
  44. {
  45.     m_bFullRowSel=FALSE;
  46.     m_bClientWidthSel=TRUE;
  47.  
  48.     m_cxClient=0;
  49.     m_cxStateImageOffset=0;
  50.  
  51.     m_clrText=::GetSysColor(COLOR_WINDOWTEXT);
  52.     m_clrTextBk=::GetSysColor(COLOR_WINDOW);
  53.     m_clrBkgnd=::GetSysColor(COLOR_WINDOW);
  54. }
  55.  
  56. CListViewEx::~CListViewEx()
  57. {
  58. }
  59.  
  60. BOOL CListViewEx::PreCreateWindow(CREATESTRUCT& cs)
  61. {
  62.     // default is report view and full row selection
  63.     cs.style&=~LVS_TYPEMASK;
  64.     cs.style|=LVS_REPORT | LVS_OWNERDRAWFIXED;
  65.     m_bFullRowSel=TRUE;
  66.  
  67.     return(CListView::PreCreateWindow(cs));
  68. }
  69.  
  70. BOOL CListViewEx::SetFullRowSel(BOOL bFullRowSel)
  71. {
  72.     // no painting during change
  73.     LockWindowUpdate();
  74.  
  75.     m_bFullRowSel=bFullRowSel;
  76.  
  77.     BOOL bRet;
  78.  
  79.     if(m_bFullRowSel)
  80.         bRet=ModifyStyle(0L,LVS_OWNERDRAWFIXED);
  81.     else
  82.         bRet=ModifyStyle(LVS_OWNERDRAWFIXED,0L);
  83.  
  84.     // repaint window if we are not changing view type
  85.     if(bRet && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
  86.         Invalidate();
  87.  
  88.     // repaint changes
  89.     UnlockWindowUpdate();
  90.  
  91.     return(bRet);
  92. }
  93.  
  94. BOOL CListViewEx::GetFullRowSel()
  95. {
  96.     return(m_bFullRowSel);
  97. }
  98.  
  99. /////////////////////////////////////////////////////////////////////////////
  100. // CListViewEx drawing
  101.  
  102. // offsets for first and other columns
  103. #define OFFSET_FIRST    2
  104. #define OFFSET_OTHER    6
  105.  
  106. void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  107. {
  108.     CListCtrl& ListCtrl=GetListCtrl();
  109.     CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
  110.     CRect rcItem(lpDrawItemStruct->rcItem);
  111.     UINT uiFlags=ILD_TRANSPARENT;
  112.     CImageList* pImageList;
  113.     int nItem=lpDrawItemStruct->itemID;
  114.     BOOL bFocus=(GetFocus()==this);
  115.     COLORREF clrTextSave, clrBkSave;
  116.     COLORREF clrImage=m_clrBkgnd;
  117.     static _TCHAR szBuff[MAX_PATH];
  118.     LPCTSTR pszText;
  119.  
  120. // get item data
  121.  
  122.     LV_ITEM lvi;
  123.     lvi.mask=LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
  124.     lvi.iItem=nItem;
  125.     lvi.iSubItem=0;
  126.     lvi.pszText=szBuff;
  127.     lvi.cchTextMax=sizeof(szBuff);
  128.     lvi.stateMask=0xFFFF;        // get all state flags
  129.     ListCtrl.GetItem(&lvi);
  130.  
  131.     BOOL bSelected=(bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
  132.     bSelected=bSelected || (lvi.state & LVIS_DROPHILITED);
  133.  
  134. // set colors if item is selected
  135.  
  136.     CRect rcAllLabels;
  137.     ListCtrl.GetItemRect(nItem,rcAllLabels,LVIR_BOUNDS);
  138.     CRect rcLabel;
  139.     ListCtrl.GetItemRect(nItem,rcLabel,LVIR_LABEL);
  140.     rcAllLabels.left=rcLabel.left;
  141.     if(m_bClientWidthSel && rcAllLabels.right<m_cxClient)
  142.         rcAllLabels.right=m_cxClient;
  143.  
  144.     if(bSelected)
  145.     {
  146.         clrTextSave=pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  147.         clrBkSave=pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
  148.  
  149.         pDC->FillRect(rcAllLabels,&CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
  150.     }
  151.     else
  152.         pDC->FillRect(rcAllLabels,&CBrush(m_clrTextBk));
  153.  
  154. // set color and mask for the icon
  155.  
  156.     if(lvi.state & LVIS_CUT)
  157.     {
  158.         clrImage=m_clrBkgnd;
  159.         uiFlags|=ILD_BLEND50;
  160.     }
  161.     else if(bSelected)
  162.     {
  163.         clrImage=::GetSysColor(COLOR_HIGHLIGHT);
  164.         uiFlags|=ILD_BLEND50;
  165.     }
  166.  
  167. // draw state icon
  168.  
  169.     UINT nStateImageMask=lvi.state & LVIS_STATEIMAGEMASK;
  170.     if(nStateImageMask)
  171.     {
  172.         int nImage=(nStateImageMask>>12)-1;
  173.         pImageList=ListCtrl.GetImageList(LVSIL_STATE);
  174.         if(pImageList)
  175.             pImageList->Draw(pDC,nImage,CPoint(rcItem.left,rcItem.top),ILD_TRANSPARENT);
  176.     }
  177.  
  178. // draw normal and overlay icon
  179.  
  180.     CRect rcIcon;
  181.     ListCtrl.GetItemRect(nItem,rcIcon,LVIR_ICON);
  182.  
  183.     pImageList=ListCtrl.GetImageList(LVSIL_SMALL);
  184.     if(pImageList)
  185.     {
  186.         UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK;
  187.         if(rcItem.left<rcItem.right-1)
  188.             ImageList_DrawEx(pImageList->m_hImageList,lvi.iImage,pDC->m_hDC,rcIcon.left,rcIcon.top,16,16,m_clrBkgnd,clrImage,uiFlags | nOvlImageMask);
  189.     }
  190.  
  191. // draw item label
  192.  
  193.     ListCtrl.GetItemRect(nItem,rcItem,LVIR_LABEL);
  194.     rcItem.right-=m_cxStateImageOffset;
  195.  
  196.     pszText=MakeShortString(pDC,szBuff,rcItem.right-rcItem.left,2*OFFSET_FIRST);
  197.  
  198.     rcLabel=rcItem;
  199.     rcLabel.left+=OFFSET_FIRST;
  200.     rcLabel.right-=OFFSET_FIRST;
  201.  
  202.     pDC->DrawText(pszText,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
  203.  
  204. // draw labels for extra columns
  205.  
  206.     LV_COLUMN lvc;
  207.     lvc.mask=LVCF_FMT | LVCF_WIDTH;
  208.  
  209.     for(int nColumn=1; ListCtrl.GetColumn(nColumn,&lvc); nColumn++)
  210.     {
  211.         rcItem.left=rcItem.right;
  212.         rcItem.right+=lvc.cx;
  213.  
  214.         int nRetLen=ListCtrl.GetItemText(nItem,nColumn,szBuff,sizeof(szBuff));
  215.         if(nRetLen==0) continue;
  216.  
  217.         pszText=MakeShortString(pDC,szBuff,rcItem.right-rcItem.left,2*OFFSET_OTHER);
  218.  
  219.         UINT nJustify=DT_LEFT;
  220.  
  221.         if(pszText==szBuff)
  222.         {
  223.             switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
  224.             {
  225.             case LVCFMT_RIGHT:
  226.                 nJustify=DT_RIGHT;
  227.                 break;
  228.             case LVCFMT_CENTER:
  229.                 nJustify=DT_CENTER;
  230.                 break;
  231.             default:
  232.                 break;
  233.             }
  234.         }
  235.  
  236.         rcLabel=rcItem;
  237.         rcLabel.left+=OFFSET_OTHER;
  238.         rcLabel.right-=OFFSET_OTHER;
  239.  
  240.         pDC->DrawText(pszText,-1,rcLabel,nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
  241.     }
  242.  
  243. // draw focus rectangle if item has focus
  244.  
  245.     if(lvi.state & LVIS_FOCUSED && bFocus)
  246.         pDC->DrawFocusRect(rcAllLabels);
  247.  
  248. // set original colors if item was selected
  249.  
  250.     if(bSelected)
  251.     {
  252.             pDC->SetTextColor(clrTextSave);
  253.         pDC->SetBkColor(clrBkSave);
  254.     }
  255. }
  256.  
  257. LPCTSTR CListViewEx::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset)
  258. {
  259.     static const _TCHAR szThreeDots[]=_T("...");
  260.  
  261.     int nStringLen=lstrlen(lpszLong);
  262.  
  263.     if(nStringLen==0 || pDC->GetTextExtent(lpszLong,nStringLen).cx+nOffset<=nColumnLen)
  264.         return(lpszLong);
  265.  
  266.     static _TCHAR szShort[MAX_PATH];
  267.  
  268.     lstrcpy(szShort,lpszLong);
  269.     int nAddLen=pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;
  270.  
  271.     for(int i=nStringLen-1; i>0; i--)
  272.     {
  273.         szShort[i]=0;
  274.         if(pDC->GetTextExtent(szShort,i).cx+nOffset+nAddLen<=nColumnLen)
  275.             break;
  276.     }
  277.  
  278.     lstrcat(szShort,szThreeDots);
  279.  
  280.     return(szShort);
  281. }
  282.  
  283. void CListViewEx::RepaintSelectedItems()
  284. {
  285.     CListCtrl& ListCtrl=GetListCtrl();
  286.     CRect rcItem, rcLabel;
  287.  
  288. // invalidate focused item so it can repaint properly
  289.  
  290.     int nItem=ListCtrl.GetNextItem(-1,LVNI_FOCUSED);
  291.  
  292.     if(nItem!=-1)
  293.     {
  294.         ListCtrl.GetItemRect(nItem,rcItem,LVIR_BOUNDS);
  295.         ListCtrl.GetItemRect(nItem,rcLabel,LVIR_LABEL);
  296.         rcItem.left=rcLabel.left;
  297.  
  298.         InvalidateRect(rcItem,FALSE);
  299.     }
  300.  
  301. // if selected items should not be preserved, invalidate them
  302.  
  303.     if(!(GetStyle() & LVS_SHOWSELALWAYS))
  304.     {
  305.         for(nItem=ListCtrl.GetNextItem(-1,LVNI_SELECTED);
  306.             nItem!=-1; nItem=ListCtrl.GetNextItem(nItem,LVNI_SELECTED))
  307.         {
  308.             ListCtrl.GetItemRect(nItem,rcItem,LVIR_BOUNDS);
  309.             ListCtrl.GetItemRect(nItem,rcLabel,LVIR_LABEL);
  310.             rcItem.left=rcLabel.left;
  311.  
  312.             InvalidateRect(rcItem,FALSE);
  313.         }
  314.     }
  315.  
  316. // update changes 
  317.  
  318.     UpdateWindow();
  319. }
  320.  
  321. /////////////////////////////////////////////////////////////////////////////
  322. // CListViewEx diagnostics
  323.  
  324. #ifdef _DEBUG
  325.  
  326. void CListViewEx::Dump(CDumpContext& dc) const
  327. {
  328.     CListView::Dump(dc);
  329.  
  330.     dc << "m_bFullRowSel = " << (UINT)m_bFullRowSel;
  331.     dc << "\n";
  332.     dc << "m_cxStateImageOffset = " << m_cxStateImageOffset;
  333.     dc << "\n";
  334. }
  335.  
  336. #endif //_DEBUG
  337.  
  338. /////////////////////////////////////////////////////////////////////////////
  339. // CListViewEx message handlers
  340.  
  341. LRESULT CListViewEx::OnSetImageList(WPARAM wParam, LPARAM lParam)
  342. {
  343.     if((int)wParam==LVSIL_STATE)
  344.     {
  345.         int cx, cy;
  346.  
  347.         if(::ImageList_GetIconSize((HIMAGELIST)lParam,&cx,&cy))
  348.             m_cxStateImageOffset=cx;
  349.         else
  350.             m_cxStateImageOffset=0;
  351.     }
  352.  
  353.     return(Default());
  354. }
  355.  
  356. LRESULT CListViewEx::OnSetTextColor(WPARAM wParam, LPARAM lParam)
  357. {
  358.     m_clrText=(COLORREF)lParam;
  359.     return(Default());
  360. }
  361.  
  362. LRESULT CListViewEx::OnSetTextBkColor(WPARAM wParam, LPARAM lParam)
  363. {
  364.     m_clrTextBk=(COLORREF)lParam;
  365.     return(Default());
  366. }
  367.  
  368. LRESULT CListViewEx::OnSetBkColor(WPARAM wParam, LPARAM lParam)
  369. {
  370.     m_clrBkgnd=(COLORREF)lParam;
  371.     return(Default());
  372. }
  373.  
  374. void CListViewEx::OnSize(UINT nType, int cx, int cy) 
  375. {
  376.     m_cxClient=cx;
  377.     CListView::OnSize(nType, cx, cy);
  378. }
  379.  
  380. void CListViewEx::OnPaint() 
  381. {
  382.     // in full row select mode, we need to extend the clipping region
  383.     // so we can paint a selection all the way to the right
  384.     if(m_bClientWidthSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT && GetFullRowSel())
  385.     {
  386.         CRect rcAllLabels;
  387.         GetListCtrl().GetItemRect(0,rcAllLabels,LVIR_BOUNDS);
  388.  
  389.         if(rcAllLabels.right<m_cxClient)
  390.         {
  391.             // need to call BeginPaint (in CPaintDC c-tor)
  392.             // to get correct clipping rect
  393.             CPaintDC dc(this);
  394.  
  395.             CRect rcClip;
  396.             dc.GetClipBox(rcClip);
  397.  
  398.             rcClip.left=min(rcAllLabels.right-1,rcClip.left);
  399.             rcClip.right=m_cxClient;
  400.  
  401.             InvalidateRect(rcClip,FALSE);
  402.             // EndPaint will be called in CPaintDC d-tor
  403.         }
  404.     }
  405.  
  406.     CListView::OnPaint();
  407. }
  408.  
  409. void CListViewEx::OnSetFocus(CWnd* pOldWnd) 
  410. {
  411.     CListView::OnSetFocus(pOldWnd);
  412.  
  413.     // check if we are getting focus from label edit box
  414.     if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
  415.         return;
  416.  
  417.     // repaint items that should change appearance
  418.     if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
  419.         RepaintSelectedItems();
  420. }
  421.  
  422. void CListViewEx::OnKillFocus(CWnd* pNewWnd) 
  423. {
  424.     CListView::OnKillFocus(pNewWnd);
  425.  
  426.     // check if we are losing focus to label edit box
  427.     if(pNewWnd!=NULL && pNewWnd->GetParent()==this)
  428.         return;
  429.  
  430.     // repaint items that should change appearance
  431.     if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
  432.         RepaintSelectedItems();
  433. }
  434.