ToolTipEx.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. #include "stdafx.h"
  2. #include "cp_main.h"
  3. #include "ToolTipEx.h"
  4. #include "BitmapHelper.h"
  5. #include "Options.h"
  6. #include "ActionEnums.h"
  7. #include "HyperLink.h"
  8. #include <Richedit.h>
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. #define HIDE_WINDOW_TIMER 1
  15. #define SAVE_SIZE 2
  16. #define TIMER_BUTTON_UP 3
  17. #define TIMER_AUTO_MAX 4
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CToolTipEx
  20. CToolTipEx::CToolTipEx(): m_dwTextStyle(DT_EXPANDTABS | DT_EXTERNALLEADING |
  21. DT_NOPREFIX | DT_WORDBREAK), m_rectMargin(2, 2, 3, 3),
  22. m_pNotifyWnd(NULL), m_clipId(0), m_clipRow(-1)
  23. {
  24. m_showPersistant = false;
  25. m_pToolTipActions = NULL;
  26. m_bMaxSetTimer = false;
  27. m_lDelayMaxSeconds = 2;
  28. }
  29. CToolTipEx::~CToolTipEx()
  30. {
  31. m_Font.DeleteObject();
  32. m_clipDataFont.DeleteObject();
  33. }
  34. BEGIN_MESSAGE_MAP(CToolTipEx, CWnd)
  35. //{{AFX_MSG_MAP(CToolTipEx)
  36. ON_WM_PAINT()
  37. ON_WM_SIZE()
  38. ON_WM_NCHITTEST()
  39. ON_WM_ACTIVATE()
  40. ON_WM_TIMER()
  41. ON_WM_NCLBUTTONDBLCLK()
  42. ON_WM_NCPAINT()
  43. ON_WM_NCCALCSIZE()
  44. ON_WM_NCLBUTTONDOWN()
  45. ON_WM_NCMOUSEMOVE()
  46. ON_WM_NCLBUTTONUP()
  47. ON_WM_ERASEBKGND()
  48. ON_COMMAND(ID_FIRST_REMEMBERWINDOWPOSITION, &CToolTipEx::OnRememberwindowposition)
  49. ON_COMMAND(ID_FIRST_SIZEWINDOWTOCONTENT, &CToolTipEx::OnSizewindowtocontent)
  50. ON_COMMAND(ID_FIRST_SCALEIMAGESTOFITWINDOW, &CToolTipEx::OnScaleimagestofitwindow)
  51. ON_COMMAND(2, OnOptions)
  52. ON_WM_RBUTTONDOWN()
  53. ON_WM_SETFOCUS()
  54. ON_COMMAND(ID_FIRST_HIDEDESCRIPTIONWINDOWONM, &CToolTipEx::OnFirstHidedescriptionwindowonm)
  55. ON_COMMAND(ID_FIRST_WRAPTEXT, &CToolTipEx::OnFirstWraptext)
  56. ON_WM_WINDOWPOSCHANGING()
  57. ON_COMMAND(ID_FIRST_ALWAYSONTOP, &CToolTipEx::OnFirstAlwaysontop)
  58. ON_NOTIFY(EN_MSGFILTER, 1, &CToolTipEx::OnEnMsgfilterRichedit21)
  59. END_MESSAGE_MAP()
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CToolTipEx message handlers
  62. BOOL CToolTipEx::Create(CWnd *pParentWnd)
  63. {
  64. m_saveWindowLockout = true;
  65. // Get the class name and create the window
  66. CString szClassName = AfxRegisterWndClass(CS_CLASSDC | CS_SAVEBITS, LoadCursor(NULL, IDC_ARROW));
  67. // Create the window - just don't show it yet.
  68. if( !CWnd::CreateEx(0, szClassName, _T(""), WS_POPUP,
  69. 0, 0, 0, 0, pParentWnd->GetSafeHwnd(), 0, NULL))
  70. {
  71. return FALSE;
  72. }
  73. //CString szClassName2 = AfxRegisterWndClass(CS_CLASSDC | CS_SAVEBITS, LoadCursor(NULL, IDC_ARROW));
  74. //BOOL b = m_imageViewer.Create(_T(""), szClassName2, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL, CRect(0, 0, 0, 0), this, 3);
  75. m_imageViewer.Create(this);
  76. m_DittoWindow.DoCreate(this);
  77. m_DittoWindow.SetCaptionColors(g_Opt.m_Theme.CaptionLeft(), g_Opt.m_Theme.CaptionRight(), g_Opt.m_Theme.Border());
  78. m_DittoWindow.SetCaptionOn(this, CGetSetOptions::GetCaptionPos(), true, g_Opt.m_Theme.GetCaptionSize(), g_Opt.m_Theme.GetCaptionFontSize());
  79. m_DittoWindow.m_bDrawMaximize = false;
  80. m_DittoWindow.m_bDrawMinimize = false;
  81. m_DittoWindow.m_bDrawChevron = true;
  82. m_DittoWindow.m_sendWMClose = false;
  83. m_RichEdit.Create(_T(""), _T(""), WS_CHILD | WS_VISIBLE | WS_VSCROLL |
  84. WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL |
  85. ES_AUTOHSCROLL, CRect(10, 10, 100, 200), this, 1);
  86. m_RichEdit.SetReadOnly();
  87. m_RichEdit.SetBackgroundColor(FALSE, g_Opt.m_Theme.DescriptionWindowBG());
  88. m_RichEdit.SetEventMask(m_RichEdit.GetEventMask() | ENM_SELCHANGE | ENM_LINK | ENM_MOUSEEVENTS | ENM_SCROLLEVENTS);
  89. m_RichEdit.SetAutoURLDetect(TRUE);
  90. ApplyWordWrap();
  91. SetLogFont(GetSystemToolTipFont(), FALSE);
  92. m_optionsButton.Create(NULL, WS_CHILD | BS_OWNERDRAW | WS_TABSTOP, CRect(0, 0, 0, 0), this, 2);
  93. m_optionsButton.LoadStdImageDPI(IDB_COG_16_16, IDB_COG_20_20, IDB_COG_24_24, cog_28, IDB_COG_32_32, _T("PNG"));
  94. m_optionsButton.SetToolTipText(theApp.m_Language.GetString(_T("DescriptionOptionsTooltip"), _T("Description Options")));
  95. m_optionsButton.ShowWindow(SW_SHOW);
  96. m_clipDataStatic.Create(_T("some text"), WS_CHILD | WS_VISIBLE | SS_SIMPLE, CRect(0, 0, 0, 0), this, 3);
  97. m_clipDataFont.CreateFont(-theApp.m_metrics.PointsToPixels(8), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
  98. m_clipDataStatic.SetFont(&m_clipDataFont);
  99. m_clipDataStatic.SetBkColor(g_Opt.m_Theme.DescriptionWindowBG());
  100. m_clipDataStatic.SetTextColor(RGB(80, 80, 80));
  101. m_saveWindowLockout = false;
  102. return TRUE;
  103. }
  104. BOOL CToolTipEx::Show(CPoint point)
  105. {
  106. m_reducedWindowSize = false;
  107. if(m_imageViewer.m_pGdiplusBitmap)
  108. {
  109. m_RichEdit.ShowWindow(SW_HIDE);
  110. m_imageViewer.ShowWindow(SW_SHOW);
  111. m_imageViewer.UpdateBitmapSize();
  112. }
  113. else
  114. {
  115. m_RichEdit.ShowWindow(SW_SHOW);
  116. m_imageViewer.ShowWindow(SW_HIDE);
  117. }
  118. CRect rect;
  119. if(CGetSetOptions::GetSizeDescWindowToContent() == FALSE)
  120. {
  121. rect.left = point.x;
  122. rect.top = point.y;
  123. CSize size;
  124. CGetSetOptions::GetDescWndSize(size);
  125. rect.right = rect.left + size.cx;
  126. rect.bottom = rect.top + size.cy;
  127. EnsureWindowVisible(&rect);
  128. }
  129. else
  130. {
  131. rect = GetBoundsRect();
  132. //account for the scroll bars
  133. rect.right += 20;
  134. rect.bottom += 20;
  135. if (m_imageViewer.m_pGdiplusBitmap)
  136. {
  137. int nWidth = m_imageViewer.m_pGdiplusBitmap->GetWidth() + ::GetSystemMetrics(SM_CXVSCROLL);
  138. int nHeight = m_imageViewer.m_pGdiplusBitmap->GetHeight() + ::GetSystemMetrics(SM_CYHSCROLL);
  139. rect.right = rect.left + nWidth;
  140. rect.bottom = rect.top + nHeight;
  141. }
  142. else if(m_csRTF != "")
  143. {
  144. //if showing rtf then increase the size because
  145. //rtf will probably draw bigger
  146. long lNewWidth = (long)rect.Width() + (long)(rect.Width() *1.5);
  147. rect.right = rect.left + lNewWidth;
  148. long lNewHeight = (long)rect.Height() + (long)(rect.Height() *1.5);
  149. rect.bottom = rect.top + lNewHeight;
  150. }
  151. rect.right += CAPTION_BORDER * 2;
  152. rect.bottom += CAPTION_BORDER * 2;
  153. CRect rcScreen;
  154. ClientToScreen(rect);
  155. CRect cr(point, point);
  156. int nMonitor = GetMonitorFromRect(&cr);
  157. GetMonitorRect(nMonitor, &rcScreen);
  158. //ensure that we don't go outside the screen
  159. if(point.x < 0)
  160. {
  161. point.x = 5;
  162. m_reducedWindowSize = true;
  163. }
  164. if(point.y < 0)
  165. {
  166. point.y = 5;
  167. m_reducedWindowSize = true;
  168. }
  169. rcScreen.DeflateRect(0, 0, 5, 5);
  170. long lWidth = rect.Width();
  171. long lHeight = rect.Height();
  172. rect.left = point.x;
  173. rect.top = point.y;
  174. rect.right = rect.left + lWidth;
  175. rect.bottom = rect.top + lHeight;
  176. if (rect.right > rcScreen.right)
  177. {
  178. rect.right = rcScreen.right;
  179. m_reducedWindowSize = true;
  180. }
  181. if (rect.bottom > rcScreen.bottom)
  182. {
  183. rect.bottom = rcScreen.bottom;
  184. m_reducedWindowSize = true;
  185. }
  186. }
  187. m_clipDataStatic.SetWindowText(m_clipData);
  188. if (m_DittoWindow.m_bMinimized)
  189. {
  190. //m_DittoWindow.MinMaxWindow(this, FORCE_MAX);
  191. m_DittoWindow.m_bMinimized = false;
  192. }
  193. m_saveWindowLockout = true;
  194. MoveWindow(rect);
  195. ShowWindow(SW_SHOWNA);
  196. this->Invalidate();
  197. this->UpdateWindow();
  198. m_saveWindowLockout = false;
  199. return TRUE;
  200. }
  201. void CToolTipEx::GetWindowRectEx(LPRECT lpRect)
  202. {
  203. if (m_DittoWindow.m_bMinimized)
  204. {
  205. *lpRect = m_DittoWindow.m_crFullSizeWindow;
  206. return;
  207. }
  208. CWnd::GetWindowRect(lpRect);
  209. }
  210. BOOL CToolTipEx::Hide()
  211. {
  212. delete m_imageViewer.m_pGdiplusBitmap;
  213. m_imageViewer.m_pGdiplusBitmap = NULL;
  214. SaveWindowSize();
  215. ShowWindow(SW_HIDE);
  216. m_csRTF = "";
  217. m_csText = "";
  218. m_clipId = 0;
  219. m_clipRow = -1;
  220. m_searchText = _T("");
  221. m_showPersistant = false;
  222. return TRUE;
  223. }
  224. void CToolTipEx::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
  225. {
  226. // toggle ShowPersistent when we double click the caption
  227. if (nHitTest == HTCAPTION)
  228. {
  229. OnFirstAlwaysontop();
  230. }
  231. CWnd::OnNcLButtonDblClk(nHitTest, point);
  232. }
  233. void CToolTipEx::SaveWindowSize()
  234. {
  235. if (::IsWindowVisible(m_hWnd))
  236. {
  237. CRect rect;
  238. if (m_DittoWindow.m_bMinimized)
  239. {
  240. rect = m_DittoWindow.m_crFullSizeWindow;
  241. }
  242. else
  243. {
  244. this->GetWindowRect(&rect);
  245. }
  246. CGetSetOptions::SetDescWndSize(rect.Size());
  247. CGetSetOptions::SetDescWndPoint(rect.TopLeft());
  248. OutputDebugString(_T("Saving tooltip size"));
  249. }
  250. }
  251. void CToolTipEx::PostNcDestroy()
  252. {
  253. CWnd::PostNcDestroy();
  254. delete this;
  255. }
  256. BOOL CToolTipEx::PreTranslateMessage(MSG *pMsg)
  257. {
  258. m_DittoWindow.DoPreTranslateMessage(pMsg);
  259. switch (pMsg->message)
  260. {
  261. case WM_KEYDOWN:
  262. switch(pMsg->wParam)
  263. {
  264. case 'C':
  265. if(GetKeyState(VK_CONTROL) &0x8000)
  266. {
  267. m_RichEdit.Copy();
  268. }
  269. break;
  270. }
  271. break;
  272. case WM_RBUTTONDOWN:
  273. {
  274. if (m_RichEdit.m_hWnd == GetFocus()->m_hWnd ||
  275. m_imageViewer.m_hWnd == GetFocus()->m_hWnd)
  276. {
  277. OnOptions();
  278. return TRUE;
  279. }
  280. }
  281. break;
  282. }
  283. if (m_pToolTipActions != NULL)
  284. {
  285. CAccel a;
  286. if (m_pToolTipActions->OnMsg(pMsg, a))
  287. {
  288. switch (a.Cmd)
  289. {
  290. case ActionEnums::CLOSEWINDOW:
  291. /*if (this->m_showPersistant &&
  292. m_DittoWindow.m_bMinimized == false)
  293. {
  294. m_DittoWindow.MinMaxWindow(this, FORCE_MIN);
  295. theApp.m_activeWnd.ReleaseFocus();
  296. return TRUE;
  297. }*/
  298. break;
  299. }
  300. }
  301. }
  302. return CWnd::PreTranslateMessage(pMsg);
  303. }
  304. BOOL CToolTipEx::OnMsg(MSG *pMsg)
  305. {
  306. if(FALSE == IsWindowVisible())
  307. {
  308. return FALSE;
  309. }
  310. switch(pMsg->message)
  311. {
  312. case WM_WINDOWPOSCHANGING:
  313. case WM_LBUTTONDOWN:
  314. {
  315. if (m_showPersistant == false)
  316. {
  317. if (CGetSetOptions::GetMouseClickHidesDescription())
  318. {
  319. if (!IsCursorInToolTip())
  320. {
  321. Hide();
  322. }
  323. }
  324. }
  325. }
  326. break;
  327. case WM_KEYDOWN:
  328. {
  329. WPARAM vk = pMsg->wParam;
  330. if(vk == VK_TAB)
  331. {
  332. m_RichEdit.SetFocus();
  333. return TRUE;
  334. }
  335. else if (vk == VK_CONTROL || vk == VK_SHIFT)
  336. {
  337. return FALSE;
  338. }
  339. else if (vk == VK_UP)
  340. {
  341. return FALSE;
  342. }
  343. else if (vk == VK_DOWN)
  344. {
  345. return FALSE;
  346. }
  347. else if (vk == VK_NEXT)
  348. {
  349. return FALSE;
  350. }
  351. else if (vk == VK_PRIOR)
  352. {
  353. return FALSE;
  354. }
  355. else if (vk == VK_DELETE)
  356. {
  357. return FALSE;
  358. }
  359. if (m_pToolTipActions != NULL)
  360. {
  361. if (m_pToolTipActions->ContainsKey((int)vk))
  362. {
  363. return FALSE;
  364. }
  365. }
  366. if (m_showPersistant == false)
  367. {
  368. Hide();
  369. }
  370. break;
  371. }
  372. case WM_LBUTTONDBLCLK:
  373. case WM_RBUTTONDBLCLK:
  374. case WM_MBUTTONDOWN:
  375. case WM_MBUTTONDBLCLK:
  376. case WM_NCLBUTTONDOWN:
  377. case WM_NCLBUTTONDBLCLK:
  378. case WM_NCRBUTTONDOWN:
  379. case WM_NCRBUTTONDBLCLK:
  380. case WM_NCMBUTTONDOWN:
  381. case WM_NCMBUTTONDBLCLK:
  382. {
  383. if (m_showPersistant == false)
  384. {
  385. Hide();
  386. }
  387. break;
  388. }
  389. case WM_MOUSEWHEEL:
  390. {
  391. if (m_imageViewer.m_pGdiplusBitmap)
  392. {
  393. m_imageViewer.PostMessageW(pMsg->message, pMsg->wParam, pMsg->lParam);
  394. return TRUE;
  395. }
  396. else
  397. {
  398. m_RichEdit.PostMessageW(pMsg->message, pMsg->wParam, pMsg->lParam);
  399. return TRUE;
  400. }
  401. }
  402. break;
  403. }
  404. return FALSE;
  405. }
  406. CRect CToolTipEx::GetBoundsRect()
  407. {
  408. DWORD d = GetTickCount();
  409. CWindowDC dc(NULL);
  410. int nLineWidth = 0;
  411. CRect rect(0, 0, 0, 0);
  412. if(nLineWidth == 0)
  413. {
  414. // Count the number of lines of text
  415. int nStart = 0;
  416. INT nNumLines = 0;
  417. int longestLength = 0;
  418. CString longestString;
  419. do
  420. {
  421. int newStart = m_csText.Find(_T("\n"), nStart);
  422. if (newStart < 0)
  423. {
  424. int length = m_csText.GetLength() - nStart;
  425. if (length > longestLength)
  426. {
  427. longestString = m_csText.Mid(nStart, length);
  428. longestLength = length;
  429. }
  430. break;
  431. }
  432. int length = newStart - nStart;
  433. if(length > longestLength)
  434. {
  435. longestString = m_csText.Mid(nStart, length);
  436. longestLength = length;
  437. }
  438. nNumLines++;
  439. nStart = newStart + 1;
  440. }
  441. while(nStart >= 0 && nNumLines < 100);
  442. CFont *pOldFont = (CFont*)dc.SelectObject((CFont*)&m_Font);
  443. CSize size = dc.GetTextExtent(longestString);
  444. dc.SelectObject(pOldFont);
  445. rect.right = size.cx;
  446. rect.bottom = size.cy * nNumLines;
  447. }
  448. rect.bottom += m_rectMargin.top + m_rectMargin.bottom;
  449. rect.right += m_rectMargin.left + m_rectMargin.right + 2;
  450. if(m_imageViewer.m_pGdiplusBitmap)
  451. {
  452. int nWidth = m_imageViewer.m_pGdiplusBitmap->GetWidth();
  453. int nHeight = m_imageViewer.m_pGdiplusBitmap->GetHeight();
  454. rect.bottom += nHeight;
  455. if((rect.left + nWidth) > rect.right)
  456. {
  457. rect.right = rect.left + nWidth;
  458. }
  459. }
  460. DWORD diff = GetTickCount() - d;
  461. if (diff > 10)
  462. {
  463. Log(StrF(_T("Size To Content: %d\n"), diff));
  464. }
  465. return rect;
  466. }
  467. CString CToolTipEx::GetFieldFromString(CString ref, int nIndex, TCHAR ch)
  468. {
  469. CString strReturn;
  470. LPCTSTR pstrStart = ref.LockBuffer();
  471. LPCTSTR pstrBuffer = pstrStart;
  472. int nCurrent = 0;
  473. int nStart = 0;
  474. int nEnd = 0;
  475. int nOldStart = 0;
  476. while(nCurrent <= nIndex && *pstrBuffer != _T('\0'))
  477. {
  478. if(*pstrBuffer == ch)
  479. {
  480. nOldStart = nStart;
  481. nStart = nEnd + 1;
  482. nCurrent++;
  483. }
  484. nEnd++;
  485. pstrBuffer++;
  486. }
  487. // May have reached the end of the string
  488. if(*pstrBuffer == _T('\0'))
  489. {
  490. nOldStart = nStart;
  491. nEnd++;
  492. }
  493. ref.UnlockBuffer();
  494. if(nCurrent < nIndex)
  495. {
  496. //TRACE1("Warning: GetStringField - Couldn't find field %d.\n", nIndex);
  497. return strReturn;
  498. }
  499. return ref.Mid(nOldStart, nEnd - nOldStart - 1);
  500. }
  501. LPLOGFONT CToolTipEx::GetSystemToolTipFont()
  502. {
  503. static LOGFONT LogFont;
  504. NONCLIENTMETRICS ncm;
  505. ncm.cbSize = sizeof(NONCLIENTMETRICS);
  506. if(!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),
  507. &ncm, 0))
  508. {
  509. return FALSE;
  510. }
  511. memcpy(&LogFont, &(ncm.lfStatusFont), sizeof(LOGFONT));
  512. return &LogFont;
  513. }
  514. BOOL CToolTipEx::SetLogFont(LPLOGFONT lpLogFont, BOOL bRedraw /*=TRUE*/)
  515. {
  516. ASSERT(lpLogFont);
  517. if(!lpLogFont)
  518. {
  519. return FALSE;
  520. }
  521. LOGFONT LogFont;
  522. // Store font as the global default
  523. memcpy(&LogFont, lpLogFont, sizeof(LOGFONT));
  524. // Create the actual font object
  525. m_Font.DeleteObject();
  526. m_Font.CreateFontIndirect(&LogFont);
  527. if(bRedraw && ::IsWindow(GetSafeHwnd()))
  528. {
  529. Invalidate();
  530. }
  531. return TRUE;
  532. }
  533. void CToolTipEx::SetGdiplusBitmap(Gdiplus::Bitmap *gdiplusBitmap)
  534. {
  535. delete m_imageViewer.m_pGdiplusBitmap;
  536. m_imageViewer.m_pGdiplusBitmap = NULL;
  537. m_imageViewer.m_pGdiplusBitmap = gdiplusBitmap;
  538. m_imageViewer.UpdateBitmapSize();
  539. Invalidate();
  540. }
  541. void CToolTipEx::OnSize(UINT nType, int cx, int cy)
  542. {
  543. CWnd::OnSize(nType, cx, cy);
  544. if(::IsWindow(m_RichEdit.GetSafeHwnd()) == FALSE)
  545. {
  546. return ;
  547. }
  548. CRect cr;
  549. GetClientRect(cr);
  550. cr.DeflateRect(0, 0, 0, theApp.m_metrics.ScaleY(21));
  551. m_RichEdit.MoveWindow(cr);
  552. m_imageViewer.MoveWindow(cr);
  553. m_optionsButton.MoveWindow(cr.left, cr.bottom + theApp.m_metrics.ScaleY(2), theApp.m_metrics.ScaleX(17), theApp.m_metrics.ScaleY(17));
  554. m_clipDataStatic.MoveWindow(cr.left + theApp.m_metrics.ScaleX(19), cr.bottom + theApp.m_metrics.ScaleY(2), cr.Width() - cr.left + theApp.m_metrics.ScaleX(19), theApp.m_metrics.ScaleY(17));
  555. this->Invalidate();
  556. m_DittoWindow.DoSetRegion(this);
  557. if (m_saveWindowLockout == false)
  558. {
  559. SetTimer(SAVE_SIZE, 250, NULL);
  560. }
  561. }
  562. BOOL CToolTipEx::IsCursorInToolTip()
  563. {
  564. CRect cr;
  565. GetWindowRect(cr);
  566. CPoint cursorPos;
  567. GetCursorPos(&cursorPos);
  568. return cr.PtInRect(cursorPos);
  569. }
  570. void CToolTipEx::SetRTFText(const char *pRTF)
  571. {
  572. m_RichEdit.SetRTF(pRTF);
  573. m_csRTF = pRTF;
  574. m_RichEdit.SetSel(0, 0);
  575. HighlightSearchText();
  576. }
  577. //void CToolTipEx::SetRTFText(const CString &csRTF)
  578. //{
  579. // m_RichEdit.SetRTF(csRTF);
  580. // m_csRTF = csRTF;
  581. //}
  582. void CToolTipEx::SetToolTipText(const CString &csText)
  583. {
  584. m_csText = csText;
  585. m_RichEdit.SetFont(&m_Font);
  586. m_RichEdit.SetText(csText);
  587. m_RichEdit.SetSel(0, 0);
  588. CHARFORMAT cfNew;
  589. cfNew.cbSize = sizeof(CHARFORMAT);
  590. cfNew.dwMask = CFM_COLOR;
  591. cfNew.dwEffects = CFM_COLOR;
  592. cfNew.dwEffects &= ~CFE_AUTOCOLOR;
  593. cfNew.crTextColor = g_Opt.m_Theme.DescriptionWindowText();
  594. m_RichEdit.SetDefaultCharFormat(cfNew);
  595. HighlightSearchText();
  596. }
  597. void CToolTipEx::HighlightSearchText()
  598. {
  599. if (m_searchText.GetLength() <= 0)
  600. return;
  601. FINDTEXTEX ft;
  602. long n = -1;
  603. ft.lpstrText = m_searchText;
  604. ft.chrg.cpMin = 0;
  605. ft.chrg.cpMax = -1;
  606. CHARFORMAT cf;
  607. cf.cbSize = sizeof(cf);
  608. cf.dwMask = CFM_COLOR;
  609. cf.dwEffects = CFE_BOLD | ~CFE_AUTOCOLOR;
  610. cf.crTextColor = RGB(255, 0, 0);
  611. do
  612. {
  613. ft.chrg.cpMin = n+1;
  614. n = m_RichEdit.FindText(FR_DOWN, &ft);
  615. if (n != -1)
  616. {
  617. m_RichEdit.SetSel(ft.chrgText);
  618. m_RichEdit.SetSelectionCharFormat(cf);
  619. }
  620. } while (n != -1);
  621. m_RichEdit.SetSel(0, 0);
  622. }
  623. void CToolTipEx::DoSearch()
  624. {
  625. if (m_searchText.GetLength() <= 0)
  626. return;
  627. FINDTEXTEX ft;
  628. long n = -1;
  629. ft.lpstrText = m_searchText;
  630. long start;
  631. long end;
  632. m_RichEdit.GetSel(start, end);
  633. ft.chrg.cpMin = end;
  634. ft.chrg.cpMax = -1;
  635. int searchDirection = FR_DOWN;
  636. if (GetKeyState(VK_SHIFT) & 0x8000)
  637. {
  638. searchDirection = 0;
  639. ft.chrg.cpMin = start;
  640. }
  641. n = m_RichEdit.FindText(searchDirection, &ft);
  642. if (n != -1)
  643. {
  644. m_RichEdit.SetSel(ft.chrgText);
  645. }
  646. else
  647. {
  648. if (searchDirection == 0)
  649. {
  650. ft.chrg.cpMin = m_RichEdit.GetTextLength();
  651. }
  652. else
  653. {
  654. ft.chrg.cpMin = 0;
  655. }
  656. ft.chrg.cpMax = -1;
  657. n = m_RichEdit.FindText(searchDirection, &ft);
  658. if (n != -1)
  659. {
  660. m_RichEdit.SetSel(ft.chrgText);
  661. }
  662. }
  663. }
  664. void CToolTipEx::OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized)
  665. {
  666. CWnd::OnActivate(nState, pWndOther, bMinimized);
  667. if (nState == WA_INACTIVE)
  668. {
  669. if(m_pNotifyWnd)
  670. {
  671. m_pNotifyWnd->PostMessage(NM_INACTIVE_TOOLTIPWND, 0, 0);
  672. }
  673. }
  674. }
  675. void CToolTipEx::OnTimer(UINT_PTR nIDEvent)
  676. {
  677. switch(nIDEvent)
  678. {
  679. case HIDE_WINDOW_TIMER:
  680. Hide();
  681. PostMessage(WM_DESTROY, 0, 0);
  682. break;
  683. case SAVE_SIZE:
  684. SaveWindowSize();
  685. KillTimer(SAVE_SIZE);
  686. break;
  687. case TIMER_BUTTON_UP:
  688. {
  689. if ((GetKeyState(VK_LBUTTON) & 0x100) == 0)
  690. {
  691. m_DittoWindow.DoNcLButtonUp(this, 0, CPoint(0, 0));
  692. KillTimer(TIMER_BUTTON_UP);
  693. }
  694. break;
  695. }
  696. case TIMER_AUTO_MAX:
  697. {
  698. if (m_DittoWindow.m_bMinimized)
  699. {
  700. CPoint cp;
  701. GetCursorPos(&cp);
  702. UINT nHitTest = (UINT)OnNcHitTest(cp);
  703. ScreenToClient(&cp);
  704. if (nHitTest == HTCAPTION)
  705. {
  706. if (m_DittoWindow.m_crCloseBT.PtInRect(cp) == false)
  707. {
  708. if (m_DittoWindow.m_crMinimizeBT.PtInRect(cp) == false)
  709. {
  710. m_DittoWindow.MinMaxWindow(this, FORCE_MAX);
  711. }
  712. }
  713. }
  714. }
  715. KillTimer(TIMER_AUTO_MAX);
  716. m_bMaxSetTimer = false;
  717. }
  718. }
  719. CWnd::OnTimer(nIDEvent);
  720. }
  721. void CToolTipEx::OnNcPaint()
  722. {
  723. m_DittoWindow.DoNcPaint(this);
  724. }
  725. void CToolTipEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
  726. {
  727. CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
  728. m_DittoWindow.DoNcCalcSize(bCalcValidRects, lpncsp);
  729. }
  730. HITTEST_RET CToolTipEx::OnNcHitTest(CPoint point)
  731. {
  732. UINT Ret = m_DittoWindow.DoNcHitTest(this, point);
  733. if(Ret == -1)
  734. return CWnd::OnNcHitTest(point);
  735. return Ret;
  736. }
  737. void CToolTipEx::OnNcLButtonDown(UINT nHitTest, CPoint point)
  738. {
  739. int buttonPressed = m_DittoWindow.DoNcLButtonDown(this, nHitTest, point);
  740. if (buttonPressed != 0)
  741. {
  742. SetTimer(TIMER_BUTTON_UP, 100, NULL);
  743. }
  744. CWnd::OnNcLButtonDown(nHitTest, point);
  745. }
  746. void CToolTipEx::OnNcLButtonUp(UINT nHitTest, CPoint point)
  747. {
  748. long lRet = m_DittoWindow.DoNcLButtonUp(this, nHitTest, point);
  749. switch(lRet)
  750. {
  751. case BUTTON_CLOSE:
  752. Hide();
  753. break;
  754. case BUTTON_CHEVRON:
  755. m_DittoWindow.MinMaxWindow(this, SWAP_MIN_MAX);
  756. OnNcPaint();
  757. break;
  758. }
  759. KillTimer(TIMER_BUTTON_UP);
  760. CWnd::OnNcLButtonUp(nHitTest, point);
  761. }
  762. void CToolTipEx::OnNcMouseMove(UINT nHitTest, CPoint point)
  763. {
  764. m_DittoWindow.DoNcMouseMove(this, nHitTest, point);
  765. if ((m_bMaxSetTimer == false) && m_DittoWindow.m_bMinimized)
  766. {
  767. COleDateTimeSpan sp = COleDateTime::GetCurrentTime() - m_DittoWindow.m_TimeMinimized;
  768. if (sp.GetTotalSeconds() >= m_lDelayMaxSeconds)
  769. {
  770. SetTimer(TIMER_AUTO_MAX, CGetSetOptions::GetTimeBeforeExpandWindow(), NULL);
  771. m_bMaxSetTimer = true;
  772. }
  773. }
  774. CWnd::OnNcMouseMove(nHitTest, point);
  775. }
  776. void CToolTipEx::OnOptions()
  777. {
  778. POINT pp;
  779. CMenu cmPopUp;
  780. CMenu *cmSubMenu = NULL;
  781. GetCursorPos(&pp);
  782. if(cmPopUp.LoadMenu(IDR_DESC_OPTIONS_MENU) != 0)
  783. {
  784. cmSubMenu = cmPopUp.GetSubMenu(0);
  785. if(!cmSubMenu)
  786. {
  787. return ;
  788. }
  789. GetCursorPos(&pp);
  790. //theApp.m_Language.UpdateRightClickMenu(cmSubMenu);
  791. if(CGetSetOptions::GetRememberDescPos())
  792. cmSubMenu->CheckMenuItem(ID_FIRST_REMEMBERWINDOWPOSITION, MF_CHECKED);
  793. if(CGetSetOptions::GetSizeDescWindowToContent())
  794. cmSubMenu->CheckMenuItem(ID_FIRST_SIZEWINDOWTOCONTENT, MF_CHECKED);
  795. if(CGetSetOptions::GetScaleImagesToDescWindow())
  796. cmSubMenu->CheckMenuItem(ID_FIRST_SCALEIMAGESTOFITWINDOW, MF_CHECKED);
  797. if (CGetSetOptions::GetMouseClickHidesDescription())
  798. cmSubMenu->CheckMenuItem(ID_FIRST_HIDEDESCRIPTIONWINDOWONM, MF_CHECKED);
  799. if (CGetSetOptions::GetWrapDescriptionText())
  800. cmSubMenu->CheckMenuItem(ID_FIRST_WRAPTEXT, MF_CHECKED);
  801. if (m_showPersistant)
  802. cmSubMenu->CheckMenuItem(ID_FIRST_ALWAYSONTOP, MF_CHECKED);
  803. UpdateMenuShortCut(cmSubMenu, ID_FIRST_WRAPTEXT, ActionEnums::TOGGLE_DESCRIPTION_WORD_WRAP);
  804. UpdateMenuShortCut(cmSubMenu, ID_FIRST_ALWAYSONTOP, ActionEnums::TOGGLESHOWPERSISTANT);
  805. cmSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, pp.x, pp.y, this, NULL);
  806. }
  807. }
  808. void CToolTipEx::UpdateMenuShortCut(CMenu *subMenu, int id, DWORD action)
  809. {
  810. if (m_pToolTipActions != NULL)
  811. {
  812. CString cs;
  813. subMenu->GetMenuString(id, cs, MF_BYCOMMAND);
  814. CString shortcutText = m_pToolTipActions->GetCmdKeyText(action);
  815. if (shortcutText != _T("") &&
  816. cs.Find("\t" + shortcutText) < 0)
  817. {
  818. cs += "\t";
  819. cs += shortcutText;
  820. subMenu->ModifyMenu(id, MF_BYCOMMAND, id, cs);
  821. }
  822. }
  823. }
  824. void CToolTipEx::OnRememberwindowposition()
  825. {
  826. CGetSetOptions::SetRememberDescPos(!CGetSetOptions::GetRememberDescPos());
  827. }
  828. void CToolTipEx::OnSizewindowtocontent()
  829. {
  830. CGetSetOptions::SetSizeDescWindowToContent(!CGetSetOptions::GetSizeDescWindowToContent());
  831. CRect rect;
  832. this->GetWindowRect(&rect);
  833. Show(rect.TopLeft());
  834. }
  835. void CToolTipEx::OnScaleimagestofitwindow()
  836. {
  837. CGetSetOptions::SetScaleImagesToDescWindow(!CGetSetOptions::GetScaleImagesToDescWindow());
  838. m_imageViewer.UpdateBitmapSize();
  839. Invalidate();
  840. }
  841. void CToolTipEx::OnRButtonDown(UINT nFlags, CPoint point)
  842. {
  843. OnOptions();
  844. CWnd::OnRButtonDown(nFlags, point);
  845. }
  846. void CToolTipEx::OnSetFocus(CWnd* pOldWnd)
  847. {
  848. CWnd::OnSetFocus(pOldWnd);
  849. m_RichEdit.SetFocus();
  850. }
  851. void CToolTipEx::OnPaint()
  852. {
  853. CPaintDC dc(this); // device context for painting
  854. CRect rect;
  855. GetClientRect(rect);
  856. CBrush Brush, *pOldBrush;
  857. Brush.CreateSolidBrush(g_Opt.m_Theme.DescriptionWindowBG());
  858. pOldBrush = dc.SelectObject(&Brush);
  859. dc.FillRect(&rect, &Brush);
  860. // Cleanup
  861. dc.SelectObject(pOldBrush);
  862. }
  863. void CToolTipEx::OnFirstHidedescriptionwindowonm()
  864. {
  865. CGetSetOptions::SetMouseClickHidesDescription(!CGetSetOptions::GetMouseClickHidesDescription());
  866. }
  867. bool CToolTipEx::ToggleWordWrap()
  868. {
  869. bool didWordWrap = false;
  870. if (m_RichEdit.IsWindowVisible())
  871. {
  872. OnFirstWraptext();
  873. didWordWrap = true;
  874. }
  875. return didWordWrap;
  876. }
  877. void CToolTipEx::OnFirstWraptext()
  878. {
  879. CGetSetOptions::SetWrapDescriptionText(!CGetSetOptions::GetWrapDescriptionText());
  880. ApplyWordWrap();
  881. }
  882. void CToolTipEx::ApplyWordWrap()
  883. {
  884. if (CGetSetOptions::GetWrapDescriptionText())
  885. {
  886. m_RichEdit.SetTargetDevice(NULL, 0);
  887. }
  888. else
  889. {
  890. m_RichEdit.SetTargetDevice(NULL, 1);
  891. }
  892. }
  893. void CToolTipEx::HideWindowInXMilliSeconds(long lms)
  894. {
  895. SetTimer(HIDE_WINDOW_TIMER, lms, NULL);
  896. }
  897. void CToolTipEx::OnWindowPosChanging(WINDOWPOS* lpwndpos)
  898. {
  899. CWnd::OnWindowPosChanging(lpwndpos);
  900. m_DittoWindow.SnapToEdge(this, lpwndpos);
  901. }
  902. void CToolTipEx::OnFirstAlwaysontop()
  903. {
  904. m_showPersistant = !m_showPersistant;
  905. if (m_showPersistant)
  906. {
  907. m_DittoWindow.m_customWindowTitle = _T("[Always on top]");
  908. m_DittoWindow.m_useCustomWindowTitle = true;
  909. ::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
  910. }
  911. else
  912. {
  913. m_DittoWindow.m_customWindowTitle = _T("");
  914. m_DittoWindow.m_useCustomWindowTitle = true;
  915. }
  916. ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  917. }
  918. BOOL CToolTipEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  919. {
  920. switch (((LPNMHDR)lParam)->code)
  921. {
  922. case EN_LINK:
  923. {
  924. ENLINK *enLinkInfo = (ENLINK *)lParam; // pointer to a ENLINK structure
  925. if (enLinkInfo->msg == WM_LBUTTONUP)
  926. {
  927. CString s;
  928. m_RichEdit.GetTextRange(enLinkInfo->chrg.cpMin, enLinkInfo->chrg.cpMax, s);
  929. CHyperLink::GotoURL(s, SW_SHOW);
  930. }
  931. }
  932. break;
  933. }
  934. return CWnd::OnNotify(wParam, lParam, pResult);
  935. }
  936. void CToolTipEx::OnEnMsgfilterRichedit21(NMHDR *pNMHDR, LRESULT *pResult)
  937. {
  938. MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
  939. if (pMsgFilter != NULL)
  940. {
  941. switch (pMsgFilter->msg)
  942. {
  943. case WM_MOUSEACTIVATE:
  944. m_RichEdit.SetFocus();
  945. break;
  946. }
  947. }
  948. *pResult = 0;
  949. }