Sync to trunk (r44933)
[reactos.git] / reactos / lib / atl / atlwin.h
1 /*
2 * ReactOS ATL
3 *
4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #ifndef _atlin_h
22 #define _atlwin_h
23
24 #ifdef __GNUC__
25 #define GCCU(x) x __attribute__((unused))
26 #define Unused(x)
27 #else
28 #define GCCU(x)
29 #define Unused(x) (x);
30 #endif // __GNUC__
31
32 #ifdef SetWindowLongPtr
33 #undef SetWindowLongPtr
34 inline LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
35 {
36 return SetWindowLong(hWnd, nIndex, (LONG)dwNewLong);
37 }
38 #endif
39
40 #ifdef GetWindowLongPtr
41 #undef GetWindowLongPtr
42 inline LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex)
43 {
44 return (LONG_PTR)GetWindowLong(hWnd, nIndex);
45 }
46 #endif
47
48 namespace ATL
49 {
50
51 struct _ATL_WNDCLASSINFOW;
52 typedef _ATL_WNDCLASSINFOW CWndClassInfo;
53
54 template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
55 class CWinTraits
56 {
57 public:
58 static DWORD GetWndStyle(DWORD dwStyle)
59 {
60 if (dwStyle == 0)
61 return t_dwStyle;
62 return dwStyle;
63 }
64
65 static DWORD GetWndExStyle(DWORD dwExStyle)
66 {
67 if (dwExStyle == 0)
68 return t_dwExStyle;
69 return dwExStyle;
70 }
71 };
72
73 typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> CControlWinTraits;
74 typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits;
75 typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
76
77 template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits>
78 class CWinTraitsOR
79 {
80 public:
81 static DWORD GetWndStyle(DWORD dwStyle)
82 {
83 return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle);
84 }
85
86 static DWORD GetWndExStyle(DWORD dwExStyle)
87 {
88 return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle);
89 }
90 };
91
92 class _U_MENUorID
93 {
94 public:
95 HMENU m_hMenu;
96 public:
97 _U_MENUorID(HMENU hMenu)
98 {
99 m_hMenu = hMenu;
100 }
101
102 _U_MENUorID(UINT nID)
103 {
104 m_hMenu = (HMENU)(UINT_PTR)nID;
105 }
106 };
107
108 class _U_RECT
109 {
110 public:
111 LPRECT m_lpRect;
112 public:
113 _U_RECT(LPRECT lpRect)
114 {
115 m_lpRect = lpRect;
116 }
117
118 _U_RECT(RECT &rc)
119 {
120 m_lpRect = &rc;
121 }
122 };
123
124 struct _ATL_MSG : public MSG
125 {
126 public:
127 BOOL bHandled;
128 public:
129 _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, BOOL bHandledIn = TRUE)
130 {
131 hwnd = hWnd;
132 message = uMsg;
133 wParam = wParamIn;
134 lParam = lParamIn;
135 time = 0;
136 pt.x = 0;
137 pt.y = 0;
138 bHandled = bHandledIn;
139 }
140 };
141
142 #if defined(_M_IX86)
143
144 #pragma pack(push,1)
145 struct thunkCode
146 {
147 DWORD m_mov;
148 DWORD m_this;
149 BYTE m_jmp;
150 DWORD m_relproc;
151 };
152 #pragma pack(pop)
153
154 class CWndProcThunk
155 {
156 public:
157 thunkCode m_thunk;
158 _AtlCreateWndData cd;
159 public:
160 BOOL Init(WNDPROC proc, void *pThis)
161 {
162 m_thunk.m_mov = 0x042444C7;
163 m_thunk.m_this = PtrToUlong(pThis);
164 m_thunk.m_jmp = 0xe9;
165 m_thunk.m_relproc = DWORD(reinterpret_cast<char *>(proc) - (reinterpret_cast<char *>(this) + sizeof(thunkCode)));
166 return TRUE;
167 }
168
169 WNDPROC GetWNDPROC()
170 {
171 return reinterpret_cast<WNDPROC>(&m_thunk);
172 }
173 };
174
175 #elif _AMD64_ //WARNING: NOT VERIFIED
176 #pragma pack(push,1)
177 struct thunkCode
178 {
179 DWORD_PTR m_mov;
180 DWORD_PTR m_this;
181 BYTE m_jmp;
182 DWORD_PTR m_relproc;
183 };
184 #pragma pack(pop)
185
186 class CWndProcThunk
187 {
188 public:
189 thunkCode m_thunk;
190 _AtlCreateWndData cd;
191 public:
192 BOOL Init(WNDPROC proc, void *pThis)
193 {
194 m_thunk.m_mov = 0xffff8000042444C7LL;
195 m_thunk.m_this = (DWORD_PTR)pThis;
196 m_thunk.m_jmp = 0xe9;
197 m_thunk.m_relproc = DWORD_PTR(reinterpret_cast<char *>(proc) - (reinterpret_cast<char *>(this) + sizeof(thunkCode)));
198 return TRUE;
199 }
200
201 WNDPROC GetWNDPROC()
202 {
203 return reinterpret_cast<WNDPROC>(&m_thunk);
204 }
205 };
206 #else
207 #error ARCH not supported
208 #endif
209
210 class CMessageMap
211 {
212 public:
213 virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID) = 0;
214 };
215
216 class CWindow
217 {
218 public:
219 HWND m_hWnd;
220 static RECT rcDefault;
221 public:
222 CWindow(HWND hWnd = NULL)
223 {
224 m_hWnd = hWnd;
225 }
226
227 operator HWND() const
228 {
229 return m_hWnd;
230 }
231
232 static LPCTSTR GetWndClassName()
233 {
234 return NULL;
235 }
236
237 HDC BeginPaint(LPPAINTSTRUCT lpPaint)
238 {
239 ATLASSERT(::IsWindow(m_hWnd));
240 return ::BeginPaint(m_hWnd, lpPaint);
241 }
242
243 BOOL DestroyWindow()
244 {
245 ATLASSERT(::IsWindow(m_hWnd));
246
247 if (!::DestroyWindow(m_hWnd))
248 return FALSE;
249
250 m_hWnd = NULL;
251 return TRUE;
252 }
253
254 void EndPaint(LPPAINTSTRUCT lpPaint)
255 {
256 ATLASSERT(::IsWindow(m_hWnd));
257 ::EndPaint(m_hWnd, lpPaint);
258 }
259
260 BOOL GetClientRect(LPRECT lpRect) const
261 {
262 ATLASSERT(::IsWindow(m_hWnd));
263 return ::GetClientRect(m_hWnd, lpRect);
264 }
265
266 CWindow GetParent() const
267 {
268 ATLASSERT(::IsWindow(m_hWnd));
269 return CWindow(::GetParent(m_hWnd));
270 }
271
272 BOOL Invalidate(BOOL bErase = TRUE)
273 {
274 ATLASSERT(::IsWindow(m_hWnd));
275 return ::InvalidateRect(m_hWnd, NULL, bErase);
276 }
277
278 BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE)
279 {
280 ATLASSERT(::IsWindow(m_hWnd));
281 return ::InvalidateRect(m_hWnd, lpRect, bErase);
282 }
283
284 BOOL IsWindow() const
285 {
286 return ::IsWindow(m_hWnd);
287 }
288
289 BOOL KillTimer(UINT_PTR nIDEvent)
290 {
291 ATLASSERT(::IsWindow(m_hWnd));
292 return ::KillTimer(m_hWnd, nIDEvent);
293 }
294
295 BOOL LockWindowUpdate(BOOL bLock = TRUE)
296 {
297 ATLASSERT(::IsWindow(m_hWnd));
298 if (bLock)
299 return ::LockWindowUpdate(m_hWnd);
300 return ::LockWindowUpdate(NULL);
301 }
302
303 BOOL ScreenToClient(LPPOINT lpPoint) const
304 {
305 ATLASSERT(::IsWindow(m_hWnd));
306 return ::ScreenToClient(m_hWnd, lpPoint);
307 }
308
309 LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
310 {
311 ATLASSERT(::IsWindow(m_hWnd));
312 return ::SendMessage(m_hWnd, message, wParam, lParam);
313 }
314
315 static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
316 {
317 ATLASSERT(::IsWindow(hWnd));
318 return ::SendMessage(hWnd, message, wParam, lParam);
319 }
320
321 HWND SetCapture()
322 {
323 ATLASSERT(::IsWindow(m_hWnd));
324 return ::SetCapture(m_hWnd);
325 }
326
327 HWND SetFocus()
328 {
329 ATLASSERT(::IsWindow(m_hWnd));
330 return ::SetFocus(m_hWnd);
331 }
332
333 UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL)
334 {
335 ATLASSERT(::IsWindow(m_hWnd));
336 return ::SetTimer(m_hWnd, nIDEvent, nElapse, reinterpret_cast<TIMERPROC>(lpfnTimer));
337 }
338
339 BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
340 {
341 ATLASSERT(::IsWindow(m_hWnd));
342 return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
343 }
344
345 BOOL SetWindowText(LPCTSTR lpszString)
346 {
347 ATLASSERT(::IsWindow(m_hWnd));
348 return ::SetWindowText(m_hWnd, lpszString);
349 }
350
351 BOOL ShowWindow(int nCmdShow)
352 {
353 ATLASSERT(::IsWindow(m_hWnd));
354 return ::ShowWindow(m_hWnd, nCmdShow);
355 }
356
357 };
358
359 _declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
360
361 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
362 class CWindowImplBaseT : public TBase, public CMessageMap
363 {
364 public:
365 enum { WINSTATE_DESTROYED = 0x00000001 };
366 DWORD m_dwState;
367 const _ATL_MSG *m_pCurrentMsg;
368 CWndProcThunk m_thunk;
369 WNDPROC m_pfnSuperWindowProc;
370 public:
371 CWindowImplBaseT()
372 {
373 m_dwState = 0;
374 m_pCurrentMsg = NULL;
375 m_pfnSuperWindowProc = ::DefWindowProc;
376 }
377
378 virtual void OnFinalMessage(HWND /* hWnd */)
379 {
380 }
381
382 BOOL SubclassWindow(HWND hWnd)
383 {
384 CWindowImplBaseT<TBase, TWinTraits> *pThis;
385 WNDPROC newWindowProc;
386 WNDPROC oldWindowProc;
387 BOOL result;
388
389 ATLASSERT(m_hWnd == NULL);
390 ATLASSERT(::IsWindow(hWnd));
391
392 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
393
394 result = m_thunk.Init(GetWindowProc(), this);
395 if (result == FALSE)
396 return FALSE;
397 newWindowProc = m_thunk.GetWNDPROC();
398 oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
399 if (oldWindowProc == NULL)
400 return FALSE;
401 m_pfnSuperWindowProc = oldWindowProc;
402 pThis->m_hWnd = hWnd;
403 return TRUE;
404 }
405
406 virtual WNDPROC GetWindowProc()
407 {
408 return WindowProc;
409 }
410
411 static DWORD GetWndStyle(DWORD dwStyle)
412 {
413 return TWinTraits::GetWndStyle(dwStyle);
414 }
415
416 static DWORD GetWndExStyle(DWORD dwExStyle)
417 {
418 return TWinTraits::GetWndExStyle(dwExStyle);
419 }
420
421 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
422 {
423 CWindowImplBaseT<TBase, TWinTraits> *pThis;
424
425 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(this);
426 return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
427 }
428
429 static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
430 {
431 CWindowImplBaseT<TBase, TWinTraits> *pThis;
432 WNDPROC newWindowProc;
433 WNDPROC GCCU(pOldProc);
434
435 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(_AtlWinModule.ExtractCreateWndData());
436 ATLASSERT(pThis != NULL);
437 if (pThis == NULL)
438 return 0;
439 pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
440 newWindowProc = pThis->m_thunk.GetWNDPROC();
441 pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
442 Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
443 pThis->m_hWnd = hWnd;
444 return newWindowProc(hWnd, uMsg, wParam, lParam);
445 }
446
447 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
448 {
449 CWindowImplBaseT<TBase, TWinTraits> *pThis = reinterpret_cast<CWindowImplBaseT< TBase, TWinTraits> *>(hWnd);
450 _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
451 LRESULT lResult;
452 const _ATL_MSG *previousMessage;
453 BOOL handled;
454 LONG_PTR saveWindowProc;
455
456 ATLASSERT(pThis != NULL && (pThis->m_dwState & WINSTATE_DESTROYED) == 0 && pThis->m_hWnd != NULL);
457 if (pThis == NULL || (pThis->m_dwState & WINSTATE_DESTROYED) != 0 || pThis->m_hWnd == NULL)
458 return 0;
459
460 hWnd = pThis->m_hWnd;
461 previousMessage = pThis->m_pCurrentMsg;
462 pThis->m_pCurrentMsg = &msg;
463
464 handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
465 ATLASSERT(pThis->m_pCurrentMsg == &msg);
466
467 if (handled == FALSE)
468 {
469 if (uMsg == WM_NCDESTROY)
470 {
471 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
472 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
473 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
474 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
475 pThis->m_dwState |= WINSTATE_DESTROYED;
476 }
477 else
478 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
479 }
480 ATLASSERT(pThis->m_pCurrentMsg == &msg);
481 pThis->m_pCurrentMsg = previousMessage;
482 if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
483 {
484 pThis->m_dwState &= ~WINSTATE_DESTROYED;
485 pThis->m_hWnd = NULL;
486 pThis->OnFinalMessage(hWnd);
487 }
488 return lResult;
489 }
490
491 HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle,
492 _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
493 {
494 HWND hWnd;
495
496 ATLASSERT(m_hWnd == NULL);
497 ATLASSERT(atom != 0);
498 if (atom == 0)
499 return NULL;
500 if (m_thunk.Init(NULL, NULL) == FALSE)
501 {
502 SetLastError(ERROR_OUTOFMEMORY);
503 return NULL;
504 }
505
506 _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
507 if (MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD) != 0)
508 MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
509 if (rect.m_lpRect == NULL)
510 rect.m_lpRect = &TBase::rcDefault;
511 hWnd = ::CreateWindowEx(dwExStyle, reinterpret_cast<LPCWSTR>(MAKEINTATOM(atom)), szWindowName, dwStyle, rect.m_lpRect->left,
512 rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top,
513 hWndParent, MenuOrID.m_hMenu, _AtlBaseModule.GetModuleInstance(), lpCreateParam);
514
515 ATLASSERT(m_hWnd == hWnd);
516
517 return hWnd;
518 }
519 };
520
521 template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
522 class CWindowImpl : public CWindowImplBaseT<TBase, TWinTraits>
523 {
524 public:
525 static LPCTSTR GetWndCaption()
526 {
527 return NULL;
528 }
529
530 HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0,
531 DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
532 {
533 CWindowImplBaseT<TBase, TWinTraits> *pThis;
534 ATOM atom;
535
536 ATLASSERT(m_hWnd == NULL);
537 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
538
539 if (T::GetWndClassInfo().m_lpszOrigName == NULL)
540 T::GetWndClassInfo().m_lpszOrigName = pThis->GetWndClassName();
541 atom = T::GetWndClassInfo().Register(&pThis->m_pfnSuperWindowProc);
542
543 if (szWindowName == NULL)
544 szWindowName = T::GetWndCaption();
545 dwStyle = T::GetWndStyle(dwStyle);
546 dwExStyle = T::GetWndExStyle(dwExStyle);
547
548 return CWindowImplBaseT<TBase, TWinTraits>::Create(hWndParent, rect, szWindowName, dwStyle,
549 dwExStyle, MenuOrID, atom, lpCreateParam);
550 }
551 };
552
553 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
554 class CContainedWindowT : public TBase
555 {
556 public:
557 CWndProcThunk m_thunk;
558 LPCTSTR m_lpszClassName;
559 WNDPROC m_pfnSuperWindowProc;
560 CMessageMap *m_pObject;
561 DWORD m_dwMsgMapID;
562 const _ATL_MSG *m_pCurrentMsg;
563 public:
564 CContainedWindowT(CMessageMap *pObject, DWORD dwMsgMapID = 0)
565 {
566 m_lpszClassName = TBase::GetWndClassName();
567 m_pfnSuperWindowProc = ::DefWindowProc;
568 m_pObject = pObject;
569 m_dwMsgMapID = dwMsgMapID;
570 m_pCurrentMsg = NULL;
571 }
572
573 CContainedWindowT(LPTSTR lpszClassName, CMessageMap *pObject, DWORD dwMsgMapID = 0)
574 {
575 m_lpszClassName = lpszClassName;
576 m_pfnSuperWindowProc = ::DefWindowProc;
577 m_pObject = pObject;
578 m_dwMsgMapID = dwMsgMapID;
579 m_pCurrentMsg = NULL;
580 }
581
582 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
583 {
584 CWindowImplBaseT<TBase, TWinTraits> *pThis;
585
586 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(this);
587 return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
588 }
589
590 BOOL SubclassWindow(HWND hWnd)
591 {
592 CContainedWindowT<TBase> *pThis;
593 WNDPROC newWindowProc;
594 WNDPROC oldWindowProc;
595 BOOL result;
596
597 ATLASSERT(m_hWnd == NULL);
598 ATLASSERT(::IsWindow(hWnd));
599
600 pThis = reinterpret_cast<CContainedWindowT<TBase> *>(this);
601
602 result = m_thunk.Init(WindowProc, pThis);
603 if (result == FALSE)
604 return FALSE;
605 newWindowProc = m_thunk.GetWNDPROC();
606 oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
607 if (oldWindowProc == NULL)
608 return FALSE;
609 m_pfnSuperWindowProc = oldWindowProc;
610 pThis->m_hWnd = hWnd;
611 return TRUE;
612 }
613
614 static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
615 {
616 CContainedWindowT<TBase> *pThis;
617 WNDPROC newWindowProc;
618 WNDPROC GCCU(pOldProc);
619
620 pThis = reinterpret_cast<CContainedWindowT<TBase> *>(_AtlWinModule.ExtractCreateWndData());
621 ATLASSERT(pThis != NULL);
622 if (pThis == NULL)
623 return 0;
624 pThis->m_thunk.Init(WindowProc, pThis);
625 newWindowProc = pThis->m_thunk.GetWNDPROC();
626 pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
627 Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
628 pThis->m_hWnd = hWnd;
629 return newWindowProc(hWnd, uMsg, wParam, lParam);
630 }
631
632 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
633 {
634 CContainedWindowT<TBase> *pThis = reinterpret_cast<CContainedWindowT<TBase> *>(hWnd);
635 _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
636 LRESULT lResult;
637 const _ATL_MSG *previousMessage;
638 BOOL handled;
639 LONG_PTR saveWindowProc;
640
641 ATLASSERT(pThis != NULL && pThis->m_hWnd != NULL && pThis->m_pObject != NULL);
642 if (pThis == NULL || pThis->m_hWnd == NULL || pThis->m_pObject == NULL)
643 return 0;
644
645 hWnd = pThis->m_hWnd;
646 previousMessage = pThis->m_pCurrentMsg;
647 pThis->m_pCurrentMsg = &msg;
648
649 handled = pThis->m_pObject->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, pThis->m_dwMsgMapID);
650 ATLASSERT(pThis->m_pCurrentMsg == &msg);
651
652 pThis->m_pCurrentMsg = previousMessage;
653 if (handled == FALSE)
654 {
655 if (uMsg == WM_NCDESTROY)
656 {
657 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
658 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
659 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
660 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
661 pThis->m_hWnd = NULL;
662 }
663 else
664 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
665 }
666 return lResult;
667 }
668
669 };
670 typedef CContainedWindowT<CWindow> CContainedWindow;
671
672 #define BEGIN_MSG_MAP(theClass) \
673 public: \
674 BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
675 { \
676 BOOL GCCU(bHandled) = TRUE; \
677 Unused(hWnd); \
678 Unused(uMsg); \
679 Unused(wParam); \
680 Unused(lParam); \
681 Unused(lResult); \
682 Unused(bHandled); \
683 switch(dwMsgMapID) \
684 { \
685 case 0:
686
687 #define END_MSG_MAP() \
688 break; \
689 default: \
690 ATLASSERT(FALSE); \
691 break; \
692 } \
693 return FALSE; \
694 }
695
696 #define MESSAGE_HANDLER(msg, func) \
697 if (uMsg == msg) \
698 { \
699 bHandled = TRUE; \
700 lResult = func(uMsg, wParam, lParam, bHandled); \
701 if (bHandled) \
702 return TRUE; \
703 }
704
705 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
706 if (uMsg >= msgFirst && uMsg <= msgLast) \
707 { \
708 bHandled = TRUE; \
709 lResult = func(uMsg, wParam, lParam, bHandled); \
710 if (bHandled) \
711 return TRUE; \
712 }
713
714 #define COMMAND_ID_HANDLER(id, func) \
715 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
716 { \
717 bHandled = TRUE; \
718 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
719 if (bHandled) \
720 return TRUE; \
721 }
722
723 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
724 if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
725 { \
726 bHandled = TRUE; \
727 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
728 if (bHandled) \
729 return TRUE; \
730 }
731
732 #define NOTIFY_CODE_HANDLER(cd, func) \
733 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
734 { \
735 bHandled = TRUE; \
736 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
737 if (bHandled) \
738 return TRUE; \
739 }
740
741 #define NOTIFY_HANDLER(id, cd, func) \
742 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
743 { \
744 bHandled = TRUE; \
745 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
746 if (bHandled) \
747 return TRUE; \
748 }
749
750 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
751 static ATL::CWndClassInfo& GetWndClassInfo() \
752 { \
753 static ATL::CWndClassInfo wc = \
754 { \
755 { sizeof(WNDCLASSEX), style, StartWindowProc, \
756 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
757 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
758 }; \
759 return wc; \
760 }
761
762 struct _ATL_WNDCLASSINFOW
763 {
764 WNDCLASSEXW m_wc;
765 LPCWSTR m_lpszOrigName;
766 WNDPROC pWndProc;
767 LPCWSTR m_lpszCursorID;
768 BOOL m_bSystemCursor;
769 ATOM m_atom;
770 WCHAR m_szAutoName[5 + sizeof(void *)];
771
772 ATOM Register(WNDPROC *p)
773 {
774 if (m_atom == 0)
775 m_atom = RegisterClassEx(&m_wc);
776 return m_atom;
777 }
778 };
779
780 }; // namespace ATL
781
782 #endif // _atlwin_h