diff options
Diffstat (limited to 'Src/Plugins/General/gen_ml/reflectmsg.cpp')
-rw-r--r-- | Src/Plugins/General/gen_ml/reflectmsg.cpp | 188 |
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 |