1
0

skinWindow.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311
  1. #include <windowsx.h>
  2. #include "main.h"
  3. #include "./api.h"
  4. #include "./wa_dlg.h"
  5. #include "./skinWindow.h"
  6. #include "./skinWindowIPC.h"
  7. #include "./wintheme.h"
  8. #include "./draw.h"
  9. #ifndef ARRAYSIZE
  10. #define ARRAYSIZE(blah) (sizeof(blah)/sizeof(*blah))
  11. #endif
  12. #ifndef OCR_NORMAL
  13. #define OCR_NORMAL 32512
  14. #endif
  15. #ifndef LONGX86
  16. #ifdef _WIN64
  17. #define LONGX86 LONG_PTR
  18. #else /*_WIN64*/
  19. #define LONGX86 LONG
  20. #endif /*_WIN64*/
  21. #endif // LONGX86
  22. #ifdef __cplusplus
  23. #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
  24. #else
  25. #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
  26. #endif // __cplusplus
  27. #define SENDWAIPC(__ipcMsgId, __param) SENDMSG(hMainWindow, WM_WA_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
  28. #ifndef WM_NCUAHDRAWCAPTION
  29. #define WM_NCUAHDRAWCAPTION 0x00AE
  30. #define WM_NCUAHDRAWFRAME 0x00AF
  31. #endif //WM_NCUAHDRAWCAPTION
  32. // additional WM_SYSCOMMAND commands
  33. #define SC_DRAGMOVE 0xF012
  34. #define SC_DRAGSIZE_N 0xF003
  35. #define SC_DRAGSIZE_S 0xF006
  36. #define SC_DRAGSIZE_E 0xF002
  37. #define SC_DRAGSIZE_W 0xF001
  38. #define SC_DRAGSIZE_NW 0xF004
  39. #define SC_DRAGSIZE_NE 0xF005
  40. #define SC_DRAGSIZE_SW 0xF007
  41. #define SC_DRAGSIZE_SE 0xF008
  42. #define MSGRESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWL_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; }
  43. #define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
  44. #define RESIZESTEP_CX 25
  45. #define RESIZESTEP_CY 29
  46. static ATOM SKINNEDWND_ATOM = 0;
  47. // this flags for iternal use
  48. #define SWS_EX_MASK 0xFFFF0000
  49. #define SWS_EX_ATTACHED 0x00010000 // window attached
  50. #define SWS_EX_UNICODE 0x00020000 // winodow is unicode
  51. #define SWS_EX_THEMED 0x00040000 // was themed before
  52. #define SWS_EX_DIALOG 0x00100000 // treat this as dialog
  53. #define BORDERWIDTH_LEFT 11
  54. #define BORDERWIDTH_TOP 20
  55. #define BORDERWIDTH_RIGHT 8
  56. #define BORDERWIDTH_BOTTOM 14
  57. #define CHILDBORDER_LEFT 1
  58. #define CHILDBORDER_TOP 1
  59. #define CHILDBORDER_RIGHT 1
  60. #define CHILDBORDER_BOTTOM 1
  61. #define CLOSEBUTTON_HEIGHT 9
  62. #define CLOSEBUTTON_WIDTH 9
  63. #define CLOSEBUTTON_OFFSET_X -11
  64. #define CLOSEBUTTON_OFFSET_Y 3
  65. #define SIZERGRIP_WIDTH 20
  66. #define SIZERGRIP_HEIGHT 20
  67. #define MOVEABLEAREA_HEIGHT 13
  68. #define BUTTON_NORMAL 0
  69. #define BUTTON_PUSHED 1
  70. #define BUTTON_DISABLED (-1)
  71. #ifndef TME_NONCLIENT
  72. #define TME_NONCLIENT 0x00000010
  73. #define WM_NCMOUSELEAVE 0x02A2
  74. #endif
  75. #define WAMSG_CLOSE (WM_USER + 101)
  76. typedef struct __SKINNEDWND
  77. {
  78. HWND hwnd;
  79. WNDPROC fnWndProc;
  80. DWORD flags;
  81. POINT movingOffset;
  82. INT buttonState;
  83. embedWindowState embedData;
  84. } SKINNEDWND;
  85. #define GetSkinnedWnd(__hwnd) ((SKINNEDWND*)GetPropW((__hwnd), ((LPCWSTR)MAKEINTATOM(SKINNEDWND_ATOM))))
  86. #define IsDialog(__skinnedWindow) (0 != (SWS_EX_DIALOG & (__skinnedWindow)->flags))
  87. #define IsUnicode(__skinnedWindow) (0 != (SWS_EX_UNICODE & (__skinnedWindow)->flags))
  88. #define SetWndLongPtr(__skinnedWnd, __index, __data)\
  89. ((LONG_PTR)(IsUnicode(__skinnedWnd) ? SetWindowLongPtrW((__skinnedWnd)->hwnd, (__index), ((LONGX86)(LONG_PTR)(__data))) :\
  90. SetWindowLongPtrA((__skinnedWnd)->hwnd, (__index), ((LONGX86)(LONG_PTR)(__data)))))
  91. #define CallWndProc(__skinnedWnd, __uMsg, __wParam, __lParam)\
  92. (IsUnicode(__skinnedWnd) ?\
  93. CallWindowProcW((__skinnedWnd)->fnWndProc, (__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam)) :\
  94. CallWindowProcA((__skinnedWnd)->fnWndProc, (__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam)))
  95. #define DefWndProc(__skinnedWnd, __uMsg, __wParam, __lParam)\
  96. (IsUnicode(__skinnedWnd) ?\
  97. DefWindowProcW((__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam)) :\
  98. DefWindowProcA((__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam)))
  99. void draw_embed_tbar(HWND hwnd, int state, int w);
  100. void SnapWindowToAllWindows(RECT *outrc, HWND hwndNoSnap);
  101. static LRESULT CALLBACK SkinnedWnd_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  102. static void SkinnedWindow_Delete(SKINNEDWND *pWnd)
  103. {
  104. HWND hDetached = NULL;
  105. if (NULL == pWnd) return;
  106. hDetached = pWnd->hwnd;
  107. SetWndLongPtr(pWnd, GWLP_USERDATA, NULL);
  108. RemovePropW(pWnd->hwnd, ((LPCWSTR)MAKEINTATOM(SKINNEDWND_ATOM)));
  109. if (NULL != pWnd->embedData.me)
  110. {
  111. EnterCriticalSection(&embedcs);
  112. embedWindowState *p = embedwndlist;
  113. if (p == &pWnd->embedData)
  114. {
  115. embedwndlist=pWnd->embedData.link; // remove ourselves
  116. embedwndlist_cnt--;
  117. }
  118. else
  119. {
  120. while (p)
  121. {
  122. if (p->link == &pWnd->embedData)
  123. {
  124. p->link=pWnd->embedData.link;
  125. embedwndlist_cnt--;
  126. break;
  127. }
  128. p=p->link;
  129. }
  130. }
  131. LeaveCriticalSection(&embedcs);
  132. }
  133. if (NULL != pWnd->fnWndProc)
  134. {
  135. SetWndLongPtr(pWnd, GWLP_WNDPROC, pWnd->fnWndProc);
  136. pWnd->fnWndProc = NULL;
  137. }
  138. free(pWnd);
  139. if (NULL != hDetached)
  140. {
  141. SetWindowPos(hDetached, NULL, 0, 0, 0, 0,
  142. SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
  143. }
  144. }
  145. static SKINNEDWND *SkinnedWindow_Cerate(HWND hwndToSkin)
  146. {
  147. if (NULL == hwndToSkin || !IsWindow(hwndToSkin))
  148. return NULL;
  149. if (NULL != GetSkinnedWnd(hwndToSkin))
  150. return NULL;
  151. if (0 == SKINNEDWND_ATOM)
  152. {
  153. SKINNEDWND_ATOM = GlobalAddAtomW(L"WASKINNEDWND");
  154. if (0 == SKINNEDWND_ATOM)
  155. return NULL;
  156. }
  157. SKINNEDWND *pWnd = (SKINNEDWND*)calloc(1, sizeof(SKINNEDWND));
  158. if (NULL == pWnd)
  159. return NULL;
  160. pWnd->hwnd = hwndToSkin;
  161. if (IsWindowUnicode(hwndToSkin)) pWnd->flags |= SWS_EX_UNICODE;
  162. WCHAR szName[128] = {0};
  163. if (GetClassNameW(hwndToSkin, szName, ARRAYSIZE(szName)))
  164. {
  165. if (CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, szName, -1, L"#32770", -1))
  166. pWnd->flags |= SWS_EX_DIALOG;
  167. }
  168. pWnd->fnWndProc = (WNDPROC)SetWndLongPtr(pWnd, GWLP_WNDPROC, SkinnedWnd_WindowProc);
  169. if (NULL == pWnd->fnWndProc || !SetPropW(hwndToSkin, ((LPCWSTR)MAKEINTATOM(SKINNEDWND_ATOM)), pWnd))
  170. {
  171. SkinnedWindow_Delete(pWnd);
  172. return NULL;
  173. }
  174. pWnd->flags |= SWS_EX_ATTACHED;
  175. if (S_OK == Dwm_LoadLibrary())
  176. {
  177. DWMNCRENDERINGPOLICY ncrp = DWMNCRP_DISABLED;
  178. DWORD allow = FALSE;
  179. DwmSetWindowAttribute(pWnd->hwnd, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp));
  180. DwmSetWindowAttribute(pWnd->hwnd, DWMWA_ALLOW_NCPAINT, &allow, sizeof(allow));
  181. }
  182. if (S_OK == UxTheme_LoadLibrary() && IsAppThemed())
  183. {
  184. SetWindowTheme(pWnd->hwnd, NULL, L"");
  185. pWnd->flags |= SWS_EX_THEMED;
  186. }
  187. if (!config_embedwnd_freesize &&
  188. 0 == (WS_CHILD & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE)))
  189. {
  190. RECT rc;
  191. if (GetWindowRect(hwndToSkin, &rc))
  192. {
  193. LONG w, h;
  194. OffsetRect(&rc, -rc.left, -rc.top);
  195. w = rc.right + (RESIZESTEP_CX - 1);
  196. w -= w % RESIZESTEP_CX;
  197. h = rc.bottom + (RESIZESTEP_CY - 1);
  198. h -= h % RESIZESTEP_CY;
  199. if (w != rc.right || h != rc.bottom)
  200. SetWindowPos(hwndToSkin, NULL, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
  201. }
  202. }
  203. return pWnd;
  204. }
  205. BOOL SkinWindow(HWND hwndToSkin, REFGUID windowGuid, UINT flagsEx, FFCALLBACK callbackFF)
  206. {
  207. SKINNEDWND *pWnd = SkinnedWindow_Cerate(hwndToSkin);
  208. if (NULL == pWnd)
  209. return FALSE;
  210. pWnd->embedData.me = pWnd->hwnd;
  211. pWnd->embedData.user_ptr = pWnd;
  212. pWnd->embedData.flags |= (EMBED_FLAGS_GUID | flagsEx);
  213. pWnd->embedData.guid = windowGuid;
  214. pWnd->embedData.callback = callbackFF;
  215. if (NULL != pWnd->embedData.callback)
  216. pWnd->embedData.flags |= EMBED_FLAGS_FFCALLBACK;
  217. GetWindowRect(pWnd->hwnd, &pWnd->embedData.r);
  218. EnterCriticalSection(&embedcs);
  219. pWnd->embedData.link = embedwndlist;
  220. embedwndlist = &pWnd->embedData;
  221. embedwndlist_cnt++;
  222. LeaveCriticalSection(&embedcs);
  223. SetWndLongPtr(pWnd, GWLP_USERDATA, &pWnd->embedData);
  224. return TRUE;
  225. }
  226. static int SkinnedWindow_GetTextWidth(LPCTSTR pszText, INT cchText)
  227. {
  228. int w = 0;
  229. while (cchText--)
  230. {
  231. char c = *pszText++;
  232. if (c >= 'a' && c <= 'z') c+='A'-'a';
  233. if (c >= 'A' && c <= 'Z' && titlebar_font_widths[c-'A'])
  234. w+=titlebar_font_widths[c-'A'];
  235. else if (c >= '0' && c <= '9' && titlebar_font_widths[c-'0'] && Skin_UseGenNums)
  236. w+=titlebar_font_num_widths[c-'0'];
  237. else if (c == '-' && titlebar_font_widths[10] && Skin_UseGenNums)
  238. w+=titlebar_font_num_widths[10];
  239. else if (c == ':' && titlebar_font_widths[11] && Skin_UseGenNums)
  240. w+=titlebar_font_num_widths[11];
  241. else w+=titlebar_font_unknown_width;
  242. }
  243. return w;
  244. }
  245. static void SkinnedWindow_DrawText(HDC hdc, HDC hdcSrc, int xp, int yp, LPCTSTR pszText, INT cchText, RECT *prc, BOOL bActive)
  246. {
  247. int w;
  248. int srcY = 88 + ((bActive) ? 8 : 0);
  249. int srcYnum = 72 + ((bActive) ? 8 : 0);
  250. int bgsrcY = ((bActive) ? 21 : 0);
  251. int bgX = prc->left;
  252. int maxw = prc->right;
  253. while (cchText-- && maxw > 0)
  254. {
  255. char c = *pszText++;
  256. if (bgX <= xp)
  257. {
  258. int bgW = 25;
  259. if (bgW + bgX > prc->right) bgW = prc->right - bgX;
  260. BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY);
  261. bgX += bgW;
  262. }
  263. if (c >= 'a' && c <= 'z') c+='A'-'a';
  264. if (c >= 'A' && c <= 'Z' && titlebar_font_widths[c-'A'])
  265. {
  266. w = titlebar_font_widths[c - 'A'];
  267. if (w > maxw) break;
  268. if (bgX <= (xp + w))
  269. {
  270. int bgW = 25;
  271. if (bgW + bgX > prc->right) bgW = prc->right - bgX;
  272. BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY);
  273. bgX += bgW;
  274. }
  275. BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_offsets[c - 'A'], srcY, SRCCOPY);
  276. }
  277. else if (c >= '0' && c <= '9' && titlebar_font_num_widths[c - '0'] && Skin_UseGenNums)
  278. {
  279. w = titlebar_font_num_widths[c - '0'];
  280. if (w > maxw) break;
  281. if (bgX <= (xp + w))
  282. {
  283. int bgW = 25;
  284. if (bgW + bgX > prc->right) bgW = prc->right - bgX;
  285. BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY);
  286. bgX += bgW;
  287. }
  288. BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_num_offsets[c - '0'], srcYnum, SRCCOPY);
  289. }
  290. else if (c == '-' && titlebar_font_num_widths[10] && Skin_UseGenNums)
  291. {
  292. w = titlebar_font_num_widths[10];
  293. if (w > maxw) break;
  294. if (bgX <= (xp + w))
  295. {
  296. int bgW = 25;
  297. if (bgW + bgX > prc->right) bgW = prc->right - bgX;
  298. BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY);
  299. bgX += bgW;
  300. }
  301. BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_num_offsets[10], srcYnum, SRCCOPY);
  302. }
  303. else if (c == ':' && titlebar_font_num_widths[11] && Skin_UseGenNums)
  304. {
  305. w = titlebar_font_num_widths[11];
  306. if (w > maxw) break;
  307. if (bgX <= (xp + w))
  308. {
  309. int bgW = 25;
  310. if (bgW + bgX > prc->right) bgW = prc->right - bgX;
  311. BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY);
  312. bgX += bgW;
  313. }
  314. BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_num_offsets[11], srcYnum, SRCCOPY);
  315. }
  316. else
  317. w = titlebar_font_unknown_width;
  318. xp += w;
  319. maxw -= w;
  320. }
  321. }
  322. static void SkinnedWindow_DrawCloseButton(HDC hdc, HDC hdcSrc, RECT *prcWindow, BOOL bActive, INT buttonState)
  323. {
  324. INT srcX, srcY;
  325. switch(buttonState)
  326. {
  327. case BUTTON_PUSHED:
  328. srcX = 148; srcY = 42;
  329. break;
  330. case BUTTON_NORMAL:
  331. srcX = 144; srcY = 3;
  332. if (!bActive) srcY += 21;
  333. break;
  334. case BUTTON_DISABLED:
  335. default:
  336. srcX = 144; srcY = 3;
  337. break;
  338. }
  339. BitBlt(hdc, prcWindow->right - 11,prcWindow->top + 3, 9, 9, hdcSrc,srcX, srcY, SRCCOPY);
  340. }
  341. static void SkinnedWindow_DrawCaptionEx(HDC hdc, HDC hdcSrc, LPCTSTR pszText, INT cchText, int state, int w, int h)
  342. {
  343. state = state ? 0 : 21;
  344. int nt;
  345. int xp=0;
  346. int textw_exact = 0, textw = 0;
  347. int cchTextOrig = cchText;
  348. if (cchText > 0)
  349. {
  350. for(;cchText > 0; cchText--)
  351. {
  352. textw_exact = SkinnedWindow_GetTextWidth(pszText, cchText);
  353. textw = textw_exact + 24;
  354. textw -= textw % 25;
  355. if ((w - textw) > 100) break;
  356. textw = 0;
  357. }
  358. }
  359. BitBlt(hdc,xp,0,25,20, hdcSrc, 0, state,SRCCOPY);
  360. xp+=25;
  361. nt = (w - 100 - textw)/25;
  362. if (nt > 0)
  363. {
  364. if (nt&1)
  365. {
  366. BitBlt(hdc,xp,0,12,20,hdcSrc,104,state,SRCCOPY);
  367. xp+=12;
  368. }
  369. nt/=2;
  370. while (nt-->0)
  371. {
  372. BitBlt(hdc,xp,0,25,20,hdcSrc,104,state,SRCCOPY);
  373. xp+=25;
  374. }
  375. }
  376. if (cchText > 0)
  377. {
  378. BitBlt(hdc,xp,0,25,20,hdcSrc,26,state,SRCCOPY);
  379. xp+=25;
  380. nt = textw/25;
  381. if (nt > 0)
  382. {
  383. RECT rt;
  384. SetRect(&rt, xp, 0, xp + textw, 20);
  385. SkinnedWindow_DrawText(hdc, hdcSrc,
  386. rt.left + ((cchText == cchTextOrig) ? (textw - textw_exact)/2 : 0), 4,
  387. pszText, cchText, &rt, state);
  388. xp += nt*25;
  389. }
  390. BitBlt(hdc,xp,0,25,20,hdcSrc,78,state,SRCCOPY);
  391. xp+=25;
  392. }
  393. else
  394. {
  395. nt = (w - 50)/2;
  396. if (nt > 25) nt = 25;
  397. if (nt > 0)
  398. {
  399. BitBlt(hdc,xp, 0, nt,20,hdcSrc,104,state,SRCCOPY);
  400. xp+=nt;
  401. if (nt < 25 && 0 != (w - 50)%2)nt++;
  402. BitBlt(hdc,xp, 0, nt, 20, hdcSrc,104 + (25- nt),state,SRCCOPY);
  403. xp+=nt;
  404. }
  405. }
  406. nt = (w - 100 - textw)/25;
  407. if (nt > 0)
  408. {
  409. if (nt&1)
  410. {
  411. BitBlt(hdc,xp,0,13,20,hdcSrc,104,state,SRCCOPY);
  412. xp+=13;
  413. }
  414. nt/=2;
  415. while (nt-->0)
  416. {
  417. BitBlt(hdc,xp,0,25,20,hdcSrc,104,state,SRCCOPY);
  418. xp+=25;
  419. }
  420. }
  421. nt = (w - 100 - textw) % 25;
  422. if (nt > 0)
  423. {
  424. BitBlt(hdc,xp,0,nt,20,hdcSrc,104,state,SRCCOPY);
  425. //StretchBlt(hdc,xp,0,nt,20,hdcSrc,104,state,25,20,SRCCOPY);
  426. xp += nt;
  427. }
  428. BitBlt(hdc,xp,0,25,20,hdcSrc,130,state,SRCCOPY);
  429. }
  430. static void SkinnedWindow_DrawCaption(SKINNEDWND *pWnd, BOOL bActive, POINT *cursor)
  431. {
  432. RECT rc;
  433. GetWindowRect(pWnd->hwnd, &rc);
  434. OffsetRect(&rc, -rc.left, -rc.top);
  435. UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN |
  436. DCX_INTERSECTUPDATE | DCX_VALIDATE | DCX_NORESETATTRS;
  437. HDC hdc = GetDCEx(pWnd->hwnd, NULL, flags);
  438. if (NULL == hdc)
  439. return;
  440. do_palmode(hdc);
  441. setSrcBM(embedBM);
  442. char szTitle[128] = {0};
  443. INT cchTitle = GetWindowTextA(pWnd->hwnd, szTitle, ARRAYSIZE(szTitle));
  444. INT state = pWnd->buttonState;
  445. if (BUTTON_PUSHED == state)
  446. {
  447. if (NULL == cursor || HTCLOSE != SendMessageW(pWnd->hwnd, WM_NCHITTEST, 0, MAKELPARAM(cursor->x, cursor->y)))
  448. state = BUTTON_NORMAL;
  449. }
  450. SkinnedWindow_DrawCaptionEx(hdc, bmDC, (LPCTSTR)szTitle, cchTitle, bActive ? 1 : (config_hilite?0:1),
  451. rc.right - rc.left, rc.bottom - rc.top);
  452. SkinnedWindow_DrawCloseButton(hdc, bmDC, &rc, bActive, state);
  453. unsetSrcBM();
  454. ReleaseDC(pWnd->hwnd, hdc);
  455. }
  456. static void SkinnedWindow_DrawBorder(SKINNEDWND *pWnd, HDC hdc, HRGN rgnUpdate, POINT *cursor)
  457. {
  458. DWORD style = GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE);
  459. if (0 == (WS_BORDER & style))
  460. return;
  461. RECT rc;
  462. GetWindowRect(pWnd->hwnd, &rc);
  463. OffsetRect(&rc, -rc.left, -rc.top);
  464. LONG w = rc.right, h = rc.bottom;
  465. do_palmode(hdc);
  466. setSrcBM(embedBM);
  467. if (0 != (WS_CHILD & style))
  468. {
  469. if (!WADlg_initted())
  470. WADlg_init(hMainWindow);
  471. COLORREF rgbOld = SetBkColor(hdc, WADlg_getColor(WADLG_HILITE));
  472. RECT part;
  473. SetRect(&part, rc.left, rc.top, rc.right, rc.top + CHILDBORDER_TOP);
  474. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL);
  475. SetRect(&part, rc.right - CHILDBORDER_RIGHT, rc.top + CHILDBORDER_TOP, rc.right, rc.bottom - CHILDBORDER_BOTTOM);
  476. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL);
  477. SetRect(&part, rc.left, rc.bottom - CHILDBORDER_BOTTOM, rc.right, rc.bottom);
  478. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL);
  479. SetRect(&part, rc.left, rc.top + CHILDBORDER_TOP, rc.left + CHILDBORDER_LEFT, rc.bottom - CHILDBORDER_BOTTOM);
  480. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL);
  481. SetBkColor(hdc, rgbOld);
  482. return;
  483. }
  484. if (0 != (WS_CAPTION & style))
  485. {
  486. char szTitle[128] = {0};
  487. INT cchTitle = GetWindowTextA(pWnd->hwnd, szTitle, ARRAYSIZE(szTitle));
  488. INT state = pWnd->buttonState;
  489. if (BUTTON_PUSHED == state)
  490. {
  491. if (NULL == cursor || HTCLOSE != SendMessageW(pWnd->hwnd, WM_NCHITTEST, 0, MAKELPARAM(cursor->x, cursor->y)))
  492. state = BUTTON_NORMAL;
  493. }
  494. BOOL bActive = (GetActiveWindow()==pWnd->hwnd) ? 1 : ((0 != config_hilite) ? 0 : 1);
  495. SkinnedWindow_DrawCaptionEx(hdc, bmDC, (LPCTSTR)szTitle, cchTitle, bActive, w, h);
  496. if (BUTTON_NORMAL != state)
  497. SkinnedWindow_DrawCloseButton(hdc, bmDC, &rc, bActive, state);
  498. }
  499. int y=(h-20-38)/29;
  500. int yp=20,x,xp;
  501. while (y-->0)
  502. {
  503. BitBlt(hdc,0,yp,11,29,bmDC,127,42,SRCCOPY);
  504. BitBlt(hdc,w-8,yp,8,29,bmDC,139,42,SRCCOPY);
  505. yp += 29;
  506. }
  507. y=(h-20-38)%29;
  508. if (y)
  509. {
  510. BitBlt(hdc,0,yp,11,y,bmDC,127,42,SRCCOPY);
  511. //StretchBlt(hdc,0,yp,11,y,bmDC,127,42,11,29,SRCCOPY);
  512. BitBlt(hdc,w-8,yp,8,y,bmDC,139,42,SRCCOPY);
  513. //StretchBlt(hdc,w-8,yp,8,y,bmDC,139,42,8,29,SRCCOPY);
  514. yp += y;
  515. }
  516. // 24 pixel lamity
  517. BitBlt(hdc,0,yp,11,24,bmDC,158,42,SRCCOPY);
  518. BitBlt(hdc,w-8,yp,8,24,bmDC,170,42,SRCCOPY);
  519. yp += 24;
  520. int realW = (w < 250) ? (w/2) : 125;
  521. BitBlt(hdc,0,yp,realW,14,bmDC,0,42,SRCCOPY);
  522. x=(w-125*2)/25;
  523. xp=realW;
  524. while (x-->0)
  525. {
  526. BitBlt(hdc,xp,yp,25,14,bmDC,127,72,SRCCOPY);
  527. xp+=25;
  528. }
  529. x=(w-125*2)%25;
  530. if (x > 0)
  531. {
  532. BitBlt(hdc,xp,yp,x,14,bmDC,127,72,SRCCOPY);
  533. //StretchBlt(hdc,xp,yp,x,14,bmDC,127,72,25,14,SRCCOPY);
  534. xp+=x;
  535. }
  536. if (realW < 125 && 0 != (w%2)) realW++;
  537. BitBlt(hdc,xp,yp,realW,14,bmDC, (125 - realW),57,SRCCOPY);
  538. if (0 != (EMBED_FLAGS_NORESIZE & pWnd->embedData.flags))
  539. {
  540. BitBlt(hdc,xp+112,yp+2,7,7,bmDC,118,72,SRCCOPY);
  541. }
  542. unsetSrcBM();
  543. }
  544. static BOOL SkinnedWindow_OnShowWindow(SKINNEDWND *pWnd, BOOL bShow, UINT flags)
  545. {
  546. if (pWnd->embedData.reparenting)
  547. return TRUE;
  548. SENDWAIPC(((bShow) ? IPC_CB_ONSHOWWND : IPC_CB_ONHIDEWND), pWnd->hwnd);
  549. return FALSE;
  550. }
  551. static LRESULT SkinnedWindow_OnNcCalcSize(SKINNEDWND *pWnd, BOOL bCalcValidRects, NCCALCSIZE_PARAMS *pncsp)
  552. {
  553. DWORD style = (DWORD)GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE);
  554. RECT rc;
  555. CopyRect(&rc, &pncsp->rgrc[0]);
  556. CallWndProc(pWnd, WM_NCCALCSIZE, bCalcValidRects, (LPARAM)pncsp);
  557. CopyRect(&pncsp->rgrc[0], &rc);
  558. if (bCalcValidRects)
  559. SetRect(&pncsp->rgrc[0], pncsp->lppos->x, pncsp->lppos->y,
  560. pncsp->lppos->x + pncsp->lppos->cx, pncsp->lppos->y + pncsp->lppos->cy);
  561. else
  562. {
  563. GetWindowRect(pWnd->hwnd, &pncsp->rgrc[0]);
  564. if (0 != (WS_CHILD & style))
  565. {
  566. HWND hParent = GetParent(pWnd->hwnd);
  567. if (NULL != hParent)
  568. MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&pncsp->rgrc[0], 2);
  569. }
  570. }
  571. if (0 != (WS_BORDER & style))
  572. {
  573. if (0 != (WS_CHILD & style))
  574. {
  575. pncsp->rgrc[0].top += CHILDBORDER_TOP;
  576. pncsp->rgrc[0].left += CHILDBORDER_LEFT;
  577. pncsp->rgrc[0].right -= CHILDBORDER_RIGHT;
  578. pncsp->rgrc[0].bottom -= CHILDBORDER_BOTTOM;
  579. }
  580. else
  581. {
  582. pncsp->rgrc[0].top += BORDERWIDTH_TOP;
  583. pncsp->rgrc[0].left += BORDERWIDTH_LEFT;
  584. pncsp->rgrc[0].right -= BORDERWIDTH_RIGHT;
  585. pncsp->rgrc[0].bottom -= BORDERWIDTH_BOTTOM;
  586. }
  587. }
  588. return 0;
  589. }
  590. static void SkinnedWindow_OnNcPaint(SKINNEDWND *pWnd, HRGN rgnUpdate)
  591. {
  592. if (0 == (WS_BORDER & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE)))
  593. return;
  594. UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS |
  595. DCX_INTERSECTUPDATE | DCX_VALIDATE | DCX_NORESETATTRS;
  596. HDC hdc = GetDCEx(pWnd->hwnd, ((HRGN)NULLREGION != rgnUpdate) ? rgnUpdate : NULL, flags);
  597. if (NULL == hdc)
  598. return;
  599. POINT pt;
  600. GetCursorPos(&pt);
  601. SkinnedWindow_DrawBorder(pWnd, hdc, rgnUpdate, &pt);
  602. ReleaseDC(pWnd->hwnd, hdc);
  603. }
  604. static void SkinnedWindow_OnPrint(SKINNEDWND *pWnd, HDC hdc, UINT options)
  605. {
  606. if ((PRF_CHECKVISIBLE & options) && !IsWindowVisible(pWnd->hwnd)) return;
  607. if (PRF_NONCLIENT & options)
  608. {
  609. POINT pt = {0, 0};
  610. SkinnedWindow_DrawBorder(pWnd, hdc, (HRGN)NULLREGION, &pt);
  611. }
  612. if (PRF_CLIENT & options)
  613. CallWndProc(pWnd, WM_PRINT, (WPARAM)hdc, (LPARAM)(~(PRF_NONCLIENT | PRF_CHECKVISIBLE) & options));
  614. }
  615. static LRESULT SkinnedWindow_OnNcHitTest(SKINNEDWND *pWnd, POINTS pts)
  616. {
  617. POINT pt;
  618. RECT rw, rt;
  619. POINTSTOPOINT(pt, pts);
  620. DWORD style = (DWORD)GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE);
  621. if (0 != (WS_DISABLED & style))
  622. return HTERROR;
  623. if (0 != (WS_CHILD & style))
  624. {
  625. if (0 != (WS_BORDER & style))
  626. {
  627. GetWindowRect(pWnd->hwnd, &rw);
  628. rw.left += CHILDBORDER_LEFT;
  629. rw.top += CHILDBORDER_TOP;
  630. rw.right -= CHILDBORDER_RIGHT;
  631. rw.bottom -= CHILDBORDER_BOTTOM;
  632. if (PtInRect(&rt, pt))
  633. return HTBORDER;
  634. }
  635. return HTCLIENT;
  636. }
  637. GetWindowRect(pWnd->hwnd, &rw);
  638. if (0 != (WS_CAPTION & style))
  639. {
  640. SetRect(&rt, rw.left, rw.top, rw.right, rw.top + BORDERWIDTH_TOP);
  641. if (PtInRect(&rt, pt)) // caption
  642. {
  643. SetRect(&rt, rw.right + CLOSEBUTTON_OFFSET_X, rw.top + CLOSEBUTTON_OFFSET_Y,
  644. rw.right + CLOSEBUTTON_OFFSET_X + CLOSEBUTTON_WIDTH, rw.top + CLOSEBUTTON_OFFSET_Y + CLOSEBUTTON_HEIGHT);
  645. if (PtInRect(&rt, pt)) // close button
  646. return HTCLOSE;
  647. return HTCAPTION;
  648. }
  649. }
  650. if (0 != (WS_BORDER & style))
  651. {
  652. SetRect(&rt, rw.left, rw.top + BORDERWIDTH_TOP, rw.left + BORDERWIDTH_LEFT, rw.bottom - BORDERWIDTH_BOTTOM);
  653. if (PtInRect(&rt, pt))
  654. return HTBORDER; // left side (non resizable)
  655. SetRect(&rt, rw.right - BORDERWIDTH_RIGHT, rw.top + BORDERWIDTH_TOP, rw.right, rw.bottom - SIZERGRIP_HEIGHT);
  656. if (PtInRect(&rt, pt))
  657. return HTBORDER; // right side (non resizable)
  658. SetRect(&rt, rw.right - BORDERWIDTH_RIGHT, rw.bottom - SIZERGRIP_HEIGHT, rw.right, rw.bottom);
  659. if (PtInRect(&rt, pt))
  660. return (0 == (EMBED_FLAGS_NORESIZE & pWnd->embedData.flags)) ? HTBOTTOMRIGHT : HTBORDER; // sizer bottomright
  661. SetRect(&rt, rw.left, rw.bottom - BORDERWIDTH_BOTTOM, rw.right -SIZERGRIP_WIDTH, rw.bottom);
  662. if (PtInRect(&rt, pt))
  663. return HTBORDER; // bottom_left + bottom (non resizable)
  664. SetRect(&rt, rw.right - SIZERGRIP_WIDTH, rw.bottom - BORDERWIDTH_BOTTOM, rw.right, rw.bottom);
  665. if (PtInRect(&rt, pt))
  666. return (0 == (EMBED_FLAGS_NORESIZE & pWnd->embedData.flags)) ? HTBOTTOMRIGHT : HTBORDER; // sizer bottomright
  667. }
  668. SetRect(&rt, rw.left, rw.top, rw.right, rw.bottom);
  669. if (PtInRect(&rt, pt))
  670. return HTCLIENT; // client
  671. return HTNOWHERE;
  672. }
  673. static LRESULT SkinnedWindow_OnSetCursor(SKINNEDWND *pWnd, HWND hwndCursor, INT hitTest, UINT uMsg)
  674. {
  675. HCURSOR hCursor = NULL;
  676. switch(uMsg)
  677. {
  678. case WM_LBUTTONDOWN:
  679. case WM_RBUTTONDOWN:
  680. case WM_MBUTTONDOWN:
  681. case WM_XBUTTONDOWN:
  682. DisabledWindow_OnMouseClick(pWnd->hwnd);
  683. break;
  684. }
  685. if (config_usecursors && !disable_skin_cursors)
  686. {
  687. int index = 15+5; // PNormal.cur
  688. switch(hitTest)
  689. {
  690. case HTCAPTION:
  691. { // this is required to emulate old behavior
  692. POINT pt;
  693. RECT rw;
  694. GetCursorPos(&pt);
  695. GetWindowRect(pWnd->hwnd, &rw);
  696. rw.bottom = rw.top + MOVEABLEAREA_HEIGHT;
  697. index = 15 + ((PtInRect(&rw, pt)) ? 2 : 5); // PTBar.cur
  698. }
  699. break;
  700. case HTCLOSE:
  701. index = 15 + 1; // PClose.cur
  702. break;
  703. case HTLEFT:
  704. case HTRIGHT:
  705. case HTTOP:
  706. case HTTOPLEFT:
  707. case HTTOPRIGHT:
  708. case HTBOTTOM:
  709. case HTBOTTOMLEFT:
  710. case HTBOTTOMRIGHT:
  711. index = 15 + 4;// PSize.cur
  712. break;
  713. }
  714. hCursor = Skin_Cursors[index];
  715. }
  716. if (NULL != hCursor)
  717. {
  718. SetCursor(hCursor);
  719. return TRUE;
  720. }
  721. return CallWndProc(pWnd, WM_SETCURSOR, (WPARAM)hwndCursor, MAKELPARAM(hitTest, uMsg));
  722. }
  723. static LRESULT SkinnedWindow_OnNcActivate(SKINNEDWND *pWnd, BOOL bActivate)
  724. {
  725. if (0 == (WS_CAPTION & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE)))
  726. return TRUE;
  727. POINT pt;
  728. GetCursorPos(&pt);
  729. SkinnedWindow_DrawCaption(pWnd, bActivate, &pt);
  730. return TRUE;
  731. }
  732. static void SkinnedWindow_OnActivate(SKINNEDWND *pWnd, unsigned int action, BOOL minimized, HWND otherWindow)
  733. {
  734. if (NULL == pWnd)
  735. return;
  736. if (NULL != WASABI_API_APP)
  737. {
  738. if (WA_INACTIVE == action)
  739. WASABI_API_APP->ActiveDialog_Unregister(pWnd->hwnd);
  740. else
  741. WASABI_API_APP->ActiveDialog_Register(pWnd->hwnd);
  742. }
  743. }
  744. static BOOL SkinnedWindow_OnNcLButtonDown(SKINNEDWND *pWnd, INT hitTest, POINTS pts)
  745. {
  746. switch(hitTest)
  747. {
  748. case HTCLOSE:
  749. {
  750. pWnd->buttonState = BUTTON_PUSHED;
  751. TRACKMOUSEEVENT tm;
  752. ZeroMemory(&tm, sizeof(TRACKMOUSEEVENT));
  753. tm.cbSize = sizeof(TRACKMOUSEEVENT);
  754. tm.dwFlags = TME_LEAVE | TME_NONCLIENT;
  755. tm.hwndTrack = pWnd->hwnd;
  756. TrackMouseEvent(&tm);
  757. RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW);
  758. }
  759. return TRUE;
  760. case HTCAPTION:
  761. if (IsWindowEnabled(pWnd->hwnd) &&
  762. GetActiveWindow() != pWnd->hwnd)
  763. SetActiveWindow(pWnd->hwnd);
  764. {
  765. RECT rw;
  766. if (GetWindowRect(pWnd->hwnd, &rw))
  767. {
  768. pWnd->movingOffset.x = pts.x - rw.left;
  769. pWnd->movingOffset.y = pts.y - rw.top;
  770. }
  771. }
  772. SendMessageW(pWnd->hwnd, WM_SYSCOMMAND, (SC_MOVE | 0x0002), (*(LPARAM*)&pts));
  773. return TRUE;
  774. case HTBOTTOM:
  775. case HTBOTTOMLEFT:
  776. case HTBOTTOMRIGHT:
  777. if (IsWindowEnabled(pWnd->hwnd) &&
  778. GetActiveWindow() != pWnd->hwnd)
  779. SetActiveWindow(pWnd->hwnd);
  780. SendMessageW(pWnd->hwnd, WM_SYSCOMMAND, SC_SIZE + hitTest - (HTLEFT - WMSZ_LEFT), (*(LPARAM*)&pts));
  781. return TRUE;
  782. }
  783. return FALSE;
  784. }
  785. static BOOL SkinnedWindow_OnNcLButtonUp(SKINNEDWND *pWnd, INT hitTest, POINTS pts)
  786. {
  787. BOOL bProcessed = FALSE;
  788. if (HTCLOSE == hitTest && BUTTON_PUSHED == pWnd->buttonState)
  789. {
  790. SNDMSG(pWnd->hwnd, WM_SYSCOMMAND, SC_CLOSE, *(LPARAM*)&pts);
  791. bProcessed = TRUE;
  792. }
  793. if (BUTTON_PUSHED == pWnd->buttonState)
  794. {
  795. pWnd->buttonState = BUTTON_NORMAL;
  796. RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME);
  797. }
  798. return bProcessed;
  799. }
  800. static BOOL SkinnedWindow_OnNcRButtonDown(SKINNEDWND *pWnd, INT hitTest, POINTS pts)
  801. {
  802. return TRUE;
  803. }
  804. static BOOL SkinnedWindow_OnNcRButtonUp(SKINNEDWND *pWnd, INT hitTest, POINTS pts)
  805. {
  806. int ret = DoTrackPopup(main_menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pts.x, pts.y, pWnd->hwnd);
  807. if (ret)
  808. SendMessageW(hMainWindow,WM_COMMAND,ret,0);
  809. return TRUE;
  810. }
  811. static void SkinnedWindow_OnNcMouseMove(SKINNEDWND *pWnd, INT hitTest, POINTS pts)
  812. {
  813. if (BUTTON_PUSHED == pWnd->buttonState && HTCLOSE == hitTest)
  814. {
  815. RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME);
  816. }
  817. }
  818. static void SkinnedWindow_OnNcMouseLeave(SKINNEDWND *pWnd)
  819. {
  820. if (BUTTON_PUSHED == pWnd->buttonState)
  821. {
  822. if(0 != (0x8000 & GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON)))
  823. {
  824. TRACKMOUSEEVENT tm;
  825. ZeroMemory(&tm, sizeof(TRACKMOUSEEVENT));
  826. tm.cbSize = sizeof(TRACKMOUSEEVENT);
  827. tm.dwFlags = TME_LEAVE | TME_NONCLIENT;
  828. tm.hwndTrack = pWnd->hwnd;
  829. TrackMouseEvent(&tm);
  830. }
  831. else
  832. {
  833. pWnd->buttonState = BUTTON_NORMAL;
  834. RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME);
  835. }
  836. }
  837. }
  838. static void SkinnedWindow_OnWinampCustomClose(SKINNEDWND *pWnd, POINTS pts)
  839. {
  840. if (0 != pWnd->embedData.reparenting)
  841. return;
  842. SNDMSG(pWnd->hwnd, WM_SYSCOMMAND, SC_CLOSE, *(LPARAM*)&pts);
  843. }
  844. static void SkinnedWindow_OnWindowPosChanging(SKINNEDWND *pWnd, WINDOWPOS *pwp)
  845. {
  846. if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
  847. {
  848. if (!config_embedwnd_freesize &&
  849. 0 == (WS_CHILD & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE)))
  850. {
  851. pwp->cx += (RESIZESTEP_CX - 1);
  852. pwp->cx -= pwp->cx % RESIZESTEP_CX;
  853. pwp->cy += (RESIZESTEP_CY - 1);
  854. pwp->cy -= pwp->cy % RESIZESTEP_CY;
  855. }
  856. if (pwp->cx < RESIZESTEP_CX*2) pwp->cx = RESIZESTEP_CX*2;
  857. if (pwp->cy < RESIZESTEP_CY*2) pwp->cy = RESIZESTEP_CY*2;
  858. }
  859. CallWndProc(pWnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pwp);
  860. }
  861. static void SkinnedWindow_OnWindowPosChanged(SKINNEDWND *pWnd, WINDOWPOS *pwp)
  862. {
  863. if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED) & pwp->flags))
  864. {
  865. SetRect(&pWnd->embedData.r, pwp->x, pwp->y, pwp->x + pwp->cx, pwp->y + pwp->cy);
  866. }
  867. CallWndProc(pWnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)pwp);
  868. }
  869. static void SkinnedWindow_OnMoving(SKINNEDWND *pWnd, RECT *prc)
  870. {
  871. if (0 == (SWS_EX_NOSNAP & pWnd->flags) &&
  872. (0xFFFF != pWnd->movingOffset.x && 0xFFFF != pWnd->movingOffset.y) &&
  873. (!!config_snap + (0 != (0x8000 & GetAsyncKeyState(VK_SHIFT))) == 1))
  874. {
  875. POINT pt;
  876. GetCursorPos(&pt);
  877. INT cx = prc->right - prc->left;
  878. INT cy = prc->bottom - prc->top;
  879. prc->left = pt.x - pWnd->movingOffset.x;
  880. prc->top = pt.y - pWnd->movingOffset.y;
  881. prc->right = prc->left + cx;
  882. prc->bottom = prc->top + cy;
  883. SnapWindowToAllWindows(prc, pWnd->hwnd);
  884. }
  885. }
  886. static void SkinnedWindow_OnSizing(SKINNEDWND *pWnd, UINT edge, RECT *prc)
  887. {
  888. LONG cx, cy;
  889. cx = prc->right - prc->left;
  890. cy = prc->bottom - prc->top;
  891. if (!config_embedwnd_freesize &&
  892. 0 == (0x8000 & GetAsyncKeyState(VK_SHIFT)))
  893. {
  894. cx += (RESIZESTEP_CX - 1);
  895. cx -= cx % RESIZESTEP_CX;
  896. cy += (RESIZESTEP_CY - 1);
  897. cy -= cy % RESIZESTEP_CY;
  898. }
  899. if (cx < RESIZESTEP_CX*2) cx = RESIZESTEP_CX*2;
  900. if (cy < RESIZESTEP_CY*2) cy = RESIZESTEP_CY*2;
  901. prc->right = prc->left + cx;
  902. prc->bottom = prc->top + cy;
  903. }
  904. static void SkinnedWindow_OnEnterSizeMove(SKINNEDWND *pWnd)
  905. {
  906. POINT pt;
  907. RECT rw;
  908. GetCursorPos(&pt);
  909. GetWindowRect(pWnd->hwnd, &rw);
  910. if (0xFFFF == pWnd->movingOffset.x)
  911. pWnd->movingOffset.x = pt.x - rw.left;
  912. if (0xFFFF == pWnd->movingOffset.y)
  913. pWnd->movingOffset.y = pt.y - rw.top;
  914. }
  915. static void SkinnedWindow_OnExitSizeMove(SKINNEDWND *pWnd)
  916. {
  917. pWnd->movingOffset.x = 0xFFFF;
  918. pWnd->movingOffset.y = 0xFFFF;
  919. }
  920. static void SkinnedWindow_PatchCursor(SKINNEDWND *pWnd)
  921. {
  922. RECT rc;
  923. POINT ptOrig, pt;
  924. if (!GetCursorPos(&ptOrig) ||
  925. !GetWindowRect(pWnd->hwnd, &rc))
  926. return;
  927. pt.x = rc.right + 1;
  928. pt.y = ptOrig.y;
  929. ShowCursor(FALSE);
  930. SetCursorPos(pt.x, pt.y);
  931. ShowCursor(TRUE);
  932. SetCursorPos(ptOrig.x, ptOrig.y);
  933. }
  934. static void SkinnedWindow_OnEnterMenuLoop(SKINNEDWND *pWnd, BOOL bTrackPopup)
  935. {
  936. PostMessageW(pWnd->hwnd, WM_SETCURSOR, (WPARAM)pWnd->hwnd, MAKELPARAM(HTCLIENT,WM_ENTERMENULOOP));
  937. }
  938. static void SkinnedWindow_OnExitMenuLoop(SKINNEDWND *pWnd, BOOL bShortcut)
  939. {
  940. }
  941. static void SkinnedWindow_OnUnskin(SKINNEDWND *pWnd)
  942. {
  943. if (NULL == pWnd) return;
  944. HWND hwnd = pWnd->hwnd;
  945. BOOL restoreVisible = FALSE;
  946. DWORD windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  947. if (0 != (WS_VISIBLE & windowStyle))
  948. {
  949. restoreVisible = TRUE;
  950. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  951. }
  952. if (NULL != pWnd->embedData.wasabi_window)
  953. {
  954. SENDWAIPC(IPC_CB_ONHIDEWND, pWnd->hwnd);
  955. // start looping till we get callback
  956. MSG msg;
  957. BOOL stopLoop = FALSE;
  958. while(FALSE == stopLoop)
  959. {
  960. DWORD status = MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
  961. if (WAIT_OBJECT_0 == status)
  962. {
  963. while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
  964. {
  965. if (WAMSG_CLOSE == msg.message && msg.hwnd == pWnd->hwnd)
  966. {
  967. stopLoop = TRUE;
  968. break;
  969. }
  970. else if (!CallMsgFilter(&msg, MSGF_DIALOGBOX))
  971. {
  972. if (msg.message == WM_QUIT)
  973. {
  974. PostQuitMessage((INT)msg.wParam);
  975. stopLoop = TRUE;
  976. break;
  977. }
  978. else
  979. {
  980. TranslateMessage(&msg);
  981. DispatchMessageW(&msg);
  982. }
  983. }
  984. }
  985. }
  986. }
  987. }
  988. SkinnedWindow_Delete(pWnd);
  989. if (FALSE != restoreVisible)
  990. SetWindowLongPtrW(hwnd, GWL_STYLE, WS_VISIBLE | GetWindowLongPtrW(hwnd, GWL_STYLE));
  991. }
  992. static LRESULT SkinnedWindow_OnWinampIPC(SKINNEDWND *pWnd, UINT uCmd, WPARAM param)
  993. {
  994. switch(uCmd)
  995. {
  996. case IPC_SKINWINDOW_SETEXSTYLE:
  997. pWnd->flags = (SWS_EX_MASK & pWnd->flags) | (~SWS_EX_MASK & param);
  998. return 0;
  999. case IPC_SKINWINDOW_GETEXSTYLE:
  1000. return (~SWS_EX_MASK & pWnd->flags);
  1001. case IPC_SKINWINDOW_SETEMBEDFLAGS:
  1002. pWnd->embedData.flags = (INT)param;
  1003. return 0;
  1004. case IPC_SKINWINDOW_GETEMBEDFLAGS:
  1005. return pWnd->embedData.flags;
  1006. case IPC_SKINWINDOW_GETWASABIWND:
  1007. return (LRESULT)pWnd->embedData.wasabi_window;
  1008. case IPC_SKINWINDOW_UNSKIN:
  1009. SkinnedWindow_OnUnskin(pWnd);
  1010. break;
  1011. case IPC_SKINWINDOW_GETGUID:
  1012. if (NULL != param)
  1013. {
  1014. CopyMemory((void*)param, &pWnd->embedData.guid, sizeof(GUID));
  1015. return TRUE;
  1016. }
  1017. break;
  1018. case IPC_SKINWINDOW_GETEMBEDNUMS:
  1019. return Skin_UseGenNums;
  1020. }
  1021. return 0;
  1022. }
  1023. static void SkinnedWindow_OnSysCommand(SKINNEDWND *pWnd, UINT uCmd, LPARAM param)
  1024. {
  1025. CallWndProc(pWnd, WM_SYSCOMMAND, (WPARAM)uCmd, param);
  1026. switch(uCmd)
  1027. {
  1028. case SC_MOVE:
  1029. case SC_SIZE:
  1030. case SC_DRAGMOVE:
  1031. case SC_DRAGSIZE_N:
  1032. case SC_DRAGSIZE_S:
  1033. case SC_DRAGSIZE_E:
  1034. case SC_DRAGSIZE_W:
  1035. case SC_DRAGSIZE_NW:
  1036. case SC_DRAGSIZE_NE:
  1037. case SC_DRAGSIZE_SW:
  1038. case SC_DRAGSIZE_SE:
  1039. SkinnedWindow_PatchCursor(pWnd);
  1040. break;
  1041. }
  1042. }
  1043. static LRESULT SkinnedWindow_OnSetText(SKINNEDWND *pWnd, LPCWSTR pszText)
  1044. {
  1045. LRESULT result = CallWndProc(pWnd, WM_SETTEXT, 0, (LPARAM)pszText);
  1046. ifc_window *wnd = pWnd->embedData.wasabi_window;
  1047. if (NULL != wnd)
  1048. {
  1049. ifc_window *parent = wnd->getRootParent();
  1050. if (NULL == parent) parent = wnd;
  1051. parent->setWindowTitle(pszText);
  1052. }
  1053. else
  1054. {
  1055. SetWindowPos(pWnd->hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
  1056. }
  1057. return result;
  1058. }
  1059. static LRESULT CALLBACK SkinnedWnd_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1060. {
  1061. SKINNEDWND *pWnd = GetSkinnedWnd(hwnd);
  1062. if (NULL == pWnd)
  1063. {
  1064. return ((IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) :
  1065. DefWindowProcA(hwnd, uMsg, wParam, lParam));
  1066. }
  1067. switch(uMsg)
  1068. {
  1069. case WM_DESTROY:
  1070. {
  1071. BOOL unicode = IsUnicode(pWnd);
  1072. WNDPROC wndProc = pWnd->fnWndProc;
  1073. SkinnedWindow_Delete(pWnd);
  1074. return ((unicode) ? CallWindowProcW(wndProc, hwnd, uMsg, wParam, lParam) :
  1075. CallWindowProcA(wndProc, hwnd, uMsg, wParam, lParam));
  1076. }
  1077. break;
  1078. case WAMSG_CLOSE: SkinnedWindow_OnWinampCustomClose(pWnd, MAKEPOINTS(lParam)); return 0;
  1079. case WM_NCHITTEST: return SkinnedWindow_OnNcHitTest(pWnd, MAKEPOINTS(lParam));
  1080. case WM_NCCALCSIZE: return SkinnedWindow_OnNcCalcSize(pWnd, (BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam);
  1081. case WM_NCPAINT: SkinnedWindow_OnNcPaint(pWnd, (HRGN)wParam); return 0;
  1082. case WM_NCACTIVATE: return SkinnedWindow_OnNcActivate(pWnd, (BOOL)wParam);
  1083. case WM_ACTIVATE: SkinnedWindow_OnActivate(pWnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return 0;
  1084. case WM_PRINT: SkinnedWindow_OnPrint(pWnd, (HDC)wParam, (UINT)lParam); return 0;
  1085. case WM_SETCURSOR: return SkinnedWindow_OnSetCursor(pWnd, (HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  1086. case WM_NCLBUTTONDOWN: if (SkinnedWindow_OnNcLButtonDown(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break;
  1087. case WM_NCLBUTTONUP: if (SkinnedWindow_OnNcLButtonUp(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break;
  1088. case WM_NCRBUTTONDOWN: if (SkinnedWindow_OnNcRButtonDown(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break;
  1089. case WM_NCRBUTTONUP: if (SkinnedWindow_OnNcRButtonUp(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break;
  1090. case WM_NCMOUSEMOVE: SkinnedWindow_OnNcMouseMove(pWnd, (INT)wParam, MAKEPOINTS(lParam)); break;
  1091. case WM_NCMOUSELEAVE: SkinnedWindow_OnNcMouseLeave(pWnd); break;
  1092. case WM_SHOWWINDOW: if (SkinnedWindow_OnShowWindow(pWnd, (BOOL)wParam, (UINT)lParam)) return 0; break;
  1093. case WM_WINDOWPOSCHANGING: SkinnedWindow_OnWindowPosChanging(pWnd, (WINDOWPOS*)lParam); return 0;
  1094. case WM_WINDOWPOSCHANGED: SkinnedWindow_OnWindowPosChanged(pWnd, (WINDOWPOS*)lParam); return 0;
  1095. case WM_ENTERSIZEMOVE: SkinnedWindow_OnEnterSizeMove(pWnd); break;
  1096. case WM_EXITSIZEMOVE: SkinnedWindow_OnExitSizeMove(pWnd); break;
  1097. case WM_MOVING: SkinnedWindow_OnMoving(pWnd, (RECT*)lParam); break;
  1098. case WM_SIZING: SkinnedWindow_OnSizing(pWnd, (UINT)wParam, (RECT*)lParam); break;
  1099. case WM_ENTERMENULOOP: SkinnedWindow_OnEnterMenuLoop(pWnd, (BOOL)wParam); break;
  1100. case WM_EXITMENULOOP: SkinnedWindow_OnExitMenuLoop(pWnd, (BOOL)wParam); break;
  1101. case WM_NCUAHDRAWCAPTION: return 0;
  1102. case WM_NCUAHDRAWFRAME: return 0;
  1103. case WM_WA_IPC: return SkinnedWindow_OnWinampIPC(pWnd, (UINT)lParam, wParam);
  1104. case WM_SYSCOMMAND: SkinnedWindow_OnSysCommand(pWnd, (UINT)wParam, lParam); return 0;
  1105. case WM_SETTEXT: return SkinnedWindow_OnSetText(pWnd, (LPCWSTR)lParam);
  1106. }
  1107. if (FALSE != IsDirectMouseWheelMessage(uMsg))
  1108. {
  1109. if (0 == (WS_CHILD & GetWindowStyle(hwnd)))
  1110. return TRUE;
  1111. else
  1112. {
  1113. HWND hParent;
  1114. hParent = GetAncestor(hwnd, GA_PARENT);
  1115. if (NULL != hParent)
  1116. return SendMessageW(hwnd, uMsg, wParam, lParam);
  1117. return FALSE;
  1118. }
  1119. }
  1120. return CallWndProc(pWnd, uMsg, wParam, lParam);
  1121. }