QListCtrl.cpp 41 KB

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