- Fix dgorbachev's copypasta.
[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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 #else
176 #error Only X86 supported
177 #endif
178
179 class CMessageMap
180 {
181 public:
182 virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID) = 0;
183 };
184
185 class CWindow
186 {
187 public:
188 HWND m_hWnd;
189 static RECT rcDefault;
190 public:
191 CWindow(HWND hWnd = NULL)
192 {
193 m_hWnd = hWnd;
194 }
195
196 operator HWND() const
197 {
198 return m_hWnd;
199 }
200
201 static LPCTSTR GetWndClassName()
202 {
203 return NULL;
204 }
205
206 HDC BeginPaint(LPPAINTSTRUCT lpPaint)
207 {
208 ATLASSERT(::IsWindow(m_hWnd));
209 return ::BeginPaint(m_hWnd, lpPaint);
210 }
211
212 BOOL DestroyWindow()
213 {
214 ATLASSERT(::IsWindow(m_hWnd));
215
216 if (!::DestroyWindow(m_hWnd))
217 return FALSE;
218
219 m_hWnd = NULL;
220 return TRUE;
221 }
222
223 void EndPaint(LPPAINTSTRUCT lpPaint)
224 {
225 ATLASSERT(::IsWindow(m_hWnd));
226 ::EndPaint(m_hWnd, lpPaint);
227 }
228
229 BOOL GetClientRect(LPRECT lpRect) const
230 {
231 ATLASSERT(::IsWindow(m_hWnd));
232 return ::GetClientRect(m_hWnd, lpRect);
233 }
234
235 CWindow GetParent() const
236 {
237 ATLASSERT(::IsWindow(m_hWnd));
238 return CWindow(::GetParent(m_hWnd));
239 }
240
241 BOOL Invalidate(BOOL bErase = TRUE)
242 {
243 ATLASSERT(::IsWindow(m_hWnd));
244 return ::InvalidateRect(m_hWnd, NULL, bErase);
245 }
246
247 BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE)
248 {
249 ATLASSERT(::IsWindow(m_hWnd));
250 return ::InvalidateRect(m_hWnd, lpRect, bErase);
251 }
252
253 BOOL IsWindow() const
254 {
255 return ::IsWindow(m_hWnd);
256 }
257
258 BOOL KillTimer(UINT_PTR nIDEvent)
259 {
260 ATLASSERT(::IsWindow(m_hWnd));
261 return ::KillTimer(m_hWnd, nIDEvent);
262 }
263
264 BOOL LockWindowUpdate(BOOL bLock = TRUE)
265 {
266 ATLASSERT(::IsWindow(m_hWnd));
267 if (bLock)
268 return ::LockWindowUpdate(m_hWnd);
269 return ::LockWindowUpdate(NULL);
270 }
271
272 BOOL ScreenToClient(LPPOINT lpPoint) const
273 {
274 ATLASSERT(::IsWindow(m_hWnd));
275 return ::ScreenToClient(m_hWnd, lpPoint);
276 }
277
278 LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
279 {
280 ATLASSERT(::IsWindow(m_hWnd));
281 return ::SendMessage(m_hWnd, message, wParam, lParam);
282 }
283
284 static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
285 {
286 ATLASSERT(::IsWindow(hWnd));
287 return ::SendMessage(hWnd, message, wParam, lParam);
288 }
289
290 HWND SetCapture()
291 {
292 ATLASSERT(::IsWindow(m_hWnd));
293 return ::SetCapture(m_hWnd);
294 }
295
296 HWND SetFocus()
297 {
298 ATLASSERT(::IsWindow(m_hWnd));
299 return ::SetFocus(m_hWnd);
300 }
301
302 UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL)
303 {
304 ATLASSERT(::IsWindow(m_hWnd));
305 return ::SetTimer(m_hWnd, nIDEvent, nElapse, reinterpret_cast<TIMERPROC>(lpfnTimer));
306 }
307
308 BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
309 {
310 ATLASSERT(::IsWindow(m_hWnd));
311 return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
312 }
313
314 BOOL SetWindowText(LPCTSTR lpszString)
315 {
316 ATLASSERT(::IsWindow(m_hWnd));
317 return ::SetWindowText(m_hWnd, lpszString);
318 }
319
320 BOOL ShowWindow(int nCmdShow)
321 {
322 ATLASSERT(::IsWindow(m_hWnd));
323 return ::ShowWindow(m_hWnd, nCmdShow);
324 }
325
326 };
327
328 _declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
329
330 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
331 class CWindowImplBaseT : public TBase, public CMessageMap
332 {
333 public:
334 enum { WINSTATE_DESTROYED = 0x00000001 };
335 DWORD m_dwState;
336 const _ATL_MSG *m_pCurrentMsg;
337 CWndProcThunk m_thunk;
338 WNDPROC m_pfnSuperWindowProc;
339 public:
340 CWindowImplBaseT()
341 {
342 m_dwState = 0;
343 m_pCurrentMsg = NULL;
344 m_pfnSuperWindowProc = ::DefWindowProc;
345 }
346
347 virtual void OnFinalMessage(HWND /* hWnd */)
348 {
349 }
350
351 BOOL SubclassWindow(HWND hWnd)
352 {
353 CWindowImplBaseT<TBase, TWinTraits> *pThis;
354 WNDPROC newWindowProc;
355 WNDPROC oldWindowProc;
356 BOOL result;
357
358 ATLASSERT(m_hWnd == NULL);
359 ATLASSERT(::IsWindow(hWnd));
360
361 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
362
363 result = m_thunk.Init(GetWindowProc(), this);
364 if (result == FALSE)
365 return FALSE;
366 newWindowProc = m_thunk.GetWNDPROC();
367 oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
368 if (oldWindowProc == NULL)
369 return FALSE;
370 m_pfnSuperWindowProc = oldWindowProc;
371 pThis->m_hWnd = hWnd;
372 return TRUE;
373 }
374
375 virtual WNDPROC GetWindowProc()
376 {
377 return WindowProc;
378 }
379
380 static DWORD GetWndStyle(DWORD dwStyle)
381 {
382 return TWinTraits::GetWndStyle(dwStyle);
383 }
384
385 static DWORD GetWndExStyle(DWORD dwExStyle)
386 {
387 return TWinTraits::GetWndExStyle(dwExStyle);
388 }
389
390 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
391 {
392 CWindowImplBaseT<TBase, TWinTraits> *pThis;
393
394 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(this);
395 return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
396 }
397
398 static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
399 {
400 CWindowImplBaseT<TBase, TWinTraits> *pThis;
401 WNDPROC newWindowProc;
402 WNDPROC GCCU(pOldProc);
403
404 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(_AtlWinModule.ExtractCreateWndData());
405 ATLASSERT(pThis != NULL);
406 if (pThis == NULL)
407 return 0;
408 pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
409 newWindowProc = pThis->m_thunk.GetWNDPROC();
410 pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
411 Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
412 pThis->m_hWnd = hWnd;
413 return newWindowProc(hWnd, uMsg, wParam, lParam);
414 }
415
416 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
417 {
418 CWindowImplBaseT<TBase, TWinTraits> *pThis = reinterpret_cast<CWindowImplBaseT< TBase, TWinTraits> *>(hWnd);
419 _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
420 LRESULT lResult;
421 const _ATL_MSG *previousMessage;
422 BOOL handled;
423 LONG_PTR saveWindowProc;
424
425 ATLASSERT(pThis != NULL && (pThis->m_dwState & WINSTATE_DESTROYED) == 0 && pThis->m_hWnd != NULL);
426 if (pThis == NULL || (pThis->m_dwState & WINSTATE_DESTROYED) != 0 || pThis->m_hWnd == NULL)
427 return 0;
428
429 hWnd = pThis->m_hWnd;
430 previousMessage = pThis->m_pCurrentMsg;
431 pThis->m_pCurrentMsg = &msg;
432
433 handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
434 ATLASSERT(pThis->m_pCurrentMsg == &msg);
435
436 if (handled == FALSE)
437 {
438 if (uMsg == WM_NCDESTROY)
439 {
440 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
441 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
442 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
443 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
444 pThis->m_dwState |= WINSTATE_DESTROYED;
445 }
446 else
447 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
448 }
449 ATLASSERT(pThis->m_pCurrentMsg == &msg);
450 pThis->m_pCurrentMsg = previousMessage;
451 if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
452 {
453 pThis->m_dwState &= ~WINSTATE_DESTROYED;
454 pThis->m_hWnd = NULL;
455 pThis->OnFinalMessage(hWnd);
456 }
457 return lResult;
458 }
459
460 HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle,
461 _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
462 {
463 HWND hWnd;
464
465 ATLASSERT(m_hWnd == NULL);
466 ATLASSERT(atom != 0);
467 if (atom == 0)
468 return NULL;
469 if (m_thunk.Init(NULL, NULL) == FALSE)
470 {
471 SetLastError(ERROR_OUTOFMEMORY);
472 return NULL;
473 }
474
475 _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
476 if (MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD) != 0)
477 MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
478 if (rect.m_lpRect == NULL)
479 rect.m_lpRect = &TBase::rcDefault;
480 hWnd = ::CreateWindowEx(dwExStyle, reinterpret_cast<LPCWSTR>(MAKEINTATOM(atom)), szWindowName, dwStyle, rect.m_lpRect->left,
481 rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top,
482 hWndParent, MenuOrID.m_hMenu, _AtlBaseModule.GetModuleInstance(), lpCreateParam);
483
484 ATLASSERT(m_hWnd == hWnd);
485
486 return hWnd;
487 }
488 };
489
490 template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
491 class CWindowImpl : public CWindowImplBaseT<TBase, TWinTraits>
492 {
493 public:
494 static LPCTSTR GetWndCaption()
495 {
496 return NULL;
497 }
498
499 HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0,
500 DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
501 {
502 CWindowImplBaseT<TBase, TWinTraits> *pThis;
503 ATOM atom;
504
505 ATLASSERT(m_hWnd == NULL);
506 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
507
508 if (T::GetWndClassInfo().m_lpszOrigName == NULL)
509 T::GetWndClassInfo().m_lpszOrigName = pThis->GetWndClassName();
510 atom = T::GetWndClassInfo().Register(&pThis->m_pfnSuperWindowProc);
511
512 if (szWindowName == NULL)
513 szWindowName = T::GetWndCaption();
514 dwStyle = T::GetWndStyle(dwStyle);
515 dwExStyle = T::GetWndExStyle(dwExStyle);
516
517 return CWindowImplBaseT<TBase, TWinTraits>::Create(hWndParent, rect, szWindowName, dwStyle,
518 dwExStyle, MenuOrID, atom, lpCreateParam);
519 }
520 };
521
522 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
523 class CContainedWindowT : public TBase
524 {
525 public:
526 CWndProcThunk m_thunk;
527 LPCTSTR m_lpszClassName;
528 WNDPROC m_pfnSuperWindowProc;
529 CMessageMap *m_pObject;
530 DWORD m_dwMsgMapID;
531 const _ATL_MSG *m_pCurrentMsg;
532 public:
533 CContainedWindowT(CMessageMap *pObject, DWORD dwMsgMapID = 0)
534 {
535 m_lpszClassName = TBase::GetWndClassName();
536 m_pfnSuperWindowProc = ::DefWindowProc;
537 m_pObject = pObject;
538 m_dwMsgMapID = dwMsgMapID;
539 m_pCurrentMsg = NULL;
540 }
541
542 CContainedWindowT(LPTSTR lpszClassName, CMessageMap *pObject, DWORD dwMsgMapID = 0)
543 {
544 m_lpszClassName = lpszClassName;
545 m_pfnSuperWindowProc = ::DefWindowProc;
546 m_pObject = pObject;
547 m_dwMsgMapID = dwMsgMapID;
548 m_pCurrentMsg = NULL;
549 }
550
551 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
552 {
553 CWindowImplBaseT<TBase, TWinTraits> *pThis;
554
555 pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(this);
556 return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
557 }
558
559 BOOL SubclassWindow(HWND hWnd)
560 {
561 CContainedWindowT<TBase> *pThis;
562 WNDPROC newWindowProc;
563 WNDPROC oldWindowProc;
564 BOOL result;
565
566 ATLASSERT(m_hWnd == NULL);
567 ATLASSERT(::IsWindow(hWnd));
568
569 pThis = reinterpret_cast<CContainedWindowT<TBase> *>(this);
570
571 result = m_thunk.Init(WindowProc, pThis);
572 if (result == FALSE)
573 return FALSE;
574 newWindowProc = m_thunk.GetWNDPROC();
575 oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
576 if (oldWindowProc == NULL)
577 return FALSE;
578 m_pfnSuperWindowProc = oldWindowProc;
579 pThis->m_hWnd = hWnd;
580 return TRUE;
581 }
582
583 static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
584 {
585 CContainedWindowT<TBase> *pThis;
586 WNDPROC newWindowProc;
587 WNDPROC GCCU(pOldProc);
588
589 pThis = reinterpret_cast<CContainedWindowT<TBase> *>(_AtlWinModule.ExtractCreateWndData());
590 ATLASSERT(pThis != NULL);
591 if (pThis == NULL)
592 return 0;
593 pThis->m_thunk.Init(WindowProc, pThis);
594 newWindowProc = pThis->m_thunk.GetWNDPROC();
595 pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
596 Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
597 pThis->m_hWnd = hWnd;
598 return newWindowProc(hWnd, uMsg, wParam, lParam);
599 }
600
601 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
602 {
603 CContainedWindowT<TBase> *pThis = reinterpret_cast<CContainedWindowT<TBase> *>(hWnd);
604 _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
605 LRESULT lResult;
606 const _ATL_MSG *previousMessage;
607 BOOL handled;
608 LONG_PTR saveWindowProc;
609
610 ATLASSERT(pThis != NULL && pThis->m_hWnd != NULL && pThis->m_pObject != NULL);
611 if (pThis == NULL || pThis->m_hWnd == NULL || pThis->m_pObject == NULL)
612 return 0;
613
614 hWnd = pThis->m_hWnd;
615 previousMessage = pThis->m_pCurrentMsg;
616 pThis->m_pCurrentMsg = &msg;
617
618 handled = pThis->m_pObject->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, pThis->m_dwMsgMapID);
619 ATLASSERT(pThis->m_pCurrentMsg == &msg);
620
621 pThis->m_pCurrentMsg = previousMessage;
622 if (handled == FALSE)
623 {
624 if (uMsg == WM_NCDESTROY)
625 {
626 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
627 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
628 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
629 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
630 pThis->m_hWnd = NULL;
631 }
632 else
633 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
634 }
635 return lResult;
636 }
637
638 };
639 typedef CContainedWindowT<CWindow> CContainedWindow;
640
641 #define BEGIN_MSG_MAP(theClass) \
642 public: \
643 BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
644 { \
645 BOOL GCCU(bHandled) = TRUE; \
646 Unused(hWnd); \
647 Unused(uMsg); \
648 Unused(wParam); \
649 Unused(lParam); \
650 Unused(lResult); \
651 Unused(bHandled); \
652 switch(dwMsgMapID) \
653 { \
654 case 0:
655
656 #define END_MSG_MAP() \
657 break; \
658 default: \
659 ATLASSERT(FALSE); \
660 break; \
661 } \
662 return FALSE; \
663 }
664
665 #define MESSAGE_HANDLER(msg, func) \
666 if (uMsg == msg) \
667 { \
668 bHandled = TRUE; \
669 lResult = func(uMsg, wParam, lParam, bHandled); \
670 if (bHandled) \
671 return TRUE; \
672 }
673
674 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
675 if (uMsg >= msgFirst && uMsg <= msgLast) \
676 { \
677 bHandled = TRUE; \
678 lResult = func(uMsg, wParam, lParam, bHandled); \
679 if (bHandled) \
680 return TRUE; \
681 }
682
683 #define COMMAND_ID_HANDLER(id, func) \
684 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
685 { \
686 bHandled = TRUE; \
687 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
688 if (bHandled) \
689 return TRUE; \
690 }
691
692 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
693 if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
694 { \
695 bHandled = TRUE; \
696 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
697 if (bHandled) \
698 return TRUE; \
699 }
700
701 #define NOTIFY_CODE_HANDLER(cd, func) \
702 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
703 { \
704 bHandled = TRUE; \
705 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
706 if (bHandled) \
707 return TRUE; \
708 }
709
710 #define NOTIFY_HANDLER(id, cd, func) \
711 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
712 { \
713 bHandled = TRUE; \
714 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
715 if (bHandled) \
716 return TRUE; \
717 }
718
719 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
720 static ATL::CWndClassInfo& GetWndClassInfo() \
721 { \
722 static ATL::CWndClassInfo wc = \
723 { \
724 { sizeof(WNDCLASSEX), style, StartWindowProc, \
725 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
726 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
727 }; \
728 return wc; \
729 }
730
731 struct _ATL_WNDCLASSINFOW
732 {
733 WNDCLASSEXW m_wc;
734 LPCWSTR m_lpszOrigName;
735 WNDPROC pWndProc;
736 LPCWSTR m_lpszCursorID;
737 BOOL m_bSystemCursor;
738 ATOM m_atom;
739 WCHAR m_szAutoName[5 + sizeof(void *)];
740
741 ATOM Register(WNDPROC *p)
742 {
743 if (m_atom == 0)
744 m_atom = RegisterClassEx(&m_wc);
745 return m_atom;
746 }
747 };
748
749 }; // namespace ATL
750
751 #endif // _atlwin_h