#include #include "main.h" #include "./api.h" #include "./wa_dlg.h" #include "./skinWindow.h" #include "./skinWindowIPC.h" #include "./wintheme.h" #include "./draw.h" #ifndef ARRAYSIZE #define ARRAYSIZE(blah) (sizeof(blah)/sizeof(*blah)) #endif #ifndef OCR_NORMAL #define OCR_NORMAL 32512 #endif #ifndef LONGX86 #ifdef _WIN64 #define LONGX86 LONG_PTR #else /*_WIN64*/ #define LONGX86 LONG #endif /*_WIN64*/ #endif // LONGX86 #ifdef __cplusplus #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam)) #else #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam)) #endif // __cplusplus #define SENDWAIPC(__ipcMsgId, __param) SENDMSG(hMainWindow, WM_WA_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId)) #ifndef WM_NCUAHDRAWCAPTION #define WM_NCUAHDRAWCAPTION 0x00AE #define WM_NCUAHDRAWFRAME 0x00AF #endif //WM_NCUAHDRAWCAPTION // additional WM_SYSCOMMAND commands #define SC_DRAGMOVE 0xF012 #define SC_DRAGSIZE_N 0xF003 #define SC_DRAGSIZE_S 0xF006 #define SC_DRAGSIZE_E 0xF002 #define SC_DRAGSIZE_W 0xF001 #define SC_DRAGSIZE_NW 0xF004 #define SC_DRAGSIZE_NE 0xF005 #define SC_DRAGSIZE_SW 0xF007 #define SC_DRAGSIZE_SE 0xF008 #define MSGRESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWL_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; } #define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) #define RESIZESTEP_CX 25 #define RESIZESTEP_CY 29 static ATOM SKINNEDWND_ATOM = 0; // this flags for iternal use #define SWS_EX_MASK 0xFFFF0000 #define SWS_EX_ATTACHED 0x00010000 // window attached #define SWS_EX_UNICODE 0x00020000 // winodow is unicode #define SWS_EX_THEMED 0x00040000 // was themed before #define SWS_EX_DIALOG 0x00100000 // treat this as dialog #define BORDERWIDTH_LEFT 11 #define BORDERWIDTH_TOP 20 #define BORDERWIDTH_RIGHT 8 #define BORDERWIDTH_BOTTOM 14 #define CHILDBORDER_LEFT 1 #define CHILDBORDER_TOP 1 #define CHILDBORDER_RIGHT 1 #define CHILDBORDER_BOTTOM 1 #define CLOSEBUTTON_HEIGHT 9 #define CLOSEBUTTON_WIDTH 9 #define CLOSEBUTTON_OFFSET_X -11 #define CLOSEBUTTON_OFFSET_Y 3 #define SIZERGRIP_WIDTH 20 #define SIZERGRIP_HEIGHT 20 #define MOVEABLEAREA_HEIGHT 13 #define BUTTON_NORMAL 0 #define BUTTON_PUSHED 1 #define BUTTON_DISABLED (-1) #ifndef TME_NONCLIENT #define TME_NONCLIENT 0x00000010 #define WM_NCMOUSELEAVE 0x02A2 #endif #define WAMSG_CLOSE (WM_USER + 101) typedef struct __SKINNEDWND { HWND hwnd; WNDPROC fnWndProc; DWORD flags; POINT movingOffset; INT buttonState; embedWindowState embedData; } SKINNEDWND; #define GetSkinnedWnd(__hwnd) ((SKINNEDWND*)GetPropW((__hwnd), ((LPCWSTR)MAKEINTATOM(SKINNEDWND_ATOM)))) #define IsDialog(__skinnedWindow) (0 != (SWS_EX_DIALOG & (__skinnedWindow)->flags)) #define IsUnicode(__skinnedWindow) (0 != (SWS_EX_UNICODE & (__skinnedWindow)->flags)) #define SetWndLongPtr(__skinnedWnd, __index, __data)\ ((LONG_PTR)(IsUnicode(__skinnedWnd) ? SetWindowLongPtrW((__skinnedWnd)->hwnd, (__index), ((LONGX86)(LONG_PTR)(__data))) :\ SetWindowLongPtrA((__skinnedWnd)->hwnd, (__index), ((LONGX86)(LONG_PTR)(__data))))) #define CallWndProc(__skinnedWnd, __uMsg, __wParam, __lParam)\ (IsUnicode(__skinnedWnd) ?\ CallWindowProcW((__skinnedWnd)->fnWndProc, (__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam)) :\ CallWindowProcA((__skinnedWnd)->fnWndProc, (__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam))) #define DefWndProc(__skinnedWnd, __uMsg, __wParam, __lParam)\ (IsUnicode(__skinnedWnd) ?\ DefWindowProcW((__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam)) :\ DefWindowProcA((__skinnedWnd)->hwnd, (__uMsg), (__wParam), (__lParam))) void draw_embed_tbar(HWND hwnd, int state, int w); void SnapWindowToAllWindows(RECT *outrc, HWND hwndNoSnap); static LRESULT CALLBACK SkinnedWnd_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static void SkinnedWindow_Delete(SKINNEDWND *pWnd) { HWND hDetached = NULL; if (NULL == pWnd) return; hDetached = pWnd->hwnd; SetWndLongPtr(pWnd, GWLP_USERDATA, NULL); RemovePropW(pWnd->hwnd, ((LPCWSTR)MAKEINTATOM(SKINNEDWND_ATOM))); if (NULL != pWnd->embedData.me) { EnterCriticalSection(&embedcs); embedWindowState *p = embedwndlist; if (p == &pWnd->embedData) { embedwndlist=pWnd->embedData.link; // remove ourselves embedwndlist_cnt--; } else { while (p) { if (p->link == &pWnd->embedData) { p->link=pWnd->embedData.link; embedwndlist_cnt--; break; } p=p->link; } } LeaveCriticalSection(&embedcs); } if (NULL != pWnd->fnWndProc) { SetWndLongPtr(pWnd, GWLP_WNDPROC, pWnd->fnWndProc); pWnd->fnWndProc = NULL; } free(pWnd); if (NULL != hDetached) { SetWindowPos(hDetached, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } } static SKINNEDWND *SkinnedWindow_Cerate(HWND hwndToSkin) { if (NULL == hwndToSkin || !IsWindow(hwndToSkin)) return NULL; if (NULL != GetSkinnedWnd(hwndToSkin)) return NULL; if (0 == SKINNEDWND_ATOM) { SKINNEDWND_ATOM = GlobalAddAtomW(L"WASKINNEDWND"); if (0 == SKINNEDWND_ATOM) return NULL; } SKINNEDWND *pWnd = (SKINNEDWND*)calloc(1, sizeof(SKINNEDWND)); if (NULL == pWnd) return NULL; pWnd->hwnd = hwndToSkin; if (IsWindowUnicode(hwndToSkin)) pWnd->flags |= SWS_EX_UNICODE; WCHAR szName[128] = {0}; if (GetClassNameW(hwndToSkin, szName, ARRAYSIZE(szName))) { if (CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, szName, -1, L"#32770", -1)) pWnd->flags |= SWS_EX_DIALOG; } pWnd->fnWndProc = (WNDPROC)SetWndLongPtr(pWnd, GWLP_WNDPROC, SkinnedWnd_WindowProc); if (NULL == pWnd->fnWndProc || !SetPropW(hwndToSkin, ((LPCWSTR)MAKEINTATOM(SKINNEDWND_ATOM)), pWnd)) { SkinnedWindow_Delete(pWnd); return NULL; } pWnd->flags |= SWS_EX_ATTACHED; if (S_OK == Dwm_LoadLibrary()) { DWMNCRENDERINGPOLICY ncrp = DWMNCRP_DISABLED; DWORD allow = FALSE; DwmSetWindowAttribute(pWnd->hwnd, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp)); DwmSetWindowAttribute(pWnd->hwnd, DWMWA_ALLOW_NCPAINT, &allow, sizeof(allow)); } if (S_OK == UxTheme_LoadLibrary() && IsAppThemed()) { SetWindowTheme(pWnd->hwnd, NULL, L""); pWnd->flags |= SWS_EX_THEMED; } if (!config_embedwnd_freesize && 0 == (WS_CHILD & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE))) { RECT rc; if (GetWindowRect(hwndToSkin, &rc)) { LONG w, h; OffsetRect(&rc, -rc.left, -rc.top); w = rc.right + (RESIZESTEP_CX - 1); w -= w % RESIZESTEP_CX; h = rc.bottom + (RESIZESTEP_CY - 1); h -= h % RESIZESTEP_CY; if (w != rc.right || h != rc.bottom) SetWindowPos(hwndToSkin, NULL, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); } } return pWnd; } BOOL SkinWindow(HWND hwndToSkin, REFGUID windowGuid, UINT flagsEx, FFCALLBACK callbackFF) { SKINNEDWND *pWnd = SkinnedWindow_Cerate(hwndToSkin); if (NULL == pWnd) return FALSE; pWnd->embedData.me = pWnd->hwnd; pWnd->embedData.user_ptr = pWnd; pWnd->embedData.flags |= (EMBED_FLAGS_GUID | flagsEx); pWnd->embedData.guid = windowGuid; pWnd->embedData.callback = callbackFF; if (NULL != pWnd->embedData.callback) pWnd->embedData.flags |= EMBED_FLAGS_FFCALLBACK; GetWindowRect(pWnd->hwnd, &pWnd->embedData.r); EnterCriticalSection(&embedcs); pWnd->embedData.link = embedwndlist; embedwndlist = &pWnd->embedData; embedwndlist_cnt++; LeaveCriticalSection(&embedcs); SetWndLongPtr(pWnd, GWLP_USERDATA, &pWnd->embedData); return TRUE; } static int SkinnedWindow_GetTextWidth(LPCTSTR pszText, INT cchText) { int w = 0; while (cchText--) { char c = *pszText++; if (c >= 'a' && c <= 'z') c+='A'-'a'; if (c >= 'A' && c <= 'Z' && titlebar_font_widths[c-'A']) w+=titlebar_font_widths[c-'A']; else if (c >= '0' && c <= '9' && titlebar_font_widths[c-'0'] && Skin_UseGenNums) w+=titlebar_font_num_widths[c-'0']; else if (c == '-' && titlebar_font_widths[10] && Skin_UseGenNums) w+=titlebar_font_num_widths[10]; else if (c == ':' && titlebar_font_widths[11] && Skin_UseGenNums) w+=titlebar_font_num_widths[11]; else w+=titlebar_font_unknown_width; } return w; } static void SkinnedWindow_DrawText(HDC hdc, HDC hdcSrc, int xp, int yp, LPCTSTR pszText, INT cchText, RECT *prc, BOOL bActive) { int w; int srcY = 88 + ((bActive) ? 8 : 0); int srcYnum = 72 + ((bActive) ? 8 : 0); int bgsrcY = ((bActive) ? 21 : 0); int bgX = prc->left; int maxw = prc->right; while (cchText-- && maxw > 0) { char c = *pszText++; if (bgX <= xp) { int bgW = 25; if (bgW + bgX > prc->right) bgW = prc->right - bgX; BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY); bgX += bgW; } if (c >= 'a' && c <= 'z') c+='A'-'a'; if (c >= 'A' && c <= 'Z' && titlebar_font_widths[c-'A']) { w = titlebar_font_widths[c - 'A']; if (w > maxw) break; if (bgX <= (xp + w)) { int bgW = 25; if (bgW + bgX > prc->right) bgW = prc->right - bgX; BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY); bgX += bgW; } BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_offsets[c - 'A'], srcY, SRCCOPY); } else if (c >= '0' && c <= '9' && titlebar_font_num_widths[c - '0'] && Skin_UseGenNums) { w = titlebar_font_num_widths[c - '0']; if (w > maxw) break; if (bgX <= (xp + w)) { int bgW = 25; if (bgW + bgX > prc->right) bgW = prc->right - bgX; BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY); bgX += bgW; } BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_num_offsets[c - '0'], srcYnum, SRCCOPY); } else if (c == '-' && titlebar_font_num_widths[10] && Skin_UseGenNums) { w = titlebar_font_num_widths[10]; if (w > maxw) break; if (bgX <= (xp + w)) { int bgW = 25; if (bgW + bgX > prc->right) bgW = prc->right - bgX; BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY); bgX += bgW; } BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_num_offsets[10], srcYnum, SRCCOPY); } else if (c == ':' && titlebar_font_num_widths[11] && Skin_UseGenNums) { w = titlebar_font_num_widths[11]; if (w > maxw) break; if (bgX <= (xp + w)) { int bgW = 25; if (bgW + bgX > prc->right) bgW = prc->right - bgX; BitBlt(hdc, bgX, prc->top, bgW, (prc->bottom - prc->top), hdcSrc, 52, bgsrcY, SRCCOPY); bgX += bgW; } BitBlt(hdc, xp, yp, w, 7, hdcSrc, titlebar_font_num_offsets[11], srcYnum, SRCCOPY); } else w = titlebar_font_unknown_width; xp += w; maxw -= w; } } static void SkinnedWindow_DrawCloseButton(HDC hdc, HDC hdcSrc, RECT *prcWindow, BOOL bActive, INT buttonState) { INT srcX, srcY; switch(buttonState) { case BUTTON_PUSHED: srcX = 148; srcY = 42; break; case BUTTON_NORMAL: srcX = 144; srcY = 3; if (!bActive) srcY += 21; break; case BUTTON_DISABLED: default: srcX = 144; srcY = 3; break; } BitBlt(hdc, prcWindow->right - 11,prcWindow->top + 3, 9, 9, hdcSrc,srcX, srcY, SRCCOPY); } static void SkinnedWindow_DrawCaptionEx(HDC hdc, HDC hdcSrc, LPCTSTR pszText, INT cchText, int state, int w, int h) { state = state ? 0 : 21; int nt; int xp=0; int textw_exact = 0, textw = 0; int cchTextOrig = cchText; if (cchText > 0) { for(;cchText > 0; cchText--) { textw_exact = SkinnedWindow_GetTextWidth(pszText, cchText); textw = textw_exact + 24; textw -= textw % 25; if ((w - textw) > 100) break; textw = 0; } } BitBlt(hdc,xp,0,25,20, hdcSrc, 0, state,SRCCOPY); xp+=25; nt = (w - 100 - textw)/25; if (nt > 0) { if (nt&1) { BitBlt(hdc,xp,0,12,20,hdcSrc,104,state,SRCCOPY); xp+=12; } nt/=2; while (nt-->0) { BitBlt(hdc,xp,0,25,20,hdcSrc,104,state,SRCCOPY); xp+=25; } } if (cchText > 0) { BitBlt(hdc,xp,0,25,20,hdcSrc,26,state,SRCCOPY); xp+=25; nt = textw/25; if (nt > 0) { RECT rt; SetRect(&rt, xp, 0, xp + textw, 20); SkinnedWindow_DrawText(hdc, hdcSrc, rt.left + ((cchText == cchTextOrig) ? (textw - textw_exact)/2 : 0), 4, pszText, cchText, &rt, state); xp += nt*25; } BitBlt(hdc,xp,0,25,20,hdcSrc,78,state,SRCCOPY); xp+=25; } else { nt = (w - 50)/2; if (nt > 25) nt = 25; if (nt > 0) { BitBlt(hdc,xp, 0, nt,20,hdcSrc,104,state,SRCCOPY); xp+=nt; if (nt < 25 && 0 != (w - 50)%2)nt++; BitBlt(hdc,xp, 0, nt, 20, hdcSrc,104 + (25- nt),state,SRCCOPY); xp+=nt; } } nt = (w - 100 - textw)/25; if (nt > 0) { if (nt&1) { BitBlt(hdc,xp,0,13,20,hdcSrc,104,state,SRCCOPY); xp+=13; } nt/=2; while (nt-->0) { BitBlt(hdc,xp,0,25,20,hdcSrc,104,state,SRCCOPY); xp+=25; } } nt = (w - 100 - textw) % 25; if (nt > 0) { BitBlt(hdc,xp,0,nt,20,hdcSrc,104,state,SRCCOPY); //StretchBlt(hdc,xp,0,nt,20,hdcSrc,104,state,25,20,SRCCOPY); xp += nt; } BitBlt(hdc,xp,0,25,20,hdcSrc,130,state,SRCCOPY); } static void SkinnedWindow_DrawCaption(SKINNEDWND *pWnd, BOOL bActive, POINT *cursor) { RECT rc; GetWindowRect(pWnd->hwnd, &rc); OffsetRect(&rc, -rc.left, -rc.top); UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_INTERSECTUPDATE | DCX_VALIDATE | DCX_NORESETATTRS; HDC hdc = GetDCEx(pWnd->hwnd, NULL, flags); if (NULL == hdc) return; do_palmode(hdc); setSrcBM(embedBM); char szTitle[128] = {0}; INT cchTitle = GetWindowTextA(pWnd->hwnd, szTitle, ARRAYSIZE(szTitle)); INT state = pWnd->buttonState; if (BUTTON_PUSHED == state) { if (NULL == cursor || HTCLOSE != SendMessageW(pWnd->hwnd, WM_NCHITTEST, 0, MAKELPARAM(cursor->x, cursor->y))) state = BUTTON_NORMAL; } SkinnedWindow_DrawCaptionEx(hdc, bmDC, (LPCTSTR)szTitle, cchTitle, bActive ? 1 : (config_hilite?0:1), rc.right - rc.left, rc.bottom - rc.top); SkinnedWindow_DrawCloseButton(hdc, bmDC, &rc, bActive, state); unsetSrcBM(); ReleaseDC(pWnd->hwnd, hdc); } static void SkinnedWindow_DrawBorder(SKINNEDWND *pWnd, HDC hdc, HRGN rgnUpdate, POINT *cursor) { DWORD style = GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE); if (0 == (WS_BORDER & style)) return; RECT rc; GetWindowRect(pWnd->hwnd, &rc); OffsetRect(&rc, -rc.left, -rc.top); LONG w = rc.right, h = rc.bottom; do_palmode(hdc); setSrcBM(embedBM); if (0 != (WS_CHILD & style)) { if (!WADlg_initted()) WADlg_init(hMainWindow); COLORREF rgbOld = SetBkColor(hdc, WADlg_getColor(WADLG_HILITE)); RECT part; SetRect(&part, rc.left, rc.top, rc.right, rc.top + CHILDBORDER_TOP); ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL); SetRect(&part, rc.right - CHILDBORDER_RIGHT, rc.top + CHILDBORDER_TOP, rc.right, rc.bottom - CHILDBORDER_BOTTOM); ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL); SetRect(&part, rc.left, rc.bottom - CHILDBORDER_BOTTOM, rc.right, rc.bottom); ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL); SetRect(&part, rc.left, rc.top + CHILDBORDER_TOP, rc.left + CHILDBORDER_LEFT, rc.bottom - CHILDBORDER_BOTTOM); ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &part, NULL, 0, NULL); SetBkColor(hdc, rgbOld); return; } if (0 != (WS_CAPTION & style)) { char szTitle[128] = {0}; INT cchTitle = GetWindowTextA(pWnd->hwnd, szTitle, ARRAYSIZE(szTitle)); INT state = pWnd->buttonState; if (BUTTON_PUSHED == state) { if (NULL == cursor || HTCLOSE != SendMessageW(pWnd->hwnd, WM_NCHITTEST, 0, MAKELPARAM(cursor->x, cursor->y))) state = BUTTON_NORMAL; } BOOL bActive = (GetActiveWindow()==pWnd->hwnd) ? 1 : ((0 != config_hilite) ? 0 : 1); SkinnedWindow_DrawCaptionEx(hdc, bmDC, (LPCTSTR)szTitle, cchTitle, bActive, w, h); if (BUTTON_NORMAL != state) SkinnedWindow_DrawCloseButton(hdc, bmDC, &rc, bActive, state); } int y=(h-20-38)/29; int yp=20,x,xp; while (y-->0) { BitBlt(hdc,0,yp,11,29,bmDC,127,42,SRCCOPY); BitBlt(hdc,w-8,yp,8,29,bmDC,139,42,SRCCOPY); yp += 29; } y=(h-20-38)%29; if (y) { BitBlt(hdc,0,yp,11,y,bmDC,127,42,SRCCOPY); //StretchBlt(hdc,0,yp,11,y,bmDC,127,42,11,29,SRCCOPY); BitBlt(hdc,w-8,yp,8,y,bmDC,139,42,SRCCOPY); //StretchBlt(hdc,w-8,yp,8,y,bmDC,139,42,8,29,SRCCOPY); yp += y; } // 24 pixel lamity BitBlt(hdc,0,yp,11,24,bmDC,158,42,SRCCOPY); BitBlt(hdc,w-8,yp,8,24,bmDC,170,42,SRCCOPY); yp += 24; int realW = (w < 250) ? (w/2) : 125; BitBlt(hdc,0,yp,realW,14,bmDC,0,42,SRCCOPY); x=(w-125*2)/25; xp=realW; while (x-->0) { BitBlt(hdc,xp,yp,25,14,bmDC,127,72,SRCCOPY); xp+=25; } x=(w-125*2)%25; if (x > 0) { BitBlt(hdc,xp,yp,x,14,bmDC,127,72,SRCCOPY); //StretchBlt(hdc,xp,yp,x,14,bmDC,127,72,25,14,SRCCOPY); xp+=x; } if (realW < 125 && 0 != (w%2)) realW++; BitBlt(hdc,xp,yp,realW,14,bmDC, (125 - realW),57,SRCCOPY); if (0 != (EMBED_FLAGS_NORESIZE & pWnd->embedData.flags)) { BitBlt(hdc,xp+112,yp+2,7,7,bmDC,118,72,SRCCOPY); } unsetSrcBM(); } static BOOL SkinnedWindow_OnShowWindow(SKINNEDWND *pWnd, BOOL bShow, UINT flags) { if (pWnd->embedData.reparenting) return TRUE; SENDWAIPC(((bShow) ? IPC_CB_ONSHOWWND : IPC_CB_ONHIDEWND), pWnd->hwnd); return FALSE; } static LRESULT SkinnedWindow_OnNcCalcSize(SKINNEDWND *pWnd, BOOL bCalcValidRects, NCCALCSIZE_PARAMS *pncsp) { DWORD style = (DWORD)GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE); RECT rc; CopyRect(&rc, &pncsp->rgrc[0]); CallWndProc(pWnd, WM_NCCALCSIZE, bCalcValidRects, (LPARAM)pncsp); CopyRect(&pncsp->rgrc[0], &rc); if (bCalcValidRects) SetRect(&pncsp->rgrc[0], pncsp->lppos->x, pncsp->lppos->y, pncsp->lppos->x + pncsp->lppos->cx, pncsp->lppos->y + pncsp->lppos->cy); else { GetWindowRect(pWnd->hwnd, &pncsp->rgrc[0]); if (0 != (WS_CHILD & style)) { HWND hParent = GetParent(pWnd->hwnd); if (NULL != hParent) MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&pncsp->rgrc[0], 2); } } if (0 != (WS_BORDER & style)) { if (0 != (WS_CHILD & style)) { pncsp->rgrc[0].top += CHILDBORDER_TOP; pncsp->rgrc[0].left += CHILDBORDER_LEFT; pncsp->rgrc[0].right -= CHILDBORDER_RIGHT; pncsp->rgrc[0].bottom -= CHILDBORDER_BOTTOM; } else { pncsp->rgrc[0].top += BORDERWIDTH_TOP; pncsp->rgrc[0].left += BORDERWIDTH_LEFT; pncsp->rgrc[0].right -= BORDERWIDTH_RIGHT; pncsp->rgrc[0].bottom -= BORDERWIDTH_BOTTOM; } } return 0; } static void SkinnedWindow_OnNcPaint(SKINNEDWND *pWnd, HRGN rgnUpdate) { if (0 == (WS_BORDER & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE))) return; UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS | DCX_INTERSECTUPDATE | DCX_VALIDATE | DCX_NORESETATTRS; HDC hdc = GetDCEx(pWnd->hwnd, ((HRGN)NULLREGION != rgnUpdate) ? rgnUpdate : NULL, flags); if (NULL == hdc) return; POINT pt; GetCursorPos(&pt); SkinnedWindow_DrawBorder(pWnd, hdc, rgnUpdate, &pt); ReleaseDC(pWnd->hwnd, hdc); } static void SkinnedWindow_OnPrint(SKINNEDWND *pWnd, HDC hdc, UINT options) { if ((PRF_CHECKVISIBLE & options) && !IsWindowVisible(pWnd->hwnd)) return; if (PRF_NONCLIENT & options) { POINT pt = {0, 0}; SkinnedWindow_DrawBorder(pWnd, hdc, (HRGN)NULLREGION, &pt); } if (PRF_CLIENT & options) CallWndProc(pWnd, WM_PRINT, (WPARAM)hdc, (LPARAM)(~(PRF_NONCLIENT | PRF_CHECKVISIBLE) & options)); } static LRESULT SkinnedWindow_OnNcHitTest(SKINNEDWND *pWnd, POINTS pts) { POINT pt; RECT rw, rt; POINTSTOPOINT(pt, pts); DWORD style = (DWORD)GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE); if (0 != (WS_DISABLED & style)) return HTERROR; if (0 != (WS_CHILD & style)) { if (0 != (WS_BORDER & style)) { GetWindowRect(pWnd->hwnd, &rw); rw.left += CHILDBORDER_LEFT; rw.top += CHILDBORDER_TOP; rw.right -= CHILDBORDER_RIGHT; rw.bottom -= CHILDBORDER_BOTTOM; if (PtInRect(&rt, pt)) return HTBORDER; } return HTCLIENT; } GetWindowRect(pWnd->hwnd, &rw); if (0 != (WS_CAPTION & style)) { SetRect(&rt, rw.left, rw.top, rw.right, rw.top + BORDERWIDTH_TOP); if (PtInRect(&rt, pt)) // caption { SetRect(&rt, rw.right + CLOSEBUTTON_OFFSET_X, rw.top + CLOSEBUTTON_OFFSET_Y, rw.right + CLOSEBUTTON_OFFSET_X + CLOSEBUTTON_WIDTH, rw.top + CLOSEBUTTON_OFFSET_Y + CLOSEBUTTON_HEIGHT); if (PtInRect(&rt, pt)) // close button return HTCLOSE; return HTCAPTION; } } if (0 != (WS_BORDER & style)) { SetRect(&rt, rw.left, rw.top + BORDERWIDTH_TOP, rw.left + BORDERWIDTH_LEFT, rw.bottom - BORDERWIDTH_BOTTOM); if (PtInRect(&rt, pt)) return HTBORDER; // left side (non resizable) SetRect(&rt, rw.right - BORDERWIDTH_RIGHT, rw.top + BORDERWIDTH_TOP, rw.right, rw.bottom - SIZERGRIP_HEIGHT); if (PtInRect(&rt, pt)) return HTBORDER; // right side (non resizable) SetRect(&rt, rw.right - BORDERWIDTH_RIGHT, rw.bottom - SIZERGRIP_HEIGHT, rw.right, rw.bottom); if (PtInRect(&rt, pt)) return (0 == (EMBED_FLAGS_NORESIZE & pWnd->embedData.flags)) ? HTBOTTOMRIGHT : HTBORDER; // sizer bottomright SetRect(&rt, rw.left, rw.bottom - BORDERWIDTH_BOTTOM, rw.right -SIZERGRIP_WIDTH, rw.bottom); if (PtInRect(&rt, pt)) return HTBORDER; // bottom_left + bottom (non resizable) SetRect(&rt, rw.right - SIZERGRIP_WIDTH, rw.bottom - BORDERWIDTH_BOTTOM, rw.right, rw.bottom); if (PtInRect(&rt, pt)) return (0 == (EMBED_FLAGS_NORESIZE & pWnd->embedData.flags)) ? HTBOTTOMRIGHT : HTBORDER; // sizer bottomright } SetRect(&rt, rw.left, rw.top, rw.right, rw.bottom); if (PtInRect(&rt, pt)) return HTCLIENT; // client return HTNOWHERE; } static LRESULT SkinnedWindow_OnSetCursor(SKINNEDWND *pWnd, 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(pWnd->hwnd); break; } if (config_usecursors && !disable_skin_cursors) { int index = 15+5; // PNormal.cur switch(hitTest) { case HTCAPTION: { // this is required to emulate old behavior POINT pt; RECT rw; GetCursorPos(&pt); GetWindowRect(pWnd->hwnd, &rw); rw.bottom = rw.top + MOVEABLEAREA_HEIGHT; index = 15 + ((PtInRect(&rw, pt)) ? 2 : 5); // 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 CallWndProc(pWnd, WM_SETCURSOR, (WPARAM)hwndCursor, MAKELPARAM(hitTest, uMsg)); } static LRESULT SkinnedWindow_OnNcActivate(SKINNEDWND *pWnd, BOOL bActivate) { if (0 == (WS_CAPTION & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE))) return TRUE; POINT pt; GetCursorPos(&pt); SkinnedWindow_DrawCaption(pWnd, bActivate, &pt); return TRUE; } static void SkinnedWindow_OnActivate(SKINNEDWND *pWnd, unsigned int action, BOOL minimized, HWND otherWindow) { if (NULL == pWnd) return; if (NULL != WASABI_API_APP) { if (WA_INACTIVE == action) WASABI_API_APP->ActiveDialog_Unregister(pWnd->hwnd); else WASABI_API_APP->ActiveDialog_Register(pWnd->hwnd); } } static BOOL SkinnedWindow_OnNcLButtonDown(SKINNEDWND *pWnd, INT hitTest, POINTS pts) { switch(hitTest) { case HTCLOSE: { pWnd->buttonState = BUTTON_PUSHED; TRACKMOUSEEVENT tm; ZeroMemory(&tm, sizeof(TRACKMOUSEEVENT)); tm.cbSize = sizeof(TRACKMOUSEEVENT); tm.dwFlags = TME_LEAVE | TME_NONCLIENT; tm.hwndTrack = pWnd->hwnd; TrackMouseEvent(&tm); RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); } return TRUE; case HTCAPTION: if (IsWindowEnabled(pWnd->hwnd) && GetActiveWindow() != pWnd->hwnd) SetActiveWindow(pWnd->hwnd); { RECT rw; if (GetWindowRect(pWnd->hwnd, &rw)) { pWnd->movingOffset.x = pts.x - rw.left; pWnd->movingOffset.y = pts.y - rw.top; } } SendMessageW(pWnd->hwnd, WM_SYSCOMMAND, (SC_MOVE | 0x0002), (*(LPARAM*)&pts)); return TRUE; case HTBOTTOM: case HTBOTTOMLEFT: case HTBOTTOMRIGHT: if (IsWindowEnabled(pWnd->hwnd) && GetActiveWindow() != pWnd->hwnd) SetActiveWindow(pWnd->hwnd); SendMessageW(pWnd->hwnd, WM_SYSCOMMAND, SC_SIZE + hitTest - (HTLEFT - WMSZ_LEFT), (*(LPARAM*)&pts)); return TRUE; } return FALSE; } static BOOL SkinnedWindow_OnNcLButtonUp(SKINNEDWND *pWnd, INT hitTest, POINTS pts) { BOOL bProcessed = FALSE; if (HTCLOSE == hitTest && BUTTON_PUSHED == pWnd->buttonState) { SNDMSG(pWnd->hwnd, WM_SYSCOMMAND, SC_CLOSE, *(LPARAM*)&pts); bProcessed = TRUE; } if (BUTTON_PUSHED == pWnd->buttonState) { pWnd->buttonState = BUTTON_NORMAL; RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME); } return bProcessed; } static BOOL SkinnedWindow_OnNcRButtonDown(SKINNEDWND *pWnd, INT hitTest, POINTS pts) { return TRUE; } static BOOL SkinnedWindow_OnNcRButtonUp(SKINNEDWND *pWnd, INT hitTest, POINTS pts) { int ret = DoTrackPopup(main_menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pts.x, pts.y, pWnd->hwnd); if (ret) SendMessageW(hMainWindow,WM_COMMAND,ret,0); return TRUE; } static void SkinnedWindow_OnNcMouseMove(SKINNEDWND *pWnd, INT hitTest, POINTS pts) { if (BUTTON_PUSHED == pWnd->buttonState && HTCLOSE == hitTest) { RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME); } } static void SkinnedWindow_OnNcMouseLeave(SKINNEDWND *pWnd) { if (BUTTON_PUSHED == pWnd->buttonState) { if(0 != (0x8000 & GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON))) { TRACKMOUSEEVENT tm; ZeroMemory(&tm, sizeof(TRACKMOUSEEVENT)); tm.cbSize = sizeof(TRACKMOUSEEVENT); tm.dwFlags = TME_LEAVE | TME_NONCLIENT; tm.hwndTrack = pWnd->hwnd; TrackMouseEvent(&tm); } else { pWnd->buttonState = BUTTON_NORMAL; RedrawWindow(pWnd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME); } } } static void SkinnedWindow_OnWinampCustomClose(SKINNEDWND *pWnd, POINTS pts) { if (0 != pWnd->embedData.reparenting) return; SNDMSG(pWnd->hwnd, WM_SYSCOMMAND, SC_CLOSE, *(LPARAM*)&pts); } static void SkinnedWindow_OnWindowPosChanging(SKINNEDWND *pWnd, WINDOWPOS *pwp) { if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags)) { if (!config_embedwnd_freesize && 0 == (WS_CHILD & GetWindowLongPtrW(pWnd->hwnd, GWL_STYLE))) { pwp->cx += (RESIZESTEP_CX - 1); pwp->cx -= pwp->cx % RESIZESTEP_CX; pwp->cy += (RESIZESTEP_CY - 1); pwp->cy -= pwp->cy % RESIZESTEP_CY; } if (pwp->cx < RESIZESTEP_CX*2) pwp->cx = RESIZESTEP_CX*2; if (pwp->cy < RESIZESTEP_CY*2) pwp->cy = RESIZESTEP_CY*2; } CallWndProc(pWnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pwp); } static void SkinnedWindow_OnWindowPosChanged(SKINNEDWND *pWnd, WINDOWPOS *pwp) { if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED) & pwp->flags)) { SetRect(&pWnd->embedData.r, pwp->x, pwp->y, pwp->x + pwp->cx, pwp->y + pwp->cy); } CallWndProc(pWnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)pwp); } static void SkinnedWindow_OnMoving(SKINNEDWND *pWnd, RECT *prc) { if (0 == (SWS_EX_NOSNAP & pWnd->flags) && (0xFFFF != pWnd->movingOffset.x && 0xFFFF != pWnd->movingOffset.y) && (!!config_snap + (0 != (0x8000 & GetAsyncKeyState(VK_SHIFT))) == 1)) { POINT pt; GetCursorPos(&pt); INT cx = prc->right - prc->left; INT cy = prc->bottom - prc->top; prc->left = pt.x - pWnd->movingOffset.x; prc->top = pt.y - pWnd->movingOffset.y; prc->right = prc->left + cx; prc->bottom = prc->top + cy; SnapWindowToAllWindows(prc, pWnd->hwnd); } } static void SkinnedWindow_OnSizing(SKINNEDWND *pWnd, UINT edge, RECT *prc) { LONG cx, cy; cx = prc->right - prc->left; cy = prc->bottom - prc->top; if (!config_embedwnd_freesize && 0 == (0x8000 & GetAsyncKeyState(VK_SHIFT))) { cx += (RESIZESTEP_CX - 1); cx -= cx % RESIZESTEP_CX; cy += (RESIZESTEP_CY - 1); cy -= cy % RESIZESTEP_CY; } if (cx < RESIZESTEP_CX*2) cx = RESIZESTEP_CX*2; if (cy < RESIZESTEP_CY*2) cy = RESIZESTEP_CY*2; prc->right = prc->left + cx; prc->bottom = prc->top + cy; } static void SkinnedWindow_OnEnterSizeMove(SKINNEDWND *pWnd) { POINT pt; RECT rw; GetCursorPos(&pt); GetWindowRect(pWnd->hwnd, &rw); if (0xFFFF == pWnd->movingOffset.x) pWnd->movingOffset.x = pt.x - rw.left; if (0xFFFF == pWnd->movingOffset.y) pWnd->movingOffset.y = pt.y - rw.top; } static void SkinnedWindow_OnExitSizeMove(SKINNEDWND *pWnd) { pWnd->movingOffset.x = 0xFFFF; pWnd->movingOffset.y = 0xFFFF; } static void SkinnedWindow_PatchCursor(SKINNEDWND *pWnd) { RECT rc; POINT ptOrig, pt; if (!GetCursorPos(&ptOrig) || !GetWindowRect(pWnd->hwnd, &rc)) return; pt.x = rc.right + 1; pt.y = ptOrig.y; ShowCursor(FALSE); SetCursorPos(pt.x, pt.y); ShowCursor(TRUE); SetCursorPos(ptOrig.x, ptOrig.y); } static void SkinnedWindow_OnEnterMenuLoop(SKINNEDWND *pWnd, BOOL bTrackPopup) { PostMessageW(pWnd->hwnd, WM_SETCURSOR, (WPARAM)pWnd->hwnd, MAKELPARAM(HTCLIENT,WM_ENTERMENULOOP)); } static void SkinnedWindow_OnExitMenuLoop(SKINNEDWND *pWnd, BOOL bShortcut) { } static void SkinnedWindow_OnUnskin(SKINNEDWND *pWnd) { if (NULL == pWnd) return; HWND hwnd = pWnd->hwnd; BOOL restoreVisible = FALSE; DWORD windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE); if (0 != (WS_VISIBLE & windowStyle)) { restoreVisible = TRUE; SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE); } if (NULL != pWnd->embedData.wasabi_window) { SENDWAIPC(IPC_CB_ONHIDEWND, pWnd->hwnd); // start looping till we get callback MSG msg; BOOL stopLoop = FALSE; while(FALSE == stopLoop) { DWORD status = MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); if (WAIT_OBJECT_0 == status) { while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { if (WAMSG_CLOSE == msg.message && msg.hwnd == pWnd->hwnd) { stopLoop = TRUE; break; } else if (!CallMsgFilter(&msg, MSGF_DIALOGBOX)) { if (msg.message == WM_QUIT) { PostQuitMessage((INT)msg.wParam); stopLoop = TRUE; break; } else { TranslateMessage(&msg); DispatchMessageW(&msg); } } } } } } SkinnedWindow_Delete(pWnd); if (FALSE != restoreVisible) SetWindowLongPtrW(hwnd, GWL_STYLE, WS_VISIBLE | GetWindowLongPtrW(hwnd, GWL_STYLE)); } static LRESULT SkinnedWindow_OnWinampIPC(SKINNEDWND *pWnd, UINT uCmd, WPARAM param) { switch(uCmd) { case IPC_SKINWINDOW_SETEXSTYLE: pWnd->flags = (SWS_EX_MASK & pWnd->flags) | (~SWS_EX_MASK & param); return 0; case IPC_SKINWINDOW_GETEXSTYLE: return (~SWS_EX_MASK & pWnd->flags); case IPC_SKINWINDOW_SETEMBEDFLAGS: pWnd->embedData.flags = (INT)param; return 0; case IPC_SKINWINDOW_GETEMBEDFLAGS: return pWnd->embedData.flags; case IPC_SKINWINDOW_GETWASABIWND: return (LRESULT)pWnd->embedData.wasabi_window; case IPC_SKINWINDOW_UNSKIN: SkinnedWindow_OnUnskin(pWnd); break; case IPC_SKINWINDOW_GETGUID: if (NULL != param) { CopyMemory((void*)param, &pWnd->embedData.guid, sizeof(GUID)); return TRUE; } break; case IPC_SKINWINDOW_GETEMBEDNUMS: return Skin_UseGenNums; } return 0; } static void SkinnedWindow_OnSysCommand(SKINNEDWND *pWnd, UINT uCmd, LPARAM param) { CallWndProc(pWnd, WM_SYSCOMMAND, (WPARAM)uCmd, param); switch(uCmd) { case SC_MOVE: case SC_SIZE: case SC_DRAGMOVE: case SC_DRAGSIZE_N: case SC_DRAGSIZE_S: case SC_DRAGSIZE_E: case SC_DRAGSIZE_W: case SC_DRAGSIZE_NW: case SC_DRAGSIZE_NE: case SC_DRAGSIZE_SW: case SC_DRAGSIZE_SE: SkinnedWindow_PatchCursor(pWnd); break; } } static LRESULT SkinnedWindow_OnSetText(SKINNEDWND *pWnd, LPCWSTR pszText) { LRESULT result = CallWndProc(pWnd, WM_SETTEXT, 0, (LPARAM)pszText); ifc_window *wnd = pWnd->embedData.wasabi_window; if (NULL != wnd) { ifc_window *parent = wnd->getRootParent(); if (NULL == parent) parent = wnd; parent->setWindowTitle(pszText); } else { SetWindowPos(pWnd->hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); } return result; } static LRESULT CALLBACK SkinnedWnd_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { SKINNEDWND *pWnd = GetSkinnedWnd(hwnd); if (NULL == pWnd) { return ((IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam)); } switch(uMsg) { case WM_DESTROY: { BOOL unicode = IsUnicode(pWnd); WNDPROC wndProc = pWnd->fnWndProc; SkinnedWindow_Delete(pWnd); return ((unicode) ? CallWindowProcW(wndProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(wndProc, hwnd, uMsg, wParam, lParam)); } break; case WAMSG_CLOSE: SkinnedWindow_OnWinampCustomClose(pWnd, MAKEPOINTS(lParam)); return 0; case WM_NCHITTEST: return SkinnedWindow_OnNcHitTest(pWnd, MAKEPOINTS(lParam)); case WM_NCCALCSIZE: return SkinnedWindow_OnNcCalcSize(pWnd, (BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam); case WM_NCPAINT: SkinnedWindow_OnNcPaint(pWnd, (HRGN)wParam); return 0; case WM_NCACTIVATE: return SkinnedWindow_OnNcActivate(pWnd, (BOOL)wParam); case WM_ACTIVATE: SkinnedWindow_OnActivate(pWnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return 0; case WM_PRINT: SkinnedWindow_OnPrint(pWnd, (HDC)wParam, (UINT)lParam); return 0; case WM_SETCURSOR: return SkinnedWindow_OnSetCursor(pWnd, (HWND)wParam, LOWORD(lParam), HIWORD(lParam)); case WM_NCLBUTTONDOWN: if (SkinnedWindow_OnNcLButtonDown(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break; case WM_NCLBUTTONUP: if (SkinnedWindow_OnNcLButtonUp(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break; case WM_NCRBUTTONDOWN: if (SkinnedWindow_OnNcRButtonDown(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break; case WM_NCRBUTTONUP: if (SkinnedWindow_OnNcRButtonUp(pWnd, (INT)wParam, MAKEPOINTS(lParam))) return 0; break; case WM_NCMOUSEMOVE: SkinnedWindow_OnNcMouseMove(pWnd, (INT)wParam, MAKEPOINTS(lParam)); break; case WM_NCMOUSELEAVE: SkinnedWindow_OnNcMouseLeave(pWnd); break; case WM_SHOWWINDOW: if (SkinnedWindow_OnShowWindow(pWnd, (BOOL)wParam, (UINT)lParam)) return 0; break; case WM_WINDOWPOSCHANGING: SkinnedWindow_OnWindowPosChanging(pWnd, (WINDOWPOS*)lParam); return 0; case WM_WINDOWPOSCHANGED: SkinnedWindow_OnWindowPosChanged(pWnd, (WINDOWPOS*)lParam); return 0; case WM_ENTERSIZEMOVE: SkinnedWindow_OnEnterSizeMove(pWnd); break; case WM_EXITSIZEMOVE: SkinnedWindow_OnExitSizeMove(pWnd); break; case WM_MOVING: SkinnedWindow_OnMoving(pWnd, (RECT*)lParam); break; case WM_SIZING: SkinnedWindow_OnSizing(pWnd, (UINT)wParam, (RECT*)lParam); break; case WM_ENTERMENULOOP: SkinnedWindow_OnEnterMenuLoop(pWnd, (BOOL)wParam); break; case WM_EXITMENULOOP: SkinnedWindow_OnExitMenuLoop(pWnd, (BOOL)wParam); break; case WM_NCUAHDRAWCAPTION: return 0; case WM_NCUAHDRAWFRAME: return 0; case WM_WA_IPC: return SkinnedWindow_OnWinampIPC(pWnd, (UINT)lParam, wParam); case WM_SYSCOMMAND: SkinnedWindow_OnSysCommand(pWnd, (UINT)wParam, lParam); return 0; case WM_SETTEXT: return SkinnedWindow_OnSetText(pWnd, (LPCWSTR)lParam); } if (FALSE != IsDirectMouseWheelMessage(uMsg)) { if (0 == (WS_CHILD & GetWindowStyle(hwnd))) return TRUE; else { HWND hParent; hParent = GetAncestor(hwnd, GA_PARENT); if (NULL != hParent) return SendMessageW(hwnd, uMsg, wParam, lParam); return FALSE; } } return CallWndProc(pWnd, uMsg, wParam, lParam); }