QListCtrl.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467
  1. // QListCtrl.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "CP_Main.h"
  5. #include "QListCtrl.h"
  6. #include "ProcessPaste.h"
  7. #include "BitmapHelper.h"
  8. #include "MainTableFunctions.h"
  9. #include "DittoCopyBuffer.h"
  10. #include <atlbase.h>
  11. #include "DrawHTML.h"
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. #define ROW_BOTTOM_BORDER 2
  18. #define ROW_LEFT_BORDER 3
  19. #define COLOR_SHADOW RGB(245, 245, 245)
  20. #define DUMMY_COL_WIDTH 1
  21. #define TIMER_SHOW_PROPERTIES 1
  22. #define TIMER_HIDE_SCROL 2
  23. #define TIMER_SHOW_SCROLL 3
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CQListCtrl
  26. CQListCtrl::CQListCtrl()
  27. {
  28. m_pchTip = NULL;
  29. m_pwchTip = NULL;
  30. m_linesPerRow = 1;
  31. LOGFONT lf;
  32. lf.lfHeight = theApp.m_metrics.PointsToPixels(-7);
  33. lf.lfWidth = 0;
  34. lf.lfEscapement = 0;
  35. lf.lfOrientation = 0;
  36. lf.lfWeight = FW_LIGHT;
  37. lf.lfItalic = FALSE;
  38. lf.lfUnderline = FALSE;
  39. lf.lfStrikeOut = FALSE;
  40. lf.lfCharSet = ANSI_CHARSET;
  41. lf.lfOutPrecision = OUT_STRING_PRECIS;
  42. lf.lfClipPrecision = CLIP_STROKE_PRECIS;
  43. lf.lfQuality = DEFAULT_QUALITY;
  44. lf.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
  45. lstrcpy(lf.lfFaceName, _T("Small Font"));
  46. m_SmallFont = ::CreateFontIndirect(&lf);
  47. m_bShowTextForFirstTenHotKeys = true;
  48. m_bStartTop = true;
  49. m_pToolTip = NULL;
  50. m_pFormatter = NULL;
  51. m_allSelected = false;
  52. m_rowHeight = 50;
  53. m_mouseOverScrollAreaStart = 0;
  54. m_groupFolder.LoadStdImageDPI(IDB_OPEN_FOLDER_16_16, IDB_OPEN_FOLDER_20_20, IDB_OPEN_FOLDER_24_24, IDB_OPEN_FOLDER_32_32, _T("PNG"));
  55. m_dontDeleteImage.LoadStdImageDPI(IDB_YELLOW_STAR_16_16, IDB_YELLOW_STAR_20_20, IDB_YELLOW_STAR_24_24, IDB_YELLOW_STAR_32_32, _T("PNG"));
  56. m_inFolderImage.LoadStdImageDPI(IDB_IN_FOLDER_16_16, IDB_IN_FOLDER_20_20, IDB_IN_FOLDER_24_24, IDB_IN_FOLDER_32_32, _T("PNG"));
  57. m_shortCutImage.LoadStdImageDPI(IDB_KEY_16_16, IDB_KEY_20_20, IDB_KEY_24_24, IDB_KEY_32_32, _T("PNG"));
  58. m_stickyImage.LoadStdImageDPI(IDB_STICKY_16_16, IDB_STICKY_20_20, IDB_STICKY_24_24, IDB_STICKY_32_32, _T("PNG"));
  59. }
  60. CQListCtrl::~CQListCtrl()
  61. {
  62. if(m_pchTip != NULL)
  63. delete m_pchTip;
  64. if(m_pwchTip != NULL)
  65. delete m_pwchTip;
  66. if( m_SmallFont )
  67. ::DeleteObject( m_SmallFont );
  68. m_Font.DeleteObject();
  69. if(m_pFormatter)
  70. {
  71. delete m_pFormatter;
  72. m_pFormatter = NULL;
  73. }
  74. }
  75. // returns the position 1-10 if the index is in the FirstTen block else -1
  76. int CQListCtrl::GetFirstTenNum( int index )
  77. {
  78. // set firstTenNum to the first ten number (1-10) corresponding to the given index
  79. int firstTenNum = -1; // -1 means that nItem is not in the FirstTen block.
  80. int count = GetItemCount();
  81. if( m_bStartTop )
  82. {
  83. if( 0 <= index && index <= 9 )
  84. firstTenNum = index + 1;
  85. }
  86. else // we are starting at the bottom and going up
  87. {
  88. int idxStartFirstTen = count-10; // start of the FirstTen block
  89. // if index is within the FirstTen block
  90. if( idxStartFirstTen <= index && index < count )
  91. firstTenNum = count - index;
  92. }
  93. return firstTenNum;
  94. }
  95. // returns the list index corresponding to the given FirstTen position number.
  96. // (ret < 0) means that "num" is not in the FirstTen block
  97. int CQListCtrl::GetFirstTenIndex( int num )
  98. {
  99. if( num <= 0 || num > 10 )
  100. return -1;
  101. if( m_bStartTop )
  102. return num-1;
  103. // else we are starting at the bottom and going up
  104. int count = GetItemCount();
  105. return count - num;
  106. }
  107. BEGIN_MESSAGE_MAP(CQListCtrl, CListCtrl)
  108. //{{AFX_MSG_MAP(CQListCtrl)
  109. ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
  110. ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
  111. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdrawList)
  112. ON_WM_MOUSEMOVE()
  113. ON_WM_SYSKEYDOWN()
  114. ON_WM_ERASEBKGND()
  115. ON_WM_CREATE()
  116. ON_WM_HSCROLL()
  117. ON_WM_TIMER()
  118. ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnSelectionChange)
  119. ON_WM_VSCROLL()
  120. ON_WM_WINDOWPOSCHANGED()
  121. ON_WM_MOUSEWHEEL()
  122. //}}AFX_MSG_MAP
  123. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
  124. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
  125. ON_WM_KILLFOCUS()
  126. ON_WM_MEASUREITEM_REFLECT()
  127. END_MESSAGE_MAP()
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CQListCtrl message handlers
  130. void CQListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
  131. {
  132. LV_KEYDOWN* pLVKeyDown = (LV_KEYDOWN*)pNMHDR;
  133. *pResult = 0;
  134. }
  135. DROPEFFECT CQListCtrl::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
  136. {
  137. return DROPEFFECT_COPY;
  138. }
  139. void CQListCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
  140. {
  141. LPNMITEMACTIVATE lpnmItem = (LPNMITEMACTIVATE) pNMHDR;
  142. UINT Flags;
  143. int nItem = -1;
  144. if ((nItem = HitTest(lpnmItem->ptAction, &Flags)) != -1)
  145. {
  146. if (Flags | LVHT_ONITEM)
  147. SendSelection(nItem);
  148. }
  149. *pResult = 0;
  150. }
  151. void CQListCtrl::SendSelection(int nItem)
  152. {
  153. GetParent()->SendMessage(NM_SELECT, 1, (LPARAM) &nItem);
  154. }
  155. void CQListCtrl::SendSelection(ARRAY &arrItems)
  156. {
  157. GetParent()->SendMessage(NM_SELECT, arrItems.GetSize(), (LPARAM) arrItems.GetData());
  158. }
  159. void CQListCtrl::GetSelectionIndexes(ARRAY &arr)
  160. {
  161. arr.RemoveAll();
  162. POSITION pos = GetFirstSelectedItemPosition();
  163. while (pos)
  164. {
  165. arr.Add(GetNextSelectedItem(pos));
  166. }
  167. }
  168. bool CQListCtrl::PutSelectedItemOnDittoCopyBuffer(long lBuffer)
  169. {
  170. bool bRet = false;
  171. ARRAY arr;
  172. GetSelectionItemData(arr);
  173. INT_PTR nCount = arr.GetSize();
  174. if(nCount > 0 && arr[0])
  175. {
  176. CDittoCopyBuffer::PutClipOnDittoCopyBuffer(arr[0], lBuffer);
  177. bRet = true;
  178. }
  179. return bRet;
  180. }
  181. void CQListCtrl::GetSelectionItemData(ARRAY &arr)
  182. {
  183. DWORD dwData;
  184. int i;
  185. arr.RemoveAll();
  186. POSITION pos = GetFirstSelectedItemPosition();
  187. while (pos)
  188. {
  189. i = GetNextSelectedItem(pos);
  190. dwData = GetItemData(i);
  191. arr.Add( dwData );
  192. }
  193. }
  194. void CQListCtrl::RemoveAllSelection()
  195. {
  196. POSITION pos = GetFirstSelectedItemPosition();
  197. while (pos)
  198. {
  199. SetSelection(GetNextSelectedItem(pos), FALSE);
  200. }
  201. }
  202. BOOL CQListCtrl::SetSelection(int nRow, BOOL bSelect)
  203. {
  204. if(bSelect)
  205. return SetItemState(nRow, LVIS_SELECTED, LVIS_SELECTED);
  206. else
  207. return SetItemState(nRow, ~LVIS_SELECTED, LVIS_SELECTED);
  208. }
  209. BOOL CQListCtrl::SetText(int nRow, int nCol, CString cs)
  210. {
  211. return SetItemText(nRow, nCol, cs);
  212. }
  213. BOOL CQListCtrl::SetCaret(int nRow, BOOL bFocus)
  214. {
  215. if(bFocus)
  216. return SetItemState(nRow, LVIS_FOCUSED, LVIS_FOCUSED);
  217. else
  218. return SetItemState(nRow, ~LVIS_FOCUSED, LVIS_FOCUSED);
  219. }
  220. long CQListCtrl::GetCaret()
  221. {
  222. return GetNextItem(-1, LVNI_FOCUSED);
  223. }
  224. // moves the caret to the given index, selects it, and ensures it is visible.
  225. BOOL CQListCtrl::SetListPos( int index )
  226. {
  227. if( index < 0 || index >= GetItemCount() )
  228. return FALSE;
  229. RemoveAllSelection();
  230. SetCaret(index);
  231. SetSelection(index);
  232. EnsureVisible(index,FALSE);
  233. return TRUE;
  234. }
  235. BOOL CQListCtrl::SetFormattedText(int nRow, int nCol, LPCTSTR lpszFormat,...)
  236. {
  237. CString csText;
  238. va_list vlist;
  239. ASSERT(AfxIsValidString(lpszFormat));
  240. va_start(vlist,lpszFormat);
  241. csText.FormatV(lpszFormat,vlist);
  242. va_end(vlist);
  243. return SetText(nRow,nCol,csText);
  244. }
  245. void CQListCtrl::SetNumberOfLinesPerRow(int nLines)
  246. {
  247. if(m_linesPerRow != nLines)
  248. {
  249. m_linesPerRow = nLines;
  250. CRect rc;
  251. GetWindowRect( &rc );
  252. WINDOWPOS wp;
  253. wp.hwnd = m_hWnd;
  254. wp.cx = rc.Width();
  255. wp.cy = rc.Height();
  256. wp.flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER;
  257. SendMessage( WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp );
  258. }
  259. }
  260. void CQListCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  261. {
  262. TEXTMETRIC tm;
  263. HDC hDC = ::GetDC(NULL);
  264. CFont* pFont = GetFont();
  265. HFONT hFontOld = (HFONT)SelectObject(hDC, pFont->GetSafeHandle());
  266. GetTextMetrics(hDC, &tm);
  267. lpMeasureItemStruct->itemHeight = ((tm.tmHeight + tm.tmExternalLeading) * m_linesPerRow) + ROW_BOTTOM_BORDER;
  268. m_rowHeight = lpMeasureItemStruct->itemHeight;
  269. SelectObject(hDC, hFontOld);
  270. ::ReleaseDC(NULL, hDC);
  271. }
  272. void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
  273. {
  274. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
  275. *pResult = 0;
  276. // Request item-specific notifications if this is the
  277. // beginning of the paint cycle.
  278. if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
  279. {
  280. *pResult = CDRF_NOTIFYITEMDRAW;
  281. }
  282. else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
  283. {
  284. LVITEM rItem;
  285. int nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec );
  286. CDC* pDC = CDC::FromHandle ( pLVCD->nmcd.hdc );
  287. COLORREF crBkgnd;
  288. BOOL bListHasFocus;
  289. CRect rcItem;
  290. bListHasFocus = ( GetSafeHwnd() == ::GetFocus() );
  291. // Get the image index and selected/focused state of the
  292. // item being drawn.
  293. ZeroMemory ( &rItem, sizeof(LVITEM) );
  294. rItem.mask = LVIF_STATE;
  295. rItem.iItem = nItem;
  296. rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  297. GetItem(&rItem);
  298. // Get the rect that bounds the text label.
  299. GetItemRect(nItem, rcItem, LVIR_LABEL);
  300. rcItem.left -= DUMMY_COL_WIDTH;
  301. COLORREF OldColor = -1;
  302. int nOldBKMode = -1;
  303. CString csText;
  304. LPTSTR lpszText = csText.GetBufferSetLength(g_Opt.m_bDescTextSize);
  305. GetItemText(nItem, 0, lpszText, g_Opt.m_bDescTextSize);
  306. csText.ReleaseBuffer();
  307. // extract symbols
  308. CString strSymbols;
  309. int nSymEnd = csText.Find('|');
  310. if (nSymEnd >= 0)
  311. {
  312. strSymbols = csText.Left(nSymEnd);
  313. csText = csText.Mid(nSymEnd + 1);
  314. }
  315. // Draw the background of the list item. Colors are selected
  316. // according to the item's state.
  317. if(rItem.state & LVIS_SELECTED)
  318. {
  319. if(bListHasFocus)
  320. {
  321. crBkgnd = g_Opt.m_Theme.ListBoxSelectedBG();
  322. OldColor = pDC->SetTextColor(g_Opt.m_Theme.ListBoxSelectedText());
  323. }
  324. else
  325. {
  326. crBkgnd = g_Opt.m_Theme.ListBoxSelectedNoFocusBG();
  327. OldColor = pDC->SetTextColor(g_Opt.m_Theme.ListBoxSelectedNoFocusText());
  328. }
  329. }
  330. else
  331. {
  332. //Shade alternating Rows
  333. if((nItem % 2) == 0)
  334. {
  335. crBkgnd = g_Opt.m_Theme.ListBoxOddRowsBG();
  336. OldColor = pDC->SetTextColor(g_Opt.m_Theme.ListBoxOddRowsText());
  337. }
  338. else
  339. {
  340. crBkgnd = g_Opt.m_Theme.ListBoxEvenRowsBG();
  341. OldColor = pDC->SetTextColor(g_Opt.m_Theme.ListBoxEvenRowsText());
  342. }
  343. }
  344. pDC->FillSolidRect(rcItem, crBkgnd);
  345. nOldBKMode = pDC->SetBkMode(TRANSPARENT);
  346. CRect rcText = rcItem;
  347. rcText.left += ROW_LEFT_BORDER;
  348. rcText.top++;
  349. // set firstTenNum to the first ten number (1-10) corresponding to
  350. // the current nItem.
  351. // -1 means that nItem is not in the FirstTen block.
  352. int firstTenNum = GetFirstTenNum(nItem);
  353. if( m_bShowTextForFirstTenHotKeys && firstTenNum > 0 )
  354. {
  355. rcText.left += theApp.m_metrics.ScaleX(12);
  356. }
  357. // if we are inside a group, don't display the "in group" flag
  358. if( theApp.m_GroupID > 0 )
  359. {
  360. int nFlag = strSymbols.Find(_T("!"));
  361. if( nFlag >= 0 )
  362. strSymbols.Delete(nFlag);
  363. }
  364. DrawBitMap(nItem, rcText, pDC, csText);
  365. // draw the symbol box
  366. if( strSymbols.GetLength() > 0 )
  367. {
  368. if(strSymbols.Find('G') >= 0) //group
  369. {
  370. m_groupFolder.Draw(pDC, this, rcText.left, rcText.top, false, false);
  371. rcText.left += m_groupFolder.ImageWidth() + theApp.m_metrics.ScaleX(2);
  372. }
  373. if (strSymbols.Find('*') >= 0 &&
  374. strSymbols.Find('G') < 0 &&
  375. strSymbols.Find(_T("sticky")) < 0) //don't auto delete
  376. {
  377. m_dontDeleteImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
  378. rcText.left += m_dontDeleteImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
  379. }
  380. if (strSymbols.Find('s') >= 0) // has shortcut
  381. {
  382. m_shortCutImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
  383. rcText.left += m_shortCutImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
  384. }
  385. if (strSymbols.Find('!') >= 0) // in group
  386. {
  387. m_inFolderImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
  388. rcText.left += m_inFolderImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
  389. }
  390. if (strSymbols.Find('Q') >= 0) // has quick paste text
  391. {
  392. }
  393. if (strSymbols.Find(_T("Sticky")) >= 0) //sticky clip
  394. {
  395. m_stickyImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
  396. rcText.left += m_stickyImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
  397. }
  398. }
  399. if(DrawRtfText(nItem, rcText, pDC) == FALSE)
  400. {
  401. if (m_searchText.GetLength() > 0 &&
  402. FindNoCaseAndInsert(csText, m_searchText, _T("<font color='#ff0000'>"), _T("</font>")) > 0)
  403. {
  404. DrawHTML(pDC->m_hDC, csText, csText.GetLength(), rcText, DT_VCENTER | DT_EXPANDTABS | DT_NOPREFIX);
  405. }
  406. else
  407. {
  408. pDC->DrawText(csText, rcText, DT_VCENTER | DT_EXPANDTABS | DT_NOPREFIX);
  409. }
  410. }
  411. // Draw a focus rect around the item if necessary.
  412. if(bListHasFocus && (rItem.state & LVIS_FOCUSED))
  413. pDC->DrawFocusRect(rcItem);
  414. if( m_bShowTextForFirstTenHotKeys && firstTenNum > 0 )
  415. {
  416. CString cs;
  417. if( firstTenNum == 10 )
  418. cs = "0";
  419. else
  420. cs.Format(_T("%d"), firstTenNum);
  421. CRect crClient;
  422. GetWindowRect(crClient);
  423. ScreenToClient(crClient);
  424. CRect crHotKey = rcItem;
  425. crHotKey.right = crHotKey.left + theApp.m_metrics.ScaleX(11);
  426. crHotKey.left += theApp.m_metrics.ScaleX(2);
  427. crHotKey.top += theApp.m_metrics.ScaleX(2);
  428. HFONT hOldFont = (HFONT)pDC->SelectObject(m_SmallFont);
  429. pDC->DrawText(cs, crHotKey, DT_BOTTOM);
  430. pDC->MoveTo(CPoint(rcItem.left + theApp.m_metrics.ScaleX(11), rcItem.top));
  431. pDC->LineTo(CPoint(rcItem.left + theApp.m_metrics.ScaleX(11), rcItem.bottom));
  432. pDC->SelectObject(hOldFont);
  433. }
  434. // restore the previous values
  435. if(OldColor > -1)
  436. pDC->SetTextColor(OldColor);
  437. if(nOldBKMode > -1)
  438. pDC->SetBkMode(nOldBKMode);
  439. *pResult = CDRF_SKIPDEFAULT; // We've painted everything.
  440. }
  441. }
  442. BOOL CQListCtrl::DrawRtfText(int nItem, CRect &crRect, CDC *pDC)
  443. {
  444. if(g_Opt.m_bDrawRTF == FALSE)
  445. return FALSE;
  446. BOOL bRet = FALSE;
  447. CClipFormat* pThumbnail = GetItem_CF_RTF_ClipFormat(nItem);
  448. if(pThumbnail == NULL)
  449. return FALSE;
  450. // if there's no data, then we're done.
  451. if(pThumbnail->m_hgData == NULL)
  452. return FALSE;
  453. if(m_pFormatter == NULL)
  454. {
  455. m_pFormatter = new CFormattedTextDraw;
  456. m_pFormatter->Create();
  457. }
  458. if(m_pFormatter)
  459. {
  460. char *pData = (char*)GlobalLock(pThumbnail->m_hgData);
  461. if(pData)
  462. {
  463. CComBSTR bStr(pData);
  464. m_pFormatter->put_RTFText(bStr);
  465. m_pFormatter->Draw(pDC->m_hDC, crRect);
  466. GlobalUnlock(pThumbnail->m_hgData);
  467. bRet = TRUE;
  468. }
  469. }
  470. return bRet;
  471. }
  472. // DrawBitMap loads a DIB from the DB, draws a crRect thumbnail of the image
  473. // to pDC and caches that thumbnail as a DIB in m_ThumbNails[ ItemID ].
  474. // ALL items are cached in m_ThumbNails (those without images are cached with NULL m_hgData)
  475. BOOL CQListCtrl::DrawBitMap(int nItem, CRect &crRect, CDC *pDC, const CString &csDescription)
  476. {
  477. if(g_Opt.m_bDrawThumbnail == FALSE)
  478. return FALSE;
  479. CClipFormatQListCtrl *format = GetItem_CF_DIB_ClipFormat(nItem);
  480. if(format != NULL)
  481. {
  482. HGLOBAL smallImage = format->GetDib(pDC, crRect.Height());
  483. if(smallImage != NULL)
  484. {
  485. //Will return the width of the bitmap in nWidth
  486. int nWidth = 0;
  487. if(CBitmapHelper::DrawDIB(pDC, smallImage, crRect.left, crRect.top, nWidth))
  488. {
  489. // adjust the rect so other information can be drawn next to the thumbnail
  490. crRect.left += nWidth + 3;
  491. }
  492. }
  493. }
  494. else if(csDescription.Find(_T("CF_DIB")) == 0)
  495. {
  496. crRect.left += crRect.Height();
  497. }
  498. return TRUE;
  499. }
  500. void CQListCtrl::RefreshVisibleRows()
  501. {
  502. int nTopIndex = GetTopIndex();
  503. int nLastIndex = nTopIndex + GetCountPerPage();
  504. RedrawItems(nTopIndex, nLastIndex);
  505. }
  506. void CQListCtrl::RefreshRow(int row)
  507. {
  508. RedrawItems(row, row);
  509. }
  510. void CQListCtrl::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  511. {
  512. CListCtrl::OnSysKeyDown(nChar, nRepCnt, nFlags);
  513. }
  514. BOOL CQListCtrl::OnEraseBkgnd(CDC* pDC)
  515. {
  516. // Simply returning TRUE seems OK since we do custom item
  517. // painting. However, there is a pixel buffer around the
  518. // border of this control (not within the item rects)
  519. // which becomes visually corrupt if it is not erased.
  520. // In most cases, I do not notice the erasure, so I have kept
  521. // the call to CListCtrl::OnEraseBkgnd(pDC);
  522. // However, for some reason, bulk erasure is very noticeable when
  523. // shift-scrolling the page to select a block of items, so
  524. // I made a special case for that:
  525. if(GetSelectedCount() >= 2)
  526. return TRUE;
  527. return CListCtrl::OnEraseBkgnd(pDC);
  528. }
  529. BOOL CQListCtrl::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
  530. {
  531. // need to handle both ANSI and UNICODE versions of the message
  532. TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
  533. TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
  534. CString strTipText;
  535. UINT_PTR nID = pNMHDR->idFrom;
  536. if(nID == 0) // Notification in NT from automatically
  537. return FALSE; // created tooltip
  538. ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 500);
  539. // Use Item's name as the tool tip. Change this for something different.
  540. // Like use its file size, etc.
  541. GetToolTipText((int)nID-1, strTipText);
  542. //Replace the tabs with spaces, the tooltip didn't like the \t s
  543. strTipText.Replace(_T("\t"), _T(" "));
  544. int nLength = strTipText.GetLength()+2;
  545. #ifndef _UNICODE
  546. if (pNMHDR->code == TTN_NEEDTEXTA)
  547. {
  548. if(m_pchTip != NULL)
  549. delete m_pchTip;
  550. m_pchTip = new TCHAR[nLength];
  551. lstrcpyn(m_pchTip, strTipText, nLength-1);
  552. m_pchTip[nLength-1] = 0;
  553. pTTTW->lpszText = (WCHAR*)m_pchTip;
  554. }
  555. else
  556. {
  557. if(m_pwchTip != NULL)
  558. delete m_pwchTip;
  559. m_pwchTip = new WCHAR[nLength];
  560. _mbstowcsz(m_pwchTip, strTipText, nLength-1);
  561. m_pwchTip[nLength-1] = 0; // end of text
  562. pTTTW->lpszText = (WCHAR*)m_pwchTip;
  563. }
  564. #else
  565. if(pNMHDR->code == TTN_NEEDTEXTA)
  566. {
  567. if(m_pchTip != NULL)
  568. delete m_pchTip;
  569. m_pchTip = new TCHAR[nLength];
  570. STRNCPY(m_pchTip, strTipText, nLength-1);
  571. m_pchTip[nLength-1] = 0; // end of text
  572. pTTTW->lpszText = (LPTSTR)m_pchTip;
  573. }
  574. else
  575. {
  576. if(m_pwchTip != NULL)
  577. delete m_pwchTip;
  578. m_pwchTip = new WCHAR[nLength];
  579. lstrcpyn(m_pwchTip, strTipText, nLength-1);
  580. m_pwchTip[nLength-1] = 0;
  581. pTTTW->lpszText = (LPTSTR) m_pwchTip;
  582. }
  583. #endif
  584. *pResult = 0;
  585. return TRUE; // message was handled
  586. }
  587. INT_PTR CQListCtrl::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
  588. {
  589. CRect rect;
  590. GetClientRect(&rect);
  591. if(rect.PtInRect(point))
  592. {
  593. if(GetItemCount())
  594. {
  595. int nTopIndex = GetTopIndex();
  596. int nBottomIndex = nTopIndex + GetCountPerPage();
  597. if(nBottomIndex > GetItemCount()) nBottomIndex = GetItemCount();
  598. for(int nIndex = nTopIndex; nIndex <= nBottomIndex; nIndex++)
  599. {
  600. GetItemRect(nIndex, rect, LVIR_BOUNDS);
  601. if(rect.PtInRect(point))
  602. {
  603. pTI->hwnd = m_hWnd;
  604. pTI->uId = (UINT)(nIndex+1);
  605. pTI->lpszText = LPSTR_TEXTCALLBACK;
  606. pTI->rect = rect;
  607. return pTI->uId;
  608. }
  609. }
  610. }
  611. }
  612. return -1;
  613. }
  614. int CQListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
  615. {
  616. if (CListCtrl::OnCreate(lpCreateStruct) == -1)
  617. return -1;
  618. EnableToolTips();
  619. m_pToolTip = new CToolTipEx;
  620. m_pToolTip->Create(this);
  621. m_pToolTip->SetNotifyWnd(GetParent());
  622. return 0;
  623. }
  624. BOOL CQListCtrl::PreTranslateMessage(MSG* pMsg)
  625. {
  626. DWORD dID;
  627. if(m_Accels.OnMsg(pMsg, dID))
  628. {
  629. switch(dID)
  630. {
  631. case COPY_BUFFER_HOT_KEY_1_ID:
  632. PutSelectedItemOnDittoCopyBuffer(0);
  633. break;
  634. case COPY_BUFFER_HOT_KEY_2_ID:
  635. PutSelectedItemOnDittoCopyBuffer(1);
  636. break;
  637. case COPY_BUFFER_HOT_KEY_3_ID:
  638. PutSelectedItemOnDittoCopyBuffer(2);
  639. break;
  640. default:
  641. GetParent()->SendMessage(NM_SELECT_DB_ID, dID, 0);
  642. }
  643. return TRUE;
  644. }
  645. if(m_pToolTip)
  646. {
  647. if(m_pToolTip->OnMsg(pMsg))
  648. return TRUE;
  649. }
  650. switch(pMsg->message)
  651. {
  652. case WM_KEYDOWN:
  653. if(HandleKeyDown(pMsg->wParam, pMsg->lParam))
  654. return TRUE;
  655. break; // end case WM_KEYDOWN
  656. case WM_VSCROLL:
  657. ASSERT(FALSE);
  658. break;
  659. } // end switch(pMsg->message)
  660. return CListCtrl::PreTranslateMessage(pMsg);
  661. }
  662. BOOL CQListCtrl::HandleKeyDown(WPARAM wParam, LPARAM lParam)
  663. {
  664. if(m_pToolTip)
  665. {
  666. MSG Msg;
  667. Msg.lParam = lParam;
  668. Msg.wParam = wParam;
  669. Msg.message = WM_KEYDOWN;
  670. if(m_pToolTip->OnMsg(&Msg))
  671. return TRUE;
  672. }
  673. WPARAM vk = wParam;
  674. // if a number key was pressed
  675. if('0' <= vk && vk <= '9')
  676. {
  677. // if <Ctrl> is required but is absent, then break
  678. if(g_Opt.m_bUseCtrlNumAccel && !(GetKeyState(VK_CONTROL) & 0x8000))
  679. return FALSE;
  680. int index = (int)vk - '0';
  681. // '0' is actually 10 in the ditto window
  682. if(index == 0)
  683. index = 10;
  684. // translate num 1-10 into the actual index (based upon m_bStartTop)
  685. index = GetFirstTenIndex(index);
  686. GetParent()->SendMessage(NM_SELECT_INDEX, index, 0);
  687. return TRUE;
  688. }
  689. if(VK_NUMPAD0 <= vk && vk <= VK_NUMPAD9)
  690. {
  691. // if <Ctrl> is required but is absent, then break
  692. if( g_Opt.m_bUseCtrlNumAccel && !(GetKeyState(VK_CONTROL) & 0x8000) )
  693. return FALSE;
  694. int index = (int)vk - VK_NUMPAD0;
  695. // '0' is actually 10 in the ditto window
  696. if(index == 0)
  697. index = 10;
  698. // translate num 1-10 into the actual index (based upon m_bStartTop)
  699. index = GetFirstTenIndex(index);
  700. GetParent()->SendMessage(NM_SELECT_INDEX, index, 0);
  701. return TRUE;
  702. }
  703. switch( vk )
  704. {
  705. case 'X': // Ctrl-X = Cut (prepare for moving the items into a Group)
  706. if(GetKeyState(VK_CONTROL) & 0x8000)
  707. {
  708. LoadCopyOrCutToClipboard();
  709. theApp.IC_Cut(); // uses selection
  710. return TRUE;
  711. }
  712. break;
  713. case 'C': // Ctrl-C = Copy (prepare for copying the items into a Group)
  714. if(GetKeyState(VK_CONTROL) & 0x8000)
  715. {
  716. LoadCopyOrCutToClipboard();
  717. theApp.IC_Copy(); // uses selection
  718. return TRUE;
  719. }
  720. break;
  721. case 'V': // Ctrl-V = Paste (actually performs the copy or move of items into the current Group)
  722. if(GetKeyState(VK_CONTROL) & 0x8000)
  723. {
  724. theApp.IC_Paste();
  725. return TRUE;
  726. }
  727. break;
  728. case 'A': // Ctrl-A = Select All
  729. if(GetKeyState(VK_CONTROL) & 0x8000)
  730. {
  731. int nCount = GetItemCount();
  732. for(int i = 0; i < nCount; i++)
  733. {
  734. SetSelection(i);
  735. }
  736. return TRUE;
  737. }
  738. break;
  739. } // end switch(vk)
  740. return FALSE;
  741. }
  742. void CQListCtrl::LoadCopyOrCutToClipboard()
  743. {
  744. ARRAY arr;
  745. GetSelectionItemData(arr);
  746. INT_PTR count = arr.GetSize();
  747. if(count <= 0)
  748. return;
  749. CProcessPaste paste;
  750. //Don't send the paste just load it into memory
  751. paste.m_bSendPaste = false;
  752. if(count > 1)
  753. paste.GetClipIDs().Copy(arr);
  754. else
  755. paste.GetClipIDs().Add(arr[0]);
  756. //Don't move these to the top
  757. BOOL bItWas = g_Opt.m_bUpdateTimeOnPaste;
  758. g_Opt.m_bUpdateTimeOnPaste = FALSE;
  759. paste.DoPaste();
  760. g_Opt.m_bUpdateTimeOnPaste = bItWas;
  761. }
  762. bool CQListCtrl::ShowFullDescription(bool bFromAuto, bool fromNextPrev)
  763. {
  764. if (this->GetSelectedCount() == 0)
  765. {
  766. return false;
  767. }
  768. int clipId = this->GetItemData(this->GetCaret());
  769. if(m_pToolTip != NULL &&
  770. m_pToolTip->GetClipId() == clipId &&
  771. ::IsWindow(m_toolTipHwnd))
  772. {
  773. return false;
  774. }
  775. int nItem = GetCaret();
  776. CRect rc, crWindow;
  777. GetWindowRect(&crWindow);
  778. GetItemRect(nItem, rc, LVIR_BOUNDS);
  779. ClientToScreen(rc);
  780. CPoint pt;
  781. if(CGetSetOptions::GetRememberDescPos())
  782. {
  783. CGetSetOptions::GetDescWndPoint(pt);
  784. }
  785. else if(bFromAuto == false)
  786. {
  787. pt = CPoint(rc.left, rc.bottom);
  788. }
  789. else
  790. {
  791. pt = CPoint((crWindow.left + (crWindow.right - crWindow.left)/2), rc.bottom);
  792. }
  793. CString csDescription;
  794. GetToolTipText(nItem, csDescription);
  795. if (m_pToolTip == NULL ||
  796. fromNextPrev == false ||
  797. ::IsWindow(m_toolTipHwnd) == FALSE)
  798. {
  799. m_pToolTip->DestroyWindow();
  800. m_pToolTip = new CToolTipEx;
  801. m_pToolTip->Create(this);
  802. m_toolTipHwnd = m_pToolTip->GetSafeHwnd();
  803. m_pToolTip->SetNotifyWnd(GetParent());
  804. }
  805. else
  806. {
  807. CRect r;
  808. m_pToolTip->GetWindowRect(r);
  809. pt = r.TopLeft();
  810. m_pToolTip->SetBitmap(NULL);
  811. m_pToolTip->SetRTFText("");
  812. m_pToolTip->SetToolTipText(_T(""));
  813. }
  814. if(m_pToolTip)
  815. {
  816. m_pToolTip->SetClipId(clipId);
  817. m_pToolTip->SetSearchText(m_searchText);
  818. m_pToolTip->SetToolTipText(_T(""));
  819. m_pToolTip->SetRTFText(" ");
  820. bool bSetPlainText = false;
  821. CClipFormat Clip;
  822. Clip.m_cfType = CF_UNICODETEXT;
  823. if(GetClipData(nItem, Clip) && Clip.m_hgData)
  824. {
  825. LPVOID pvData = GlobalLock(Clip.m_hgData);
  826. if(pvData)
  827. {
  828. CString csText = (WCHAR*)pvData;
  829. m_pToolTip->SetToolTipText(csText);
  830. bSetPlainText = true;
  831. }
  832. GlobalUnlock(Clip.m_hgData);
  833. Clip.Free();
  834. Clip.Clear();
  835. }
  836. if(bSetPlainText == false)
  837. {
  838. Clip.m_cfType = CF_TEXT;
  839. if(GetClipData(nItem, Clip) && Clip.m_hgData)
  840. {
  841. LPVOID pvData = GlobalLock(Clip.m_hgData);
  842. if(pvData)
  843. {
  844. CString csText = (char*)pvData;
  845. m_pToolTip->SetToolTipText(csText);
  846. bSetPlainText = true;
  847. }
  848. GlobalUnlock(Clip.m_hgData);
  849. Clip.Free();
  850. Clip.Clear();
  851. }
  852. }
  853. if(bSetPlainText == false)
  854. {
  855. m_pToolTip->SetToolTipText(csDescription);
  856. }
  857. Clip.m_cfType = RegisterClipboardFormat(CF_RTF);
  858. if(GetClipData(nItem, Clip) && Clip.m_hgData)
  859. {
  860. LPVOID pvData = GlobalLock(Clip.m_hgData);
  861. if(pvData)
  862. {
  863. m_pToolTip->SetRTFText((char*)pvData);
  864. }
  865. GlobalUnlock(Clip.m_hgData);
  866. Clip.Free();
  867. Clip.Clear();
  868. }
  869. Clip.m_cfType = CF_DIB;
  870. if(GetClipData(nItem, Clip) && Clip.m_hgData)
  871. {
  872. CBitmap *pBitMap = new CBitmap;
  873. if(pBitMap)
  874. {
  875. CRect rcItem;
  876. GetWindowRect(rcItem);
  877. CDC *pDC = GetDC();;
  878. CBitmapHelper::GetCBitmap(&Clip, pDC, pBitMap, MAXINT);
  879. ReleaseDC(pDC);
  880. //Tooltip wnd will release
  881. m_pToolTip->SetBitmap(pBitMap);
  882. }
  883. Clip.Free();
  884. Clip.Clear();
  885. }
  886. m_pToolTip->Show(pt);
  887. }
  888. return true;
  889. }
  890. void CQListCtrl::GetToolTipText(int nItem, CString &csText)
  891. {
  892. CWnd* pParent=GetParent();
  893. if(pParent && (pParent->GetSafeHwnd() != NULL))
  894. {
  895. CQListToolTipText info;
  896. memset(&info, 0, sizeof(info));
  897. info.hdr.code = NM_GETTOOLTIPTEXT;
  898. info.hdr.hwndFrom = GetSafeHwnd();
  899. info.hdr.idFrom = GetDlgCtrlID();
  900. info.lItem = nItem;
  901. //plus 100 for extra info - shortcut and such
  902. info.cchTextMax = g_Opt.m_bDescTextSize + 100;
  903. info.pszText = csText.GetBufferSetLength(info.cchTextMax);
  904. pParent->SendMessage(WM_NOTIFY,(WPARAM)info.hdr.idFrom,(LPARAM)&info);
  905. csText.ReleaseBuffer();
  906. }
  907. }
  908. BOOL CQListCtrl::GetClipData(int nItem, CClipFormat &Clip)
  909. {
  910. return theApp.GetClipData(GetItemData(nItem), Clip);
  911. }
  912. DWORD CQListCtrl::GetItemData(int nItem)
  913. {
  914. if((GetStyle() & LVS_OWNERDATA))
  915. {
  916. CWnd* pParent=GetParent();
  917. if(pParent && (pParent->GetSafeHwnd() != NULL))
  918. {
  919. LV_DISPINFO info;
  920. memset(&info, 0, sizeof(info));
  921. info.hdr.code = LVN_GETDISPINFO;
  922. info.hdr.hwndFrom = GetSafeHwnd();
  923. info.hdr.idFrom = GetDlgCtrlID();
  924. info.item.iItem = nItem;
  925. info.item.lParam = -1;
  926. info.item.mask = LVIF_PARAM;
  927. pParent->SendMessage(WM_NOTIFY,(WPARAM)info.hdr.idFrom,(LPARAM)&info);
  928. return (DWORD)info.item.lParam;
  929. }
  930. }
  931. return (DWORD)CListCtrl::GetItemData(nItem);
  932. }
  933. CClipFormatQListCtrl* CQListCtrl::GetItem_CF_DIB_ClipFormat(int nItem)
  934. {
  935. CClipFormatQListCtrl *format = NULL;
  936. CWnd* pParent=GetParent();
  937. if(pParent && (pParent->GetSafeHwnd() != NULL))
  938. {
  939. LV_DISPINFO info;
  940. memset(&info, 0, sizeof(info));
  941. info.hdr.code = LVN_GETDISPINFO;
  942. info.hdr.hwndFrom = GetSafeHwnd();
  943. info.hdr.idFrom = GetDlgCtrlID();
  944. info.item.iItem = nItem;
  945. info.item.lParam = NULL;
  946. info.item.mask = LVIF_CF_DIB;
  947. pParent->SendMessage(WM_NOTIFY,(WPARAM)info.hdr.idFrom,(LPARAM)&info);
  948. if(info.item.lParam != NULL)
  949. {
  950. format = (CClipFormatQListCtrl *)info.item.lParam;
  951. }
  952. }
  953. return format;
  954. }
  955. CClipFormatQListCtrl* CQListCtrl::GetItem_CF_RTF_ClipFormat(int nItem)
  956. {
  957. CClipFormatQListCtrl *format = NULL;
  958. CWnd* pParent=GetParent();
  959. if(pParent && (pParent->GetSafeHwnd() != NULL))
  960. {
  961. LV_DISPINFO info;
  962. memset(&info, 0, sizeof(info));
  963. info.hdr.code = LVN_GETDISPINFO;
  964. info.hdr.hwndFrom = GetSafeHwnd();
  965. info.hdr.idFrom = GetDlgCtrlID();
  966. info.item.iItem = nItem;
  967. info.item.lParam = NULL;
  968. info.item.mask = LVIF_CF_RICHTEXT;
  969. pParent->SendMessage(WM_NOTIFY, (WPARAM)info.hdr.idFrom, (LPARAM)&info);
  970. if(info.item.lParam != NULL)
  971. {
  972. format = (CClipFormatQListCtrl *)info.item.lParam;
  973. }
  974. }
  975. return format;
  976. }
  977. void CQListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  978. {
  979. CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
  980. }
  981. void CQListCtrl::DestroyAndCreateAccelerator(BOOL bCreate, CppSQLite3DB &db)
  982. {
  983. m_Accels.RemoveAll();
  984. if(bCreate)
  985. {
  986. CMainTableFunctions::LoadAcceleratorKeys(m_Accels, db);
  987. LoadDittoCopyBufferHotkeys();
  988. }
  989. }
  990. void CQListCtrl::LoadDittoCopyBufferHotkeys()
  991. {
  992. CCopyBufferItem Item;
  993. CAccel a;
  994. g_Opt.GetCopyBufferItem(0, Item);
  995. if(Item.m_lCopyHotKey > 0)
  996. {
  997. a.Cmd = COPY_BUFFER_HOT_KEY_1_ID;
  998. a.Key = Item.m_lCopyHotKey;
  999. m_Accels.AddAccel(a);
  1000. }
  1001. g_Opt.GetCopyBufferItem(1, Item);
  1002. if(Item.m_lCopyHotKey > 0)
  1003. {
  1004. a.Cmd = COPY_BUFFER_HOT_KEY_2_ID;
  1005. a.Key = Item.m_lCopyHotKey;
  1006. m_Accels.AddAccel(a);
  1007. }
  1008. g_Opt.GetCopyBufferItem(2, Item);
  1009. if(Item.m_lCopyHotKey > 0)
  1010. {
  1011. a.Cmd = COPY_BUFFER_HOT_KEY_3_ID;
  1012. a.Key = Item.m_lCopyHotKey;
  1013. m_Accels.AddAccel(a);
  1014. }
  1015. }
  1016. void CQListCtrl::OnKillFocus(CWnd* pNewWnd)
  1017. {
  1018. CListCtrl::OnKillFocus(pNewWnd);
  1019. //if(FocusOnToolTip() == FALSE)
  1020. //m_pToolTip->Hide();
  1021. }
  1022. HWND CQListCtrl::GetToolTipHWnd()
  1023. {
  1024. return m_pToolTip->GetSafeHwnd();
  1025. }
  1026. BOOL CQListCtrl::SetItemCountEx(int iCount, DWORD dwFlags /* = 0 */)
  1027. {
  1028. return CListCtrl::SetItemCountEx(iCount, dwFlags);
  1029. }
  1030. void CQListCtrl::OnSelectionChange(NMHDR* pNMHDR, LRESULT* pResult)
  1031. {
  1032. NMLISTVIEW *pnmv = (NMLISTVIEW *) pNMHDR;
  1033. if((pnmv->uNewState == 3) ||
  1034. (pnmv->uNewState == 1))
  1035. {
  1036. if(g_Opt.m_bAllwaysShowDescription)
  1037. {
  1038. KillTimer(TIMER_SHOW_PROPERTIES);
  1039. SetTimer(TIMER_SHOW_PROPERTIES, 300, NULL);
  1040. }
  1041. if(GetSelectedCount() > 0 )
  1042. theApp.SetStatus(NULL, FALSE);
  1043. }
  1044. if(GetSelectedCount() == this->GetItemCount())
  1045. {
  1046. if(m_allSelected == false)
  1047. {
  1048. Log(StrF(_T("List box Select All")));
  1049. GetParent()->SendMessage(NM_ALL_SELECTED, 0, 0);
  1050. m_allSelected = true;
  1051. }
  1052. }
  1053. else if(m_allSelected == true)
  1054. {
  1055. Log(StrF(_T("List box REMOVED Select All")));
  1056. m_allSelected = false;
  1057. }
  1058. }
  1059. void CQListCtrl::OnTimer(UINT_PTR nIDEvent)
  1060. {
  1061. //http://support.microsoft.com/kb/200054
  1062. //OnTimer() Is Not Called Repeatedly for a List Control
  1063. bool callBase = true;
  1064. switch(nIDEvent)
  1065. {
  1066. case TIMER_SHOW_PROPERTIES:
  1067. {
  1068. if( theApp.m_bShowingQuickPaste )
  1069. ShowFullDescription(true);
  1070. KillTimer(TIMER_SHOW_PROPERTIES);
  1071. callBase = false;
  1072. }
  1073. break;
  1074. case TIMER_HIDE_SCROL:
  1075. {
  1076. CPoint cursorPos;
  1077. GetCursorPos(&cursorPos);
  1078. CRect crWindow;
  1079. this->GetWindowRect(&crWindow);
  1080. //check and see if they moved out of the scroll area
  1081. //If they did tell our parent so
  1082. if(MouseInScrollBarArea(crWindow, cursorPos) == false)
  1083. {
  1084. StopHideScrollBarTimer();
  1085. }
  1086. callBase = false;
  1087. }
  1088. break;
  1089. case TIMER_SHOW_SCROLL:
  1090. {
  1091. CPoint cursorPos;
  1092. GetCursorPos(&cursorPos);
  1093. CRect crWindow;
  1094. this->GetWindowRect(&crWindow);
  1095. //Adjust for the v-scroll bar being off of the screen
  1096. crWindow.right -= theApp.m_metrics.ScaleX(GetSystemMetrics(SM_CXVSCROLL));
  1097. crWindow.bottom -= theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXHSCROLL));
  1098. //Check and see if we are still in the cursor area
  1099. if(MouseInScrollBarArea(crWindow, cursorPos))
  1100. {
  1101. m_timerToHideScrollAreaSet = true;
  1102. GetParent()->SendMessage(NM_SHOW_HIDE_SCROLLBARS, 1, 0);
  1103. //Start looking to hide the scroll bars
  1104. SetTimer(TIMER_HIDE_SCROL, 1000, NULL);
  1105. }
  1106. KillTimer(TIMER_SHOW_SCROLL);
  1107. callBase = false;
  1108. }
  1109. break;
  1110. }
  1111. if(callBase)
  1112. {
  1113. CListCtrl::OnTimer(nIDEvent);
  1114. }
  1115. }
  1116. void CQListCtrl::SetLogFont(LOGFONT &font)
  1117. {
  1118. m_Font.DeleteObject();
  1119. m_Font.CreateFontIndirect(&font);
  1120. SetFont(&m_Font);
  1121. }
  1122. void CQListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  1123. {
  1124. CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
  1125. }
  1126. BOOL CQListCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  1127. {
  1128. return CListCtrl::OnMouseWheel(nFlags, zDelta, pt);
  1129. }
  1130. BOOL CQListCtrl::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
  1131. {
  1132. NMLVCACHEHINT* pcachehint = NULL;
  1133. if(message == WM_NOTIFY)
  1134. {
  1135. NMHDR* phdr = (NMHDR*)lParam;
  1136. switch(phdr->code)
  1137. {
  1138. case LVN_ODCACHEHINT:
  1139. pcachehint= (NMLVCACHEHINT*) phdr;
  1140. GetParent()->SendMessage(NM_FILL_REST_OF_LIST, pcachehint->iFrom, pcachehint->iTo);
  1141. return FALSE;
  1142. }
  1143. }
  1144. return CListCtrl::OnChildNotify(message, wParam, lParam, pLResult);
  1145. }
  1146. BOOL CQListCtrl::OnItemDeleted(long lID)
  1147. {
  1148. BOOL bRet2 = m_RTFData.RemoveKey(lID);
  1149. return (bRet2);
  1150. }
  1151. void CQListCtrl::OnMouseMove(UINT nFlags, CPoint point)
  1152. {
  1153. if(g_Opt.m_showScrollBar == FALSE)
  1154. {
  1155. CRect crWindow;
  1156. this->GetWindowRect(&crWindow);
  1157. ScreenToClient(&crWindow);
  1158. crWindow.right -= theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXVSCROLL));
  1159. crWindow.bottom -= theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXHSCROLL));
  1160. if(MouseInScrollBarArea(crWindow, point))
  1161. {
  1162. if((GetTickCount() - m_mouseOverScrollAreaStart) > 500)
  1163. {
  1164. SetTimer(TIMER_SHOW_SCROLL, 500, NULL);
  1165. m_mouseOverScrollAreaStart = GetTickCount();
  1166. }
  1167. }
  1168. else
  1169. {
  1170. if(m_timerToHideScrollAreaSet)
  1171. {
  1172. StopHideScrollBarTimer();
  1173. }
  1174. KillTimer(TIMER_SHOW_SCROLL);
  1175. }
  1176. }
  1177. }
  1178. bool CQListCtrl::MouseInScrollBarArea(CRect crWindow, CPoint point)
  1179. {
  1180. CRect crRight(crWindow);
  1181. CRect crBottom(crWindow);
  1182. crRight.left = crRight.right - theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXVSCROLL));
  1183. crBottom.top = crBottom.bottom - theApp.m_metrics.ScaleY(::GetSystemMetrics(SM_CYHSCROLL));
  1184. /*CString cs;
  1185. cs.Format(_T("point.x: %d, Width: %d, Height: %d\n"), point.x, crWindow.Width(), crWindow.Height());
  1186. OutputDebugString(cs);*/
  1187. if(crRight.PtInRect(point) || crBottom.PtInRect(point))
  1188. {
  1189. return true;
  1190. }
  1191. return false;
  1192. }
  1193. void CQListCtrl::StopHideScrollBarTimer()
  1194. {
  1195. GetParent()->SendMessage(NM_SHOW_HIDE_SCROLLBARS, 0, 0);
  1196. m_timerToHideScrollAreaSet = false;
  1197. KillTimer(TIMER_HIDE_SCROL);
  1198. }
  1199. void CQListCtrl::SetSearchText(CString text)
  1200. {
  1201. m_searchText = text;
  1202. }