diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/General/gen_ml/skinnedwnd.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/General/gen_ml/skinnedwnd.cpp')
-rw-r--r-- | Src/Plugins/General/gen_ml/skinnedwnd.cpp | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_ml/skinnedwnd.cpp b/Src/Plugins/General/gen_ml/skinnedwnd.cpp new file mode 100644 index 00000000..0e16bb25 --- /dev/null +++ b/Src/Plugins/General/gen_ml/skinnedwnd.cpp @@ -0,0 +1,569 @@ +#include "./skinnedwnd.h" +#include "../winamp/wa_dlg.h" +#include "../nu/trace.h" +#include "./mldwm.h" +#include "../nu/CGlobalAtom.h" + +static CGlobalAtom WNDDATAPROPW(L"SWDATA"); + +static UINT WINAMP_WM_DIRECT_MOUSE_WHEEL = WM_NULL; + + +#ifndef LONGX86 +#ifdef _WIN64 + #define LONGX86 LONG_PTR +#else /*_WIN64*/ + #define LONGX86 LONG +#endif /*_WIN64*/ +#endif // LONGX86 + +#define SWS_ATTACHED 0x00010000 // window attached +#define SWS_UNICODE 0x00020000 // winodow is unicode +#define SWS_THEMED 0x00040000 // was themed before +#define SWS_REFLECT 0x00080000 // support message reflection +#define SWS_DIALOG 0x00100000 // treat this as dialog + +#define BORDER_WIDTH 1 + +extern HRESULT(WINAPI *SetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); //xp theme shit +extern BOOL (__stdcall *IsAppThemed)(void); + + +#define DWM_COMPOSITION_CHECK ((UINT)-1) +#define DWM_COMPOSITION_DISABLED ((UINT)0) +#define DWM_COMPOSITION_ENABLED ((UINT)1) + +static UINT dwmCompositionEnabled = DWM_COMPOSITION_CHECK; + + +static BOOL CALLBACK SkinChangedNotifyCB(HWND hwnd, LPARAM param) +{ + SendMessageW(hwnd, (UINT)WM_ML_IPC, MAKEWPARAM(TRUE, param), (LPARAM)ML_IPC_SKINNEDWND_SKINCHANGED); + return TRUE; +} + +SkinnedWnd *SkinnedWnd::GetFromHWND(HWND hwndSkinned) +{ + return (hwndSkinned && IsWindow(hwndSkinned)) ? (SkinnedWnd*)GetPropW(hwndSkinned, WNDDATAPROPW) : NULL; +} + +BOOL SkinnedWnd::IsDwmCompositionEnabled() +{ + if (DWM_COMPOSITION_CHECK == dwmCompositionEnabled) + { + dwmCompositionEnabled = DWM_COMPOSITION_DISABLED; + BOOL bEnabled; + if (S_OK == MlDwm_LoadLibrary() && S_OK == MlDwm_IsCompositionEnabled(&bEnabled) && bEnabled) + dwmCompositionEnabled = DWM_COMPOSITION_ENABLED; + } + return (DWM_COMPOSITION_ENABLED == dwmCompositionEnabled); +} + +SkinnedWnd::SkinnedWnd(BOOL bIsDialog) + : hwnd(NULL), style(SWS_NORMAL), uiState(NULL), redrawLock(0), + fnWndProc(NULL), wnddata(SKINNEDWND_TYPE_WINDOW | ((bIsDialog) ? SWS_DIALOG : 0)) +{ + minSize.cx = 0; + minSize.cy = 0; + maxSize.cx = 0; + maxSize.cy = 0; + + if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL) + WINAMP_WM_DIRECT_MOUSE_WHEEL = RegisterWindowMessageW(L"WINAMP_WM_DIRECT_MOUSE_WHEEL"); +} + +SkinnedWnd::~SkinnedWnd(void) +{ + if (!hwnd || !IsWindow(hwnd)) return; + RemovePropW(hwnd, WNDDATAPROPW); + if (fnWndProc) + { + INT index; + index = (SWS_DIALOG & wnddata) ? DWLP_DLGPROC : GWLP_WNDPROC; + (SWS_UNICODE & wnddata) ? SetWindowLongPtrW(hwnd, index, (LONGX86)(LONG_PTR)fnWndProc) : SetWindowLongPtrA(hwnd, index, (LONGX86)(LONG_PTR)fnWndProc); + } + if ((SWS_THEMED & wnddata) && IsAppThemed && IsAppThemed() && SetWindowTheme) SetWindowTheme(hwnd, NULL, NULL); +} + +BOOL SkinnedWnd::IsUnicode(void) +{ + return ( 0 != (SWS_UNICODE & wnddata)); +} + +BOOL SkinnedWnd::IsAttached(void) +{ + return ( 0 != (SWS_ATTACHED & wnddata)); +} + +BOOL SkinnedWnd::Attach(HWND hwndToSkin) +{ + INT index; + if (hwnd) return FALSE; + + hwnd = hwndToSkin; + if(!hwnd || GetPropW(hwnd, WNDDATAPROPW)) return FALSE; + + wnddata &= (SKINNEDWND_TYPE_WINDOW | SWS_DIALOG); + + if(IsWindowUnicode(hwnd)) wnddata |= SWS_UNICODE; + + index = (SWS_DIALOG & wnddata) ? DWLP_DLGPROC : GWLP_WNDPROC; + + + fnWndProc= (WNDPROC)(LONG_PTR)((SWS_UNICODE & wnddata) ? SetWindowLongPtrW(hwnd, index, (LONGX86)(LONG_PTR)WindowProcReal) : SetWindowLongPtrA(hwnd, index, (LONGX86)(LONG_PTR)WindowProcReal)); + if (!fnWndProc || !SetPropW(hwnd, WNDDATAPROPW, this)) return FALSE; + + RemoveReflector(hwnd); // we will use this refelector + + wnddata |= (SWS_ATTACHED | SWS_REFLECT); + + + if (S_OK == MlDwm_LoadLibrary()) + { + DWMNCRENDERINGPOLICY ncrp = DWMNCRP_DISABLED; + DWORD allow = FALSE; + MlDwm_SetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp)); + MlDwm_SetWindowAttribute(hwnd, DWMWA_ALLOW_NCPAINT, &allow, sizeof(allow)); + } + + if (IsAppThemed && IsAppThemed() && SetWindowTheme) + { + SetWindowTheme(hwnd, NULL, L""); + wnddata |= SWS_THEMED; + } + + uiState =(WORD)SendMessageW(hwnd, WM_QUERYUISTATE, 0, 0L); + + return TRUE; +} + +LRESULT SkinnedWnd::CallPrevWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return (SWS_UNICODE & wnddata) ? CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(fnWndProc, hwnd, uMsg, wParam, lParam); +} + +LRESULT SkinnedWnd::CallDefWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return (SWS_UNICODE & wnddata) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam); +} + +void SkinnedWnd::OnSkinChanged(BOOL bNotifyChildren, BOOL bRedraw) +{ + if (SWS_USESKINFONT & style) + { + HFONT skinFont; + + skinFont = (HFONT)MlStockObjects_Get(SKIN_FONT); + + if (NULL == skinFont) + skinFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT); + + if (NULL != skinFont) + { + HFONT windowFont = (HFONT)CallPrevWndProc(WM_GETFONT, 0, 0L); + if (skinFont != windowFont) + { + DisableRedraw(); + + SendMessageW(hwnd, WM_SETFONT, (WPARAM)skinFont, MAKELPARAM(0, bRedraw)); + + if (FALSE != bRedraw) + { + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | + SWP_FRAMECHANGED | SWP_NOREDRAW); + } + + EnableRedraw(SWR_NONE); + } + } + } + + if (bNotifyChildren) + EnumChildWindows(hwnd, SkinChangedNotifyCB, bRedraw); + + SendMessageW(hwnd, (UINT)WM_ML_IPC, + MAKEWPARAM(bNotifyChildren, bRedraw), + (LPARAM)ML_IPC_SKINNEDWND_SKINUPDATED); + + if (bRedraw) + InvalidateRect(hwnd, NULL, TRUE); +} + +void SkinnedWnd::OnSkinUpdated(BOOL bNotifyChildren, BOOL bRedraw) +{ +} + +void SkinnedWnd::SkinChanged(BOOL bNotifyChildren, BOOL bRedraw) +{ + OnSkinChanged(bNotifyChildren, bRedraw); +} + +void SkinnedWnd::EnableReflection(BOOL bEnable) +{ + wnddata = (wnddata & ~SWS_REFLECT) | ((bEnable) ? SWS_REFLECT : 0); +} + +BOOL SkinnedWnd::SetStyle(UINT newStyle, BOOL bRedraw) +{ + style = newStyle; + + if (NULL != hwnd) + SkinChanged(FALSE, bRedraw); + + return TRUE; +} + +void SkinnedWnd::SetMinMaxInfo(MLSKINNEDMINMAXINFO *minMax) +{ + if (NULL != minMax) + { + minSize.cx = minMax->min.cx; + if (minSize.cx < 0) + minSize.cx = 0; + + minSize.cy = minMax->min.cy; + if (minSize.cy < 0) + minSize.cy = 0; + + maxSize.cx = minMax->max.cx; + if (maxSize.cx < 0) + maxSize.cx = 0; + + maxSize.cy = minMax->max.cy; + if (maxSize.cy < 0) + maxSize.cy = 0; + } + else + { + memset(&minSize, 0, sizeof(minSize)); + memset(&maxSize, 0, sizeof(maxSize)); + } +} + + +BOOL SkinnedWnd::OnMediaLibraryIPC(INT msg, INT_PTR param, LRESULT *pResult) +{ + switch(msg) + { + case ML_IPC_SKINNEDWND_ISSKINNED: *pResult = IsAttached(); return TRUE; + case ML_IPC_SKINNEDWND_SKINCHANGED: SkinChanged(LOWORD(param), HIWORD(param)); *pResult = 1; return TRUE; + case ML_IPC_SKINNEDWND_SKINUPDATED: OnSkinUpdated(LOWORD(param), HIWORD(param)); break; + case ML_IPC_SKINNEDWND_GETTYPE: *pResult = GetType(); return TRUE; + case ML_IPC_SKINNEDWND_ENABLEREFLECTION: EnableReflection((BOOL)param); *pResult = 1; return TRUE; + case ML_IPC_SKINNEDWND_GETPREVWNDPROC: + if (param) *((BOOL*)param) = (SWS_UNICODE & wnddata); + *pResult = (INT_PTR)fnWndProc; + return TRUE; + case ML_IPC_SKINNEDWND_SETSTYLE: *pResult = style; style = (UINT)param; return TRUE; + case ML_IPC_SKINNEDWND_GETSTYLE: *pResult = style; return TRUE; + case ML_IPC_SKINNEDWND_SETMINMAXINFO: + SetMinMaxInfo((MLSKINNEDMINMAXINFO*)param); + *pResult = TRUE; + return TRUE; + } + return FALSE; +} + + +INT SkinnedWnd::OnNcHitTest(POINTS pts) +{ + return (INT)CallPrevWndProc(WM_NCHITTEST, 0, *(LPARAM*)&pts); +} + +void SkinnedWnd::DrawBorder(HDC hdc, RECT *prc, UINT type, HPEN pen) +{ + HPEN penOld; + INT o = (BORDER_WIDTH/2) + ((BORDER_WIDTH%2) ? 1 : 0); + + switch(type) + { + case BORDER_SUNKEN: + case BORDER_FLAT: + penOld = (HPEN)SelectObject(hdc, pen); + + MoveToEx(hdc, prc->right - o, prc->top, NULL); + LineTo(hdc, prc->right - o, prc->bottom); + MoveToEx(hdc, prc->right - BORDER_WIDTH, prc->bottom - o, NULL); + LineTo(hdc, prc->left - 1, prc->bottom - o); + + if (BORDER_FLAT == type) + { + MoveToEx(hdc, prc->left + BORDER_WIDTH/2, prc->bottom - BORDER_WIDTH, NULL); + LineTo(hdc, prc->left + BORDER_WIDTH/2, prc->top); + MoveToEx(hdc, prc->left, prc->top + BORDER_WIDTH/2, NULL); + LineTo(hdc, prc->right - BORDER_WIDTH, prc->top + BORDER_WIDTH/2); + } + SelectObject(hdc, penOld); + break; + } +} + +UINT SkinnedWnd::GetBorderType(void) +{ + DWORD ws = (DWORD)GetWindowLongPtrW(hwnd, GWL_EXSTYLE); + if (WS_EX_STATICEDGE & ws) return BORDER_FLAT; + else if (WS_EX_CLIENTEDGE & ws) return BORDER_SUNKEN; + ws = (DWORD)GetWindowLongPtrW(hwnd, GWL_STYLE); + return (WS_BORDER & ws) ? BORDER_FLAT : BORDER_NONE; +} + +void SkinnedWnd::DrawBorder(HDC hdc) +{ + UINT borderType = GetBorderType(); + + if (BORDER_NONE != borderType) + { + RECT rc; + GetWindowRect(hwnd, &rc); + OffsetRect(&rc, -rc.left, -rc.top); + DrawBorder(hdc, &rc, borderType, GetBorderPen()); + } +} + +void SkinnedWnd::OnNcPaint(HRGN rgnUpdate) +{ + UINT borderType = GetBorderType(); + if (BORDER_NONE == borderType) return; + + UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS | + DCX_INTERSECTUPDATE | DCX_VALIDATE; + + HDC hdc = GetDCEx(hwnd, ((HRGN)NULLREGION != rgnUpdate) ? rgnUpdate : NULL, flags); + + if (NULL == hdc) return; + + DrawBorder(hdc); + ReleaseDC(hwnd, hdc); +} + + +INT SkinnedWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *pncsp) +{ + UINT borderType = GetBorderType(); + switch(borderType) + { + case BORDER_SUNKEN: + case BORDER_FLAT: + if (bCalcValidRects) + { + SetRect(&pncsp->rgrc[0], + pncsp->lppos->x, pncsp->lppos->y, + pncsp->lppos->x + pncsp->lppos->cx - BORDER_WIDTH, pncsp->lppos->y + pncsp->lppos->cy - BORDER_WIDTH); + } + else + { + GetWindowRect(hwnd, &pncsp->rgrc[0]); + pncsp->rgrc[0].right -= BORDER_WIDTH; + pncsp->rgrc[0].bottom -= BORDER_WIDTH; + + } + if (BORDER_FLAT == borderType) + { + pncsp->rgrc[0].left += BORDER_WIDTH; + pncsp->rgrc[0].top += BORDER_WIDTH; + } + break; + } + + return 0; +} + +void SkinnedWnd::OnPrint(HDC hdc, UINT options) +{ + if ((PRF_CHECKVISIBLE & options) && !IsWindowVisible(hwnd)) return; + if (PRF_NONCLIENT & options) DrawBorder(hdc); + if (PRF_CLIENT & options) + { + CallPrevWndProc(WM_PRINT, (WPARAM)hdc, (LPARAM)(~(PRF_NONCLIENT | PRF_CHECKVISIBLE) & options)); + } +} + +HPEN SkinnedWnd::GetBorderPen(void) +{ + return (HPEN)MlStockObjects_Get(HILITE_PEN); +} + + +void SkinnedWnd::OnUpdateUIState(UINT uAction, UINT uState) +{ + CallPrevWndProc(WM_UPDATEUISTATE, MAKEWPARAM(uAction, uState), 0L); + uiState =(WORD)SendMessageW(hwnd, WM_QUERYUISTATE, 0, 0L); +} + +void SkinnedWnd::OnStyleChanged(INT styleType, STYLESTRUCT *pss) +{ + if (0 != redrawLock) + { + if (0 != (GWL_STYLE & styleType) && + (WS_VISIBLE & pss->styleOld) != (WS_VISIBLE & pss->styleNew)) + { + redrawLock = 0; + } + } + + CallPrevWndProc(WM_STYLECHANGED, (WPARAM)styleType, (LPARAM)pss); +} + +void SkinnedWnd::OnDwmCompositionChanged(void) +{ + dwmCompositionEnabled = DWM_COMPOSITION_CHECK; +} + +void SkinnedWnd::DisableRedraw() +{ + if (0 == redrawLock) + { + UINT windowStyle = (UINT)GetWindowLongPtrW(hwnd, GWL_STYLE); + if (0 == (WS_VISIBLE & windowStyle)) + return; + + CallDefWndProc(WM_SETREDRAW, FALSE, 0L); + } + + redrawLock++; +} + +void SkinnedWnd::EnableRedraw(SkinnedWndRedraw redrawFlags) +{ + UINT rdwFlags(0); + + if (0 == redrawLock) + return; + + redrawLock--; + if (0 != redrawLock) + return; + + CallDefWndProc(WM_SETREDRAW, TRUE, 0L); + + if (0 != (SWR_INVALIDATE & redrawFlags)) + { + rdwFlags |= RDW_INVALIDATE; + if (0 != (SWR_UPDATE & redrawFlags)) + rdwFlags |= RDW_UPDATENOW; + } + + if (0 != (SWR_ERASE & redrawFlags)) + { + rdwFlags |= RDW_ERASE; + if (0 != (SWR_UPDATE & redrawFlags)) + rdwFlags |= RDW_ERASENOW; + } + + if (0 != rdwFlags) + { + if (0 != (SWR_ALLCHILDREN & redrawFlags)) + rdwFlags |= RDW_ALLCHILDREN; + + RedrawWindow(hwnd, NULL, NULL, rdwFlags); + } + +} + +BOOL SkinnedWnd::OnDirectMouseWheel(INT delta, UINT vtKey, POINTS pts) +{ + SendMessageW(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(vtKey, delta), *((LPARAM*)&pts)); + return TRUE; +} + +void SkinnedWnd::OnGetMinMaxInfo(MINMAXINFO *minMax) +{ + if (NULL == minMax) + return; + + CallPrevWndProc(WM_GETMINMAXINFO, 0, (LPARAM)minMax); + + if (0 != minSize.cx) + minMax->ptMinTrackSize.x = minSize.cx; + + if (0 != minSize.cy) + minMax->ptMinTrackSize.y = minSize.cy; + + if (0 != maxSize.cx) + minMax->ptMaxTrackSize.x = maxSize.cx; + + if (0 != maxSize.cy) + minMax->ptMaxTrackSize.y = maxSize.cy; +} + +LRESULT SkinnedWnd::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_NCHITTEST: return OnNcHitTest(MAKEPOINTS(lParam)); + case WM_NCPAINT: OnNcPaint((HRGN)wParam); return 0; + case WM_NCCALCSIZE: return OnNcCalcSize((BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam); + case WM_PRINT: OnPrint((HDC)wParam, (UINT)lParam); return 0; + case WM_UPDATEUISTATE: OnUpdateUIState(LOWORD(wParam), HIWORD(wParam)); return 0; + case WM_STYLECHANGED: OnStyleChanged((INT)wParam, (STYLESTRUCT*)lParam); return 0; + case WM_SUPPORTREFLECT: + { + BOOL reflectionSupported = (0 != (SWS_REFLECT & wnddata) && CanReflect((UINT)wParam)); + if (0 != (SWS_DIALOG & wnddata)) + { + SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, reflectionSupported); + return TRUE; + } + return reflectionSupported; + } + case WM_ML_IPC: + { + LRESULT result; + if (OnMediaLibraryIPC((INT)lParam, (INT_PTR)wParam, &result)) + { + if (SWS_DIALOG & wnddata) + { + SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONGX86)result); + return TRUE; + } + return result; + } + break; + } + + case WM_DWMCOMPOSITIONCHANGED: OnDwmCompositionChanged(); return 0; + case WM_GETMINMAXINFO: OnGetMinMaxInfo((MINMAXINFO*)lParam); return 0; + + } + + // Reflection + if (0 != (SWS_REFLECT & wnddata)) + { + LRESULT result; + if (ReflectMessage(hwnd, uMsg, wParam, lParam, (0 != (SWS_DIALOG & wnddata)), &result)) + return result; + } + + if ( 0 == (SWS_NO_DIRECT_MOUSE_WHEEL & style) && + WINAMP_WM_DIRECT_MOUSE_WHEEL == uMsg && + WM_NULL != WINAMP_WM_DIRECT_MOUSE_WHEEL && + FALSE != OnDirectMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), MAKEPOINTS(lParam))) + { + if (0 != (SWS_DIALOG & wnddata)) + SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, TRUE); + return TRUE; + } + + return CallPrevWndProc(uMsg, wParam, lParam); +} + +LRESULT WINAPI SkinnedWnd::WindowProcReal(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + SkinnedWnd *pWnd = (SkinnedWnd*)GetPropW(hwnd, WNDDATAPROPW); + if (!pWnd) + return (IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam); + + switch(uMsg) + { + case WM_NCDESTROY: + { + WNDPROC fnWndProc = pWnd->fnWndProc; + delete(pWnd); + + return IsWindowUnicode(hwnd) ? CallWindowProcW(fnWndProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(fnWndProc, hwnd, uMsg, wParam, lParam); + } + break; + } + return pWnd->WindowProc(uMsg, wParam, lParam); +}
\ No newline at end of file |