embwnd.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author:
  6. ** Created:
  7. **/
  8. #include <windowsx.h>
  9. #include "main.h"
  10. #include "api.h"
  11. void draw_paint_emb( HWND, int, int, int );
  12. void draw_embed_tbar( HWND, int, int );
  13. void draw_embed_tbutton( HWND, int, int );
  14. void draw_embed( HDC, int, int );
  15. // all of this stuff is barely working. I will be fixing it soon soon.
  16. /// embed ui shit
  17. #define inreg(x,y,x2,y2) \
  18. ((mouse_x <= ( x2 ) && mouse_x >= ( x ) && \
  19. mouse_y <= ( y2 ) && mouse_y >= ( y )))
  20. enum
  21. {
  22. NO_CAP, TITLE_CAP, TB_CAP, SZ_CAP
  23. };
  24. static void do_titlebar( HWND hwnd, embedWindowState *state );
  25. static void do_titlebuttons( HWND hwnd, embedWindowState *state );
  26. static void do_size( HWND hwnd, embedWindowState *state );
  27. static int mouse_x, mouse_y, mouse_type, mouse_stats;
  28. static int which_cap = 0;
  29. static HWND capwnd;
  30. void embedui_handlemouseevent( HWND hwnd, int x, int y, int type, int stats, embedWindowState *state )
  31. {
  32. if ( which_cap != NO_CAP && hwnd != capwnd ) return;
  33. mouse_x = x;
  34. mouse_y = y;
  35. mouse_type = type;
  36. mouse_stats = stats;
  37. switch ( which_cap )
  38. {
  39. case TITLE_CAP: do_titlebar( hwnd, state ); return;
  40. case TB_CAP: do_titlebuttons( hwnd, state ); return;
  41. case SZ_CAP: do_size( hwnd, state ); return;
  42. default: break;
  43. }
  44. do_titlebuttons( hwnd, state );
  45. do_size( hwnd, state );
  46. do_titlebar( hwnd, state );
  47. if ( which_cap != NO_CAP ) capwnd = hwnd; // not sure if this is gonna work
  48. }
  49. static void do_titlebar( HWND hwnd, embedWindowState *state )
  50. {
  51. if ( which_cap == TITLE_CAP || ( !which_cap && ( config_easymove || mouse_y < 14 ) ) )
  52. {
  53. static int clickx, clicky;
  54. switch ( mouse_type )
  55. {
  56. case 1:
  57. {
  58. which_cap = TITLE_CAP;
  59. clickx = mouse_x;
  60. clicky = mouse_y;
  61. }
  62. break;
  63. case -1:
  64. which_cap = 0;
  65. break;
  66. case 0:
  67. if ( which_cap == TITLE_CAP && mouse_stats & MK_LBUTTON )
  68. {
  69. // TODO need to convert this into an API method so
  70. // we can call it externally e.g. enhancer...
  71. // or something like it to allow state->r to
  72. // be updated once the move has been finished
  73. POINT p = { mouse_x, mouse_y };
  74. ClientToScreen( hwnd, &p );
  75. int w = state->r.right - state->r.left;
  76. int h = state->r.bottom - state->r.top;
  77. state->r.left = p.x - clickx;
  78. state->r.top = p.y - clicky;
  79. state->r.right = state->r.left + w;
  80. state->r.bottom = state->r.top + h;
  81. if ( !!config_snap + !!( mouse_stats & MK_SHIFT ) == 1 )
  82. {
  83. SnapWindowToAllWindows( &state->r, hwnd );
  84. }
  85. POINT pt = { state->r.left, state->r.top };
  86. SendMessageW( hwnd, WM_USER + 0x100, 1, (LPARAM) &pt );
  87. SetWindowPos( hwnd, 0, state->r.left, state->r.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
  88. }
  89. break;
  90. }
  91. }
  92. }
  93. static void do_titlebuttons( HWND hwnd, embedWindowState *state )
  94. {
  95. int w = 0;
  96. w = inreg( state->r.right - state->r.left - 10, 3, state->r.right - state->r.left - 1, 3 + 9 ) ? 1 : 0;
  97. if ( w ) // kill button
  98. {
  99. if ( mouse_type == -1 && which_cap == TB_CAP )
  100. {
  101. which_cap = 0;
  102. draw_embed_tbutton( hwnd, 0, ( state->r.right - state->r.left ) );
  103. SendMessageW( hwnd, WM_USER + 101, 0, 0 );
  104. }
  105. else if ( mouse_stats & MK_LBUTTON )
  106. {
  107. which_cap = TB_CAP;
  108. draw_embed_tbutton( hwnd, w ? 1 : 0, ( state->r.right - state->r.left ) );
  109. }
  110. }
  111. else if ( which_cap == TB_CAP )
  112. {
  113. which_cap = 0;
  114. draw_embed_tbutton( hwnd, 0, ( state->r.right - state->r.left ) );
  115. }
  116. }
  117. typedef struct _WNDREPAINT
  118. {
  119. HWND hwndSender;
  120. RECT rwR;
  121. RECT rwB;
  122. } WNDREPAINT;
  123. static BOOL CALLBACK EnumWndRepaintProc( HWND hwnd, LPARAM param )
  124. {
  125. WNDREPAINT *pwp = (WNDREPAINT *) param;
  126. if ( hwnd != pwp->hwndSender && IsWindowVisible( hwnd ) )
  127. {
  128. RECT rw;
  129. GetWindowRect( hwnd, &rw );
  130. if ( ( rw.left < pwp->rwR.right && rw.right > pwp->rwR.left && rw.top < pwp->rwR.bottom && rw.bottom > pwp->rwR.top ) ||
  131. ( rw.top < pwp->rwB.bottom && rw.bottom > pwp->rwB.top && rw.left < pwp->rwB.right && rw.right > pwp->rwB.left ) )
  132. {
  133. UpdateWindow( hwnd );
  134. }
  135. }
  136. return TRUE;
  137. }
  138. static void do_size( HWND hwnd, embedWindowState *state )
  139. {
  140. if ( state->flags & EMBED_FLAGS_NORESIZE )
  141. {
  142. if ( which_cap == SZ_CAP ) which_cap = 0;
  143. return;
  144. }
  145. if ( which_cap == SZ_CAP || ( !which_cap &&
  146. mouse_x > ( state->r.right - state->r.left ) - 20 && mouse_y > ( state->r.bottom - state->r.top ) - 20 &&
  147. ( ( ( state->r.right - state->r.left ) - mouse_x + ( state->r.bottom - state->r.top ) - mouse_y ) <= 30 ) ) )
  148. {
  149. static int dx, dy;
  150. if ( !which_cap && mouse_type == 1 )
  151. {
  152. dx = ( state->r.right - state->r.left ) - mouse_x;
  153. dy = ( state->r.bottom - state->r.top ) - mouse_y;
  154. which_cap = SZ_CAP;
  155. }
  156. if ( which_cap == SZ_CAP )
  157. {
  158. if ( mouse_type == -1 ) which_cap = 0;
  159. int x = mouse_x + dx;
  160. int y = mouse_y + dy;
  161. // if (x >= GetSystemMetrics(SM_CXSCREEN)) x = GetSystemMetrics(SM_CXSCREEN)-24;
  162. // if (y >= GetSystemMetrics(SM_CYSCREEN)) y = GetSystemMetrics(SM_CYSCREEN)-28;
  163. if ( !config_embedwnd_freesize )
  164. {
  165. x += 24;
  166. x -= x % 25;
  167. y += 28;
  168. y -= y % 29;
  169. }
  170. if ( x < 275 ) x = 275;
  171. if ( y < 20 + 38 + 29 + 29 ) y = 20 + 38 + 29 + 29;
  172. if ( x != ( state->r.right - state->r.left ) || y != ( state->r.bottom - state->r.top ) )
  173. {
  174. // TODO need to ensure this isn't used when freesize is disabled
  175. // isn't keeping track of the positions correctly on change
  176. // as some windows only part snap e.g. ml won't dock to edges or to bottom of main window
  177. RECT rw = { 0 }, r = { 0 };
  178. POINT pt = { x, y };
  179. SendMessageW( hwnd, WM_USER + 0x101, 1, (LPARAM) &pt );
  180. GetWindowRect( hwnd, &rw );
  181. // trying to get classic skins to dock to other windows on resizing
  182. /*rw.left = state->r.left;
  183. rw.top = state->r.top;
  184. rw.right = state->r.left + x;
  185. rw.bottom = state->r.top + y;
  186. CopyRect(&r, &rw);
  187. //if (!!config_snap + !!(mouse_stats & MK_SHIFT) == 1)
  188. {
  189. SnapWindowToAllWindows(&rw, hwnd);
  190. }
  191. x += (rw.right - r.right);
  192. y += (rw.bottom - r.bottom);
  193. SetWindowPos(hwnd, 0, 0, 0, x, y, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);*/
  194. SetWindowPos( hwnd, 0, 0, 0, x, y, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
  195. if ( x < ( rw.right - rw.left ) || y < ( rw.bottom - rw.top ) )
  196. {
  197. WNDREPAINT wrp;
  198. wrp.hwndSender = hwnd;
  199. SetRect( &wrp.rwR, min( rw.left + x, rw.right ), rw.top, rw.right, rw.bottom );
  200. SetRect( &wrp.rwB, rw.left, min( rw.top + y, rw.bottom ), rw.right, rw.bottom );
  201. EnumThreadWindows( GetCurrentThreadId(), EnumWndRepaintProc, (LPARAM) &wrp );
  202. }
  203. }
  204. }
  205. }
  206. }
  207. //// embed window shut
  208. static int emb_OnLButtonUp( HWND hwnd, int x, int y, UINT flags );
  209. static int emb_OnRButtonUp( HWND hwnd, int x, int y, UINT flags );
  210. static int emb_OnLButtonDown( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags );
  211. static int emb_OnMouseMove( HWND hwnd, int x, int y, UINT keyFlags );
  212. static int emb_OnLButtonDblClk( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags );
  213. static BOOL emb_OnNCActivate( HWND hwnd, BOOL fActive, HWND hwndActDeact, BOOL fMinimized );
  214. static int emb_OnRButtonUp( HWND hwnd, int x, int y, UINT flags )
  215. {
  216. //display winamp's main popup menu
  217. POINT p;
  218. GetCursorPos( &p );
  219. int ret = DoTrackPopup( main_menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, p.x, p.y, hwnd );
  220. if ( ret ) SendMessageW( hMainWindow, WM_COMMAND, ret, 0 );
  221. return 1;
  222. }
  223. static int emb_OnLButtonUp( HWND hwnd, int x, int y, UINT flags )
  224. {
  225. ReleaseCapture();
  226. embedui_handlemouseevent( hwnd, x, y, -1, flags, (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ) );
  227. return 1;
  228. }
  229. static int emb_OnLButtonDown( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags )
  230. {
  231. SetCapture( hwnd );
  232. embedui_handlemouseevent( hwnd, x, y, 1, keyFlags, (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ) );
  233. return 1;
  234. }
  235. static int emb_OnMouseMove( HWND hwnd, int x, int y, UINT keyFlags )
  236. {
  237. embedui_handlemouseevent( hwnd, x, y, 0, keyFlags, (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ) );
  238. return 1;
  239. }
  240. static BOOL emb_OnNCActivate( HWND hwnd, BOOL fActive, HWND hwndActDeact, BOOL fMinimized )
  241. {
  242. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  243. if ( fActive == FALSE )
  244. {
  245. draw_embed_tbar( hwnd, config_hilite ? 0 : 1, ( state->r.right - state->r.left ) );
  246. which_cap = NO_CAP;
  247. capwnd = 0;
  248. }
  249. else
  250. {
  251. draw_embed_tbar( hwnd, 1, ( state->r.right - state->r.left ) );
  252. }
  253. return TRUE;
  254. }
  255. static int emb_OnLButtonDblClk( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags )
  256. {
  257. return 1;
  258. }
  259. CRITICAL_SECTION embedcs;
  260. embedWindowState *embedwndlist; // linked list
  261. int embedwndlist_cnt;
  262. static void EmbedWindow_OnShowWindow( HWND hwnd, BOOL fShow, UINT status )
  263. {
  264. if ( 0 != status )
  265. {
  266. SetPropW( hwnd, L"EmbedWnd_ShowStatus", (HANDLE) status );
  267. DefWindowProcW( hwnd, WM_SHOWWINDOW, (WPARAM) fShow, (LPARAM) status );
  268. RemovePropW( hwnd, L"EmbedWnd_ShowStatus" );
  269. return;
  270. }
  271. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  272. HWND hChild = FindWindowExW( hwnd, NULL, NULL, NULL );
  273. INT toggleResult = 1;
  274. if ( state && FALSE == state->reparenting )
  275. {
  276. INT result = Ipc_WindowToggle( (INT_PTR) hwnd, ( FALSE != fShow ) ? 1 : 0 );
  277. if ( fShow ) toggleResult = result;
  278. }
  279. if ( NULL != hChild && 0 != toggleResult )
  280. {
  281. if ( FALSE != fShow && NULL != state )
  282. {
  283. SetWindowPos( hChild, NULL, 11, 20,
  284. ( state->r.right - state->r.left ) - 11 - 8,
  285. ( state->r.bottom - state->r.top ) - 20 - 14,
  286. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOOWNERZORDER );
  287. }
  288. EMBEDSHOW embedShow;
  289. embedShow.hdr.code = EWN_SHOWWINDOW;
  290. embedShow.hdr.hwndFrom = hwnd;
  291. embedShow.hdr.idFrom = GetDlgCtrlID( hwnd );
  292. embedShow.fShow = fShow;
  293. embedShow.nStatus = (UINT) (UINT_PTR) GetPropW( hwnd, L"EmbedWnd_ShowStatus" );
  294. SendMessageW( hChild, WM_NOTIFY, (WPARAM) embedShow.hdr.idFrom, (LPARAM) &embedShow );
  295. }
  296. }
  297. typedef struct __EMBEDWNDPART
  298. {
  299. INT id;
  300. RECT rect;
  301. }EMBEDWNDPART;
  302. static INT EmbedWindow_HitTest( HWND hwnd, POINT pt )
  303. {
  304. DWORD windowStyle = GetWindowLongPtrW( hwnd, GWL_STYLE );
  305. if ( 0 != ( WS_DISABLED & windowStyle ) )
  306. return HTERROR;
  307. MapWindowPoints( HWND_DESKTOP, hwnd, &pt, 1 );
  308. RECT clientRect;
  309. if ( !GetClientRect( hwnd, &clientRect ) )
  310. return HTERROR;
  311. if ( 0 != ( WS_CHILD & windowStyle ) )
  312. {
  313. return ( PtInRect( &clientRect, pt ) ) ? HTCLIENT : HTNOWHERE;
  314. }
  315. static EMBEDWNDPART embedWindowParts[] =
  316. {
  317. { HTCLOSE, {-( 275 - 264 ), 3,-( 275 - 272 ), 12}},
  318. { HTCAPTION, {0, 0, -1, 13}},
  319. { HTBOTTOMRIGHT, {-20,-20,-1,-1}},
  320. };
  321. INT hitTest = HTCLIENT;
  322. RECT part;
  323. for ( INT i = 0; i < ARRAYSIZE( embedWindowParts ); i++ )
  324. {
  325. CopyRect( &part, &embedWindowParts[ i ].rect );
  326. if ( part.left < 0 ) part.left += clientRect.right;
  327. if ( part.right < 0 ) part.right += clientRect.right;
  328. if ( part.top < 0 ) part.top += clientRect.bottom;
  329. if ( part.bottom < 0 ) part.bottom += clientRect.bottom;
  330. if ( PtInRect( &part, pt ) )
  331. {
  332. hitTest = embedWindowParts[ i ].id;
  333. break;
  334. }
  335. }
  336. if ( HTBOTTOMRIGHT == hitTest )
  337. {
  338. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  339. if ( 0 != ( EMBED_FLAGS_NORESIZE & state->flags ) )
  340. hitTest = HTBORDER;
  341. }
  342. return hitTest;
  343. }
  344. static LRESULT EmbedWindow_OnSetCursor( HWND hwnd, HWND hwndCursor, INT hitTest, UINT uMsg )
  345. {
  346. HCURSOR hCursor = NULL;
  347. switch ( uMsg )
  348. {
  349. case WM_LBUTTONDOWN:
  350. case WM_RBUTTONDOWN:
  351. case WM_MBUTTONDOWN:
  352. case WM_XBUTTONDOWN:
  353. DisabledWindow_OnMouseClick( hwnd );
  354. break;
  355. }
  356. if ( config_usecursors && !disable_skin_cursors )
  357. {
  358. int index = 15 + 5; // PNormal.cur
  359. POINT pt;
  360. GetCursorPos( &pt );
  361. hitTest = EmbedWindow_HitTest( hwnd, pt );
  362. switch ( hitTest )
  363. {
  364. case HTCAPTION:
  365. index = 15 + 2; // PTBar.cur
  366. break;
  367. case HTCLOSE:
  368. index = 15 + 1; // PClose.cur
  369. break;
  370. case HTLEFT:
  371. case HTRIGHT:
  372. case HTTOP:
  373. case HTTOPLEFT:
  374. case HTTOPRIGHT:
  375. case HTBOTTOM:
  376. case HTBOTTOMLEFT:
  377. case HTBOTTOMRIGHT:
  378. index = 15 + 4;// PSize.cur
  379. break;
  380. }
  381. hCursor = Skin_Cursors[ index ];
  382. }
  383. if ( NULL != hCursor )
  384. {
  385. SetCursor( hCursor );
  386. return TRUE;
  387. }
  388. return DefWindowProcW( hwnd, WM_SETCURSOR, (WPARAM) hwndCursor, MAKELPARAM( hitTest, uMsg ) );
  389. }
  390. extern "C"
  391. {
  392. LRESULT CALLBACK emb_WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  393. {
  394. switch ( uMsg )
  395. {
  396. case WM_INITMENUPOPUP:
  397. return SendMessageW( hMainWindow, uMsg, wParam, lParam ); // for popup menus
  398. HANDLE_MSG( hwnd, WM_QUERYNEWPALETTE, Main_OnQueryNewPalette );
  399. HANDLE_MSG( hwnd, WM_PALETTECHANGED, Main_OnPaletteChanged );
  400. HANDLE_MSG( hwnd, WM_LBUTTONUP, emb_OnLButtonUp );
  401. HANDLE_MSG( hwnd, WM_RBUTTONUP, emb_OnRButtonUp );
  402. HANDLE_MSG( hwnd, WM_LBUTTONDOWN, emb_OnLButtonDown );
  403. HANDLE_MSG( hwnd, WM_MOUSEMOVE, emb_OnMouseMove );
  404. HANDLE_MSG( hwnd, WM_NCACTIVATE, emb_OnNCActivate );
  405. HANDLE_MSG( hwnd, WM_LBUTTONDBLCLK, emb_OnLButtonDblClk );
  406. case WM_SYSCOMMAND:
  407. if ( ( wParam & 0xfff0 ) == SC_SCREENSAVE || ( wParam & 0xfff0 ) == SC_MONITORPOWER )
  408. return SendMessageW( hMainWindow, uMsg, wParam, lParam );
  409. case WM_COMMAND:
  410. case WM_KEYDOWN:
  411. case WM_KEYUP:
  412. case WM_SYSKEYDOWN:
  413. case WM_SYSKEYUP:
  414. {
  415. if ( ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) && wParam == VK_F4 )
  416. {
  417. if ( uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN )
  418. SendMessageW( hwnd, WM_USER + 101, 0, 0 );
  419. }
  420. else
  421. {
  422. // HWND hh=FindWindowExW(hwnd,NULL,NULL,NULL);
  423. // if (hh) PostMessageW(hh,uMsg,wParam,lParam);
  424. // else PostMessageW(hMainWindow,uMsg,wParam,lParam);
  425. }
  426. }
  427. break;
  428. case WM_USER + 101:
  429. {
  430. HWND hh = FindWindowExW( hwnd, NULL, NULL, NULL );
  431. if ( hh ) PostMessageW( hh, WM_CLOSE, 0, 0 );
  432. }
  433. return 0;
  434. case WM_USER + 102:
  435. {
  436. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  437. if ( !state || !state->reparenting )
  438. ShowWindow( hwnd, SW_SHOWNA );
  439. }
  440. break;
  441. case WM_USER + 103:
  442. SetFocus( hwnd );
  443. break;
  444. case WM_SHOWWINDOW:
  445. EmbedWindow_OnShowWindow( hwnd, (BOOL) wParam, (UINT) lParam );
  446. RefreshIconicThumbnail();
  447. return 0;
  448. case WM_DISPLAYCHANGE:
  449. {
  450. HWND hh = FindWindowExW( hwnd, NULL, NULL, NULL );
  451. if ( hh )
  452. SendMessageW( hh, uMsg, wParam, lParam );
  453. }
  454. InvalidateRect( hwnd, NULL, TRUE );
  455. return 0;
  456. case WM_CLOSE:
  457. SendMessageW( GetParent( hwnd ), WM_CLOSE, 0, 0 );
  458. return 0;
  459. case WM_PAINT:
  460. {
  461. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  462. if ( state ) draw_paint_emb( hwnd, ( state->r.right - state->r.left ), ( state->r.bottom - state->r.top ), state->flags );
  463. }
  464. return 0;
  465. case WM_WINDOWPOSCHANGING:
  466. {
  467. /*
  468. if extra_data[EMBED_STATE_EXTRA_REPARENTING] is set, we are being reparented by the freeform lib, so we should
  469. just ignore this message because our visibility will not change once the freeform
  470. takeover/restoration is complete
  471. */
  472. WINDOWPOS *windowPos = (WINDOWPOS *) lParam;
  473. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  474. if ( state && state->reparenting )
  475. {
  476. if ( 0 != ( WS_CHILD & GetWindowLongPtrW( windowPos->hwnd, GWL_STYLE ) ) )
  477. windowPos->flags |= ( SWP_NOREDRAW );
  478. break;
  479. }
  480. }
  481. break;
  482. case WM_WINDOWPOSCHANGED:
  483. {
  484. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  485. if ( state && 0 == ( SWP_NOSIZE & ( (WINDOWPOS *) lParam )->flags ) )
  486. {
  487. HWND hh;
  488. HRGN rgnChild;
  489. INT cx, cy, ox;//, oy;
  490. RECT rv;
  491. ox = state->r.right - state->r.left;
  492. //oy = state->r.bottom - state->r.top;
  493. cx = ( (WINDOWPOS *) lParam )->cx;
  494. cy = ( (WINDOWPOS *) lParam )->cy;
  495. state->r.right = state->r.left + cx;
  496. state->r.bottom = state->r.top + cy;
  497. hh = FindWindowExW( hwnd, NULL, NULL, NULL );
  498. if ( 0 == ( SWP_NOREDRAW & ( (WINDOWPOS *) lParam )->flags ) )
  499. InvalidateRect( hwnd, NULL, FALSE );
  500. if ( hh )
  501. {
  502. INT cx, cy;
  503. cx = ( state->r.right - state->r.left ) - 11 - 8;
  504. cy = ( state->r.bottom - state->r.top ) - 20 - 14;
  505. SetRect( &rv, 11, 20, 11 + cx, 20 + cy );
  506. ValidateRect( hwnd, &rv );
  507. rgnChild = CreateRectRgn( 0, 0, cx, cy );
  508. if ( IsWindowVisible( hh ) )
  509. SendMessageW( hh, WM_USER + 0x201, MAKEWPARAM( 0, 0 ), (LPARAM) rgnChild );
  510. SetWindowPos( hh, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOCOPYBITS );
  511. if ( IsWindowVisible( hh ) )
  512. SendMessageW( hh, WM_USER + 0x201, 0, (LPARAM) NULL );
  513. }
  514. else rgnChild = NULL;
  515. if ( ox == cx )
  516. {
  517. SetRect( &rv, 0, 0, cx, 14 );
  518. ValidateRect( hwnd, &rv );
  519. }
  520. if ( 0 == ( SWP_NOREDRAW & ( (WINDOWPOS *) lParam )->flags ) )
  521. {
  522. HRGN rgnWnd;
  523. rgnWnd = CreateRectRgn( 0, 0, 0, 0 );
  524. if ( GetUpdateRect( hwnd, NULL, FALSE ) )
  525. GetUpdateRgn( hwnd, rgnWnd, FALSE );
  526. if ( rgnChild )
  527. {
  528. OffsetRgn( rgnChild, 11, 20 );
  529. CombineRgn( rgnWnd, rgnWnd, rgnChild, RGN_OR );
  530. }
  531. RedrawWindow( hwnd, NULL, rgnWnd, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN );
  532. if ( rgnWnd )
  533. DeleteObject( rgnWnd );
  534. }
  535. if ( rgnChild )
  536. DeleteObject( rgnChild );
  537. }
  538. }
  539. return 0;
  540. case WM_CREATE:
  541. {
  542. EMBEDWND *pew = (EMBEDWND *) calloc( 1, sizeof( EMBEDWND ) );
  543. SetPropW( hwnd, EMBEDWND_PROPW, pew );
  544. SetWindowLongPtrW( hwnd, GWLP_USERDATA, (LONG_PTR) ( (LPCREATESTRUCT) lParam )->lpCreateParams );
  545. embedWindowState *state = (embedWindowState *) ( (LPCREATESTRUCT) lParam )->lpCreateParams;
  546. state->me = hwnd;
  547. int w = ( state->r.right - state->r.left );
  548. int h = ( state->r.bottom - state->r.top );
  549. if ( !config_embedwnd_freesize )
  550. {
  551. w -= w % 25;
  552. h -= h % 29;
  553. }
  554. if ( w < 275 ) w = 275;
  555. if ( h < 116 ) h = 116;
  556. state->r.right = state->r.left + w;
  557. state->r.bottom = state->r.top + h;
  558. EnterCriticalSection( &embedcs );
  559. GUID temp = GUID_NULL;
  560. if ( state->flags & EMBED_FLAGS_GUID )
  561. temp = state->guid;
  562. memset( state->extra_data, 0, sizeof( state->extra_data ) );
  563. if ( state->flags & EMBED_FLAGS_GUID )
  564. state->guid = temp;
  565. state->link = embedwndlist;
  566. embedwndlist = state;
  567. embedwndlist_cnt++;
  568. LeaveCriticalSection( &embedcs );
  569. SetWindowLong( hwnd, GWL_STYLE, GetWindowLongW( hwnd, GWL_STYLE ) & ~( WS_CAPTION ) );
  570. SetWindowPos( hwnd, 0, state->r.left, state->r.top, state->r.right - state->r.left, state->r.bottom - state->r.top, SWP_NOACTIVATE | SWP_NOZORDER );
  571. }
  572. return 0;
  573. case WM_DESTROY:
  574. {
  575. embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
  576. if ( state )
  577. {
  578. EnterCriticalSection( &embedcs );
  579. embedWindowState *p = embedwndlist;
  580. if ( p == state )
  581. {
  582. embedwndlist = state->link;// remove ourselves
  583. embedwndlist_cnt--;
  584. }
  585. else
  586. {
  587. while ( p )
  588. {
  589. if ( p->link == state )
  590. {
  591. p->link = state->link;
  592. embedwndlist_cnt--;
  593. break;
  594. }
  595. p = p->link;
  596. }
  597. }
  598. LeaveCriticalSection( &embedcs );
  599. }
  600. HWND hh = FindWindowExW( hwnd, NULL, NULL, NULL );
  601. if ( hh ) DestroyWindow( hh );
  602. EMBEDWND *pew = GetEmbedWnd( hwnd );
  603. if ( pew )
  604. {
  605. RemovePropW( hwnd, EMBEDWND_PROPW );
  606. free( pew );
  607. }
  608. }
  609. return 0;
  610. case WM_SETCURSOR:
  611. return EmbedWindow_OnSetCursor( hwnd, (HWND) wParam, LOWORD( lParam ), HIWORD( lParam ) );
  612. case WM_GETMINMAXINFO:
  613. {
  614. MINMAXINFO *p = (MINMAXINFO *) lParam;
  615. if ( NULL != p )
  616. {
  617. p->ptMaxTrackSize.x = 16384;
  618. p->ptMaxTrackSize.y = 16384;
  619. }
  620. }
  621. return 0;
  622. case WM_MOUSEACTIVATE:
  623. if ( NULL != WASABI_API_APP )
  624. WASABI_API_APP->ActiveDialog_Register( hwnd );
  625. break;
  626. case WM_CHILDACTIVATE:
  627. if ( NULL != WASABI_API_APP )
  628. WASABI_API_APP->ActiveDialog_Register( hwnd );
  629. break;
  630. case WM_ACTIVATE:
  631. if ( WA_INACTIVE == LOWORD( wParam ) )
  632. {
  633. EMBEDWND *pew = GetEmbedWnd( hwnd );
  634. if ( pew )
  635. {
  636. pew->hLastFocus = GetFocus();
  637. if ( !IsChild( hwnd, pew->hLastFocus ) )
  638. pew->hLastFocus = NULL;
  639. }
  640. if ( NULL != WASABI_API_APP )
  641. WASABI_API_APP->ActiveDialog_Unregister( hwnd );
  642. }
  643. else
  644. {
  645. if ( WA_CLICKACTIVE == LOWORD( wParam ) )
  646. {
  647. EMBEDWND *pew = GetEmbedWnd( hwnd );
  648. if ( pew )
  649. {
  650. POINT pt;
  651. DWORD pts = GetMessagePos();
  652. POINTSTOPOINT( pt, pts );
  653. MapWindowPoints( HWND_DESKTOP, hwnd, &pt, 1 );
  654. HWND hTarget = ChildWindowFromPointEx( hwnd, pt, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED | CWP_SKIPTRANSPARENT );
  655. if ( hTarget && hTarget != hwnd )
  656. pew->hLastFocus = hTarget;
  657. }
  658. }
  659. if ( NULL != WASABI_API_APP )
  660. WASABI_API_APP->ActiveDialog_Register( hwnd );
  661. }
  662. break;
  663. case WM_SETFOCUS:
  664. {
  665. HWND hChild, hTab;
  666. EMBEDWND *pew;
  667. hChild = FindWindowExW( hwnd, NULL, NULL, NULL );
  668. pew = GetEmbedWnd( hwnd );
  669. hTab = NULL;
  670. if ( pew )
  671. {
  672. while ( pew->hLastFocus && IsChild( hwnd, pew->hLastFocus ) )
  673. {
  674. if ( IsWindowEnabled( pew->hLastFocus ) && IsWindowVisible( pew->hLastFocus ) && 0 != ( WS_TABSTOP & GetWindowLongPtrW( pew->hLastFocus, GWL_STYLE ) ) )
  675. {
  676. hTab = pew->hLastFocus;
  677. break;
  678. }
  679. pew->hLastFocus = GetParent( pew->hLastFocus );
  680. }
  681. }
  682. if ( !hTab )
  683. hTab = ( hChild ) ? GetNextDlgTabItem( hwnd, hChild, FALSE ) : hwnd;
  684. if ( hTab && hTab != hwnd )
  685. {
  686. WCHAR szName[ 128 ] = { 0 };
  687. DWORD lcid = MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ), SORT_DEFAULT );
  688. if ( GetClassNameW( hChild, szName, sizeof( szName ) / sizeof( WCHAR ) ) && CSTR_EQUAL == CompareStringW( lcid, NORM_IGNORECASE, szName, -1, L"#32770", -1 ) )
  689. SendMessageW( hChild, WM_NEXTDLGCTL, (WPARAM) hTab, TRUE );
  690. else
  691. SetFocus( hTab );
  692. //return 0;
  693. }
  694. }
  695. break;
  696. case WM_KILLFOCUS:
  697. {
  698. EMBEDWND *pew = GetEmbedWnd( hwnd );
  699. if ( pew )
  700. {
  701. pew->hLastFocus = GetFocus();
  702. if ( !IsChild( hwnd, pew->hLastFocus ) )
  703. pew->hLastFocus = NULL;
  704. }
  705. }
  706. break;
  707. }
  708. if ( FALSE != IsDirectMouseWheelMessage( uMsg ) )
  709. {
  710. if ( ( WS_CHILD & GetWindowStyle( hwnd ) ) == 0 )
  711. return TRUE;
  712. else
  713. {
  714. HWND hParent;
  715. hParent = GetAncestor( hwnd, GA_PARENT );
  716. if ( hParent != NULL )
  717. return SendMessageW( hwnd, uMsg, wParam, lParam );
  718. return FALSE;
  719. }
  720. }
  721. return DefWindowProcW( hwnd, uMsg, wParam, lParam );
  722. }
  723. HWND embedWindow( embedWindowState *state )
  724. {
  725. HWND hwnd;
  726. if ( !state ) return NULL;
  727. hwnd = CreateWindowExW( WS_EX_NOPARENTNOTIFY /*| WS_EX_CONTROLPARENT | WS_EX_TOOLWINDOW*/,
  728. L"Winamp Gen",
  729. L"",
  730. WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  731. 0, 0, 200, 200,
  732. hMainWindow,
  733. NULL,
  734. hMainInstance,
  735. state );
  736. return hwnd;
  737. }
  738. BOOL SnapToScreen( RECT *outrc )
  739. {
  740. if ( config_keeponscreen & 1 )
  741. {
  742. RECT rc;
  743. int w = outrc->right - outrc->left;
  744. int h = outrc->bottom - outrc->top;
  745. getViewport( &rc, NULL, 0, outrc );
  746. if ( outrc->left < ( rc.left + config_snaplen ) && outrc->left >( rc.left - config_snaplen ) )
  747. {
  748. outrc->left = rc.left;
  749. outrc->right = rc.left + w;
  750. }
  751. if ( outrc->top < ( rc.top + config_snaplen ) && outrc->top >( rc.top - config_snaplen ) )
  752. {
  753. outrc->top = rc.top;
  754. outrc->bottom = rc.top + h;
  755. }
  756. if ( outrc->right > rc.right - config_snaplen && outrc->right < rc.right + config_snaplen )
  757. {
  758. outrc->left = rc.right - w;
  759. outrc->right = rc.right;
  760. }
  761. if ( outrc->bottom > rc.bottom - config_snaplen && outrc->bottom < rc.bottom + config_snaplen )
  762. {
  763. outrc->top = rc.bottom - h;
  764. outrc->bottom = rc.bottom;
  765. return TRUE;
  766. }
  767. }
  768. return FALSE;
  769. }
  770. void SnapWindowToAllWindows( RECT *outrc, HWND hwndNoSnap )
  771. {
  772. RECT rc;
  773. SnapToScreen( outrc );
  774. if ( config_pe_open && hwndNoSnap != hPLWindow )
  775. {
  776. GetWindowRect( hPLWindow, &rc );
  777. SnapWindowToWindow( outrc, rc );
  778. }
  779. if ( config_eq_open && hwndNoSnap != hEQWindow )
  780. {
  781. GetWindowRect( hEQWindow, &rc );
  782. SnapWindowToWindow( outrc, rc );
  783. }
  784. if ( config_mw_open && hwndNoSnap != hMainWindow )
  785. {
  786. GetWindowRect( hMainWindow, &rc );
  787. FixMainWindowRect( &rc );
  788. SnapWindowToWindow( outrc, rc );
  789. }
  790. if ( config_video_open && hwndNoSnap != hVideoWindow )
  791. {
  792. GetWindowRect( hVideoWindow, &rc );
  793. SnapWindowToWindow( outrc, rc );
  794. }
  795. EnterCriticalSection( &embedcs );
  796. embedWindowState *state = embedwndlist;
  797. while ( state )
  798. {
  799. if ( state->me != hwndNoSnap && IsWindowVisible( state->me ) )
  800. SnapWindowToWindow( outrc, state->r );
  801. state = state->link;
  802. }
  803. LeaveCriticalSection( &embedcs );
  804. }
  805. };