aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/General/gen_ml/reflectmsg.cpp
diff options
context:
space:
mode:
authorJean-Francois Mauguit <jfmauguit@mac.com>2024-09-24 09:03:25 -0400
committerGitHub <noreply@github.com>2024-09-24 09:03:25 -0400
commitbab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/General/gen_ml/reflectmsg.cpp
parent4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff)
parent20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff)
downloadwinamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/Plugins/General/gen_ml/reflectmsg.cpp')
-rw-r--r--Src/Plugins/General/gen_ml/reflectmsg.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_ml/reflectmsg.cpp b/Src/Plugins/General/gen_ml/reflectmsg.cpp
new file mode 100644
index 00000000..984db922
--- /dev/null
+++ b/Src/Plugins/General/gen_ml/reflectmsg.cpp
@@ -0,0 +1,188 @@
+#include "main.h"
+#include "./reflectmsg.h"
+#include "./skinnedwnd.h"
+#include "./skinnedmenu.h"
+#include "./skinnedmenuthreadinfo.h"
+
+
+
+BOOL CanReflect(UINT uMsg)
+{
+ switch(uMsg)
+ {
+ case WM_DRAWITEM:
+ case WM_NOTIFY:
+ case WM_COMMAND:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_MEASUREITEM:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ReflectMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bDialog, LRESULT *pResult)
+{
+ HWND hwndReflect = NULL;
+
+ switch(uMsg)
+ {
+ case WM_DRAWITEM:
+ hwndReflect = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
+ if (NULL != hwndReflect && ODT_MENU == ((LPDRAWITEMSTRUCT)lParam)->CtlType)
+ hwndReflect = SkinnedMenu::WindowFromHandle((HMENU)hwndReflect);
+ break;
+ case WM_NOTIFY:
+ hwndReflect = ((LPNMHDR)lParam)->hwndFrom;
+ break;
+ case WM_COMMAND:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ hwndReflect =(HWND)lParam;
+ break;
+ case WM_MEASUREITEM:
+ if (0 == wParam && ODT_MENU == ((MEASUREITEMSTRUCT*)lParam)->CtlType)
+ {
+ SkinnedMenuThreadInfo *threadInfo;
+ if (S_OK == SkinnedMenuThreadInfo::GetInstance(FALSE, &threadInfo))
+ {
+ hwndReflect = SkinnedMenu::WindowFromHandle(threadInfo->GetActiveMeasureMenu());
+ threadInfo->Release();
+ }
+ }
+ break;
+ }
+ // make sure that hwndReflect is a valid hwnd otherwise it can incorrectly lose valid messages
+ // when sent as custom version of normally valid ones ie faked wm_command messages where lparam is -1
+ if (NULL != hwndReflect &&
+ hwnd != hwndReflect &&
+ IsWindow(hwndReflect))
+ {
+ REFLECTPARAM rParam;
+ rParam.result = 0;
+ rParam.lParam = lParam;
+ rParam.hwndFrom = hwnd;
+
+ if (REFLECTMESSAGE(hwndReflect, uMsg, wParam, (LPARAM)&rParam))
+ {
+ *pResult = rParam.result;
+ if (bDialog)
+ {
+ switch(uMsg)
+ {
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ return TRUE;
+ }
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONGX86)(LONG_PTR)*pResult);
+ *pResult = TRUE;
+ }
+ return TRUE;
+ }
+ }
+ *pResult = 0;
+ return FALSE;
+}
+
+
+typedef struct __REFLECTORWND
+{
+ BOOL bUnicode;
+ BOOL bDialog;
+ WNDPROC windowProc;
+}REFLECTORWND;
+
+static ATOM REFLECTOR = 0;
+
+static LRESULT CALLBACK Reflector_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+HRESULT InstallReflector(HWND hwnd)
+{
+ if (0 == REFLECTOR)
+ {
+ REFLECTOR = GlobalAddAtomW(L"WAREFLECTOR");
+ if (0 == REFLECTOR) return E_UNEXPECTED;
+ }
+
+ if (NULL == hwnd || !IsWindow(hwnd))
+ return E_INVALIDARG;
+
+ if (NULL != GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR)) ||
+ NULL != SkinnedWnd::GetFromHWND(hwnd))
+ return S_FALSE;
+
+ REFLECTORWND *prw = (REFLECTORWND*)calloc(1, sizeof(REFLECTORWND));
+ if (NULL == prw)
+ return E_OUTOFMEMORY;
+
+ ZeroMemory(prw, sizeof(REFLECTORWND));
+
+ prw->bUnicode = IsWindowUnicode(hwnd);
+ prw->windowProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)Reflector_WindowProc);
+
+ if (NULL == prw->windowProc ||
+ !SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR), prw))
+ {
+ RemoveReflector(hwnd);
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
+BOOL RemoveReflector(HWND hwnd)
+{
+ if (!hwnd || !IsWindow(hwnd))
+ return FALSE;
+
+ REFLECTORWND *prw = (REFLECTORWND*)GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR));
+ RemovePropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR));
+
+ if (NULL == prw)
+ return FALSE;
+
+ if (prw->windowProc)
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)prw->windowProc);
+
+ free(prw);
+ return TRUE;
+
+}
+
+static LRESULT CALLBACK Reflector_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ REFLECTORWND *prw = (REFLECTORWND*)GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR));
+ if (NULL == prw || NULL == prw->windowProc)
+ {
+ return (IsWindowUnicode(hwnd)) ?
+ DefWindowProcW(hwnd, uMsg, wParam, lParam) :
+ DefWindowProcA(hwnd, uMsg, wParam, lParam);
+ }
+
+ if (WM_DESTROY == uMsg)
+ {
+ BOOL unicode = prw->bUnicode;
+ WNDPROC windowProc = prw->windowProc;
+ RemoveReflector(hwnd);
+ return (unicode) ?
+ CallWindowProcW(windowProc, hwnd, uMsg, wParam, lParam) :
+ CallWindowProcA(windowProc, hwnd, uMsg, wParam, lParam);
+ }
+
+ LRESULT result;
+ if (ReflectMessage(hwnd, uMsg, wParam, lParam, prw->bDialog, &result))
+ return result;
+
+ return (prw->bUnicode) ?
+ CallWindowProcW(prw->windowProc, hwnd, uMsg, wParam, lParam) :
+ CallWindowProcA(prw->windowProc, hwnd, uMsg, wParam, lParam);
+} \ No newline at end of file