ListCtrlEx.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /******************************************************************************\
  2. * file : ListCtrlEx.cpp
  3. * created: 1997.09.22
  4. *
  5. * Zafir Anjum - Original author.
  6. * Mark Findlay - IE4 fixes.
  7. * Matthew Bells - Better TitleTips.
  8. *
  9. * description:
  10. * A super CListControl.
  11. * <P>features:
  12. * <UL>
  13. * <LI>Title Tip item expantion
  14. * <LI>full row selection<BR>
  15. * <I>Note:</I> this is also a feature in IE 4.0 with
  16. * LVS_EX_FULLROWSELECT.
  17. * <LI>notifies parent selection has changed
  18. * <LI>supports column dragging (with IE4) which changes the column order
  19. * </UL>
  20. *
  21. \******************************************************************************/
  22. // ListCtrlEx.cpp : implementation of the CListCtrlEx class
  23. #include "stdafx.h"
  24. #include <assert.h>
  25. #include "ListCtrlEx.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CListCtrlEx
  33. IMPLEMENT_DYNCREATE(CListCtrlEx, CListCtrl)
  34. BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
  35. //{{AFX_MSG_MAP(CListCtrlEx)
  36. ON_WM_PAINT()
  37. ON_WM_SETFOCUS()
  38. ON_WM_KILLFOCUS()
  39. ON_WM_MOUSEMOVE()
  40. ON_WM_LBUTTONDOWN()
  41. ON_WM_KEYDOWN()
  42. ON_WM_DESTROY()
  43. ON_WM_MEASUREITEM()
  44. //}}AFX_MSG_MAP
  45. ON_MESSAGE(LVM_SETTEXTCOLOR, OnSetTextColor)
  46. ON_MESSAGE(LVM_SETTEXTBKCOLOR, OnSetTextBkColor)
  47. ON_MESSAGE(LVM_SETBKCOLOR, OnSetBkColor)
  48. ON_WM_MEASUREITEM_REFLECT( )
  49. END_MESSAGE_MAP()
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CListCtrlEx construction/destruction
  52. CListCtrlEx::CListCtrlEx()
  53. {
  54. m_bFullRowSel = FALSE;
  55. m_bClientWidthSel = TRUE;
  56. m_clrText = ::GetSysColor(COLOR_WINDOWTEXT);
  57. m_clrTextBk = ::GetSysColor(COLOR_WINDOW);
  58. m_clrBkgnd = ::GetSysColor(COLOR_WINDOW);
  59. bShowLine = true;
  60. nFontHeight = -1;
  61. nTxtColor = 0;
  62. }
  63. CListCtrlEx::~CListCtrlEx()
  64. {
  65. }
  66. /*
  67. BOOL CListCtrlEx::OnEraseBkgnd(CDC* pDC)
  68. {
  69. CBitmap bmp;
  70. CBitmap *ptrBmpOld;
  71. CDC dcMemory;
  72. BITMAP bm;
  73. CRect rect;
  74. int i, j;
  75. int nHor, nVer;
  76. bmp.LoadBitmap("BackGround");
  77. bmp.GetBitmap(&bm);
  78. GetClientRect(rect);
  79. nHor=rect.Width()/bm.bmWidth+1;
  80. nVer=rect.Height()/bm.bmHeight+1;
  81. dcMemory.CreateCompatibleDC(pDC);
  82. ptrBmpOld=dcMemory.SelectObject(&bmp);
  83. for(i=0; i<nHor; i++)
  84. {
  85. for(j=0; j<nVer; j++)
  86. {
  87. pDC->BitBlt
  88. (
  89. i*bm.bmWidth,
  90. j*bm.bmHeight,
  91. bm.bmWidth,
  92. bm.bmHeight,
  93. &dcMemory,
  94. 0,
  95. 0,
  96. SRCCOPY
  97. );
  98. }
  99. }
  100. dcMemory.SelectObject(ptrBmpOld);
  101. return true;
  102. }
  103. //*/
  104. // Make sure the control is owner drawn
  105. BOOL CListCtrlEx::PreCreateWindow(CREATESTRUCT& cs)
  106. {
  107. // default is report view and full row selection
  108. cs.style &= ~LVS_TYPEMASK;
  109. cs.style |= LVS_REPORT | LVS_OWNERDRAWFIXED;
  110. m_bFullRowSel = TRUE;
  111. return(CListCtrl::PreCreateWindow(cs));
  112. }
  113. BOOL CListCtrlEx::SetFullRowSel(BOOL bFullRowSel)
  114. {
  115. // no painting during change
  116. LockWindowUpdate();
  117. m_bFullRowSel = bFullRowSel;
  118. BOOL bRet;
  119. if (m_bFullRowSel)
  120. bRet = ModifyStyle(0L, LVS_OWNERDRAWFIXED);
  121. else
  122. bRet = ModifyStyle(LVS_OWNERDRAWFIXED, 0L);
  123. // repaint window if we are not changing view type
  124. if (bRet && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
  125. Invalidate();
  126. // repaint changes
  127. UnlockWindowUpdate();
  128. return(bRet);
  129. }
  130. BOOL CListCtrlEx::GetFullRowSel()
  131. {
  132. return(m_bFullRowSel);
  133. }
  134. /////////////////////////////////////////////////////////////////////////////
  135. // CListCtrlEx drawing
  136. /*
  137. * DrawItem() is called by the framework whenever an item needs to be drawn
  138. * for owner drawn controls.
  139. * Note:
  140. * <UL>
  141. * <LI>LVS_SHOWSELALWAYS: non owner drawn controls show an item is
  142. * highlighted when the control does not have focus with a different
  143. * highlight color is (usually gray). This is not supported for
  144. * this control.
  145. * </UL>
  146. */
  147. void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  148. {
  149. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  150. int iSavedDC = pDC->SaveDC(); // Save DC state
  151. //*
  152. CFont *pOldFont = NULL;
  153. CFont font;
  154. if( nFontHeight != -1 )
  155. {
  156. CFont* ptf = GetFont(); // 得到原来的字体
  157. LOGFONT lf;
  158. ptf->GetLogFont(&lf);
  159. lf.lfHeight = nFontHeight; // 改变字体高度
  160. //strcpy (lf.lfFaceName, "Arial Black"); // 改变字体名称
  161. strcpy (lf.lfFaceName, "Arial"); // 改变字体名称
  162. lf.lfWeight = 700;
  163. lf.lfCharSet = DEFAULT_CHARSET; //DEFAULT_CHARSET ANSI_CHARSET GB2312_CHARSET
  164. font.CreateFontIndirect(&lf);
  165. pOldFont = (CFont *)pDC->SelectObject(&font);
  166. // LOGFONT lf;//字体
  167. // lf.lfStrikeOut=0;//删除线
  168. // lf.lfCharSet = DEFAULT_CHARSET ;//字符集
  169. // lf.lfEscapement =0;//角度
  170. // lf.lfItalic = 0 ;//倾斜
  171. // lf.lfUnderline = 0;//下划线
  172. // lf.lfHeight = nFontHeight;//字号
  173. //strcpy( lf.lfFaceName, "宋体" );
  174. // font.CreateFontIndirect(&lf);
  175. // CFont *pOldFont = (CFont *)pDC->SelectObject(&font);
  176. }
  177. //*/
  178. int iItem = lpDrawItemStruct->itemID;
  179. // Get item image and state info
  180. LV_ITEM lvi;
  181. lvi.mask = LVIF_IMAGE | LVIF_STATE;
  182. lvi.iItem = iItem;
  183. lvi.iSubItem = 0;
  184. lvi.stateMask = 0xFFFF; // get all state flags
  185. GetItem(&lvi);
  186. bool bHighlight = (
  187. (lvi.state & LVIS_DROPHILITED) ||
  188. ((lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS)))
  189. );
  190. // Get rectangles for drawing
  191. CRect rcBounds;
  192. CRect rcLabel;
  193. CRect rcIcon;
  194. GetItemRect(iItem, rcBounds, LVIR_BOUNDS);
  195. GetItemRect(iItem, rcLabel, LVIR_LABEL);
  196. GetItemRect(iItem, rcIcon, LVIR_ICON);
  197. CRect rcItem(rcBounds);
  198. CString sLabel = GetItemText(iItem, 0);
  199. // Labels are offset by a certain amount
  200. // This offset is related to the width of a space character
  201. int offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2;
  202. rcBounds.left = rcLabel.left;
  203. CRect rcWnd;
  204. GetClientRect(&rcWnd);
  205. if(m_bClientWidthSel && rcBounds.right<rcWnd.right)
  206. rcBounds.right = rcWnd.right;
  207. // Draw the background
  208. if(bHighlight)
  209. {
  210. pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  211. pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
  212. pDC->FillRect(rcBounds, &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
  213. }
  214. else
  215. {
  216. if( nTxtColor != 0 )
  217. pDC->SetTextColor( nTxtColor );
  218. if( bShowLine )
  219. {
  220. if( iItem%2 )
  221. pDC->FillRect(rcBounds, &CBrush(m_clrTextBk));
  222. else
  223. pDC->FillRect(rcBounds, &CBrush(RGB(212,212,212)));
  224. }
  225. else
  226. {
  227. DWORD_PTR pRGB = GetItemData(iItem);
  228. COLORREF color = (COLORREF)pRGB;
  229. COLORREF white(RGB(255, 255, 255));
  230. if(color != RGB(0, 0, 0))
  231. pDC->FillRect(rcBounds, &CBrush(color));
  232. else
  233. pDC->FillRect(rcBounds, &CBrush(white));
  234. //pDC->FillRect(rcBounds, &CBrush(m_clrTextBk));
  235. }
  236. }
  237. // Set clip region
  238. rcItem.right = rcItem.left + GetColumnWidth(0);
  239. // Draw state icon
  240. if(lvi.state & LVIS_STATEIMAGEMASK)
  241. {
  242. int nImage = ((lvi.state & LVIS_STATEIMAGEMASK)>>12) - 1;
  243. CImageList* pImageList = GetImageList(LVSIL_STATE);
  244. if(pImageList)
  245. {
  246. pImageList->Draw(pDC, nImage,
  247. CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT);
  248. }
  249. }
  250. // Draw normal and overlay icon
  251. CImageList* pImageList = GetImageList(LVSIL_SMALL);
  252. if(pImageList)
  253. {
  254. UINT nOvlImageMask = lvi.state & LVIS_OVERLAYMASK;
  255. pImageList->Draw(pDC, lvi.iImage,
  256. CPoint(rcIcon.left, rcIcon.top),
  257. (bHighlight?ILD_BLEND50:0) | ILD_TRANSPARENT | nOvlImageMask );
  258. }
  259. // Draw item label - Column 0
  260. rcLabel.left += offset/2-1;
  261. rcLabel.right -= offset;
  262. pDC->DrawText(sLabel,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX
  263. | DT_VCENTER | DT_END_ELLIPSIS);
  264. // Draw labels for remaining columns
  265. LV_COLUMN lvc;
  266. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  267. /*
  268. // set clip region
  269. rcBounds.right = rcHighlight.right > rcBounds.right ? rcHighlight.right :
  270. rcBounds.right;
  271. rgn.CreateRectRgnIndirect(&rcBounds);
  272. pDC->SelectClipRgn(&rgn);
  273. */
  274. for(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++)
  275. {
  276. rcItem.left = rcItem.right;
  277. rcItem.right += lvc.cx;
  278. sLabel = GetItemText(iItem, nColumn);
  279. // Get the text just ification
  280. UINT nJustify = DT_LEFT;
  281. switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
  282. {
  283. case LVCFMT_RIGHT:
  284. nJustify = DT_RIGHT;
  285. break;
  286. case LVCFMT_CENTER:
  287. nJustify = DT_CENTER;
  288. break;
  289. default:
  290. break;
  291. }
  292. rcLabel = rcItem;
  293. rcLabel.left += offset;
  294. rcLabel.right -= offset;
  295. pDC->DrawText(sLabel, -1, rcLabel,
  296. nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS);
  297. }
  298. // draw focus rectangle if item has focus
  299. if ((lvi.state & LVIS_FOCUSED) && (GetFocus() == this))
  300. pDC->DrawFocusRect(rcBounds);
  301. //*
  302. if( pOldFont != NULL )
  303. pDC->SelectObject( pOldFont );
  304. if( nFontHeight != -1 )
  305. font.DeleteObject();
  306. //*/
  307. pDC->RestoreDC(iSavedDC); // Restore DC.
  308. }
  309. /////////////////////////////////////////////////////////////////////////////
  310. // CListCtrlEx diagnostics
  311. #ifdef _DEBUG
  312. void CListCtrlEx::Dump(CDumpContext& dc) const
  313. {
  314. CListCtrl::Dump(dc);
  315. dc << "m_bFullRowSel = " << m_bFullRowSel;
  316. dc << "\n";
  317. }
  318. #endif //_DEBUG
  319. /**
  320. * @param iRow [in] row of cell
  321. * @param iColunm [in] column of cell
  322. * @return Rectangle corresponding to the given cell.
  323. */
  324. CRect CListCtrlEx::GetCellRect(int iRow, int iColumn)const
  325. {
  326. // Make sure that the ListView is in LVS_REPORT
  327. if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT)
  328. return CRect(0,0,0,0);
  329. // Get the number of columns
  330. {
  331. CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
  332. int iColumnCount = pHeader->GetItemCount();
  333. assert(iColumn < iColumnCount);
  334. }
  335. CRect rect;
  336. GetItemRect(iRow, &rect, LVIR_BOUNDS);
  337. // Now find the column
  338. for(int colnum = 0; colnum < iColumn; colnum++)
  339. {
  340. rect.left += GetTrueColumnWidth(colnum);
  341. }
  342. // Found the column
  343. rect.right = rect.left + GetTrueColumnWidth(iColumn);
  344. RECT rectClient;
  345. GetClientRect(&rectClient);
  346. if(rect.right > rectClient.right)
  347. rect.right = rectClient.right;
  348. return rect;
  349. }
  350. /**
  351. * @author Mark Findlay
  352. */
  353. CString CListCtrlEx::GetTrueItemText(int row, int col)const
  354. {
  355. // Get the header control
  356. CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
  357. _ASSERTE(pHeader);
  358. // get the current number of columns
  359. int nCount = pHeader->GetItemCount();
  360. // find the actual column requested. We will compare
  361. // against hi.iOrder
  362. for (int x=0; x< nCount; x++)
  363. {
  364. HD_ITEM hi = {0};
  365. hi.mask = HDI_ORDER;
  366. BOOL bRet = pHeader->GetItem(x,&hi);
  367. _ASSERTE(bRet);
  368. if (hi.iOrder == col)
  369. {
  370. // Found it, get the associated text
  371. return GetItemText(row,x);
  372. }
  373. }
  374. _ASSERTE(FALSE);
  375. return "We better never fall through to here!";
  376. }
  377. /**
  378. * @author Mark Findlay
  379. */
  380. int CListCtrlEx::GetTrueColumnWidth(int nCurrentPosition)const
  381. {
  382. CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
  383. _ASSERTE(pHeader);
  384. int nCount = pHeader->GetItemCount();
  385. for (int x=0; x< nCount; x++)
  386. {
  387. HD_ITEM hi = {0};
  388. hi.mask = HDI_WIDTH | HDI_ORDER;
  389. BOOL bRet = pHeader->GetItem(x,&hi);
  390. _ASSERTE(bRet);
  391. if (hi.iOrder == nCurrentPosition)
  392. return hi.cxy;
  393. }
  394. _ASSERTE(FALSE);
  395. return 0; // We would never fall through to here!
  396. }
  397. void CListCtrlEx::HideTitleTip()
  398. {
  399. m_titletip.ShowWindow(SW_HIDE);
  400. }
  401. /**
  402. * @param point [in] point in client coordinates
  403. * @param iRow [out] row containing the point
  404. * @param iColunm [out] column containing the point
  405. *
  406. * @author Matthew Bells
  407. */
  408. bool CListCtrlEx::HitTestRowCol(CPoint& point, int& iRow, int& iColumn)const
  409. {
  410. // Make sure that the ListView is in LVS_REPORT
  411. if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT)
  412. return false;
  413. int iPosX = point.x;
  414. iRow = HitTest(point);
  415. // Get the number of columns
  416. CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
  417. int iColumnCount = pHeader->GetItemCount();
  418. for(iColumn = 0; iColumn < iColumnCount; ++iColumn)
  419. {
  420. iPosX -= GetTrueColumnWidth(iColumn);
  421. if(iPosX < 0)
  422. break;
  423. }
  424. if(iColumn == iColumnCount)
  425. iColumn = -1;
  426. return (iRow != -1 && iColumn != -1);
  427. }
  428. void CListCtrlEx::RepaintSelectedItems()
  429. {
  430. CRect rcItem;
  431. CRect rcLabel;
  432. // Invalidate focused item so it can repaint
  433. int iItem = GetNextItem(-1, LVNI_FOCUSED);
  434. if(iItem != -1)
  435. {
  436. GetItemRect(iItem, rcItem, LVIR_BOUNDS);
  437. GetItemRect(iItem, rcLabel, LVIR_LABEL);
  438. rcItem.left = rcLabel.left;
  439. InvalidateRect(rcItem, FALSE);
  440. }
  441. // Invalidate selected items depending on LVS_SHOWSELALWAYS
  442. if(!(GetStyle() & LVS_SHOWSELALWAYS))
  443. {
  444. for(iItem = GetNextItem(-1, LVNI_SELECTED);
  445. iItem != -1; iItem = GetNextItem(iItem, LVNI_SELECTED))
  446. {
  447. GetItemRect(iItem, rcItem, LVIR_BOUNDS);
  448. GetItemRect(iItem, rcLabel, LVIR_LABEL);
  449. rcItem.left = rcLabel.left;
  450. InvalidateRect(rcItem, FALSE);
  451. }
  452. }
  453. UpdateWindow();
  454. }
  455. /////////////////////////////////////////////////////////////////////////////
  456. // CListCtrlEx message handlers
  457. void CListCtrlEx::OnDestroy()
  458. {
  459. m_titletip.DestroyWindow();
  460. CListCtrl::OnDestroy();
  461. }
  462. void CListCtrlEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  463. {
  464. inherited::OnChar(nChar, nRepCnt, nFlags);
  465. HideTitleTip();
  466. SendSelChangedNotification();
  467. }
  468. void CListCtrlEx::OnKillFocus(CWnd* pNewWnd)
  469. {
  470. CListCtrl::OnKillFocus(pNewWnd);
  471. // This should be hidden no matter if another control is getting focus
  472. // or the edit box.
  473. HideTitleTip();
  474. // this really still has focus if one of its chilren (ie. the edit box)
  475. // has focus
  476. if(pNewWnd != NULL && pNewWnd->GetParent() == this)
  477. return;
  478. // repaint items that should change appearance
  479. if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
  480. RepaintSelectedItems();
  481. }
  482. void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
  483. {
  484. int iTest = GetKeyState(VK_LMENU);
  485. // Shortcut to editing.
  486. if((GetKeyState(VK_LMENU) & 0x8000) || (GetKeyState(VK_RMENU) & 0x8000))
  487. {
  488. int iRow;
  489. int iColumn;
  490. if(HitTestRowCol(point, iRow, iColumn))
  491. {
  492. SetFocus();
  493. PostMessage(LVM_EDITLABEL, (WPARAM)iRow, 0);
  494. }
  495. }
  496. else
  497. {
  498. inherited::OnLButtonDown(nFlags, point);
  499. ShowTitleTip(point); // Make sure TitleTip changes if needed.
  500. SendSelChangedNotification();
  501. }
  502. }
  503. void CListCtrlEx::OnMouseMove(UINT nFlags, CPoint point)
  504. {
  505. if( nFlags == 0 )
  506. {
  507. ShowTitleTip(point); // Make sure TitleTip changes if needed.
  508. }
  509. CListCtrl::OnMouseMove(nFlags, point);
  510. }
  511. /*
  512. * When the regular list view control repaints an item, it repaints only the
  513. * area occupied by defined columns. If the last column does not extend to the
  514. * end of the client area, then the space to the right of the last column is
  515. * not repainted. If we are highlighting the full row then this area also needs
  516. * to be invalidated so that the code in DrawItem() can add or remove the
  517. * highlighting from this area.
  518. */
  519. void CListCtrlEx::OnPaint()
  520. {
  521. /*for test 在这里装入Header的图片
  522. CHeaderCtrl* pHeader = GetHeaderCtrl();
  523. HD_ITEM Item;
  524. pHeader->GetItem( 0, &Item );
  525. CRect ItemRect;
  526. pHeader->GetItemRect( 0, &ItemRect );
  527. CDC *pTmpDC = pHeader->GetDC();
  528. pTmpDC->FillRect( ItemRect, &CBrush(RGB(255,0,0)));
  529. ReleaseDC( pTmpDC );
  530. //for test*/
  531. // in full row select mode, we need to extend the clipping region
  532. // so we can paint a selection all the way to the right
  533. if (m_bClientWidthSel &&
  534. (GetStyle() & LVS_TYPEMASK) == LVS_REPORT && GetFullRowSel())
  535. {
  536. CRect rcAllLabels;
  537. GetItemRect(0, rcAllLabels, LVIR_BOUNDS);
  538. CRect rcClient;
  539. GetClientRect(&rcClient);
  540. if(rcAllLabels.right < rcClient.right)
  541. {
  542. // need to call BeginPaint (in CPaintDC c-tor)
  543. // to get correct clipping rect
  544. CPaintDC dc(this);
  545. CRect rcClip;
  546. dc.GetClipBox(rcClip);
  547. rcClip.left = min(rcAllLabels.right-1, rcClip.left);
  548. rcClip.right = rcClient.right;
  549. InvalidateRect(rcClip, FALSE);
  550. // EndPaint will be called in CPaintDC d-tor
  551. }
  552. }
  553. CListCtrl::OnPaint();
  554. }
  555. LRESULT CListCtrlEx::OnSetBkColor(WPARAM wParam, LPARAM lParam)
  556. {
  557. m_clrBkgnd = (COLORREF)lParam;
  558. return(Default());
  559. }
  560. /*
  561. * This is another step to mimic the default behaviour of the list view
  562. * control. When the control loses focus, the focus rectangle around the
  563. * selected (focus) item has to be removed. When the control gets back
  564. * focus, then the focus rectangle has to be redrawn. Both these handlers
  565. * call the RepaintSelectedItems() helper function.
  566. */
  567. void CListCtrlEx::OnSetFocus(CWnd* pOldWnd)
  568. {
  569. CListCtrl::OnSetFocus(pOldWnd);
  570. // check if we are getting focus from label edit box
  571. // if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
  572. // return;
  573. // repaint items that should change appearance
  574. if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
  575. RepaintSelectedItems();
  576. }
  577. LRESULT CListCtrlEx::OnSetTextBkColor(WPARAM wParam, LPARAM lParam)
  578. {
  579. m_clrTextBk = (COLORREF)lParam;
  580. return(Default());
  581. }
  582. LRESULT CListCtrlEx::OnSetTextColor(WPARAM wParam, LPARAM lParam)
  583. {
  584. m_clrText = (COLORREF)lParam;
  585. return(Default());
  586. }
  587. void CListCtrlEx::PreSubclassWindow()
  588. {
  589. CListCtrl::PreSubclassWindow();
  590. m_titletip.Create(this);
  591. m_titletip.SetBackground(CBrush(GetBkColor()));
  592. }
  593. void CListCtrlEx::SendSelChangedNotification()
  594. {
  595. NMHDR nmh;
  596. nmh.hwndFrom = *this;
  597. nmh.idFrom = GetDlgCtrlID();
  598. nmh.code = LVNU_SELCHANGED;
  599. GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmh);
  600. }
  601. void CListCtrlEx::ShowTitleTip(CPoint point)
  602. {
  603. int iRow;
  604. int iCol;
  605. if(HitTestRowCol(point, iRow, iCol))
  606. {
  607. CRect cellrect = GetCellRect(iRow, iCol);
  608. // offset is equal to TextExtent of 2 space characters.
  609. // Make sure you have the right font selected into the
  610. // device context before calling GetTextExtent.
  611. // You can save this value as a member variable.
  612. // offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2;
  613. int offset = 6;
  614. /*if(iCol == 0)
  615. {
  616. CRect rcLabel;
  617. GetItemRect(iRow, &rcLabel, LVIR_LABEL );
  618. offset = rcLabel.left - cellrect.left + offset / 2 - 1;
  619. }*/
  620. if(iCol == 0) // TBD: test this with IE4
  621. cellrect.left -= 2; // Does it also move the first column???
  622. cellrect.top--;
  623. if(GetItemState(iRow, LVIS_SELECTED))
  624. {
  625. m_titletip.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
  626. m_titletip.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  627. }
  628. else
  629. {
  630. m_titletip.SetBkColor(m_clrTextBk);
  631. m_titletip.SetTextColor(m_clrText);
  632. }
  633. m_titletip.Show(cellrect, GetTrueItemText(iRow, iCol), offset-1);
  634. }
  635. }
  636. void CListCtrlEx::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  637. {
  638. if( nFontHeight != -1 )
  639. {
  640. lpMeasureItemStruct->itemHeight = nFontHeight + 4 ;
  641. }
  642. CListCtrl::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
  643. }
  644. void CListCtrlEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  645. {
  646. if( nFontHeight != -1 )
  647. {
  648. lpMeasureItemStruct->itemHeight = nFontHeight + 4 ;
  649. }
  650. /*
  651. logfont lf;
  652. getfont()->getlogfont( &lf );
  653. if( lf.lfheight <0 ) lpmeasureitemstruct->itemheight = -lf.lfheight;
  654. else
  655. lpmeasureitemstruct->itemheight = lf.lfheight;
  656. //*/
  657. }
  658. //sendmessage( wm_windowposchanged, 0, (lparam)&wp );