QListCtrl.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. // QListCtrl.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "CP_Main.h"
  5. #include "QListCtrl.h"
  6. #include "ProcessPaste.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. #define ROW_BOTTOM_BORDER 2
  13. #define ROW_LEFT_BORDER 3
  14. #define COLOR_SHADOW RGB(245, 245, 245)
  15. #define DUMMY_COL_WIDTH 1
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CQListCtrl
  18. CQListCtrl::CQListCtrl()
  19. {
  20. m_pchTip = NULL;
  21. m_pwchTip = NULL;
  22. LOGFONT lf;
  23. lf.lfHeight = -9;
  24. lf.lfWidth = 0;
  25. lf.lfEscapement = 0;
  26. lf.lfOrientation = 0;
  27. lf.lfWeight = FW_LIGHT;
  28. lf.lfItalic = FALSE;
  29. lf.lfUnderline = FALSE;
  30. lf.lfStrikeOut = FALSE;
  31. lf.lfCharSet = ANSI_CHARSET;
  32. lf.lfOutPrecision = OUT_STRING_PRECIS;
  33. lf.lfClipPrecision = CLIP_STROKE_PRECIS;
  34. lf.lfQuality = DEFAULT_QUALITY;
  35. lf.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
  36. lstrcpy(lf.lfFaceName, "Small Font");
  37. m_SmallFont = ::CreateFontIndirect(&lf);
  38. m_bShowTextForFirstTenHotKeys = true;
  39. m_bStartTop = true;
  40. }
  41. CQListCtrl::~CQListCtrl()
  42. {
  43. if(m_pchTip != NULL)
  44. delete m_pchTip;
  45. if(m_pwchTip != NULL)
  46. delete m_pwchTip;
  47. if( m_SmallFont )
  48. ::DeleteObject( m_SmallFont );
  49. DestroyAndCreateAccelerator(FALSE);
  50. }
  51. // returns the position 1-10 if the index is in the FirstTen block else -1
  52. int CQListCtrl::GetFirstTenNum( int index )
  53. {
  54. // set firstTenNum to the first ten number (1-10) corresponding to the given index
  55. int firstTenNum = -1; // -1 means that nItem is not in the FirstTen block.
  56. int count = GetItemCount();
  57. if( m_bStartTop )
  58. {
  59. if( 0 <= index && index <= 9 )
  60. firstTenNum = index + 1;
  61. }
  62. else // we are starting at the bottom and going up
  63. {
  64. int idxStartFirstTen = count-10; // start of the FirstTen block
  65. // if index is within the FirstTen block
  66. if( idxStartFirstTen <= index && index < count )
  67. firstTenNum = count - index;
  68. }
  69. return firstTenNum;
  70. }
  71. // returns the list index corresponding to the given FirstTen position number.
  72. // (ret < 0) means that "num" is not in the FirstTen block
  73. int CQListCtrl::GetFirstTenIndex( int num )
  74. {
  75. if( num <= 0 || num > 10 )
  76. return -1;
  77. if( m_bStartTop )
  78. return num-1;
  79. // else we are starting at the bottom and going up
  80. int count = GetItemCount();
  81. return count - num;
  82. }
  83. BEGIN_MESSAGE_MAP(CQListCtrl, CListCtrl)
  84. //{{AFX_MSG_MAP(CQListCtrl)
  85. ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
  86. ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
  87. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdrawList)
  88. ON_WM_SYSKEYDOWN()
  89. ON_WM_ERASEBKGND()
  90. ON_WM_CREATE()
  91. ON_WM_VSCROLL()
  92. ON_WM_HSCROLL()
  93. //}}AFX_MSG_MAP
  94. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
  95. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
  96. ON_WM_KILLFOCUS()
  97. END_MESSAGE_MAP()
  98. /////////////////////////////////////////////////////////////////////////////
  99. // CQListCtrl message handlers
  100. void CQListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
  101. {
  102. LV_KEYDOWN* pLVKeyDown = (LV_KEYDOWN*)pNMHDR;
  103. switch (pLVKeyDown->wVKey)
  104. {
  105. case VK_RETURN:
  106. {
  107. ARRAY arr;
  108. GetSelectionIndexes(arr);
  109. SendSelection(arr);
  110. }
  111. break;
  112. case VK_ESCAPE:
  113. GetParent()->SendMessage(NM_END, 0, 0);
  114. break;
  115. case VK_RIGHT:
  116. {
  117. int nItem = GetNextItem(-1, LVNI_SELECTED);
  118. if (nItem != -1)
  119. GetParent()->SendMessage(NM_RIGHT, nItem, 0);
  120. }
  121. break;
  122. case VK_LEFT:
  123. GetParent()->SendMessage(NM_LEFT, 0, 0);
  124. break;
  125. case VK_DELETE:
  126. GetParent()->SendMessage(NM_DELETE, 0, 0);
  127. break;
  128. }
  129. *pResult = 0;
  130. }
  131. void CQListCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
  132. {
  133. LPNMITEMACTIVATE lpnmItem = (LPNMITEMACTIVATE) pNMHDR;
  134. UINT Flags;
  135. int nItem = -1;
  136. if ((nItem = HitTest(lpnmItem->ptAction, &Flags)) != -1)
  137. {
  138. if (Flags | LVHT_ONITEM)
  139. SendSelection(nItem);
  140. }
  141. *pResult = 0;
  142. }
  143. void CQListCtrl::SendSelection(int nItem)
  144. {
  145. GetParent()->SendMessage(NM_SELECT, 1, (LPARAM) &nItem);
  146. }
  147. void CQListCtrl::SendSelection(ARRAY &arrItems)
  148. {
  149. GetParent()->SendMessage(NM_SELECT, arrItems.GetSize(), (LPARAM) arrItems.GetData());
  150. }
  151. void CQListCtrl::GetSelectionIndexes(ARRAY &arr)
  152. {
  153. arr.RemoveAll();
  154. POSITION pos = GetFirstSelectedItemPosition();
  155. while (pos)
  156. arr.Add(GetNextSelectedItem(pos));
  157. /*
  158. int nItem = GetNextItem(-1, LVNI_SELECTED);
  159. while (nItem != -1)
  160. {
  161. arr.Add(nItem);
  162. nItem = GetNextItem(nItem, LVNI_SELECTED);
  163. }
  164. */
  165. }
  166. void CQListCtrl::GetSelectionItemData(ARRAY &arr)
  167. {
  168. DWORD dwData;
  169. int i;
  170. arr.RemoveAll();
  171. POSITION pos = GetFirstSelectedItemPosition();
  172. while (pos)
  173. {
  174. i = GetNextSelectedItem(pos);
  175. dwData = GetItemData(i);
  176. arr.Add( dwData );
  177. }
  178. /*
  179. int nItem = GetNextItem(-1, LVNI_SELECTED);
  180. while (nItem != -1)
  181. {
  182. arr.Add((int)GetItemData(nItem));
  183. nItem = GetNextItem(nItem, LVNI_SELECTED);
  184. }
  185. */
  186. }
  187. void CQListCtrl::RemoveAllSelection()
  188. {
  189. POSITION pos = GetFirstSelectedItemPosition();
  190. while (pos)
  191. {
  192. SetSelection(GetNextSelectedItem(pos), FALSE);
  193. }
  194. }
  195. BOOL CQListCtrl::SetSelection(int nRow, BOOL bSelect)
  196. {
  197. if(bSelect)
  198. return SetItemState(nRow, LVIS_SELECTED, LVIS_SELECTED);
  199. else
  200. return SetItemState(nRow, ~LVIS_SELECTED, LVIS_SELECTED);
  201. }
  202. BOOL CQListCtrl::SetText(int nRow, int nCol, CString cs)
  203. {
  204. return SetItemText(nRow, nCol, cs);
  205. }
  206. BOOL CQListCtrl::SetCaret(int nRow, BOOL bFocus)
  207. {
  208. if(bFocus)
  209. return SetItemState(nRow, LVIS_FOCUSED, LVIS_FOCUSED);
  210. else
  211. return SetItemState(nRow, ~LVIS_FOCUSED, LVIS_FOCUSED);
  212. }
  213. long CQListCtrl::GetCaret()
  214. {
  215. return GetNextItem(-1, LVNI_FOCUSED);
  216. }
  217. // moves the caret to the given index, selects it, and ensures it is visible.
  218. BOOL CQListCtrl::SetListPos( int index )
  219. {
  220. if( index < 0 || index >= GetItemCount() )
  221. return FALSE;
  222. RemoveAllSelection();
  223. SetCaret(index);
  224. SetSelection(index);
  225. EnsureVisible(index,FALSE);
  226. return TRUE;
  227. }
  228. BOOL CQListCtrl::SetFormattedText(int nRow, int nCol, LPCTSTR lpszFormat,...)
  229. {
  230. CString csText;
  231. va_list vlist;
  232. ASSERT(AfxIsValidString(lpszFormat));
  233. va_start(vlist,lpszFormat);
  234. csText.FormatV(lpszFormat,vlist);
  235. va_end(vlist);
  236. return SetText(nRow,nCol,csText);
  237. }
  238. void CQListCtrl::SetNumberOfLinesPerRow(int nLines)
  239. {
  240. CDC *pDC = GetDC();
  241. CRect crRect(0, 0, 0, 0);
  242. CFont *pOldFont = pDC->SelectObject(GetFont());
  243. //Get the height to draw one character
  244. pDC->DrawText("W", crRect, DT_VCENTER | DT_EXPANDTABS | DT_CALCRECT);
  245. pDC->SelectObject(pOldFont);
  246. //Get the total height of each row
  247. int nHeight = (crRect.Height() * nLines) + ROW_BOTTOM_BORDER;
  248. //Create a image list of that height and set it to the list box
  249. CImageList imglist;
  250. imglist.Create(DUMMY_COL_WIDTH, nHeight, ILC_COLOR16 | ILC_MASK, 1, 1);
  251. SetImageList(&imglist, LVSIL_SMALL );
  252. }
  253. void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
  254. {
  255. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
  256. *pResult = 0;
  257. // Request item-specific notifications if this is the
  258. // beginning of the paint cycle.
  259. if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
  260. {
  261. *pResult = CDRF_NOTIFYITEMDRAW;
  262. }
  263. else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
  264. {
  265. LVITEM rItem;
  266. int nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec );
  267. CDC* pDC = CDC::FromHandle ( pLVCD->nmcd.hdc );
  268. COLORREF crBkgnd;
  269. BOOL bListHasFocus;
  270. CRect rcItem;
  271. bListHasFocus = ( GetSafeHwnd() == ::GetFocus() );
  272. // Get the image index and selected/focused state of the
  273. // item being drawn.
  274. ZeroMemory ( &rItem, sizeof(LVITEM) );
  275. rItem.mask = LVIF_STATE;
  276. rItem.iItem = nItem;
  277. rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  278. GetItem(&rItem);
  279. // Get the rect that bounds the text label.
  280. GetItemRect(nItem, rcItem, LVIR_LABEL);
  281. rcItem.left -= DUMMY_COL_WIDTH;
  282. CPen cpWhite;
  283. cpWhite.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
  284. CPen *pOldPen = NULL;
  285. COLORREF OldColor = -1;
  286. int nOldBKMode = -1;
  287. // Draw the background of the list item. Colors are selected
  288. // according to the item's state.
  289. if(rItem.state & LVIS_SELECTED)
  290. {
  291. if(bListHasFocus)
  292. {
  293. crBkgnd = GetSysColor(COLOR_HIGHLIGHT);
  294. OldColor = pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
  295. pOldPen = pDC->SelectObject((CPen*)&cpWhite);
  296. }
  297. else
  298. {
  299. crBkgnd = GetSysColor(COLOR_BTNFACE);
  300. OldColor = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
  301. }
  302. }
  303. else
  304. {
  305. //Shade alternating Rows
  306. if((nItem % 2) == 0)
  307. crBkgnd = COLOR_SHADOW;
  308. else
  309. crBkgnd = GetSysColor(COLOR_WINDOW);
  310. OldColor = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
  311. }
  312. pDC->FillSolidRect(rcItem, crBkgnd);
  313. nOldBKMode = pDC->SetBkMode(TRANSPARENT);
  314. CRect rcText = rcItem;
  315. rcText.left += ROW_LEFT_BORDER;
  316. rcText.top++;
  317. // Draw the text.
  318. //CString csText = GetItemText(nItem, 0);
  319. CString csText;
  320. LPTSTR lpszText = csText.GetBufferSetLength(g_Opt.m_bDescTextSize);
  321. GetItemText(nItem, 0, lpszText, g_Opt.m_bDescTextSize);
  322. csText.ReleaseBuffer();
  323. // extract symbols
  324. CString strSymbols;
  325. int nSymEnd = csText.Find('|');
  326. if( nSymEnd >= 0 )
  327. {
  328. strSymbols = csText.Left(nSymEnd);
  329. csText = csText.Mid(nSymEnd+1);
  330. }
  331. // set firstTenNum to the first ten number (1-10) corresponding to
  332. // the current nItem.
  333. // -1 means that nItem is not in the FirstTen block.
  334. int firstTenNum = GetFirstTenNum(nItem);
  335. if( m_bShowTextForFirstTenHotKeys && firstTenNum > 0 )
  336. {
  337. rcText.left += 12;
  338. }
  339. // if we are inside a group, don't display the "in group" flag
  340. if( theApp.m_GroupID > 0 )
  341. {
  342. int nFlag = strSymbols.Find("!");
  343. if( nFlag >= 0 )
  344. strSymbols.Delete(nFlag);
  345. }
  346. // draw the symbol box
  347. if( strSymbols.GetLength() > 0 )
  348. {
  349. strSymbols = " " + strSymbols + " "; // leave space for box
  350. // add spaces to leave room for the symbols
  351. CRect rectSym(rcText.left, rcText.top+1, rcText.left, rcText.top+1);
  352. CRect rectSpace(0,0,0,0);
  353. //Get text bounds
  354. pDC->DrawText(" ", &rectSpace, DT_VCENTER | DT_EXPANDTABS | DT_CALCRECT);
  355. pDC->DrawText(strSymbols, &rectSym, DT_VCENTER | DT_EXPANDTABS | DT_CALCRECT);
  356. VERIFY( rectSpace.Width() > 0 );
  357. int numSpaces = rectSym.Width() / rectSpace.Width();
  358. numSpaces++;
  359. csText = CString(' ',numSpaces) + csText;
  360. // draw the symbols
  361. // pDC->FillSolidRect( rectSym, GetSysColor(COLOR_INFOBK) );
  362. pDC->FillSolidRect( rectSym, RGB(0,255,255) );
  363. pDC->Draw3dRect(rectSym, GetSysColor(COLOR_3DLIGHT), GetSysColor(COLOR_3DDKSHADOW));
  364. // COLORREF crOld = pDC->SetTextColor(GetSysColor(COLOR_INFOTEXT));
  365. COLORREF crOld = pDC->SetTextColor(0);
  366. pDC->DrawText(strSymbols, rectSym, DT_VCENTER | DT_EXPANDTABS);
  367. pDC->SetTextColor(crOld);
  368. }
  369. pDC->DrawText(csText, rcText, DT_VCENTER | DT_EXPANDTABS);
  370. // Draw a focus rect around the item if necessary.
  371. if(bListHasFocus && (rItem.state & LVIS_FOCUSED))
  372. pDC->DrawFocusRect(rcItem);
  373. if( m_bShowTextForFirstTenHotKeys && firstTenNum > 0 )
  374. {
  375. CString cs;
  376. if( firstTenNum == 10 )
  377. cs = "0";
  378. else
  379. cs.Format("%d", firstTenNum);
  380. CRect crClient;
  381. GetWindowRect(crClient);
  382. ScreenToClient(crClient);
  383. CRect crHotKey = rcItem;
  384. crHotKey.right = crHotKey.left + 11;
  385. crHotKey.left += 2;
  386. crHotKey.top += 2;
  387. HFONT hOldFont = (HFONT)pDC->SelectObject(m_SmallFont);
  388. pDC->DrawText(cs, crHotKey, DT_BOTTOM);
  389. pDC->MoveTo(CPoint(rcItem.left + 11, rcItem.top));
  390. pDC->LineTo(CPoint(rcItem.left + 11, rcItem.bottom));
  391. pDC->SelectObject(hOldFont);
  392. }
  393. // restore the previous values
  394. if(pOldPen)
  395. pDC->SelectObject(pOldPen);
  396. if(OldColor > -1)
  397. pDC->SetTextColor(OldColor);
  398. if(nOldBKMode > -1)
  399. pDC->SetBkMode(nOldBKMode);
  400. *pResult = CDRF_SKIPDEFAULT; // We've painted everything.
  401. }
  402. }
  403. void CQListCtrl::RefreshVisibleRows()
  404. {
  405. int nTopIndex = GetTopIndex();
  406. int nLastIndex = nTopIndex + GetCountPerPage();
  407. RedrawItems(nTopIndex, nLastIndex);
  408. ::UpdateWindow(m_hWnd);
  409. }
  410. void CQListCtrl::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  411. {
  412. if(GetKeyState(VK_RETURN) & 0x800)
  413. GetParent()->SendMessage(NM_PROPERTIES, 0, 0);
  414. else
  415. CListCtrl::OnSysKeyDown(nChar, nRepCnt, nFlags);
  416. }
  417. BOOL CQListCtrl::OnEraseBkgnd(CDC* pDC)
  418. {
  419. // return TRUE;
  420. return CListCtrl::OnEraseBkgnd(pDC);
  421. }
  422. BOOL CQListCtrl::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
  423. {
  424. // need to handle both ANSI and UNICODE versions of the message
  425. TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
  426. TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
  427. CString strTipText;
  428. UINT nID = pNMHDR->idFrom;
  429. if(nID == 0) // Notification in NT from automatically
  430. return FALSE; // created tooltip
  431. ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 500);
  432. // Use Item's name as the tool tip. Change this for something different.
  433. // Like use its file size, etc.
  434. GetToolTipText(nID-1, strTipText);
  435. //Replace the tabs with spaces, the tooltip didn't like the \t s
  436. strTipText.Replace("\t", " ");
  437. #ifndef _UNICODE
  438. if (pNMHDR->code == TTN_NEEDTEXTA)
  439. {
  440. if(m_pchTip != NULL)
  441. delete m_pchTip;
  442. m_pchTip = new TCHAR[strTipText.GetLength()+1];
  443. lstrcpyn(m_pchTip, strTipText, strTipText.GetLength());
  444. m_pchTip[strTipText.GetLength()] = 0;
  445. pTTTW->lpszText = (WCHAR*)m_pchTip;
  446. }
  447. else
  448. {
  449. if(m_pwchTip != NULL)
  450. delete m_pwchTip;
  451. m_pwchTip = new WCHAR[strTipText.GetLength()+1];
  452. _mbstowcsz(m_pwchTip, strTipText, strTipText.GetLength());
  453. m_pwchTip[strTipText.GetLength()] = 0; // end of text
  454. pTTTW->lpszText = (WCHAR*)m_pwchTip;
  455. }
  456. #else
  457. if(pNMHDR->code == TTN_NEEDTEXTA)
  458. {
  459. if(m_pchTip != NULL)
  460. delete m_pchTip;
  461. m_pchTip = new TCHAR[strTipText.GetLength()+1];
  462. _wcstombsz(m_pchTip, strTipText, strTipText.GetLength());
  463. m_pchTip[strTipText.GetLength()] = 0; // end of text
  464. pTTTA->lpszText = (LPTSTR)m_pchTip;
  465. }
  466. else
  467. {
  468. if(m_pwchTip != NULL)
  469. delete m_pwchTip;
  470. m_pwchTip = new WCHAR[strTipText.GetLength()+1];
  471. lstrcpyn(m_pwchTip, strTipText, strTipText.GetLength());
  472. m_pwchTip[strTipText.GetLength()] = 0;
  473. pTTTA->lpszText = (LPTSTR) m_pwchTip;
  474. }
  475. #endif
  476. *pResult = 0;
  477. return TRUE; // message was handled
  478. }
  479. int CQListCtrl::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
  480. {
  481. CRect rect;
  482. GetClientRect(&rect);
  483. if(rect.PtInRect(point))
  484. {
  485. if(GetItemCount())
  486. {
  487. int nTopIndex = GetTopIndex();
  488. int nBottomIndex = nTopIndex + GetCountPerPage();
  489. if(nBottomIndex > GetItemCount()) nBottomIndex = GetItemCount();
  490. for(int nIndex = nTopIndex; nIndex <= nBottomIndex; nIndex++)
  491. {
  492. GetItemRect(nIndex, rect, LVIR_BOUNDS);
  493. if(rect.PtInRect(point))
  494. {
  495. pTI->hwnd = m_hWnd;
  496. pTI->uId = (UINT)(nIndex+1);
  497. pTI->lpszText = LPSTR_TEXTCALLBACK;
  498. pTI->rect = rect;
  499. return pTI->uId;
  500. }
  501. }
  502. }
  503. }
  504. return -1;
  505. }
  506. int CQListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
  507. {
  508. if (CListCtrl::OnCreate(lpCreateStruct) == -1)
  509. return -1;
  510. EnableToolTips();
  511. m_Popup.Init();
  512. // m_Popup.SetTTWnd( GetToolTips()->m_hWnd );
  513. // m_Popup.m_TI.hwnd = m_hWnd;
  514. return 0;
  515. }
  516. BOOL CQListCtrl::PreTranslateMessage(MSG* pMsg)
  517. {
  518. DWORD dID;
  519. if(m_Accels.OnMsg(pMsg, dID))
  520. if(GetParent()->SendMessage(NM_SELECT_DB_ID, dID, 0) )
  521. return TRUE;
  522. switch(pMsg->message)
  523. {
  524. case WM_LBUTTONDOWN:
  525. case WM_RBUTTONDOWN:
  526. if(m_Popup.m_bIsShowing)
  527. {
  528. m_Popup.Hide();
  529. }
  530. break;
  531. case WM_KEYDOWN:
  532. WPARAM vk = pMsg->wParam;
  533. if(m_Popup.m_bIsShowing)
  534. {
  535. m_Popup.Hide();
  536. if(vk == VK_ESCAPE)
  537. return TRUE;
  538. }
  539. // if a number key was pressed
  540. if( '0' <= vk && vk <= '9' )
  541. {
  542. // if <Ctrl> is required but is absent, then break
  543. if( g_Opt.m_bUseCtrlNumAccel && !(GetKeyState(VK_CONTROL) & 0x8000) )
  544. break;
  545. int index = vk - '0';
  546. // '0' is actually 10 in the ditto window
  547. if( index == 0 )
  548. index = 10;
  549. // translate num 1-10 into the actual index (based upon m_bStartTop)
  550. index = GetFirstTenIndex( index );
  551. GetParent()->SendMessage(NM_SELECT_INDEX, index, 0);
  552. return TRUE;
  553. }
  554. switch( vk )
  555. {
  556. case 'X': // Ctrl-X = Cut (prepare for moving the items into a Group)
  557. if(GetKeyState(VK_CONTROL) & 0x8000)
  558. {
  559. theApp.IC_Cut(); // uses selection
  560. return TRUE;
  561. }
  562. break;
  563. case 'C': // Ctrl-C = Copy (prepare for copying the items into a Group)
  564. if(GetKeyState(VK_CONTROL) & 0x8000)
  565. {
  566. theApp.IC_Copy(); // uses selection
  567. return TRUE;
  568. }
  569. break;
  570. case 'V': // Ctrl-V = Paste (actually performs the copy or move of items into the current Group)
  571. if(GetKeyState(VK_CONTROL) & 0x8000)
  572. {
  573. theApp.IC_Paste();
  574. return TRUE;
  575. }
  576. break;
  577. case 'A': // Ctrl-A = Select All
  578. if(GetKeyState(VK_CONTROL) & 0x8000)
  579. {
  580. int nCount = GetItemCount();
  581. for(int i = 0; i < nCount; i++)
  582. {
  583. SetSelection(i);
  584. }
  585. return TRUE;
  586. }
  587. break;
  588. case VK_F3:
  589. {
  590. ShowFullDescription();
  591. return TRUE;
  592. break;
  593. }
  594. } // end switch(vk)
  595. break; // end case WM_KEYDOWN
  596. } // end switch(pMsg->message)
  597. return CListCtrl::PreTranslateMessage(pMsg);
  598. }
  599. void CQListCtrl::ShowFullDescription()
  600. {
  601. int nItem = GetCaret();
  602. CRect rc;
  603. GetItemRect(nItem, rc, LVIR_BOUNDS);
  604. ClientToScreen(rc);
  605. m_Popup.m_Pos = CPoint(rc.left, rc.bottom); // rc.top??
  606. CString cs;
  607. GetToolTipText(nItem, cs);
  608. m_Popup.Show( cs );
  609. }
  610. void CQListCtrl::GetToolTipText(int nItem, CString &csText)
  611. {
  612. if((GetStyle() & LVS_OWNERDATA))
  613. {
  614. CWnd* pParent=GetParent();
  615. if(pParent && (pParent->GetSafeHwnd() != NULL))
  616. {
  617. CQListToolTipText info;
  618. memset(&info, 0, sizeof(info));
  619. info.hdr.code = NM_GETTOOLTIPTEXT;
  620. info.hdr.hwndFrom = GetSafeHwnd();
  621. info.hdr.idFrom = GetDlgCtrlID();
  622. info.lItem = nItem;
  623. //plus 100 for extra info - shortcut and such
  624. info.cchTextMax = g_Opt.m_bDescTextSize + 100;
  625. info.pszText = csText.GetBufferSetLength(info.cchTextMax);
  626. pParent->SendMessage(WM_NOTIFY,(WPARAM)info.hdr.idFrom,(LPARAM)&info);
  627. csText.ReleaseBuffer();
  628. }
  629. }
  630. }
  631. DWORD CQListCtrl::GetItemData(int nItem)
  632. {
  633. if((GetStyle() & LVS_OWNERDATA))
  634. {
  635. CWnd* pParent=GetParent();
  636. if(pParent && (pParent->GetSafeHwnd() != NULL))
  637. {
  638. LV_DISPINFO info;
  639. memset(&info, 0, sizeof(info));
  640. info.hdr.code = LVN_GETDISPINFO;
  641. info.hdr.hwndFrom = GetSafeHwnd();
  642. info.hdr.idFrom = GetDlgCtrlID();
  643. info.item.iItem = nItem;
  644. info.item.lParam = -1;
  645. info.item.mask = LVIF_PARAM;
  646. pParent->SendMessage(WM_NOTIFY,(WPARAM)info.hdr.idFrom,(LPARAM)&info);
  647. return info.item.lParam;
  648. }
  649. }
  650. return CListCtrl::GetItemData(nItem);
  651. }
  652. void CQListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  653. {
  654. CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
  655. }
  656. void CQListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  657. {
  658. CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
  659. }
  660. void CQListCtrl::DestroyAndCreateAccelerator(BOOL bCreate)
  661. {
  662. if( bCreate )
  663. CMainTable::LoadAcceleratorKeys( m_Accels );
  664. }
  665. void CQListCtrl::OnKillFocus(CWnd* pNewWnd)
  666. {
  667. CListCtrl::OnKillFocus(pNewWnd);
  668. m_Popup.Hide();
  669. }
  670. BOOL CQListCtrl::SetItemCountEx(int iCount, DWORD dwFlags /* = LVSICF_NOINVALIDATEALL */)
  671. {
  672. theApp.SetStatus(NULL, TRUE);
  673. return CListCtrl::SetItemCountEx(iCount, dwFlags);
  674. }