soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SMenuWndHook.cpp
1/*########################################################################
2 Filename: MenuWndHook.cpp
3 ----------------------------------------------------
4 Remarks: ...
5 ----------------------------------------------------
6 Author: 成真
7 Email: anyou@sina.com
8 anyou@msn.com
9 Created: 7/4/2003 17:38
10 6/20/2012 黄建雄,修改为使用SSkin皮肤绘制非客户区边框,支持边框大小配置
11 ########################################################################*/
12
13#include "souistd.h"
14#include "helper/SMenuWndHook.h"
15#include "res.mgr/SSkinPool.h"
16#include "core/SSkin.h"
17
18#ifdef _WIN64
19#define GWL_WNDPROC GWLP_WNDPROC
20#endif //_WIN64
21
22#ifdef _WIN32
23
24SNSBEGIN
25
26const TCHAR CoolMenu_oldProc[] = _T("CoolMenu_oldProc");
27
28#define SM_CXMENUBORDER 3 //默认菜单边框大小
29
30/*########################################################################
31 ------------------------------------------------
32 class CMenuWndHook
33 ------------------------------------------------
34 ########################################################################*/
35SMap<HWND, SMenuWndHook *> SMenuWndHook::m_WndMenuMap;
36
37HHOOK SMenuWndHook::m_hMenuHook = NULL;
38SStringW SMenuWndHook::m_strSkinName;
39
40SMenuWndHook::SMenuWndHook(HWND hWnd)
41 : m_hWnd(hWnd)
42{
43}
44
45SMenuWndHook::~SMenuWndHook()
46{
47 WNDPROC oldWndProc = (WNDPROC)::GetProp(m_hWnd, CoolMenu_oldProc);
48 if (oldWndProc != NULL)
49 {
50 ::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc);
51 ::RemoveProp(m_hWnd, CoolMenu_oldProc);
52 }
53 m_WndMenuMap.RemoveKey(m_hWnd);
54}
55
56void SMenuWndHook::InstallHook(HINSTANCE hInst, LPCWSTR pszSkinName)
57{
58 if (m_hMenuHook == NULL)
59 {
60 m_hMenuHook = ::SetWindowsHookEx(WH_CALLWNDPROC, WindowHook, hInst, ::GetCurrentThreadId());
61 m_strSkinName = pszSkinName;
62 }
63}
64
65void SMenuWndHook::UnInstallHook()
66{
67 SPOSITION pos = m_WndMenuMap.GetStartPosition();
68 while (pos)
69 {
70 SMap<HWND, SMenuWndHook *>::CPair *p = m_WndMenuMap.GetNext(pos);
71 delete p->m_value;
72 }
73 m_WndMenuMap.RemoveAll();
74
75 if (m_hMenuHook != NULL)
76 {
77 ::UnhookWindowsHookEx(m_hMenuHook);
78 }
79}
80
81SMenuWndHook *SMenuWndHook::GetWndHook(HWND hwnd)
82{
83
84 SMap<HWND, SMenuWndHook *>::CPair *p = m_WndMenuMap.Lookup(hwnd);
85 if (!p)
86 return NULL;
87 return p->m_value;
88}
89
90SMenuWndHook *SMenuWndHook::AddWndHook(HWND hwnd)
91{
92 SMenuWndHook *pWnd = GetWndHook(hwnd);
93 if (pWnd)
94 return pWnd;
95
96 pWnd = new SMenuWndHook(hwnd);
97 if (pWnd != NULL)
98 {
99 m_WndMenuMap[hwnd] = pWnd;
100 }
101 return pWnd;
102}
103
104/*########################################################################
105 ------------------------------------------------
106 消息过程
107 ------------------------------------------------
108 ########################################################################*/
109LRESULT CALLBACK SMenuWndHook::WindowHook(int code, WPARAM wParam, LPARAM lParam)
110{
111 CWPSTRUCT *pStruct = (CWPSTRUCT *)lParam;
112
113 while (code == HC_ACTION)
114 {
115 HWND hWnd = pStruct->hwnd;
116
117 if (pStruct->message != WM_CREATE && pStruct->message != 0x01E2)
118 {
119 break;
120 }
121
122 // 是否为菜单类 ----------------------------------------
123 TCHAR strClassName[10];
124 int Count = ::GetClassName(hWnd, strClassName, sizeof(strClassName) / sizeof(strClassName[0]));
125 if (Count != 6 || _tcscmp(strClassName, _T("#32768")) != 0)
126 {
127 break;
128 }
129
130 // 是否已经被子类化 ------------------------------------
131 if (::GetProp(hWnd, CoolMenu_oldProc) != NULL)
132 {
133 break;
134 }
135
136 AddWndHook(pStruct->hwnd);
137
138 // 取得原来的窗口过程 ----------------------------------
139 WNDPROC oldWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
140 if (oldWndProc == NULL)
141 {
142 break;
143 }
144
145 SASSERT(oldWndProc != CoolMenuProc);
146 // 保存到窗口的属性中 ----------------------------------
147 if (!SetProp(hWnd, CoolMenu_oldProc, (HANDLE)oldWndProc))
148 {
149 break;
150 }
151
152 // 子类化 ----------------------------------------------
153 if (!SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)CoolMenuProc))
154 {
155 ::RemoveProp(hWnd, CoolMenu_oldProc);
156 break;
157 }
158
159 break;
160 }
161 return CallNextHookEx(m_hMenuHook, code, wParam, lParam);
162}
163
164LRESULT CALLBACK SMenuWndHook::CoolMenuProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
165{
166 WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, CoolMenu_oldProc);
167 SMenuWndHook *pWnd = NULL;
168
169 switch (uMsg)
170 {
171 case WM_CREATE:
172 {
173 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
174 if ((pWnd = GetWndHook(hWnd)) != NULL)
175 {
176 lResult = (LRESULT)pWnd->OnCreate((LPCREATESTRUCT)lParam);
177 }
178 return lResult;
179 }
180 break;
181 case WM_NCCALCSIZE:
182 {
183 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
184 if ((pWnd = GetWndHook(hWnd)) != NULL)
185 {
186 pWnd->OnNcCalcsize((BOOL)wParam, (NCCALCSIZE_PARAMS *)lParam);
187 }
188 return lResult;
189 }
190 break;
191 case WM_WINDOWPOSCHANGING:
192 {
193 if ((pWnd = GetWndHook(hWnd)) != NULL)
194 {
195 pWnd->OnWindowPosChanging((LPWINDOWPOS)lParam);
196 }
197 }
198 break;
199 case WM_WINDOWPOSCHANGED:
200 {
201 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
202 if ((pWnd = GetWndHook(hWnd)) != NULL)
203 {
204 pWnd->OnWindowPosChanged();
205 }
206 return lResult;
207 }
208 break;
209 case WM_PRINT:
210 {
211 LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
212 if ((pWnd = GetWndHook(hWnd)) != NULL)
213 {
214 pWnd->OnPrint((HDC)wParam);
215 }
216 return lResult;
217 }
218 break;
219 case WM_NCPAINT:
220 {
221 if ((pWnd = GetWndHook(hWnd)) != NULL)
222 {
223 pWnd->OnNcPaint();
224 return 0;
225 }
226 }
227 break;
228 case WM_NCDESTROY:
229 {
230 if ((pWnd = GetWndHook(hWnd)) != NULL)
231 {
232 pWnd->OnNcDestroy();
233 }
234 }
235 break;
236 }
237 return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
238}
239
240/*########################################################################
241 ------------------------------------------------
242 消息处理函数
243 ------------------------------------------------
244 ########################################################################*/
245int SMenuWndHook::OnCreate(LPCREATESTRUCT lpCreateStruct)
246{
247 SetClassLong(m_hWnd, GCL_STYLE, GetClassLong(m_hWnd, GCL_STYLE) & ~CS_DROPSHADOW);
248 return 0;
249}
250
251void SMenuWndHook::OnWindowPosChanging(WINDOWPOS *pWindowPos)
252{
253 if (m_strSkinName.IsEmpty())
254 return;
255 ISkinObj *pSkin = GETSKIN(m_strSkinName, 100);
256 if (!pSkin || !pSkin->IsClass(SSkinImgFrame::GetClassName()))
257 return;
258 SSkinImgFrame *pBorderSkin = static_cast<SSkinImgFrame *>(pSkin);
259 if (!pBorderSkin)
260 return;
261 pWindowPos->cx += pBorderSkin->GetMargin().left + pBorderSkin->GetMargin().right - SM_CXMENUBORDER * 2;
262 pWindowPos->cy += pBorderSkin->GetMargin().top + pBorderSkin->GetMargin().bottom - SM_CXMENUBORDER * 2;
263}
264
265void SMenuWndHook::OnNcCalcsize(BOOL bValidCalc, NCCALCSIZE_PARAMS *lpncsp)
266{
267 if (m_strSkinName.IsEmpty())
268 return;
269 ISkinObj *pSkin = GETSKIN(m_strSkinName, 100);
270 if (!pSkin || !pSkin->IsClass(SSkinImgFrame::GetClassName()))
271 return;
272 SSkinImgFrame *pBorderSkin = static_cast<SSkinImgFrame *>(pSkin);
273 if (!pBorderSkin)
274 return;
275
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;
280}
281
282void SMenuWndHook::OnNcPaint()
283{
284 HDC dc = GetWindowDC(m_hWnd);
285 OnPrint(dc);
286 ReleaseDC(m_hWnd, dc);
287}
288
289void SMenuWndHook::OnPrint(HDC dc)
290{
291 if (m_strSkinName.IsEmpty())
292 return;
293 ISkinObj *pSkin = GETSKIN(m_strSkinName, 100);
294 if (!pSkin)
295 return;
296 SSkinImgList *pBorderSkin = static_cast<SSkinImgList *>(pSkin);
297 if (!pBorderSkin)
298 return;
299
300 CRect rcClient;
301 GetClientRect(m_hWnd, &rcClient);
302 ClientToScreen(m_hWnd, (LPPOINT)&rcClient);
303 ClientToScreen(m_hWnd, ((LPPOINT)&rcClient) + 1);
304 CRect rcWnd;
305 GetWindowRect(m_hWnd, &rcWnd);
306 rcClient.OffsetRect(-rcWnd.TopLeft());
307
308 int nSave = ::SaveDC(dc);
309 ::ExcludeClipRect(dc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
310 rcWnd.MoveToXY(0, 0);
311
312 SAutoRefPtr<IRenderTarget> pRT;
313 GETRENDERFACTORY->CreateRenderTarget(&pRT, rcWnd.Width(), rcWnd.Height());
314 pRT->BeginDraw();
315 pBorderSkin->DrawByIndex(pRT, rcWnd, 0);
316 pRT->EndDraw();
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);
321}
322
323void SMenuWndHook::OnNcDestroy()
324{
325 delete this;
326}
327
328//不能设计窗口半透明,设置区域后,非客户区位置发生改变,不明白原因。
329void SMenuWndHook::OnWindowPosChanged()
330{
331 /*
332 CRect rcWnd;
333 GetWindowRect(m_hWnd,&rcWnd);
334 rcWnd.MoveToXY(0,0);
335 HRGN hRgn = ::CreateEllipticRgnIndirect(&rcWnd);
336 SetWindowRgn(m_hWnd,hRgn,TRUE);
337 DeleteObject(hRgn);
338 */
339}
340
341SNSEND
342
343#endif //_WIN32
Skin Classes for SOUI.
Skin Object Pool Management.
static LPCWSTR GetClassName()
Definition Sobject.hpp:41
CRect GetMargin()
Gets the margins for the image frame.
Definition SSkin.h:245
void DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState) SCONST OVERRIDE
Draws the skin by index without alpha blending.
A class representing an ASCII string.
Definition sstringw.h:96
BOOL IsClass(LPCWSTR lpszName) SCONST PURE
Checks if the object is of a specified class type.