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