skinnededit.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. #include "./skinnededit.h"
  2. #include "../winamp/wa_dlg.h"
  3. #include "./skinning.h"
  4. #include "./stockobjects.h"
  5. #include "./skinnedmenu.h"
  6. #include "../nu/trace.h"
  7. #include <windowsx.h>
  8. #include <strsafe.h>
  9. #define EDIT_TEXT_MAX 65536
  10. static WCHAR *pszTextGlobal = NULL;
  11. static int caretPos = -1;
  12. static BOOL updateCaret = FALSE;
  13. #define GET_CHAR_X(__hwnd, __index) (GET_X_LPARAM(CallPrevWndProc(EM_POSFROMCHAR, (WPARAM)(__index), 0L)))
  14. #define MLSEM_FIRST (WM_APP + 0x2FFE)
  15. #define MLSEM_ENABLEREDRAW (MLSEM_FIRST - 0)
  16. SkinnedEdit::SkinnedEdit(void) : SkinnedWnd(FALSE), firstVisible(0), lastVisible(0),
  17. firstSelected(0), lastSelected(0), maxCharWidth(0),
  18. mouseWParam(0), mouseLParam(0), cx(0), cy(0)
  19. {
  20. if (NULL == pszTextGlobal)
  21. pszTextGlobal = (LPWSTR)calloc(EDIT_TEXT_MAX, sizeof(WCHAR));
  22. }
  23. SkinnedEdit::~SkinnedEdit(void)
  24. {
  25. }
  26. BOOL SkinnedEdit::Attach(HWND hwndEdit)
  27. {
  28. if(!SkinnedWnd::Attach(hwndEdit)) return FALSE;
  29. SetType(SKINNEDWND_TYPE_EDIT);
  30. FontChanged();
  31. SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
  32. return TRUE;
  33. }
  34. void SkinnedEdit::EraseBckGnd(HDC hdc, RECT *prc, RECT *prcText, BOOL fEraseAll, HBRUSH hBrush)
  35. {
  36. HRGN rgn = CreateRectRgnIndirect(prc);
  37. if (!IsRectEmpty(prcText))
  38. {
  39. HRGN rgn2 = CreateRectRgnIndirect(prcText);
  40. if (NULL != rgn2)
  41. {
  42. CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
  43. /* if (FALSE != fEraseAll)
  44. {
  45. SetRectRgn(rgn2, prc->left, prc->top, prc->right, prcText->top);
  46. CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
  47. SetRectRgn(rgn2, prc->left, prcText->bottom, prc->right, prc->bottom);
  48. CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
  49. }*/
  50. DeleteObject(rgn2);
  51. }
  52. }
  53. FillRgn(hdc, rgn, hBrush);
  54. DeleteObject(rgn);
  55. }
  56. void SkinnedEdit::DrawText(HDC hdc, RECT *prc, RECT *prcText, LPCWSTR pszText, INT cchText)
  57. {
  58. if ((lastSelected != firstSelected) &&
  59. (lastSelected > firstVisible) &&
  60. (firstSelected < lastVisible) &&
  61. ((hwnd == GetFocus()) || (ES_NOHIDESEL & GetWindowLongPtrW(hwnd, GWL_STYLE))))
  62. {
  63. RECT rt;
  64. int lim, limSel;
  65. LPCWSTR pszTextOut;
  66. pszTextOut = pszText + firstVisible;
  67. lim = firstSelected - firstVisible;
  68. CopyRect(&rt, prcText);
  69. if (lim > 0)
  70. {
  71. // DrawTextW(hdc, pszTextOut, lim, prcText,DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP);
  72. ExtTextOutW(hdc, rt.left, rt.top, 0, &rt, pszTextOut, lim, NULL);
  73. pszTextOut += lim;
  74. }
  75. limSel = min(lastSelected, lastVisible) - (int)(pszTextOut - pszText);
  76. lim = lastVisible - lastSelected;
  77. if(lim > 0)
  78. {
  79. rt.left = GET_CHAR_X(hwnd, lastSelected);
  80. // DrawTextW(hdc, pszTextOut + limSel, lim, &rt, DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP);
  81. ExtTextOutW(hdc, rt.left, rt.top, 0, &rt, pszTextOut + limSel, lim, NULL);
  82. }
  83. SetTextColor(hdc, WADlg_getColor(WADLG_SELBAR_FGCOLOR));
  84. SetBkColor(hdc, WADlg_getColor(WADLG_SELBAR_BGCOLOR));
  85. if (lim > 0) rt.right = rt.left - 1;
  86. rt.left = GET_CHAR_X(hwnd, max(firstSelected, firstVisible));
  87. // DrawTextW(hdc, pszTextOut, limSel, &rt, DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP );
  88. if (rt.right > rt.left) ExtTextOutW(hdc, rt.left, rt.top, ETO_CLIPPED, &rt, pszTextOut, limSel, NULL);
  89. }
  90. else
  91. {
  92. // DrawTextW(hdc, pszText + firstVisible, cchText - firstVisible - (cchText - lastVisible), prcText, DT_TOP | DT_NOPREFIX | DT_NOCLIP);
  93. ExtTextOutW(hdc, prcText->left, prcText->top, 0, prcText,
  94. pszText+ firstVisible, cchText - firstVisible - (cchText - lastVisible), NULL);
  95. }
  96. }
  97. static void GetEditColors(DWORD windowStyle, BOOL bEnabled, COLORREF *prgbText, COLORREF *prgbTextBk)
  98. {
  99. COLORREF fg, bg;
  100. bg = WADlg_getColor((ES_READONLY & windowStyle) ? WADLG_WNDBG : WADLG_ITEMBG);
  101. fg = WADlg_getColor((ES_READONLY & windowStyle) ? WADLG_WNDFG : WADLG_ITEMFG);
  102. if(!bEnabled)
  103. {
  104. fg = RGB((GetRValue(fg)+GetRValue(bg))/2,
  105. (GetGValue(fg)+GetGValue(bg))/2,
  106. (GetBValue(fg)+GetBValue(bg))/2);
  107. }
  108. if (prgbText) *prgbText = fg;
  109. if (prgbTextBk) *prgbTextBk = bg;
  110. }
  111. void SkinnedEdit::OnPaint()
  112. {
  113. HDC hdc;
  114. int cchText;
  115. PAINTSTRUCT ps;
  116. RECT rc, rt;
  117. HFONT hFont, hFontOld;
  118. DWORD margins, ws;
  119. TEXTMETRICW tm;
  120. cchText = (INT)CallPrevWndProc(WM_GETTEXTLENGTH, 0, 0);
  121. if (cchText) CallPrevWndProc(WM_GETTEXT, (WPARAM)EDIT_TEXT_MAX, (LPARAM)pszTextGlobal);
  122. hFont = (HFONT)CallPrevWndProc(WM_GETFONT, 0, 0L);
  123. if (!hFont) hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
  124. hdc = GetDCEx(hwnd, NULL, DCX_PARENTCLIP | DCX_CACHE | DCX_CLIPSIBLINGS |
  125. DCX_INTERSECTUPDATE | DCX_VALIDATE);
  126. if (NULL == hdc) return;
  127. hFontOld = (hFont) ? (HFONT)SelectObject(hdc, hFont) : NULL;
  128. GetTextMetricsW(hdc, &tm);
  129. GetClientRect(hwnd, &rc);
  130. CopyRect(&rt, &rc);
  131. if (SWES_BOTTOM & style)
  132. {
  133. if ((rt.bottom - tm.tmHeight) > rt.top) rt.top = rt.bottom - tm.tmHeight;
  134. }
  135. else if (SWES_VCENTER & style)
  136. {
  137. INT t = rc.top + ((rc.bottom - rc.top) - tm.tmHeight)/2;
  138. if (t > rc.top) rt.top = t;
  139. }
  140. ws = GetWindowLongPtrW(hwnd, GWL_STYLE);
  141. margins = (DWORD)CallPrevWndProc(EM_GETMARGINS, 0, 0L);
  142. if (cchText)
  143. {
  144. int x;
  145. CallPrevWndProc(EM_GETSEL, (WPARAM)&firstSelected, (LPARAM)&lastSelected);
  146. lastVisible = (int)(INT_PTR)CallPrevWndProc(EM_CHARFROMPOS, 0, MAKELPARAM(rc.right - (GET_Y_LPARAM(margins)), 0));
  147. if ( -1 == lastVisible) lastVisible = cchText;
  148. firstVisible =(INT)(INT_PTR)CallPrevWndProc(EM_CHARFROMPOS, 0, MAKELPARAM(rc.left + GET_X_LPARAM(margins), 0));
  149. if (cchText == firstVisible) firstVisible = 0;
  150. else if (firstVisible > 0) firstVisible++;
  151. while (12000 < (x = GET_CHAR_X(hwnd, firstVisible))) firstVisible++;
  152. rt.left = x;
  153. if (firstVisible > 0 && rt.left > rc.left + GET_X_LPARAM(margins) + 1)
  154. { // we can try to display one more
  155. int t = GET_CHAR_X(hwnd, firstVisible -1);
  156. if (t != -1 && t < rc.right) { rt.left = t; firstVisible--; }
  157. }
  158. if (lastVisible)
  159. {
  160. if (lastVisible < cchText -1)
  161. {
  162. rt.right = GET_CHAR_X(hwnd, lastVisible);
  163. }
  164. else
  165. {
  166. INT i = lastVisible - ((cchText == lastVisible && cchText) ? 1 : 0);
  167. ABC abc;
  168. if (GetCharABCWidthsW(hdc, pszTextGlobal[i], pszTextGlobal[i], &abc))
  169. rt.right = abc.abcA + abc.abcB + abc.abcC;
  170. else
  171. GetCharWidth32W(hdc, pszTextGlobal[i], pszTextGlobal[i], (INT*)&rt.right);
  172. rt.right += GET_CHAR_X(hwnd, i);
  173. }
  174. }
  175. else rt.right = rt.left;
  176. if (rt.top + tm.tmHeight < rt.bottom) rt.bottom = rt.top + tm.tmHeight;
  177. if (rt.right > rc.right - GET_Y_LPARAM(margins)) rt.right = rc.right - GET_Y_LPARAM(margins);
  178. }
  179. else
  180. {
  181. firstVisible = 0;
  182. lastVisible = 0;
  183. rt.left += GET_X_LPARAM(margins);
  184. rt.right -= GET_Y_LPARAM(margins);
  185. if (ES_CENTER & ws)
  186. {
  187. rt.left += (rt.right - rt.left)/2;
  188. rt.right = rt.left;
  189. }
  190. else if (ES_RIGHT & ws) rt.left = rt.right;
  191. else rt.right = rt.left;
  192. }
  193. if (FALSE != updateCaret)
  194. {
  195. updateCaret = FALSE;
  196. // ShowCaret(hwnd);
  197. if (hwnd == GetFocus())
  198. {
  199. INT x;
  200. if (caretPos >= lastVisible) x = rt.right;
  201. else if (caretPos <= firstVisible) x = rt.left;
  202. else x = GET_CHAR_X(hwnd, caretPos);
  203. if (x < rc.left)
  204. x = rc.left;
  205. else
  206. {
  207. INT caretWidth = GetSystemMetrics(SM_CXBORDER);
  208. if (x + caretWidth > rc.right)
  209. x = rc.right - caretWidth;
  210. }
  211. SetCaretPos(x, rt.top);
  212. }
  213. }
  214. if (hFontOld) SelectObject(hdc, hFontOld);
  215. ReleaseDC(hwnd, hdc);
  216. hdc = BeginPaint(hwnd, &ps);
  217. if (NULL == hdc) return;
  218. hFontOld = (hFont) ? (HFONT)SelectObject(hdc, hFont) : NULL;
  219. HBRUSH brushBk = NULL;
  220. BOOL overrideColors = FALSE;
  221. HWND hParent = GetParent(hwnd);
  222. if (NULL != hParent)
  223. {
  224. UINT uMsg = (0 == ((ES_READONLY | WS_DISABLED) & ws)) ? WM_CTLCOLOREDIT : WM_CTLCOLORSTATIC;
  225. brushBk = (HBRUSH)SendMessage(hParent, uMsg, (WPARAM)hdc, (LPARAM)hwnd);
  226. HBRUSH stockBursh = GetSysColorBrush( (0 == ((ES_READONLY | WS_DISABLED) & ws)) ? COLOR_WINDOW : COLOR_3DFACE);
  227. if (NULL == brushBk || stockBursh == brushBk)
  228. overrideColors = TRUE;
  229. }
  230. if (FALSE != overrideColors)
  231. {
  232. COLORREF rgbText, rgbTextBk;
  233. GetEditColors(ws, IsWindowEnabled(hwnd), &rgbText, &rgbTextBk);
  234. SetBkColor(hdc, rgbTextBk);
  235. SetTextColor(hdc, rgbText);
  236. brushBk = (HBRUSH)MlStockObjects_Get((ES_READONLY & ws) ? WNDBCK_BRUSH : ITEMBCK_BRUSH);
  237. }
  238. IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
  239. EraseBckGnd(hdc, &rc, NULL, ps.fErase, brushBk);
  240. if (cchText)
  241. {
  242. IntersectClipRect(hdc, rc.left + GET_X_LPARAM(margins), rt.top, rc.right - GET_Y_LPARAM(margins), rt.bottom);
  243. DrawText(hdc, &rc, &rt, pszTextGlobal, cchText);
  244. }
  245. if (hFontOld) SelectObject(hdc, hFontOld);
  246. EndPaint(hwnd, &ps);
  247. }
  248. void SkinnedEdit::OnSkinUpdated(BOOL bNotifyChildren, BOOL bRedraw)
  249. {
  250. __super::OnSkinUpdated(bNotifyChildren, bRedraw);
  251. if (SWS_USESKINFONT & style)
  252. {
  253. CallPrevWndProc(EM_SETMARGINS, (WPARAM)(EC_LEFTMARGIN | EC_RIGHTMARGIN), MAKELPARAM(EC_USEFONTINFO, EC_USEFONTINFO));
  254. }
  255. }
  256. BOOL SkinnedEdit::GetSelection(SELECTION *selection, INT cchText, const RECT *clientRect)
  257. {
  258. if (NULL == selection) return FALSE;
  259. if (0 == cchText)
  260. {
  261. selection->first = 0;
  262. selection->last = 0;
  263. selection->leftX = clientRect->left;
  264. selection->rightX = clientRect->left;
  265. return TRUE;
  266. }
  267. CallPrevWndProc(EM_GETSEL, (WPARAM)&selection->first, (LPARAM)&selection->last);
  268. selection->leftX = GET_CHAR_X(hwnd, selection->first);
  269. if (-1 == selection->last || cchText == selection->last)
  270. {
  271. selection->last = cchText;
  272. selection->rightX = GET_CHAR_X(hwnd, cchText - 1) + maxCharWidth;
  273. }
  274. else
  275. {
  276. selection->rightX = GET_CHAR_X(hwnd, selection->last);
  277. }
  278. return TRUE;
  279. }
  280. LRESULT SkinnedEdit::OverrideDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
  281. {
  282. LRESULT result;
  283. UINT windowStyle = GetWindowStyle(hwnd);
  284. if (0 == (WS_VISIBLE & windowStyle))
  285. {
  286. result = __super::WindowProc(uMsg, wParam, lParam);
  287. return result;
  288. }
  289. SELECTION selectionOrig;
  290. RECT ri;
  291. GetClientRect(hwnd, &ri);
  292. INT lengthOrig = (INT)CallPrevWndProc(WM_GETTEXTLENGTH, 0, 0L);
  293. INT startXOrig = (lengthOrig > 0) ? GET_CHAR_X(hwnd, 0) : 0;
  294. GetSelection(&selectionOrig, lengthOrig, &ri);
  295. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~ WS_VISIBLE);
  296. result = __super::WindowProc(uMsg, wParam, lParam);
  297. windowStyle = GetWindowStyle(hwnd);
  298. if (0 == (WS_VISIBLE & windowStyle))
  299. {
  300. windowStyle |= WS_VISIBLE;
  301. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle);
  302. }
  303. if (hwnd == GetFocus())
  304. {
  305. INT length = (INT)CallPrevWndProc(WM_GETTEXTLENGTH, 0, 0L);
  306. SELECTION selection;
  307. GetSelection(&selection, length, &ri);
  308. if (selectionOrig.first != selection.first || selectionOrig.last != selection.last || lengthOrig != length )
  309. {
  310. caretPos = (selectionOrig.last != selection.last) ? selection.last : selection.first;
  311. if( FALSE == updateCaret)
  312. updateCaret = TRUE;
  313. if (0 != (WS_VISIBLE & windowStyle))
  314. {
  315. INT startX = (lengthOrig > 0) ? GET_CHAR_X(hwnd, 0) : 0;
  316. if (lengthOrig != length || startXOrig != startX)
  317. {
  318. RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOERASE | RDW_ERASENOW | RDW_UPDATENOW | RDW_NOCHILDREN);
  319. }
  320. else
  321. {
  322. //RECT ri;
  323. GetClientRect(hwnd, &ri);
  324. if (selectionOrig.first != selectionOrig.last)
  325. {
  326. if (selectionOrig.rightX > selection.leftX && selectionOrig.rightX < selection.rightX)
  327. selectionOrig.rightX--;
  328. if (selectionOrig.leftX > selection.leftX && selectionOrig.leftX < selection.rightX)
  329. selectionOrig.leftX++;
  330. }
  331. // aTRACE_FMT("redraw: (%d, %d) - (%d, %d)\r\n",selectionOrig.leftX, selectionOrig.rightX, selection.leftX, selection.rightX);
  332. HRGN rgn1 = CreateRectRgn(selectionOrig.leftX, ri.top, selectionOrig.rightX, ri.bottom);
  333. HRGN rgn2 = CreateRectRgn(selection.leftX, ri.top, selection.rightX, ri.bottom);
  334. CombineRgn(rgn1, rgn1, rgn2, (selectionOrig.first != selectionOrig.last) ? RGN_XOR : RGN_OR);
  335. POINT caretPt;
  336. if (FALSE != GetCaretPos(&caretPt))
  337. {
  338. INT caretWidth = GetSystemMetrics(SM_CXBORDER);
  339. if (0 == caretWidth) caretWidth = 1;
  340. SetRectRgn(rgn2, caretPt.x, ri.top, caretPt.x + caretWidth, ri.bottom);
  341. CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
  342. }
  343. RedrawWindow(hwnd, NULL, rgn1, RDW_INVALIDATE | RDW_NOERASE | RDW_ERASENOW | RDW_UPDATENOW);
  344. INT scrollCX = 0;
  345. if (selectionOrig.first == selection.first && selectionOrig.leftX != selection.leftX)
  346. {
  347. scrollCX = selectionOrig.leftX - selection.leftX;
  348. }
  349. if (selectionOrig.last == selection.last && selectionOrig.rightX != selection.rightX)
  350. {
  351. scrollCX = selectionOrig.rightX - selection.rightX;
  352. }
  353. if (0 != scrollCX)
  354. {
  355. if (scrollCX > 0)
  356. aTRACE_LINE("move on left side");
  357. else
  358. aTRACE_LINE("move on right side");
  359. }
  360. DeleteObject(rgn1);
  361. DeleteObject(rgn2);
  362. }
  363. }
  364. }
  365. }
  366. return result;
  367. }
  368. void SkinnedEdit::OnWindowPosChanged(WINDOWPOS *pwp)
  369. {
  370. HRGN updateRgn = CreateRectRgn(0, 0, 0, 0);
  371. UINT windowStyle = GetWindowStyle(hwnd);
  372. if (0 != (WS_VISIBLE & windowStyle))
  373. {
  374. if (NULL != updateRgn)
  375. {
  376. GetUpdateRgn(hwnd, updateRgn, FALSE);
  377. }
  378. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~ WS_VISIBLE);
  379. }
  380. __super::WindowProc(WM_WINDOWPOSCHANGED, 0, (LPARAM)pwp);
  381. if (0 != (WS_VISIBLE & windowStyle))
  382. {
  383. windowStyle = GetWindowStyle(hwnd);
  384. if (0 == (WS_VISIBLE & windowStyle))
  385. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  386. }
  387. RECT rc;
  388. GetClientRect(hwnd, &rc);
  389. if( FALSE == updateCaret)
  390. {
  391. updateCaret = TRUE;
  392. // HideCaret(hwnd);
  393. }
  394. if (0 == ((SWP_NOSIZE | SWP_NOREDRAW) & pwp->flags))
  395. {
  396. HRGN rgn = NULL;
  397. if (rc.right - rc.left != cx)
  398. {
  399. cx -= GET_Y_LPARAM((DWORD)CallPrevWndProc(EM_GETMARGINS, 0, 0L));
  400. cx -= maxCharWidth;
  401. LONG l = rc.left;
  402. rc.left = cx;
  403. if (NULL != rgn) SetRectRgn(rgn, rc.left, rc.top, rc.right, rc.bottom);
  404. else rgn = CreateRectRgnIndirect(&rc);
  405. rc.left = l;
  406. }
  407. if (rc.bottom - rc.top != cy)
  408. {
  409. LONG t = rc.top;
  410. rc.top = cy;
  411. if (NULL != rgn) SetRectRgn(rgn, rc.left, rc.top, rc.right, rc.bottom);
  412. else rgn = CreateRectRgnIndirect(&rc);
  413. CombineRgn(updateRgn, updateRgn, rgn, RGN_OR);
  414. rc.top = t;
  415. }
  416. if (0 == (SWP_NOREDRAW & pwp->flags))
  417. {
  418. if (NULL != updateRgn)
  419. InvalidateRgn(hwnd, updateRgn, FALSE);
  420. }
  421. if (NULL != rgn)
  422. DeleteObject(rgn);
  423. }
  424. cx = rc.right - rc.left;
  425. cy = rc.bottom - rc.top;
  426. if (NULL != updateRgn)
  427. DeleteObject(updateRgn);
  428. }
  429. void SkinnedEdit::FontChanged()
  430. {
  431. HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  432. if (NULL != hdc)
  433. {
  434. HFONT font, fontOrig;
  435. font = (HFONT)CallPrevWndProc(WM_GETFONT, 0, 0L);
  436. if (NULL != font)
  437. fontOrig = (HFONT)SelectObject(hdc, font);
  438. TEXTMETRICW tm;
  439. maxCharWidth = (FALSE != GetTextMetricsW(hdc, &tm)) ? tm.tmMaxCharWidth : 0;
  440. if (NULL != font)
  441. SelectObject(hdc, fontOrig);
  442. ReleaseDC(hwnd, hdc);
  443. }
  444. }
  445. void SkinnedEdit::OnSetFont(HFONT hFont, BOOL fRedraw)
  446. {
  447. __super::WindowProc(WM_SETFONT, (WPARAM)hFont, (LPARAM)fRedraw);
  448. FontChanged();
  449. }
  450. LRESULT SkinnedEdit::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  451. {
  452. if ( 0 != (SWES_SELECTONCLICK & style))
  453. {
  454. switch(uMsg)
  455. {
  456. case WM_LBUTTONDOWN:
  457. case WM_RBUTTONDOWN:
  458. if (hwnd != GetFocus())
  459. {
  460. CallPrevWndProc(EM_SETSEL, 0, -1);
  461. SetFocus(hwnd);
  462. if (WM_LBUTTONDOWN == uMsg) return 0;
  463. }
  464. break;
  465. }
  466. }
  467. if (SWS_USESKINCOLORS & style)
  468. {
  469. UINT windowStyle = GetWindowStyle(hwnd);
  470. switch(uMsg)
  471. {
  472. case WM_CONTEXTMENU:
  473. if (IsSkinnedPopupEnabled(FALSE))
  474. {
  475. SkinnedMenu sm;
  476. if (sm.InitializeHook(hwnd, SMS_USESKINFONT, NULL, 0, NULL, 0L))
  477. {
  478. __super::WindowProc(uMsg, wParam, lParam);
  479. InvalidateRect(hwnd, NULL, TRUE);
  480. UpdateWindow(hwnd);
  481. return 0;
  482. }
  483. }
  484. break;
  485. case MLSEM_ENABLEREDRAW:
  486. windowStyle = GetWindowStyle(hwnd);
  487. if (0 == (WS_VISIBLE & windowStyle))
  488. {
  489. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  490. }
  491. return 0;
  492. }
  493. if (0 == (ES_MULTILINE & windowStyle))
  494. {
  495. switch(uMsg)
  496. {
  497. case WM_PAINT: OnPaint(); return 0;
  498. case WM_ERASEBKGND: return 0;
  499. case WM_SETFONT: OnSetFont((HFONT)wParam, (BOOL)lParam); return 0;
  500. case WM_MOUSEMOVE:
  501. if (wParam == mouseWParam && lParam == mouseLParam) return 0;
  502. mouseWParam = wParam;
  503. mouseLParam = lParam;
  504. return (MK_LBUTTON & mouseWParam) ? OverrideDefault(uMsg, wParam, lParam) : 0;
  505. case WM_SETFOCUS:
  506. caretPos = -1;
  507. case WM_CAPTURECHANGED:
  508. if (0 != (WS_VISIBLE & windowStyle))
  509. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  510. __super::WindowProc(uMsg, wParam, lParam);
  511. if (0 != (WS_VISIBLE & windowStyle))
  512. {
  513. windowStyle = GetWindowStyle(hwnd);
  514. if (0 == (WS_VISIBLE & windowStyle))
  515. {
  516. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  517. InvalidateRect(hwnd, NULL, FALSE);
  518. }
  519. }
  520. if (FALSE == updateCaret)
  521. {
  522. // HideCaret(hwnd);
  523. updateCaret = TRUE;
  524. }
  525. return 0;
  526. case WM_UPDATEUISTATE:
  527. case WM_KILLFOCUS:
  528. if (0 != (WS_VISIBLE & windowStyle))
  529. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  530. __super::WindowProc(uMsg, wParam, lParam);
  531. if (0 != (WS_VISIBLE & windowStyle))
  532. {
  533. windowStyle = GetWindowStyle(hwnd);
  534. if (0 == (WS_VISIBLE & windowStyle))
  535. {
  536. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  537. RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
  538. }
  539. }
  540. return 0;
  541. case WM_WINDOWPOSCHANGED:
  542. OnWindowPosChanged((WINDOWPOS*)lParam);
  543. return 0;
  544. case WM_SETTEXT:
  545. if (OverrideDefault(uMsg, wParam, lParam))
  546. {
  547. InvalidateRect(hwnd, NULL, TRUE);
  548. return TRUE;
  549. }
  550. return FALSE;
  551. case EM_SETSEL:
  552. {
  553. BOOL recoverRegion = FALSE;
  554. HRGN windowRegion = CreateRectRgn(0, 0, 0, 0);
  555. INT result = GetWindowRgn(hwnd, windowRegion);
  556. if (SIMPLEREGION != result && COMPLEXREGION != result)
  557. {
  558. DeleteObject(windowRegion);
  559. windowRegion = NULL;
  560. }
  561. if (0 != (WS_VISIBLE & windowStyle))
  562. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  563. HRGN fakeRegion = CreateRectRgn(0, 0, 0, 0);
  564. if (0 != SetWindowRgn(hwnd, fakeRegion, FALSE))
  565. recoverRegion = TRUE;
  566. INT prevFirst, prevLast, currFirst, currLast;
  567. CallPrevWndProc(EM_GETSEL, (WPARAM)&prevFirst, (LPARAM)&prevLast);
  568. __super::WindowProc(uMsg, wParam, lParam);
  569. CallPrevWndProc(EM_GETSEL, (WPARAM)&currFirst, (LPARAM)&currLast);
  570. if (currFirst != prevFirst || currLast != prevLast)
  571. {
  572. if (currLast != prevLast) caretPos = currLast;
  573. else caretPos = currFirst;
  574. if (FALSE == updateCaret)
  575. {
  576. // HideCaret(hwnd);
  577. updateCaret = TRUE;
  578. }
  579. }
  580. if (FALSE != recoverRegion)
  581. SetWindowRgn(hwnd, windowRegion, FALSE);
  582. if (NULL != windowRegion)
  583. {
  584. DeleteObject(windowRegion);
  585. windowRegion = NULL;
  586. }
  587. if (0 != (WS_VISIBLE & windowStyle))
  588. {
  589. windowStyle = GetWindowStyle(hwnd);
  590. if (0 == (WS_VISIBLE & windowStyle))
  591. {
  592. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  593. InvalidateRect(hwnd, NULL, FALSE);
  594. }
  595. }
  596. }
  597. return 0;
  598. case WM_LBUTTONUP:
  599. {
  600. if (0 != (WS_VISIBLE & windowStyle))
  601. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  602. __super::WindowProc(uMsg, wParam, lParam);
  603. if (0 != (WS_VISIBLE & windowStyle))
  604. {
  605. windowStyle = GetWindowStyle(hwnd);
  606. if (0 == (WS_VISIBLE & windowStyle))
  607. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  608. }
  609. }
  610. return 0;
  611. case WM_CHAR:
  612. case WM_KEYDOWN:
  613. case WM_CUT:
  614. //case WM_PASTE:
  615. case WM_CLEAR:
  616. case WM_UNDO:
  617. case EM_UNDO:
  618. case WM_LBUTTONDBLCLK:
  619. case WM_LBUTTONDOWN:
  620. return OverrideDefault(uMsg, wParam, lParam);
  621. }
  622. }
  623. }
  624. switch(uMsg)
  625. {
  626. case WM_SETCURSOR:
  627. if ((HWND)wParam == hwnd && HTCLIENT == LOWORD(lParam))
  628. {
  629. HCURSOR cursor;
  630. cursor = LoadCursor(NULL, IDC_IBEAM);
  631. if (NULL != cursor)
  632. {
  633. SetCursor(cursor);
  634. return TRUE;
  635. }
  636. }
  637. break;
  638. }
  639. return __super::WindowProc(uMsg, wParam, lParam);
  640. }