14#include "helper/SMenuWndHook.h"
19#define GWL_WNDPROC GWLP_WNDPROC
26const TCHAR CoolMenu_oldProc[] = _T(
"CoolMenu_oldProc");
28#define SM_CXMENUBORDER 3
35SMap<HWND, SMenuWndHook *> SMenuWndHook::m_WndMenuMap;
37HHOOK SMenuWndHook::m_hMenuHook = NULL;
40SMenuWndHook::SMenuWndHook(HWND hWnd)
45SMenuWndHook::~SMenuWndHook()
47 WNDPROC oldWndProc = (WNDPROC)::GetProp(m_hWnd, CoolMenu_oldProc);
48 if (oldWndProc != NULL)
50 ::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc);
51 ::RemoveProp(m_hWnd, CoolMenu_oldProc);
53 m_WndMenuMap.RemoveKey(m_hWnd);
56void SMenuWndHook::InstallHook(HINSTANCE hInst, LPCWSTR pszSkinName)
58 if (m_hMenuHook == NULL)
60 m_hMenuHook = ::SetWindowsHookEx(WH_CALLWNDPROC, WindowHook, hInst, ::GetCurrentThreadId());
61 m_strSkinName = pszSkinName;
65void SMenuWndHook::UnInstallHook()
67 SPOSITION pos = m_WndMenuMap.GetStartPosition();
70 SMap<HWND, SMenuWndHook *>::CPair *p = m_WndMenuMap.GetNext(pos);
73 m_WndMenuMap.RemoveAll();
75 if (m_hMenuHook != NULL)
77 ::UnhookWindowsHookEx(m_hMenuHook);
81SMenuWndHook *SMenuWndHook::GetWndHook(HWND hwnd)
84 SMap<HWND, SMenuWndHook *>::CPair *p = m_WndMenuMap.Lookup(hwnd);
90SMenuWndHook *SMenuWndHook::AddWndHook(HWND hwnd)
92 SMenuWndHook *pWnd = GetWndHook(hwnd);
96 pWnd =
new SMenuWndHook(hwnd);
99 m_WndMenuMap[hwnd] = pWnd;
109LRESULT CALLBACK SMenuWndHook::WindowHook(
int code, WPARAM wParam, LPARAM lParam)
111 CWPSTRUCT *pStruct = (CWPSTRUCT *)lParam;
113 while (code == HC_ACTION)
115 HWND hWnd = pStruct->hwnd;
117 if (pStruct->message != WM_CREATE && pStruct->message != 0x01E2)
123 TCHAR strClassName[10];
124 int Count = ::GetClassName(hWnd, strClassName,
sizeof(strClassName) /
sizeof(strClassName[0]));
125 if (Count != 6 || _tcscmp(strClassName, _T(
"#32768")) != 0)
131 if (::GetProp(hWnd, CoolMenu_oldProc) != NULL)
136 AddWndHook(pStruct->hwnd);
139 WNDPROC oldWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
140 if (oldWndProc == NULL)
145 SASSERT(oldWndProc != CoolMenuProc);
147 if (!SetProp(hWnd, CoolMenu_oldProc, (HANDLE)oldWndProc))
153 if (!SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)CoolMenuProc))
155 ::RemoveProp(hWnd, CoolMenu_oldProc);
161 return CallNextHookEx(m_hMenuHook, code, wParam, lParam);
164LRESULT CALLBACK SMenuWndHook::CoolMenuProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
166 WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, CoolMenu_oldProc);
167 SMenuWndHook *pWnd = NULL;
173 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
174 if ((pWnd = GetWndHook(hWnd)) != NULL)
176 lResult = (LRESULT)pWnd->OnCreate((LPCREATESTRUCT)lParam);
183 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
184 if ((pWnd = GetWndHook(hWnd)) != NULL)
186 pWnd->OnNcCalcsize((BOOL)wParam, (NCCALCSIZE_PARAMS *)lParam);
191 case WM_WINDOWPOSCHANGING:
193 if ((pWnd = GetWndHook(hWnd)) != NULL)
195 pWnd->OnWindowPosChanging((LPWINDOWPOS)lParam);
199 case WM_WINDOWPOSCHANGED:
201 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
202 if ((pWnd = GetWndHook(hWnd)) != NULL)
204 pWnd->OnWindowPosChanged();
211 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
212 if ((pWnd = GetWndHook(hWnd)) != NULL)
214 pWnd->OnPrint((HDC)wParam);
221 if ((pWnd = GetWndHook(hWnd)) != NULL)
230 if ((pWnd = GetWndHook(hWnd)) != NULL)
237 return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
245int SMenuWndHook::OnCreate(LPCREATESTRUCT lpCreateStruct)
247 SetClassLong(m_hWnd, GCL_STYLE, GetClassLong(m_hWnd, GCL_STYLE) & ~CS_DROPSHADOW);
251void SMenuWndHook::OnWindowPosChanging(WINDOWPOS *pWindowPos)
253 if (m_strSkinName.IsEmpty())
255 ISkinObj *pSkin = GETSKIN(m_strSkinName, 100);
258 SSkinImgFrame *pBorderSkin =
static_cast<SSkinImgFrame *
>(pSkin);
261 pWindowPos->cx += pBorderSkin->
GetMargin().left + pBorderSkin->
GetMargin().right - SM_CXMENUBORDER * 2;
262 pWindowPos->cy += pBorderSkin->
GetMargin().top + pBorderSkin->
GetMargin().bottom - SM_CXMENUBORDER * 2;
265void SMenuWndHook::OnNcCalcsize(BOOL bValidCalc, NCCALCSIZE_PARAMS *lpncsp)
267 if (m_strSkinName.IsEmpty())
269 ISkinObj *pSkin = GETSKIN(m_strSkinName, 100);
272 SSkinImgFrame *pBorderSkin =
static_cast<SSkinImgFrame *
>(pSkin);
276 lpncsp->rgrc[0].left = lpncsp->lppos->x + pBorderSkin->
GetMargin().left;
277 lpncsp->rgrc[0].top = lpncsp->lppos->y + pBorderSkin->
GetMargin().top;
278 lpncsp->rgrc[0].right = lpncsp->lppos->x + lpncsp->lppos->cx - pBorderSkin->
GetMargin().right;
279 lpncsp->rgrc[0].bottom = lpncsp->lppos->y + lpncsp->lppos->cy - pBorderSkin->
GetMargin().bottom;
282void SMenuWndHook::OnNcPaint()
284 HDC dc = GetWindowDC(m_hWnd);
286 ReleaseDC(m_hWnd, dc);
289void SMenuWndHook::OnPrint(HDC dc)
291 if (m_strSkinName.IsEmpty())
293 ISkinObj *pSkin = GETSKIN(m_strSkinName, 100);
296 SSkinImgList *pBorderSkin =
static_cast<SSkinImgList *
>(pSkin);
301 GetClientRect(m_hWnd, &rcClient);
302 ClientToScreen(m_hWnd, (LPPOINT)&rcClient);
303 ClientToScreen(m_hWnd, ((LPPOINT)&rcClient) + 1);
305 GetWindowRect(m_hWnd, &rcWnd);
306 rcClient.OffsetRect(-rcWnd.TopLeft());
308 int nSave = ::SaveDC(dc);
309 ::ExcludeClipRect(dc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
310 rcWnd.MoveToXY(0, 0);
312 SAutoRefPtr<IRenderTarget> pRT;
313 GETRENDERFACTORY->CreateRenderTarget(&pRT, rcWnd.Width(), rcWnd.Height());
317 HDC hmemdc = pRT->GetDC(0);
318 ::BitBlt(dc, 0, 0, rcWnd.Width(), rcWnd.Height(), hmemdc, 0, 0, SRCCOPY);
319 pRT->ReleaseDC(hmemdc, NULL);
320 ::RestoreDC(dc, nSave);
323void SMenuWndHook::OnNcDestroy()
329void SMenuWndHook::OnWindowPosChanged()
Skin Object Pool Management.
static LPCWSTR GetClassName()
CRect GetMargin()
Gets the margins for the image frame.
void DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState) SCONST OVERRIDE
Draws the skin by index without alpha blending.
A class representing an ASCII string.
BOOL IsClass(LPCWSTR lpszName) SCONST PURE
Checks if the object is of a specified class type.