diff options
Diffstat (limited to 'Src/Winamp/embwnd.cpp')
-rw-r--r-- | Src/Winamp/embwnd.cpp | 937 |
1 files changed, 937 insertions, 0 deletions
diff --git a/Src/Winamp/embwnd.cpp b/Src/Winamp/embwnd.cpp new file mode 100644 index 00000000..7f74fb0f --- /dev/null +++ b/Src/Winamp/embwnd.cpp @@ -0,0 +1,937 @@ +/** (c) Nullsoft, Inc. C O N F I D E N T I A L + ** Filename: + ** Project: + ** Description: + ** Author: + ** Created: + **/ + +#include <windowsx.h> + +#include "main.h" +#include "api.h" + +void draw_paint_emb( HWND, int, int, int ); +void draw_embed_tbar( HWND, int, int ); +void draw_embed_tbutton( HWND, int, int ); +void draw_embed( HDC, int, int ); + +// all of this stuff is barely working. I will be fixing it soon soon. + +/// embed ui shit +#define inreg(x,y,x2,y2) \ + ((mouse_x <= ( x2 ) && mouse_x >= ( x ) && \ + mouse_y <= ( y2 ) && mouse_y >= ( y ))) + +enum +{ + NO_CAP, TITLE_CAP, TB_CAP, SZ_CAP +}; + +static void do_titlebar( HWND hwnd, embedWindowState *state ); +static void do_titlebuttons( HWND hwnd, embedWindowState *state ); +static void do_size( HWND hwnd, embedWindowState *state ); + +static int mouse_x, mouse_y, mouse_type, mouse_stats; +static int which_cap = 0; +static HWND capwnd; + +void embedui_handlemouseevent( HWND hwnd, int x, int y, int type, int stats, embedWindowState *state ) +{ + if ( which_cap != NO_CAP && hwnd != capwnd ) return; + + mouse_x = x; + mouse_y = y; + mouse_type = type; + mouse_stats = stats; + switch ( which_cap ) + { + case TITLE_CAP: do_titlebar( hwnd, state ); return; + case TB_CAP: do_titlebuttons( hwnd, state ); return; + case SZ_CAP: do_size( hwnd, state ); return; + default: break; + } + do_titlebuttons( hwnd, state ); + do_size( hwnd, state ); + do_titlebar( hwnd, state ); + + if ( which_cap != NO_CAP ) capwnd = hwnd; // not sure if this is gonna work +} + +static void do_titlebar( HWND hwnd, embedWindowState *state ) +{ + if ( which_cap == TITLE_CAP || ( !which_cap && ( config_easymove || mouse_y < 14 ) ) ) + { + static int clickx, clicky; + switch ( mouse_type ) + { + case 1: + { + which_cap = TITLE_CAP; + clickx = mouse_x; + clicky = mouse_y; + } + break; + case -1: + which_cap = 0; + break; + case 0: + if ( which_cap == TITLE_CAP && mouse_stats & MK_LBUTTON ) + { + // TODO need to convert this into an API method so + // we can call it externally e.g. enhancer... + // or something like it to allow state->r to + // be updated once the move has been finished + POINT p = { mouse_x, mouse_y }; + ClientToScreen( hwnd, &p ); + int w = state->r.right - state->r.left; + int h = state->r.bottom - state->r.top; + + state->r.left = p.x - clickx; + state->r.top = p.y - clicky; + state->r.right = state->r.left + w; + state->r.bottom = state->r.top + h; + + if ( !!config_snap + !!( mouse_stats & MK_SHIFT ) == 1 ) + { + SnapWindowToAllWindows( &state->r, hwnd ); + } + POINT pt = { state->r.left, state->r.top }; + SendMessageW( hwnd, WM_USER + 0x100, 1, (LPARAM) &pt ); + SetWindowPos( hwnd, 0, state->r.left, state->r.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + } + break; + } + } +} + +static void do_titlebuttons( HWND hwnd, embedWindowState *state ) +{ + int w = 0; + w = inreg( state->r.right - state->r.left - 10, 3, state->r.right - state->r.left - 1, 3 + 9 ) ? 1 : 0; + + if ( w ) // kill button + { + if ( mouse_type == -1 && which_cap == TB_CAP ) + { + which_cap = 0; + draw_embed_tbutton( hwnd, 0, ( state->r.right - state->r.left ) ); + SendMessageW( hwnd, WM_USER + 101, 0, 0 ); + } + else if ( mouse_stats & MK_LBUTTON ) + { + which_cap = TB_CAP; + draw_embed_tbutton( hwnd, w ? 1 : 0, ( state->r.right - state->r.left ) ); + } + } + else if ( which_cap == TB_CAP ) + { + which_cap = 0; + draw_embed_tbutton( hwnd, 0, ( state->r.right - state->r.left ) ); + } +} + +typedef struct _WNDREPAINT +{ + HWND hwndSender; + RECT rwR; + RECT rwB; +} WNDREPAINT; + +static BOOL CALLBACK EnumWndRepaintProc( HWND hwnd, LPARAM param ) +{ + WNDREPAINT *pwp = (WNDREPAINT *) param; + if ( hwnd != pwp->hwndSender && IsWindowVisible( hwnd ) ) + { + RECT rw; + GetWindowRect( hwnd, &rw ); + if ( ( rw.left < pwp->rwR.right && rw.right > pwp->rwR.left && rw.top < pwp->rwR.bottom && rw.bottom > pwp->rwR.top ) || + ( rw.top < pwp->rwB.bottom && rw.bottom > pwp->rwB.top && rw.left < pwp->rwB.right && rw.right > pwp->rwB.left ) ) + { + UpdateWindow( hwnd ); + } + + } + return TRUE; +} +static void do_size( HWND hwnd, embedWindowState *state ) +{ + if ( state->flags & EMBED_FLAGS_NORESIZE ) + { + if ( which_cap == SZ_CAP ) which_cap = 0; + return; + } + if ( which_cap == SZ_CAP || ( !which_cap && + mouse_x > ( state->r.right - state->r.left ) - 20 && mouse_y > ( state->r.bottom - state->r.top ) - 20 && + ( ( ( state->r.right - state->r.left ) - mouse_x + ( state->r.bottom - state->r.top ) - mouse_y ) <= 30 ) ) ) + { + static int dx, dy; + if ( !which_cap && mouse_type == 1 ) + { + dx = ( state->r.right - state->r.left ) - mouse_x; + dy = ( state->r.bottom - state->r.top ) - mouse_y; + which_cap = SZ_CAP; + } + if ( which_cap == SZ_CAP ) + { + if ( mouse_type == -1 ) which_cap = 0; + + int x = mouse_x + dx; + int y = mouse_y + dy; + // if (x >= GetSystemMetrics(SM_CXSCREEN)) x = GetSystemMetrics(SM_CXSCREEN)-24; + // if (y >= GetSystemMetrics(SM_CYSCREEN)) y = GetSystemMetrics(SM_CYSCREEN)-28; + if ( !config_embedwnd_freesize ) + { + x += 24; + x -= x % 25; + y += 28; + y -= y % 29; + } + + if ( x < 275 ) x = 275; + if ( y < 20 + 38 + 29 + 29 ) y = 20 + 38 + 29 + 29; + + if ( x != ( state->r.right - state->r.left ) || y != ( state->r.bottom - state->r.top ) ) + { + // TODO need to ensure this isn't used when freesize is disabled + // isn't keeping track of the positions correctly on change + // as some windows only part snap e.g. ml won't dock to edges or to bottom of main window + RECT rw = { 0 }, r = { 0 }; + POINT pt = { x, y }; + SendMessageW( hwnd, WM_USER + 0x101, 1, (LPARAM) &pt ); + + GetWindowRect( hwnd, &rw ); + + // trying to get classic skins to dock to other windows on resizing + /*rw.left = state->r.left; + rw.top = state->r.top; + rw.right = state->r.left + x; + rw.bottom = state->r.top + y; + CopyRect(&r, &rw); + //if (!!config_snap + !!(mouse_stats & MK_SHIFT) == 1) + { + SnapWindowToAllWindows(&rw, hwnd); + } + + x += (rw.right - r.right); + y += (rw.bottom - r.bottom); + SetWindowPos(hwnd, 0, 0, 0, x, y, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);*/ + + SetWindowPos( hwnd, 0, 0, 0, x, y, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + if ( x < ( rw.right - rw.left ) || y < ( rw.bottom - rw.top ) ) + { + WNDREPAINT wrp; + wrp.hwndSender = hwnd; + SetRect( &wrp.rwR, min( rw.left + x, rw.right ), rw.top, rw.right, rw.bottom ); + SetRect( &wrp.rwB, rw.left, min( rw.top + y, rw.bottom ), rw.right, rw.bottom ); + EnumThreadWindows( GetCurrentThreadId(), EnumWndRepaintProc, (LPARAM) &wrp ); + } + } + } + } +} + +//// embed window shut + +static int emb_OnLButtonUp( HWND hwnd, int x, int y, UINT flags ); +static int emb_OnRButtonUp( HWND hwnd, int x, int y, UINT flags ); +static int emb_OnLButtonDown( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags ); +static int emb_OnMouseMove( HWND hwnd, int x, int y, UINT keyFlags ); +static int emb_OnLButtonDblClk( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags ); +static BOOL emb_OnNCActivate( HWND hwnd, BOOL fActive, HWND hwndActDeact, BOOL fMinimized ); + +static int emb_OnRButtonUp( HWND hwnd, int x, int y, UINT flags ) +{ + //display winamp's main popup menu + POINT p; + GetCursorPos( &p ); + int ret = DoTrackPopup( main_menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, p.x, p.y, hwnd ); + if ( ret ) SendMessageW( hMainWindow, WM_COMMAND, ret, 0 ); + return 1; +} + +static int emb_OnLButtonUp( HWND hwnd, int x, int y, UINT flags ) +{ + ReleaseCapture(); + embedui_handlemouseevent( hwnd, x, y, -1, flags, (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ) ); + return 1; +} + +static int emb_OnLButtonDown( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags ) +{ + SetCapture( hwnd ); + embedui_handlemouseevent( hwnd, x, y, 1, keyFlags, (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ) ); + return 1; +} + +static int emb_OnMouseMove( HWND hwnd, int x, int y, UINT keyFlags ) +{ + embedui_handlemouseevent( hwnd, x, y, 0, keyFlags, (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ) ); + return 1; +} + +static BOOL emb_OnNCActivate( HWND hwnd, BOOL fActive, HWND hwndActDeact, BOOL fMinimized ) +{ + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + if ( fActive == FALSE ) + { + draw_embed_tbar( hwnd, config_hilite ? 0 : 1, ( state->r.right - state->r.left ) ); + which_cap = NO_CAP; + capwnd = 0; + } + else + { + draw_embed_tbar( hwnd, 1, ( state->r.right - state->r.left ) ); + } + return TRUE; +} + +static int emb_OnLButtonDblClk( HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags ) +{ + return 1; +} + +CRITICAL_SECTION embedcs; +embedWindowState *embedwndlist; // linked list +int embedwndlist_cnt; + +static void EmbedWindow_OnShowWindow( HWND hwnd, BOOL fShow, UINT status ) +{ + if ( 0 != status ) + { + SetPropW( hwnd, L"EmbedWnd_ShowStatus", (HANDLE) status ); + DefWindowProcW( hwnd, WM_SHOWWINDOW, (WPARAM) fShow, (LPARAM) status ); + RemovePropW( hwnd, L"EmbedWnd_ShowStatus" ); + return; + } + + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + + HWND hChild = FindWindowExW( hwnd, NULL, NULL, NULL ); + + INT toggleResult = 1; + + if ( state && FALSE == state->reparenting ) + { + INT result = Ipc_WindowToggle( (INT_PTR) hwnd, ( FALSE != fShow ) ? 1 : 0 ); + if ( fShow ) toggleResult = result; + } + + if ( NULL != hChild && 0 != toggleResult ) + { + if ( FALSE != fShow && NULL != state ) + { + SetWindowPos( hChild, NULL, 11, 20, + ( state->r.right - state->r.left ) - 11 - 8, + ( state->r.bottom - state->r.top ) - 20 - 14, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOOWNERZORDER ); + } + + EMBEDSHOW embedShow; + embedShow.hdr.code = EWN_SHOWWINDOW; + embedShow.hdr.hwndFrom = hwnd; + embedShow.hdr.idFrom = GetDlgCtrlID( hwnd ); + embedShow.fShow = fShow; + embedShow.nStatus = (UINT) (UINT_PTR) GetPropW( hwnd, L"EmbedWnd_ShowStatus" ); + + SendMessageW( hChild, WM_NOTIFY, (WPARAM) embedShow.hdr.idFrom, (LPARAM) &embedShow ); + } +} + +typedef struct __EMBEDWNDPART +{ + INT id; + RECT rect; +}EMBEDWNDPART; + + +static INT EmbedWindow_HitTest( HWND hwnd, POINT pt ) +{ + DWORD windowStyle = GetWindowLongPtrW( hwnd, GWL_STYLE ); + if ( 0 != ( WS_DISABLED & windowStyle ) ) + return HTERROR; + + MapWindowPoints( HWND_DESKTOP, hwnd, &pt, 1 ); + + RECT clientRect; + if ( !GetClientRect( hwnd, &clientRect ) ) + return HTERROR; + + if ( 0 != ( WS_CHILD & windowStyle ) ) + { + return ( PtInRect( &clientRect, pt ) ) ? HTCLIENT : HTNOWHERE; + } + + static EMBEDWNDPART embedWindowParts[] = + { + { HTCLOSE, {-( 275 - 264 ), 3,-( 275 - 272 ), 12}}, + { HTCAPTION, {0, 0, -1, 13}}, + { HTBOTTOMRIGHT, {-20,-20,-1,-1}}, + }; + + INT hitTest = HTCLIENT; + + RECT part; + for ( INT i = 0; i < ARRAYSIZE( embedWindowParts ); i++ ) + { + CopyRect( &part, &embedWindowParts[ i ].rect ); + if ( part.left < 0 ) part.left += clientRect.right; + if ( part.right < 0 ) part.right += clientRect.right; + if ( part.top < 0 ) part.top += clientRect.bottom; + if ( part.bottom < 0 ) part.bottom += clientRect.bottom; + + if ( PtInRect( &part, pt ) ) + { + hitTest = embedWindowParts[ i ].id; + break; + } + } + + if ( HTBOTTOMRIGHT == hitTest ) + { + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + if ( 0 != ( EMBED_FLAGS_NORESIZE & state->flags ) ) + hitTest = HTBORDER; + } + + return hitTest; +} + +static LRESULT EmbedWindow_OnSetCursor( HWND hwnd, HWND hwndCursor, INT hitTest, UINT uMsg ) +{ + HCURSOR hCursor = NULL; + + switch ( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_XBUTTONDOWN: + DisabledWindow_OnMouseClick( hwnd ); + break; + } + + if ( config_usecursors && !disable_skin_cursors ) + { + int index = 15 + 5; // PNormal.cur + POINT pt; + GetCursorPos( &pt ); + hitTest = EmbedWindow_HitTest( hwnd, pt ); + switch ( hitTest ) + { + case HTCAPTION: + index = 15 + 2; // PTBar.cur + break; + case HTCLOSE: + index = 15 + 1; // PClose.cur + break; + case HTLEFT: + case HTRIGHT: + case HTTOP: + case HTTOPLEFT: + case HTTOPRIGHT: + case HTBOTTOM: + case HTBOTTOMLEFT: + case HTBOTTOMRIGHT: + index = 15 + 4;// PSize.cur + break; + } + + hCursor = Skin_Cursors[ index ]; + } + + if ( NULL != hCursor ) + { + SetCursor( hCursor ); + return TRUE; + } + + return DefWindowProcW( hwnd, WM_SETCURSOR, (WPARAM) hwndCursor, MAKELPARAM( hitTest, uMsg ) ); +} + +extern "C" +{ + LRESULT CALLBACK emb_WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) + { + switch ( uMsg ) + { + case WM_INITMENUPOPUP: + return SendMessageW( hMainWindow, uMsg, wParam, lParam ); // for popup menus + HANDLE_MSG( hwnd, WM_QUERYNEWPALETTE, Main_OnQueryNewPalette ); + HANDLE_MSG( hwnd, WM_PALETTECHANGED, Main_OnPaletteChanged ); + HANDLE_MSG( hwnd, WM_LBUTTONUP, emb_OnLButtonUp ); + HANDLE_MSG( hwnd, WM_RBUTTONUP, emb_OnRButtonUp ); + HANDLE_MSG( hwnd, WM_LBUTTONDOWN, emb_OnLButtonDown ); + HANDLE_MSG( hwnd, WM_MOUSEMOVE, emb_OnMouseMove ); + HANDLE_MSG( hwnd, WM_NCACTIVATE, emb_OnNCActivate ); + HANDLE_MSG( hwnd, WM_LBUTTONDBLCLK, emb_OnLButtonDblClk ); + case WM_SYSCOMMAND: + if ( ( wParam & 0xfff0 ) == SC_SCREENSAVE || ( wParam & 0xfff0 ) == SC_MONITORPOWER ) + return SendMessageW( hMainWindow, uMsg, wParam, lParam ); + case WM_COMMAND: + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + { + if ( ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) && wParam == VK_F4 ) + { + if ( uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN ) + SendMessageW( hwnd, WM_USER + 101, 0, 0 ); + } + else + { + // HWND hh=FindWindowExW(hwnd,NULL,NULL,NULL); + // if (hh) PostMessageW(hh,uMsg,wParam,lParam); + // else PostMessageW(hMainWindow,uMsg,wParam,lParam); + } + } + break; + case WM_USER + 101: + { + HWND hh = FindWindowExW( hwnd, NULL, NULL, NULL ); + if ( hh ) PostMessageW( hh, WM_CLOSE, 0, 0 ); + } + return 0; + case WM_USER + 102: + { + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + if ( !state || !state->reparenting ) + ShowWindow( hwnd, SW_SHOWNA ); + } + break; + case WM_USER + 103: + SetFocus( hwnd ); + break; + case WM_SHOWWINDOW: + EmbedWindow_OnShowWindow( hwnd, (BOOL) wParam, (UINT) lParam ); + + RefreshIconicThumbnail(); + return 0; + + case WM_DISPLAYCHANGE: + { + HWND hh = FindWindowExW( hwnd, NULL, NULL, NULL ); + if ( hh ) + SendMessageW( hh, uMsg, wParam, lParam ); + } + + InvalidateRect( hwnd, NULL, TRUE ); + return 0; + case WM_CLOSE: + SendMessageW( GetParent( hwnd ), WM_CLOSE, 0, 0 ); + return 0; + + case WM_PAINT: + { + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + if ( state ) draw_paint_emb( hwnd, ( state->r.right - state->r.left ), ( state->r.bottom - state->r.top ), state->flags ); + } + return 0; + + case WM_WINDOWPOSCHANGING: + { + /* + if extra_data[EMBED_STATE_EXTRA_REPARENTING] is set, we are being reparented by the freeform lib, so we should + just ignore this message because our visibility will not change once the freeform + takeover/restoration is complete + */ + + WINDOWPOS *windowPos = (WINDOWPOS *) lParam; + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + if ( state && state->reparenting ) + { + if ( 0 != ( WS_CHILD & GetWindowLongPtrW( windowPos->hwnd, GWL_STYLE ) ) ) + windowPos->flags |= ( SWP_NOREDRAW ); + break; + + } + } + break; + + case WM_WINDOWPOSCHANGED: + { + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + if ( state && 0 == ( SWP_NOSIZE & ( (WINDOWPOS *) lParam )->flags ) ) + { + + HWND hh; + HRGN rgnChild; + INT cx, cy, ox;//, oy; + RECT rv; + + ox = state->r.right - state->r.left; + //oy = state->r.bottom - state->r.top; + cx = ( (WINDOWPOS *) lParam )->cx; + cy = ( (WINDOWPOS *) lParam )->cy; + + state->r.right = state->r.left + cx; + state->r.bottom = state->r.top + cy; + + hh = FindWindowExW( hwnd, NULL, NULL, NULL ); + + if ( 0 == ( SWP_NOREDRAW & ( (WINDOWPOS *) lParam )->flags ) ) + InvalidateRect( hwnd, NULL, FALSE ); + + if ( hh ) + { + INT cx, cy; + cx = ( state->r.right - state->r.left ) - 11 - 8; + cy = ( state->r.bottom - state->r.top ) - 20 - 14; + + SetRect( &rv, 11, 20, 11 + cx, 20 + cy ); + ValidateRect( hwnd, &rv ); + + rgnChild = CreateRectRgn( 0, 0, cx, cy ); + + if ( IsWindowVisible( hh ) ) + SendMessageW( hh, WM_USER + 0x201, MAKEWPARAM( 0, 0 ), (LPARAM) rgnChild ); + + SetWindowPos( hh, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOCOPYBITS ); + + if ( IsWindowVisible( hh ) ) + SendMessageW( hh, WM_USER + 0x201, 0, (LPARAM) NULL ); + + } + else rgnChild = NULL; + + if ( ox == cx ) + { + SetRect( &rv, 0, 0, cx, 14 ); + ValidateRect( hwnd, &rv ); + } + + if ( 0 == ( SWP_NOREDRAW & ( (WINDOWPOS *) lParam )->flags ) ) + { + HRGN rgnWnd; + rgnWnd = CreateRectRgn( 0, 0, 0, 0 ); + + if ( GetUpdateRect( hwnd, NULL, FALSE ) ) + GetUpdateRgn( hwnd, rgnWnd, FALSE ); + + if ( rgnChild ) + { + OffsetRgn( rgnChild, 11, 20 ); + CombineRgn( rgnWnd, rgnWnd, rgnChild, RGN_OR ); + } + + RedrawWindow( hwnd, NULL, rgnWnd, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN ); + if ( rgnWnd ) + DeleteObject( rgnWnd ); + } + + if ( rgnChild ) + DeleteObject( rgnChild ); + } + } + return 0; + + case WM_CREATE: + { + EMBEDWND *pew = (EMBEDWND *) calloc( 1, sizeof( EMBEDWND ) ); + SetPropW( hwnd, EMBEDWND_PROPW, pew ); + + SetWindowLongPtrW( hwnd, GWLP_USERDATA, (LONG_PTR) ( (LPCREATESTRUCT) lParam )->lpCreateParams ); + embedWindowState *state = (embedWindowState *) ( (LPCREATESTRUCT) lParam )->lpCreateParams; + + state->me = hwnd; + + int w = ( state->r.right - state->r.left ); + int h = ( state->r.bottom - state->r.top ); + if ( !config_embedwnd_freesize ) + { + w -= w % 25; + h -= h % 29; + } + if ( w < 275 ) w = 275; + if ( h < 116 ) h = 116; + state->r.right = state->r.left + w; + state->r.bottom = state->r.top + h; + + EnterCriticalSection( &embedcs ); + GUID temp = GUID_NULL; + if ( state->flags & EMBED_FLAGS_GUID ) + temp = state->guid; + + memset( state->extra_data, 0, sizeof( state->extra_data ) ); + if ( state->flags & EMBED_FLAGS_GUID ) + state->guid = temp; + + state->link = embedwndlist; + embedwndlist = state; + embedwndlist_cnt++; + LeaveCriticalSection( &embedcs ); + + SetWindowLong( hwnd, GWL_STYLE, GetWindowLongW( hwnd, GWL_STYLE ) & ~( WS_CAPTION ) ); + 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 ); + } + return 0; + case WM_DESTROY: + { + embedWindowState *state = (embedWindowState *) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + if ( state ) + { + EnterCriticalSection( &embedcs ); + embedWindowState *p = embedwndlist; + if ( p == state ) + { + embedwndlist = state->link;// remove ourselves + embedwndlist_cnt--; + } + else + { + while ( p ) + { + if ( p->link == state ) + { + p->link = state->link; + embedwndlist_cnt--; + break; + } + p = p->link; + } + } + LeaveCriticalSection( &embedcs ); + } + HWND hh = FindWindowExW( hwnd, NULL, NULL, NULL ); + if ( hh ) DestroyWindow( hh ); + EMBEDWND *pew = GetEmbedWnd( hwnd ); + if ( pew ) + { + RemovePropW( hwnd, EMBEDWND_PROPW ); + free( pew ); + } + } + return 0; + case WM_SETCURSOR: + return EmbedWindow_OnSetCursor( hwnd, (HWND) wParam, LOWORD( lParam ), HIWORD( lParam ) ); + + case WM_GETMINMAXINFO: + { + MINMAXINFO *p = (MINMAXINFO *) lParam; + if ( NULL != p ) + { + p->ptMaxTrackSize.x = 16384; + p->ptMaxTrackSize.y = 16384; + } + } + return 0; + + case WM_MOUSEACTIVATE: + if ( NULL != WASABI_API_APP ) + WASABI_API_APP->ActiveDialog_Register( hwnd ); + break; + + case WM_CHILDACTIVATE: + if ( NULL != WASABI_API_APP ) + WASABI_API_APP->ActiveDialog_Register( hwnd ); + break; + + case WM_ACTIVATE: + if ( WA_INACTIVE == LOWORD( wParam ) ) + { + EMBEDWND *pew = GetEmbedWnd( hwnd ); + if ( pew ) + { + pew->hLastFocus = GetFocus(); + if ( !IsChild( hwnd, pew->hLastFocus ) ) + pew->hLastFocus = NULL; + } + + if ( NULL != WASABI_API_APP ) + WASABI_API_APP->ActiveDialog_Unregister( hwnd ); + } + else + { + if ( WA_CLICKACTIVE == LOWORD( wParam ) ) + { + EMBEDWND *pew = GetEmbedWnd( hwnd ); + if ( pew ) + { + POINT pt; + DWORD pts = GetMessagePos(); + POINTSTOPOINT( pt, pts ); + MapWindowPoints( HWND_DESKTOP, hwnd, &pt, 1 ); + + HWND hTarget = ChildWindowFromPointEx( hwnd, pt, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED | CWP_SKIPTRANSPARENT ); + if ( hTarget && hTarget != hwnd ) + pew->hLastFocus = hTarget; + } + } + + if ( NULL != WASABI_API_APP ) + WASABI_API_APP->ActiveDialog_Register( hwnd ); + + } + break; + case WM_SETFOCUS: + { + HWND hChild, hTab; + EMBEDWND *pew; + + hChild = FindWindowExW( hwnd, NULL, NULL, NULL ); + pew = GetEmbedWnd( hwnd ); + hTab = NULL; + if ( pew ) + { + while ( pew->hLastFocus && IsChild( hwnd, pew->hLastFocus ) ) + { + if ( IsWindowEnabled( pew->hLastFocus ) && IsWindowVisible( pew->hLastFocus ) && 0 != ( WS_TABSTOP & GetWindowLongPtrW( pew->hLastFocus, GWL_STYLE ) ) ) + { + hTab = pew->hLastFocus; + break; + } + + pew->hLastFocus = GetParent( pew->hLastFocus ); + } + } + + if ( !hTab ) + hTab = ( hChild ) ? GetNextDlgTabItem( hwnd, hChild, FALSE ) : hwnd; + + if ( hTab && hTab != hwnd ) + { + WCHAR szName[ 128 ] = { 0 }; + DWORD lcid = MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ), SORT_DEFAULT ); + if ( GetClassNameW( hChild, szName, sizeof( szName ) / sizeof( WCHAR ) ) && CSTR_EQUAL == CompareStringW( lcid, NORM_IGNORECASE, szName, -1, L"#32770", -1 ) ) + SendMessageW( hChild, WM_NEXTDLGCTL, (WPARAM) hTab, TRUE ); + else + SetFocus( hTab ); + + //return 0; + } + + } + break; + case WM_KILLFOCUS: + { + EMBEDWND *pew = GetEmbedWnd( hwnd ); + if ( pew ) + { + pew->hLastFocus = GetFocus(); + if ( !IsChild( hwnd, pew->hLastFocus ) ) + pew->hLastFocus = NULL; + } + } + break; + } + + if ( FALSE != IsDirectMouseWheelMessage( uMsg ) ) + { + if ( ( WS_CHILD & GetWindowStyle( hwnd ) ) == 0 ) + return TRUE; + else + { + HWND hParent; + hParent = GetAncestor( hwnd, GA_PARENT ); + if ( hParent != NULL ) + return SendMessageW( hwnd, uMsg, wParam, lParam ); + + return FALSE; + } + } + + return DefWindowProcW( hwnd, uMsg, wParam, lParam ); + } + + HWND embedWindow( embedWindowState *state ) + { + HWND hwnd; + if ( !state ) return NULL; + + hwnd = CreateWindowExW( WS_EX_NOPARENTNOTIFY /*| WS_EX_CONTROLPARENT | WS_EX_TOOLWINDOW*/, + L"Winamp Gen", + L"", + WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + 0, 0, 200, 200, + hMainWindow, + NULL, + hMainInstance, + state ); + return hwnd; + } + + BOOL SnapToScreen( RECT *outrc ) + { + if ( config_keeponscreen & 1 ) + { + RECT rc; + int w = outrc->right - outrc->left; + int h = outrc->bottom - outrc->top; + + getViewport( &rc, NULL, 0, outrc ); + + if ( outrc->left < ( rc.left + config_snaplen ) && outrc->left >( rc.left - config_snaplen ) ) + { + outrc->left = rc.left; + outrc->right = rc.left + w; + } + + if ( outrc->top < ( rc.top + config_snaplen ) && outrc->top >( rc.top - config_snaplen ) ) + { + outrc->top = rc.top; + outrc->bottom = rc.top + h; + } + + if ( outrc->right > rc.right - config_snaplen && outrc->right < rc.right + config_snaplen ) + { + outrc->left = rc.right - w; + outrc->right = rc.right; + } + + if ( outrc->bottom > rc.bottom - config_snaplen && outrc->bottom < rc.bottom + config_snaplen ) + { + outrc->top = rc.bottom - h; + outrc->bottom = rc.bottom; + + return TRUE; + } + } + + return FALSE; + } + + void SnapWindowToAllWindows( RECT *outrc, HWND hwndNoSnap ) + { + RECT rc; + SnapToScreen( outrc ); + + if ( config_pe_open && hwndNoSnap != hPLWindow ) + { + GetWindowRect( hPLWindow, &rc ); + SnapWindowToWindow( outrc, rc ); + } + + if ( config_eq_open && hwndNoSnap != hEQWindow ) + { + GetWindowRect( hEQWindow, &rc ); + SnapWindowToWindow( outrc, rc ); + } + + if ( config_mw_open && hwndNoSnap != hMainWindow ) + { + GetWindowRect( hMainWindow, &rc ); + FixMainWindowRect( &rc ); + SnapWindowToWindow( outrc, rc ); + } + + if ( config_video_open && hwndNoSnap != hVideoWindow ) + { + GetWindowRect( hVideoWindow, &rc ); + SnapWindowToWindow( outrc, rc ); + } + + EnterCriticalSection( &embedcs ); + embedWindowState *state = embedwndlist; + while ( state ) + { + if ( state->me != hwndNoSnap && IsWindowVisible( state->me ) ) + SnapWindowToWindow( outrc, state->r ); + + state = state->link; + } + + LeaveCriticalSection( &embedcs ); + } +};
\ No newline at end of file |