SymbolEdit.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. // AeroEdit.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "SymbolEdit.h"
  5. #include "cp_main.h"
  6. #include "QListCtrl.h"
  7. // CSymbolEdit
  8. #define RANGE_START 3000
  9. #define CLEAR_LIST 3050
  10. #define LIST_MAX_COUNT 50
  11. IMPLEMENT_DYNAMIC(CSymbolEdit, CEdit)
  12. CSymbolEdit::CSymbolEdit() :
  13. m_hSymbolIcon(NULL),
  14. m_bInternalIcon(false),
  15. m_colorPromptText(RGB(127, 127, 127))
  16. {
  17. m_fontPrompt.CreateFont(
  18. 16, // nHeight
  19. 0, // nWidth
  20. 0, // nEscapement
  21. 0, // nOrientation
  22. FW_NORMAL, // nWeight
  23. TRUE, // bItalic
  24. FALSE, // bUnderline
  25. 0, // cStrikeOut
  26. DEFAULT_CHARSET, // nCharSet
  27. OUT_DEFAULT_PRECIS, // nOutPrecision
  28. CLIP_DEFAULT_PRECIS, // nClipPrecision
  29. DEFAULT_QUALITY, // nQuality
  30. DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
  31. _T("Calibri"));
  32. m_mouseDownOnSearches = false;
  33. m_mouseHoveringOverSearches = false;
  34. m_mouseDownOnClose = false;
  35. m_mouseHoveringOverClose = false;
  36. //m_searchButton.LoadStdImageDPI(Search_16, Search_20, Search_24, Search_32, _T("PNG"));
  37. m_closeButton.LoadStdImageDPI(search_close_16, Search_20, Search_24, Search_28, Search_32, _T("PNG"));
  38. m_searchesButton.LoadStdImageDPI(down_16, down_20, down_24, down_28, down_32, _T("PNG"));
  39. }
  40. CSymbolEdit::~CSymbolEdit()
  41. {
  42. DestroyIcon();
  43. }
  44. BEGIN_MESSAGE_MAP(CSymbolEdit, CEdit)
  45. ON_WM_PAINT()
  46. ON_MESSAGE(WM_SETFONT, OnSetFont)
  47. //ON_MESSAGE(WM_EXITMENULOOP, OnMenuExit)
  48. ON_WM_CTLCOLOR_REFLECT()
  49. ON_WM_SETFOCUS()
  50. ON_WM_KILLFOCUS()
  51. ON_WM_SETCURSOR()
  52. ON_WM_LBUTTONUP()
  53. ON_WM_LBUTTONDOWN()
  54. ON_WM_MOUSEMOVE()
  55. ON_COMMAND_RANGE(RANGE_START, (RANGE_START+ LIST_MAX_COUNT), OnSelectSearchString)
  56. ON_WM_EXITSIZEMOVE()
  57. END_MESSAGE_MAP()
  58. BOOL CSymbolEdit::PreTranslateMessage(MSG* pMsg)
  59. {
  60. // TODO: Add your specialized code here and/or call the base class
  61. // Intercept Ctrl + Z (Undo), Ctrl + X (Cut), Ctrl + C (Copy), Ctrl + V (Paste) and Ctrl + A (Select All)
  62. // before CEdit base class gets a hold of them.
  63. if (pMsg->message == WM_KEYDOWN &&
  64. CONTROL_PRESSED)
  65. {
  66. switch (pMsg->wParam)
  67. {
  68. case 'Z':
  69. Undo();
  70. return TRUE;
  71. case 'X':
  72. Cut();
  73. return TRUE;
  74. case 'C':
  75. Copy();
  76. return TRUE;
  77. case 'V':
  78. Paste();
  79. return TRUE;
  80. case 'A':
  81. SetSel(0, -1);
  82. return TRUE;
  83. }
  84. }
  85. switch (pMsg->message)
  86. {
  87. case WM_KEYDOWN:
  88. {
  89. if (pMsg->wParam == VK_RETURN)
  90. {
  91. CWnd *pWnd = GetParent();
  92. if (pWnd)
  93. {
  94. if (g_Opt.m_bFindAsYouType)
  95. {
  96. pWnd->SendMessage(NM_SEARCH_ENTER_PRESSED, 0, 0);
  97. }
  98. else
  99. {
  100. //Send a message to the parent to refill the lb from the search
  101. pWnd->PostMessage(CB_SEARCH, 0, 0);
  102. }
  103. AddToSearchHistory();
  104. }
  105. return TRUE;
  106. }
  107. else if (pMsg->wParam == VK_DOWN &&
  108. ((GetKeyState(VK_CONTROL) & 0x8000) || ((GetKeyState(VK_CONTROL) & 0x8000) && (GetKeyState(VK_SHIFT) & 0x8000))))
  109. {
  110. if (ShowSearchHistoryMenu())
  111. {
  112. return TRUE;
  113. }
  114. }
  115. else if (pMsg->wParam == VK_DOWN ||
  116. pMsg->wParam == VK_UP ||
  117. pMsg->wParam == VK_F3 ||
  118. pMsg->wParam == VK_PRIOR ||
  119. pMsg->wParam == VK_NEXT)
  120. {
  121. CWnd *pWnd = GetParent();
  122. if (pWnd)
  123. {
  124. pWnd->SendMessage(CB_UPDOWN, pMsg->wParam, pMsg->lParam);
  125. return TRUE;
  126. }
  127. }
  128. else if (pMsg->wParam == VK_DELETE)
  129. {
  130. int startChar;
  131. int endChar;
  132. this->GetSel(startChar, endChar);
  133. CString cs;
  134. this->GetWindowText(cs);
  135. //if selection is at the end then forward this on to the parent to delete the selected clip
  136. if(startChar == cs.GetLength() &&
  137. endChar == cs.GetLength())
  138. {
  139. CWnd *pWnd = GetParent();
  140. if (pWnd)
  141. {
  142. pWnd->SendMessage(NM_DELETE, pMsg->wParam, pMsg->lParam);
  143. return TRUE;
  144. }
  145. }
  146. }
  147. break;
  148. }
  149. }
  150. return CEdit::PreTranslateMessage(pMsg);
  151. }
  152. void CSymbolEdit::AddToSearchHistory()
  153. {
  154. CString cs;
  155. this->GetWindowText(cs);
  156. if (cs != _T(""))
  157. {
  158. if (m_searches.GetCount() >= LIST_MAX_COUNT)
  159. {
  160. m_searches.RemoveAt(0);
  161. }
  162. bool existing = false;
  163. int count = m_searches.GetCount();
  164. for (int i = 0; i < count; i++)
  165. {
  166. if (m_searches[i] == cs)
  167. {
  168. m_searches.RemoveAt(i);
  169. m_searches.Add(cs);
  170. existing = true;
  171. break;
  172. }
  173. }
  174. if (existing == false)
  175. {
  176. m_searches.Add(cs);
  177. }
  178. }
  179. }
  180. bool CSymbolEdit::ShowSearchHistoryMenu()
  181. {
  182. if (m_searches.GetCount() == 0)
  183. {
  184. return false;
  185. }
  186. CMenu cmPopUp;
  187. cmPopUp.CreatePopupMenu();
  188. int count = min(m_searches.GetCount(), LIST_MAX_COUNT);
  189. for (int i = count-1; i >= 0; i--)
  190. {
  191. cmPopUp.AppendMenuW(MF_STRING, (RANGE_START + i), m_searches[i]);
  192. }
  193. cmPopUp.AppendMenu(MF_SEPARATOR);
  194. cmPopUp.AppendMenuW(MF_STRING, CLEAR_LIST, _T("Clear List"));
  195. CRect windowRect;
  196. this->GetWindowRect(&windowRect);
  197. POINT pp;
  198. GetCursorPos(&pp);
  199. POINT x = this->GetCaretPos();
  200. ClientToScreen(&x);
  201. x.y += windowRect.Height();
  202. cmPopUp.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, x.x, x.y, this, NULL);
  203. Invalidate();
  204. return true;
  205. }
  206. void CSymbolEdit::DestroyIcon()
  207. {
  208. // if icon was loaded internally, destroy it
  209. if (m_bInternalIcon || m_hSymbolIcon != NULL)
  210. ::DestroyIcon(m_hSymbolIcon);
  211. }
  212. void CSymbolEdit::PreSubclassWindow()
  213. {
  214. RecalcLayout();
  215. }
  216. void CSymbolEdit::SetSymbolIcon(HICON hIcon, BOOL redraw)
  217. {
  218. DestroyIcon();
  219. m_hSymbolIcon = hIcon;
  220. // icon was not loaded internally
  221. m_bInternalIcon = false;
  222. RecalcLayout();
  223. if (redraw)
  224. Invalidate(TRUE);
  225. }
  226. void CSymbolEdit::SetSymbolIcon(UINT id, BOOL redraw)
  227. {
  228. DestroyIcon();
  229. m_hSymbolIcon = (HICON)::LoadImage(
  230. AfxGetResourceHandle(),
  231. MAKEINTRESOURCE(id),
  232. IMAGE_ICON,
  233. 16,
  234. 16,
  235. LR_DEFAULTCOLOR | LR_LOADTRANSPARENT);
  236. ASSERT(m_hSymbolIcon != NULL);
  237. // icon was loaded internally
  238. m_bInternalIcon = true;
  239. RecalcLayout();
  240. if (redraw)
  241. Invalidate(TRUE);
  242. }
  243. void CSymbolEdit::SetPromptText(CString text, BOOL redraw)
  244. {
  245. m_strPromptText = text;
  246. if (redraw)
  247. Invalidate(TRUE);
  248. }
  249. void CSymbolEdit::SetPromptText(LPCTSTR szText, BOOL redraw)
  250. {
  251. m_strPromptText = szText;
  252. if (redraw)
  253. Invalidate(TRUE);
  254. }
  255. void CSymbolEdit::SetPromptTextColor(COLORREF color, BOOL redraw)
  256. {
  257. m_colorPromptText = color;
  258. if (redraw)
  259. Invalidate(TRUE);
  260. }
  261. void CSymbolEdit::SetPromptFont(CFont& font, BOOL redraw)
  262. {
  263. LOGFONT lf;
  264. memset(&lf, 0, sizeof(LOGFONT));
  265. font.GetLogFont(&lf);
  266. SetPromptFont(&lf);
  267. if (redraw)
  268. Invalidate(TRUE);
  269. }
  270. void CSymbolEdit::SetPromptFont(const LOGFONT* lpLogFont, BOOL redraw)
  271. {
  272. m_fontPrompt.DeleteObject();
  273. m_fontPrompt.CreateFontIndirect(lpLogFont);
  274. if (redraw)
  275. Invalidate(TRUE);
  276. }
  277. void CSymbolEdit::RecalcLayout()
  278. {
  279. int width = GetSystemMetrics(SM_CXSMICON);
  280. if (m_hSymbolIcon)
  281. {
  282. DWORD dwMargins = GetMargins();
  283. SetMargins(LOWORD(dwMargins), width + 6);
  284. }
  285. else
  286. {
  287. SetMargins(4, theApp.m_metrics.ScaleX(34));
  288. }
  289. }
  290. // CSymbolEdit message handlers
  291. void CSymbolEdit::OnPaint()
  292. {
  293. CPaintDC dc(this);
  294. CRect rect;
  295. GetClientRect(&rect);
  296. DWORD margins = GetMargins();
  297. CRect textRect(rect);
  298. textRect.left += LOWORD(margins);
  299. textRect.right -= HIWORD(margins);
  300. // Clearing the background
  301. dc.FillSolidRect(rect, GetSysColor(COLOR_WINDOW));
  302. if (m_hSymbolIcon)
  303. {
  304. // Drawing the icon
  305. int width = GetSystemMetrics(SM_CXSMICON);
  306. int height = GetSystemMetrics(SM_CYSMICON);
  307. ::DrawIconEx(
  308. dc.m_hDC,
  309. rect.right - width - 1,
  310. 1,
  311. m_hSymbolIcon,
  312. width,
  313. height,
  314. 0,
  315. NULL,
  316. DI_NORMAL);
  317. rect.left += LOWORD(margins) + 1;
  318. rect.right -= (width + 7);
  319. }
  320. else
  321. {
  322. //rect.left += (LOWORD(dwMargins) + 1);
  323. //rect.right -= (HIWORD(dwMargins) + 1);
  324. }
  325. CString text;
  326. GetWindowText(text);
  327. CFont* oldFont = NULL;
  328. //rect.top += 1;
  329. if(this == GetFocus() || text.GetLength() > 0)
  330. {
  331. dc.FillSolidRect(rect, g_Opt.m_Theme.SearchTextBoxFocusBG());
  332. oldFont = dc.SelectObject(GetFont());
  333. COLORREF oldColor = dc.GetTextColor();
  334. dc.SetTextColor(g_Opt.m_Theme.SearchTextBoxFocusText());
  335. dc.DrawText(text, textRect, DT_SINGLELINE | DT_INTERNAL | DT_EDITCONTROL);
  336. dc.SelectObject(oldFont);
  337. dc.SetTextColor(oldColor);
  338. }
  339. else
  340. {
  341. dc.FillSolidRect(rect, g_Opt.m_Theme.MainWindowBG());
  342. }
  343. if (text.GetLength() == 0 && m_strPromptText.GetLength() > 0)
  344. {
  345. //if we aren't showing the close icon, then use the full space
  346. textRect.right += theApp.m_metrics.ScaleX(16);
  347. //textRect.right -= LOWORD(margins);
  348. oldFont = dc.SelectObject(&m_fontPrompt);
  349. COLORREF color = dc.GetTextColor();
  350. dc.SetTextColor(m_colorPromptText);
  351. dc.DrawText(m_strPromptText, textRect, DT_LEFT | DT_SINGLELINE | DT_EDITCONTROL | DT_VCENTER);
  352. dc.SetTextColor(color);
  353. dc.SelectObject(oldFont);
  354. }
  355. int right = rect.right;
  356. if ((text.GetLength() > 0 || this == GetFocus()))
  357. {
  358. m_searchesButtonRect.SetRect(rect.right - theApp.m_metrics.ScaleX(18), 0, rect.right, rect.bottom);
  359. right = rect.right - theApp.m_metrics.ScaleX(18);
  360. m_searchesButton.Draw(&dc, this, m_searchesButtonRect.left, 4, m_mouseHoveringOverSearches, m_mouseDownOnSearches);
  361. }
  362. else
  363. {
  364. m_searchesButtonRect.SetRect(0, 0, 0, 0);
  365. //m_searchButton.Draw(&dc, this, rect.right - 22, 4, false, false);
  366. }
  367. if (text.GetLength() > 0)
  368. {
  369. OutputDebugString(_T("showing close button\n"));
  370. m_closeButtonRect.SetRect(right - theApp.m_metrics.ScaleX(16), 0, right, rect.bottom);
  371. m_closeButton.Draw(&dc, this, m_closeButtonRect.left, 4, m_mouseHoveringOverClose, m_mouseDownOnClose);
  372. }
  373. else
  374. {
  375. OutputDebugString(_T("not showing close button\n"));
  376. m_closeButtonRect.SetRect(0, 0, 0, 0);
  377. //m_searchButton.Draw(&dc, this, rect.right - 22, 4, false, false);
  378. }
  379. //OutputDebugString(_T("OnPaint"));
  380. }
  381. void CSymbolEdit::OnSize(UINT nType, int cx, int cy)
  382. {
  383. CEdit::OnSize(nType, cx, cy);
  384. RecalcLayout();
  385. }
  386. LRESULT CSymbolEdit::OnSetFont(WPARAM wParam, LPARAM lParam)
  387. {
  388. DefWindowProc(WM_SETFONT, wParam, lParam);
  389. RecalcLayout();
  390. return 0;
  391. }
  392. HBRUSH CSymbolEdit::CtlColor(CDC* pDC, UINT n)
  393. {
  394. if (::GetFocus() == m_hWnd)
  395. {
  396. pDC->SetBkColor(RGB(255, 255, 255));
  397. return CreateSolidBrush(RGB(255, 255, 255));
  398. }
  399. else
  400. {
  401. pDC->SetBkColor(g_Opt.m_Theme.MainWindowBG());
  402. return CreateSolidBrush(g_Opt.m_Theme.MainWindowBG());
  403. }
  404. }
  405. void CSymbolEdit::OnSetFocus(CWnd* pOldWnd)
  406. {
  407. Invalidate(FALSE);
  408. CEdit::OnSetFocus(pOldWnd);
  409. CWnd *pWnd = GetParent();
  410. if (pWnd)
  411. {
  412. if (g_Opt.m_bFindAsYouType)
  413. {
  414. pWnd->SendMessage(NM_FOCUS_ON_SEARCH, 0, 0);
  415. }
  416. }
  417. }
  418. void CSymbolEdit::OnKillFocus(CWnd* pNewWnd)
  419. {
  420. AddToSearchHistory();
  421. Invalidate(FALSE);
  422. CEdit::OnKillFocus(pNewWnd);
  423. }
  424. BOOL CSymbolEdit::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  425. {
  426. CPoint pntCursor;
  427. GetCursorPos(&pntCursor);
  428. ScreenToClient(&pntCursor);
  429. if(m_closeButtonRect.PtInRect(pntCursor))
  430. {
  431. HCURSOR h = ::LoadCursor(NULL, IDC_ARROW);
  432. ::SetCursor(h);
  433. return TRUE;
  434. }
  435. if (m_searchesButtonRect.PtInRect(pntCursor))
  436. {
  437. HCURSOR h = ::LoadCursor(NULL, IDC_ARROW);
  438. ::SetCursor(h);
  439. return TRUE;
  440. }
  441. return CEdit::OnSetCursor(pWnd, nHitTest, message);
  442. }
  443. void CSymbolEdit::OnLButtonUp(UINT nFlags, CPoint point)
  444. {
  445. if (m_mouseDownOnClose)
  446. {
  447. ReleaseCapture();
  448. InvalidateRect(m_closeButtonRect);
  449. }
  450. if (m_mouseDownOnSearches)
  451. {
  452. ReleaseCapture();
  453. InvalidateRect(m_searchesButtonRect);
  454. }
  455. m_mouseDownOnClose = false;
  456. m_mouseDownOnSearches = false;
  457. if (m_closeButtonRect.PtInRect(point))
  458. {
  459. if ((GetWindowTextLength() > 0))
  460. {
  461. CWnd *pOwner = GetOwner();
  462. if (pOwner)
  463. {
  464. pOwner->SendMessage(NM_CANCEL_SEARCH, 0, 0);
  465. }
  466. }
  467. }
  468. if (m_searchesButtonRect.PtInRect(point))
  469. {
  470. this->ShowSearchHistoryMenu();
  471. }
  472. CEdit::OnLButtonUp(nFlags, point);
  473. }
  474. void CSymbolEdit::OnLButtonDown(UINT nFlags, CPoint point)
  475. {
  476. if (m_closeButtonRect.PtInRect(point))
  477. {
  478. m_mouseDownOnClose = true;
  479. SetCapture();
  480. InvalidateRect(m_closeButtonRect);
  481. }
  482. else
  483. {
  484. m_mouseDownOnClose = false;
  485. }
  486. if (m_searchesButtonRect.PtInRect(point))
  487. {
  488. m_mouseDownOnSearches = true;
  489. SetCapture();
  490. InvalidateRect(m_searchesButtonRect);
  491. }
  492. else
  493. {
  494. m_mouseDownOnSearches = false;
  495. }
  496. CEdit::OnLButtonDown(nFlags, point);
  497. }
  498. void CSymbolEdit::OnMouseMove(UINT nFlags, CPoint point)
  499. {
  500. if (m_closeButtonRect.PtInRect(point))
  501. {
  502. if (m_mouseHoveringOverClose == false)
  503. {
  504. m_mouseHoveringOverClose = true;
  505. InvalidateRect(m_closeButtonRect);
  506. }
  507. }
  508. else if(m_mouseHoveringOverClose)
  509. {
  510. m_mouseHoveringOverClose = false;
  511. InvalidateRect(m_closeButtonRect);
  512. }
  513. if (m_searchesButtonRect.PtInRect(point))
  514. {
  515. if (m_mouseHoveringOverSearches == false)
  516. {
  517. m_mouseHoveringOverSearches = true;
  518. InvalidateRect(m_searchesButtonRect);
  519. }
  520. }
  521. else if (m_mouseHoveringOverSearches)
  522. {
  523. m_mouseHoveringOverSearches = false;
  524. InvalidateRect(m_searchesButtonRect);
  525. }
  526. CEdit::OnMouseMove(nFlags, point);
  527. }
  528. void CSymbolEdit::OnSelectSearchString(UINT idIn)
  529. {
  530. int index = idIn - RANGE_START;
  531. if (idIn == CLEAR_LIST)
  532. {
  533. m_searches.RemoveAll();
  534. }
  535. else if (index >= 0 &&
  536. index < m_searches.GetCount())
  537. {
  538. CString cs = m_searches[index];
  539. this->SetWindowTextW(cs);
  540. this->SetFocus();
  541. this->SetSel(-1);
  542. this->Invalidate();
  543. m_searches.RemoveAt(index);
  544. m_searches.Add(cs);
  545. }
  546. }