reflectmsg.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "main.h"
  2. #include "./reflectmsg.h"
  3. #include "./skinnedwnd.h"
  4. #include "./skinnedmenu.h"
  5. #include "./skinnedmenuthreadinfo.h"
  6. BOOL CanReflect(UINT uMsg)
  7. {
  8. switch(uMsg)
  9. {
  10. case WM_DRAWITEM:
  11. case WM_NOTIFY:
  12. case WM_COMMAND:
  13. case WM_CTLCOLORBTN:
  14. case WM_CTLCOLOREDIT:
  15. case WM_CTLCOLORLISTBOX:
  16. case WM_CTLCOLORSCROLLBAR:
  17. case WM_CTLCOLORSTATIC:
  18. case WM_MEASUREITEM:
  19. return TRUE;
  20. }
  21. return FALSE;
  22. }
  23. BOOL ReflectMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bDialog, LRESULT *pResult)
  24. {
  25. HWND hwndReflect = NULL;
  26. switch(uMsg)
  27. {
  28. case WM_DRAWITEM:
  29. hwndReflect = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
  30. if (NULL != hwndReflect && ODT_MENU == ((LPDRAWITEMSTRUCT)lParam)->CtlType)
  31. hwndReflect = SkinnedMenu::WindowFromHandle((HMENU)hwndReflect);
  32. break;
  33. case WM_NOTIFY:
  34. hwndReflect = ((LPNMHDR)lParam)->hwndFrom;
  35. break;
  36. case WM_COMMAND:
  37. case WM_CTLCOLORBTN:
  38. case WM_CTLCOLOREDIT:
  39. case WM_CTLCOLORLISTBOX:
  40. case WM_CTLCOLORSCROLLBAR:
  41. case WM_CTLCOLORSTATIC:
  42. hwndReflect =(HWND)lParam;
  43. break;
  44. case WM_MEASUREITEM:
  45. if (0 == wParam && ODT_MENU == ((MEASUREITEMSTRUCT*)lParam)->CtlType)
  46. {
  47. SkinnedMenuThreadInfo *threadInfo;
  48. if (S_OK == SkinnedMenuThreadInfo::GetInstance(FALSE, &threadInfo))
  49. {
  50. hwndReflect = SkinnedMenu::WindowFromHandle(threadInfo->GetActiveMeasureMenu());
  51. threadInfo->Release();
  52. }
  53. }
  54. break;
  55. }
  56. // make sure that hwndReflect is a valid hwnd otherwise it can incorrectly lose valid messages
  57. // when sent as custom version of normally valid ones ie faked wm_command messages where lparam is -1
  58. if (NULL != hwndReflect &&
  59. hwnd != hwndReflect &&
  60. IsWindow(hwndReflect))
  61. {
  62. REFLECTPARAM rParam;
  63. rParam.result = 0;
  64. rParam.lParam = lParam;
  65. rParam.hwndFrom = hwnd;
  66. if (REFLECTMESSAGE(hwndReflect, uMsg, wParam, (LPARAM)&rParam))
  67. {
  68. *pResult = rParam.result;
  69. if (bDialog)
  70. {
  71. switch(uMsg)
  72. {
  73. case WM_CTLCOLORBTN:
  74. case WM_CTLCOLOREDIT:
  75. case WM_CTLCOLORLISTBOX:
  76. case WM_CTLCOLORSCROLLBAR:
  77. case WM_CTLCOLORSTATIC:
  78. return TRUE;
  79. }
  80. SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONGX86)(LONG_PTR)*pResult);
  81. *pResult = TRUE;
  82. }
  83. return TRUE;
  84. }
  85. }
  86. *pResult = 0;
  87. return FALSE;
  88. }
  89. typedef struct __REFLECTORWND
  90. {
  91. BOOL bUnicode;
  92. BOOL bDialog;
  93. WNDPROC windowProc;
  94. }REFLECTORWND;
  95. static ATOM REFLECTOR = 0;
  96. static LRESULT CALLBACK Reflector_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  97. HRESULT InstallReflector(HWND hwnd)
  98. {
  99. if (0 == REFLECTOR)
  100. {
  101. REFLECTOR = GlobalAddAtomW(L"WAREFLECTOR");
  102. if (0 == REFLECTOR) return E_UNEXPECTED;
  103. }
  104. if (NULL == hwnd || !IsWindow(hwnd))
  105. return E_INVALIDARG;
  106. if (NULL != GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR)) ||
  107. NULL != SkinnedWnd::GetFromHWND(hwnd))
  108. return S_FALSE;
  109. REFLECTORWND *prw = (REFLECTORWND*)calloc(1, sizeof(REFLECTORWND));
  110. if (NULL == prw)
  111. return E_OUTOFMEMORY;
  112. ZeroMemory(prw, sizeof(REFLECTORWND));
  113. prw->bUnicode = IsWindowUnicode(hwnd);
  114. prw->windowProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)Reflector_WindowProc);
  115. if (NULL == prw->windowProc ||
  116. !SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR), prw))
  117. {
  118. RemoveReflector(hwnd);
  119. return E_FAIL;
  120. }
  121. return S_OK;
  122. }
  123. BOOL RemoveReflector(HWND hwnd)
  124. {
  125. if (!hwnd || !IsWindow(hwnd))
  126. return FALSE;
  127. REFLECTORWND *prw = (REFLECTORWND*)GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR));
  128. RemovePropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR));
  129. if (NULL == prw)
  130. return FALSE;
  131. if (prw->windowProc)
  132. SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)prw->windowProc);
  133. free(prw);
  134. return TRUE;
  135. }
  136. static LRESULT CALLBACK Reflector_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  137. {
  138. REFLECTORWND *prw = (REFLECTORWND*)GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(REFLECTOR));
  139. if (NULL == prw || NULL == prw->windowProc)
  140. {
  141. return (IsWindowUnicode(hwnd)) ?
  142. DefWindowProcW(hwnd, uMsg, wParam, lParam) :
  143. DefWindowProcA(hwnd, uMsg, wParam, lParam);
  144. }
  145. if (WM_DESTROY == uMsg)
  146. {
  147. BOOL unicode = prw->bUnicode;
  148. WNDPROC windowProc = prw->windowProc;
  149. RemoveReflector(hwnd);
  150. return (unicode) ?
  151. CallWindowProcW(windowProc, hwnd, uMsg, wParam, lParam) :
  152. CallWindowProcA(windowProc, hwnd, uMsg, wParam, lParam);
  153. }
  154. LRESULT result;
  155. if (ReflectMessage(hwnd, uMsg, wParam, lParam, prw->bDialog, &result))
  156. return result;
  157. return (prw->bUnicode) ?
  158. CallWindowProcW(prw->windowProc, hwnd, uMsg, wParam, lParam) :
  159. CallWindowProcA(prw->windowProc, hwnd, uMsg, wParam, lParam);
  160. }