xref: /reactos/sdk/lib/atl/atlwin.h (revision 7e22dc05)
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 #if defined(__GNUC__) || defined(__clang__)
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 #if !defined(_WIN64)
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 #endif // !_WIN64
48 
49 #pragma push_macro("SubclassWindow")
50 #undef SubclassWindow
51 
52 namespace ATL
53 {
54 
55 #ifndef GET_X_LPARAM
56 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
57 #endif
58 #ifndef GET_Y_LPARAM
59 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
60 #endif
61 
62 
63 struct _ATL_WNDCLASSINFOW;
64 typedef _ATL_WNDCLASSINFOW CWndClassInfo;
65 
66 template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
67 class CWinTraits
68 {
69 public:
70     static DWORD GetWndStyle(DWORD dwStyle)
71     {
72         if (dwStyle == 0)
73             return t_dwStyle;
74         return dwStyle;
75     }
76 
77     static DWORD GetWndExStyle(DWORD dwExStyle)
78     {
79         if (dwExStyle == 0)
80             return t_dwExStyle;
81         return dwExStyle;
82     }
83 };
84 
85 typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> CControlWinTraits;
86 typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits;
87 typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
88 
89 template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits>
90 class CWinTraitsOR
91 {
92 public:
93     static DWORD GetWndStyle(DWORD dwStyle)
94     {
95         return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle);
96     }
97 
98     static DWORD GetWndExStyle(DWORD dwExStyle)
99     {
100         return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle);
101     }
102 };
103 
104 class _U_MENUorID
105 {
106 public:
107     HMENU m_hMenu;
108 public:
109     _U_MENUorID(HMENU hMenu)
110     {
111         m_hMenu = hMenu;
112     }
113 
114     _U_MENUorID(UINT nID)
115     {
116         m_hMenu = (HMENU)(UINT_PTR)nID;
117     }
118 };
119 
120 class _U_RECT
121 {
122 public:
123     LPRECT m_lpRect;
124 public:
125     _U_RECT(LPRECT lpRect)
126     {
127         m_lpRect = lpRect;
128     }
129 
130     _U_RECT(RECT &rc)
131     {
132         m_lpRect = &rc;
133     }
134 };
135 
136 struct _ATL_MSG : public MSG
137 {
138 public:
139     BOOL bHandled;
140 public:
141     _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, BOOL bHandledIn = TRUE)
142     {
143         hwnd = hWnd;
144         message = uMsg;
145         wParam = wParamIn;
146         lParam = lParamIn;
147         time = 0;
148         pt.x = 0;
149         pt.y = 0;
150         bHandled = bHandledIn;
151     }
152 };
153 
154 #if defined(_M_IX86)
155 
156 #pragma pack(push,1)
157 struct thunkCode
158 {
159     DWORD  m_mov; /* mov dword ptr [esp+4], m_this */
160     DWORD  m_this;
161     BYTE   m_jmp; /* jmp relproc */
162     DWORD  m_relproc;
163 
164     void
165     Init(WNDPROC proc, void *pThis)
166     {
167         m_mov = 0x042444C7;
168         m_this = PtrToUlong(pThis);
169         m_jmp = 0xe9;
170         m_relproc = DWORD(reinterpret_cast<char*>(proc) - (reinterpret_cast<char*>(this) + sizeof(thunkCode)));
171         FlushInstructionCache(GetCurrentProcess(), this, sizeof(thunkCode));
172     }
173 };
174 #pragma pack(pop)
175 
176 #elif defined(_AMD64_)
177 
178 #pragma pack(push,1)
179 struct thunkCode
180 {
181     USHORT  m_mov_rcx; /* mov rcx, m_this */
182     ULONG64 m_this;
183     USHORT  m_mov_rax; /* mov rax, m_proc */
184     ULONG64 m_proc;
185     USHORT  m_jmp;    /* jmp rax */
186 
187     void
188     Init(WNDPROC proc, void *pThis)
189     {
190         m_mov_rcx = 0xb948;
191         m_this = (ULONG64)pThis;
192         m_mov_rax = 0xb848;
193         m_proc = (ULONG64)proc;
194         m_jmp = 0xe0ff;
195         FlushInstructionCache(GetCurrentProcess(), this, sizeof(thunkCode));
196     }
197 };
198 #pragma pack(pop)
199 
200 #elif defined(_M_ARM)
201 
202 #pragma pack(push,4)
203 struct thunkCode
204 {
205     DWORD m_mov_r0; /* mov r0, m_this */
206     DWORD m_mov_pc; /* mov pc, m_proc */
207     DWORD m_this;
208     DWORD m_proc;
209 
210     void
211     Init(WNDPROC proc, void *pThis)
212     {
213         m_mov_r0 = 0xE59F0000;
214         m_mov_pc = 0xE59FF000;
215         m_this = (DWORD)pThis;
216         m_proc = (DWORD)proc;
217         FlushInstructionCache(GetCurrentProcess(), this, sizeof(thunkCode));
218     }
219 };
220 #pragma pack(pop)
221 
222 #else
223 #error ARCH not supported
224 #endif
225 
226 class CWndProcThunk
227 {
228 public:
229     thunkCode *m_pthunk;
230     _AtlCreateWndData cd;
231 
232 public:
233     CWndProcThunk()
234     {
235         m_pthunk = (thunkCode*)VirtualAlloc(NULL, sizeof(thunkCode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
236     }
237 
238     ~CWndProcThunk()
239     {
240         if (m_pthunk != NULL)
241             VirtualFree(m_pthunk, 0, MEM_RELEASE);
242     }
243 
244     BOOL Init(WNDPROC proc, void *pThis)
245     {
246         if (m_pthunk == NULL)
247             return FALSE;
248         m_pthunk->Init(proc, pThis);
249         return TRUE;
250     }
251 
252     WNDPROC GetWNDPROC()
253     {
254         return reinterpret_cast<WNDPROC>(m_pthunk);
255     }
256 };
257 
258 class CMessageMap
259 {
260 public:
261     virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID) = 0;
262 };
263 
264 class CWindow
265 {
266 public:
267     HWND m_hWnd;
268     static RECT rcDefault;
269 
270 public:
271     CWindow(HWND hWnd = NULL)
272     {
273         m_hWnd = hWnd;
274     }
275 
276     operator HWND() const
277     {
278         return m_hWnd;
279     }
280 
281     static LPCTSTR GetWndClassName()
282     {
283         return NULL;
284     }
285 
286     UINT ArrangeIconicWindows()
287     {
288         ATLASSERT(::IsWindow(m_hWnd));
289         return ::ArrangeIconicWindows(m_hWnd);
290     }
291 
292     void Attach(HWND hWndNew)
293     {
294         m_hWnd = hWndNew;
295     }
296 
297     HDC BeginPaint(LPPAINTSTRUCT lpPaint)
298     {
299         ATLASSERT(::IsWindow(m_hWnd));
300         return ::BeginPaint(m_hWnd, lpPaint);
301     }
302 
303     BOOL BringWindowToTop()
304     {
305         ATLASSERT(::IsWindow(m_hWnd));
306         return ::BringWindowToTop(m_hWnd);
307     }
308 
309     BOOL CenterWindow(HWND hWndCenter = NULL)
310     {
311         ATLASSERT(::IsWindow(m_hWnd));
312         if (hWndCenter == NULL)
313             hWndCenter = ::GetParent(m_hWnd);
314         if (hWndCenter == NULL)
315             return FALSE;
316         RECT wndCenterRect, wndRect;
317         if (!::GetWindowRect(hWndCenter, &wndCenterRect) || !::GetWindowRect(m_hWnd, &wndRect))
318             return FALSE;
319         int wndCenterWidth = wndCenterRect.right - wndCenterRect.left;
320         int wndCenterHeight = wndCenterRect.bottom - wndCenterRect.top;
321         int wndWidth = wndRect.right - wndRect.left;
322         int wndHeight = wndRect.bottom - wndRect.top;
323         return ::MoveWindow(m_hWnd,
324                             wndCenterRect.left + ((wndCenterWidth - wndWidth + 1) >> 1),
325                             wndCenterRect.top + ((wndCenterHeight - wndHeight + 1) >> 1),
326                             wndWidth, wndHeight, TRUE);
327     }
328 
329     BOOL ChangeClipboardChain(HWND hWndNewNext)
330     {
331         ATLASSERT(::IsWindow(m_hWnd));
332         return ::ChangeClipboardChain(m_hWnd, hWndNewNext);
333     }
334 
335     BOOL CheckDlgButton(int nIDButton, UINT nCheck)
336     {
337         ATLASSERT(::IsWindow(m_hWnd));
338         return ::CheckDlgButton(m_hWnd, nIDButton, nCheck);
339     }
340 
341     BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton)
342     {
343         ATLASSERT(::IsWindow(m_hWnd));
344         return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton);
345     }
346 
347     HWND ChildWindowFromPoint(POINT point) const
348     {
349         ATLASSERT(::IsWindow(m_hWnd));
350         return ::ChildWindowFromPoint(m_hWnd, point);
351     }
352 
353     HWND ChildWindowFromPointEx(POINT point, UINT uFlags) const
354     {
355         ATLASSERT(::IsWindow(m_hWnd));
356         return ::ChildWindowFromPointEx(m_hWnd, point, uFlags);
357     }
358 
359     BOOL ClientToScreen(LPPOINT lpPoint) const
360     {
361         ATLASSERT(::IsWindow(m_hWnd));
362         return ::ClientToScreen(m_hWnd, lpPoint);
363     }
364 
365     BOOL ClientToScreen(LPRECT lpRect) const
366     {
367         if (lpRect == NULL)
368             return FALSE;
369         ATLASSERT(::IsWindow(m_hWnd));
370         POINT leftTop = {lpRect->left, lpRect->top};
371         POINT rightBottom = {lpRect->right, lpRect->bottom};
372         BOOL success = ::ClientToScreen(m_hWnd, &leftTop) && ::ClientToScreen(m_hWnd, &rightBottom);
373         if (success)
374         {
375             lpRect->left = leftTop.x;
376             lpRect->top = leftTop.y;
377             lpRect->right = rightBottom.x;
378             lpRect->bottom = rightBottom.y;
379         }
380         return success;
381     }
382 
383     HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
384     {
385         HWND hWnd;
386         ATLASSERT(m_hWnd == NULL);
387         hWnd = ::CreateWindowEx(dwExStyle,
388                                 lpstrWndClass,
389                                 szWindowName,
390                                 dwStyle,
391                                 rect.m_lpRect->left,
392                                 rect.m_lpRect->top,
393                                 rect.m_lpRect->right - rect.m_lpRect->left,
394                                 rect.m_lpRect->bottom - rect.m_lpRect->top,
395                                 hWndParent,
396                                 MenuOrID.m_hMenu,
397                                 _AtlBaseModule.GetModuleInstance(),
398                                 lpCreateParam);
399         if (hWnd != NULL)
400             m_hWnd = hWnd;
401         return hWnd;
402     }
403 
404     BOOL CreateCaret(HBITMAP pBitmap)
405     {
406         ATLASSERT(::IsWindow(m_hWnd));
407         return ::CreateCaret(m_hWnd, pBitmap, 0, 0);
408     }
409 
410     BOOL CreateGrayCaret(int nWidth, int nHeight)
411     {
412         ATLASSERT(::IsWindow(m_hWnd));
413         return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight);
414     }
415 
416     BOOL CreateSolidCaret(int nWidth, int nHeight)
417     {
418         ATLASSERT(::IsWindow(m_hWnd));
419         return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight);
420     }
421 
422     HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags)
423     {
424         ATLASSERT(::IsWindow(m_hWnd));
425         return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
426     }
427 
428     BOOL DestroyWindow()
429     {
430         ATLASSERT(::IsWindow(m_hWnd));
431 
432         if (!::DestroyWindow(m_hWnd))
433             return FALSE;
434 
435         m_hWnd = NULL;
436         return TRUE;
437     }
438 
439     HWND Detach()
440     {
441         HWND hWnd = m_hWnd;
442         m_hWnd = NULL;
443         return hWnd;
444     }
445 
446     int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT nFileType)
447     {
448         ATLASSERT(::IsWindow(m_hWnd));
449         return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType);
450     }
451 
452     int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT nFileType)
453     {
454         ATLASSERT(::IsWindow(m_hWnd));
455         return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType);
456     }
457 
458     BOOL DlgDirSelect(LPTSTR lpString, int nCount, int nIDListBox)
459     {
460         ATLASSERT(::IsWindow(m_hWnd));
461         return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox);
462     }
463 
464     BOOL DlgDirSelectComboBox(LPTSTR lpString, int nCount, int nIDComboBox)
465     {
466         ATLASSERT(::IsWindow(m_hWnd));
467         return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox);
468     }
469 
470     void DragAcceptFiles(BOOL bAccept = TRUE)
471     {
472         ATLASSERT(::IsWindow(m_hWnd));
473 // FIXME following line requires shellapi.h
474 //         ::DragAcceptFiles(m_hWnd, bAccept);
475     }
476 
477     BOOL DrawMenuBar()
478     {
479         ATLASSERT(::IsWindow(m_hWnd));
480         return ::DrawMenuBar(m_hWnd);
481     }
482 
483     BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH)
484     {
485         ATLASSERT(::IsWindow(m_hWnd));
486         return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags);
487     }
488 
489     BOOL EnableWindow(BOOL bEnable = TRUE)
490     {
491         ATLASSERT(::IsWindow(m_hWnd));
492         return ::EnableWindow(m_hWnd, bEnable);
493     }
494 
495     void EndPaint(LPPAINTSTRUCT lpPaint)
496     {
497         ATLASSERT(::IsWindow(m_hWnd));
498         ::EndPaint(m_hWnd, lpPaint);
499     }
500 
501     BOOL FlashWindow(BOOL bInvert)
502     {
503         ATLASSERT(::IsWindow(m_hWnd));
504         return ::FlashWindow(m_hWnd, bInvert);
505     }
506 
507     BOOL GetClientRect(LPRECT lpRect) const
508     {
509         ATLASSERT(::IsWindow(m_hWnd));
510         return ::GetClientRect(m_hWnd, lpRect);
511     }
512 
513     HDC GetDC()
514     {
515         ATLASSERT(::IsWindow(m_hWnd));
516         return ::GetDC(m_hWnd);
517     }
518 
519     HDC GetDCEx(HRGN hRgnClip, DWORD flags)
520     {
521         ATLASSERT(::IsWindow(m_hWnd));
522         return ::GetDCEx(m_hWnd, hRgnClip, flags);
523     }
524 
525 private:
526     typedef struct _IDHWNDPAIR {
527         int nID;
528         HWND hWnd;
529     } IDHWNDPAIR, *PIDHWNDPAIR;
530 
531     static BOOL CALLBACK GetDescendantWindowCallback(HWND hWnd, LPARAM lParam)
532     {
533         if (::GetWindowLong(hWnd, GWL_ID) == ((PIDHWNDPAIR)lParam)->nID)
534         {
535             ((PIDHWNDPAIR)lParam)->hWnd = hWnd;
536             return FALSE;
537         }
538         ::EnumChildWindows(hWnd, &GetDescendantWindowCallback, lParam);
539         return (((PIDHWNDPAIR)lParam)->hWnd == NULL);
540     }
541 
542 public:
543     HWND GetDescendantWindow(int nID) const
544     {
545         ATLASSERT(::IsWindow(m_hWnd));
546         IDHWNDPAIR idHWndPair;
547         idHWndPair.nID = nID;
548         idHWndPair.hWnd = NULL;
549         ::EnumChildWindows(m_hWnd, &GetDescendantWindowCallback, (LPARAM)&idHWndPair);
550         return idHWndPair.hWnd;
551     }
552 
553     HRESULT GetDlgControl(int nID, REFIID iid, void** ppCtrl)
554     {
555         ATLASSERT(::IsWindow(m_hWnd));
556         return E_FAIL;//FIXME stub
557     }
558 
559     int GetDlgCtrlID() const
560     {
561         ATLASSERT(::IsWindow(m_hWnd));
562         return ::GetDlgCtrlID(m_hWnd);
563     }
564 
565     HRESULT GetDlgHost(int nID, REFIID iid, void** ppHost)
566     {
567         ATLASSERT(::IsWindow(m_hWnd));
568         return E_FAIL;//FIXME stub
569     }
570 
571     HWND GetDlgItem(_In_ int nID) const
572     {
573         ATLASSERT(::IsWindow(m_hWnd));
574         return ::GetDlgItem(m_hWnd, nID);
575     }
576 
577     UINT GetDlgItemInt(
578         _In_ int nID,
579         _Out_opt_ BOOL* lpTrans = NULL,
580         _In_ BOOL bSigned = TRUE) const
581     {
582         ATLASSERT(::IsWindow(m_hWnd));
583         return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned);
584     }
585 
586     UINT GetDlgItemText(
587         _In_ int nID,
588         _Out_writes_to_(nMaxCount, return + 1) LPTSTR lpStr,
589         _In_ int nMaxCount) const
590     {
591         ATLASSERT(::IsWindow(m_hWnd));
592         return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount);
593     }
594 
595 #ifdef __ATLSTR_H__
596     UINT GetDlgItemText(_In_ int nID, _Inout_ CSimpleString& strText) const
597     {
598         HWND item = GetDlgItem(nID);
599         if (!item)
600         {
601             strText.Empty();
602             return 0;
603         }
604         return CWindow(item).GetWindowText(strText);
605     }
606 #endif
607 
608     BOOL GetDlgItemText(
609         _In_ int nID,
610         _Inout_ _Outref_result_maybenull_ _Post_z_ BSTR& bstrText) const
611     {
612         HWND item = GetDlgItem(nID);
613         if (!item)
614             return FALSE;
615         return CWindow(item).GetWindowText(bstrText);
616     }
617 
618     DWORD GetExStyle() const
619     {
620         ATLASSERT(::IsWindow(m_hWnd));
621         return ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
622     }
623 
624     HFONT GetFont() const
625     {
626         ATLASSERT(::IsWindow(m_hWnd));
627         return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0);
628     }
629 
630     DWORD GetHotKey() const
631     {
632         ATLASSERT(::IsWindow(m_hWnd));
633         return (DWORD)::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0);
634     }
635 
636     HICON GetIcon(BOOL bBigIcon = TRUE) const
637     {
638         ATLASSERT(::IsWindow(m_hWnd));
639         return (HICON)::SendMessage(m_hWnd, WM_GETICON, (WPARAM)bBigIcon, 0);
640     }
641 
642     HWND GetLastActivePopup() const
643     {
644         ATLASSERT(::IsWindow(m_hWnd));
645         return ::GetLastActivePopup(m_hWnd);
646     }
647 
648     HMENU GetMenu() const
649     {
650         ATLASSERT(::IsWindow(m_hWnd));
651         return ::GetMenu(m_hWnd);
652     }
653 
654     HWND GetNextDlgGroupItem(HWND hWndCtl, BOOL bPrevious = FALSE) const
655     {
656         ATLASSERT(::IsWindow(m_hWnd));
657         return ::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious);
658     }
659 
660     HWND GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const
661     {
662         ATLASSERT(::IsWindow(m_hWnd));
663         return ::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious);
664     }
665 
666     CWindow GetParent() const
667     {
668         ATLASSERT(::IsWindow(m_hWnd));
669         return CWindow(::GetParent(m_hWnd));
670     }
671 
672     BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
673     {
674         ATLASSERT(::IsWindow(m_hWnd));
675         return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo);
676     }
677 
678     BOOL GetScrollPos(int nBar)
679     {
680         ATLASSERT(::IsWindow(m_hWnd));
681         return ::GetScrollPos(m_hWnd, nBar);
682     }
683 
684     BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
685     {
686         ATLASSERT(::IsWindow(m_hWnd));
687         return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos);
688     }
689 
690     DWORD GetStyle() const
691     {
692         ATLASSERT(::IsWindow(m_hWnd));
693         return ::GetWindowLong(m_hWnd, GWL_STYLE);
694     }
695 
696     HMENU GetSystemMenu(BOOL bRevert)
697     {
698         ATLASSERT(::IsWindow(m_hWnd));
699         return ::GetSystemMenu(m_hWnd, bRevert);
700     }
701 
702     HWND GetTopLevelParent() const
703     {
704         ATLASSERT(::IsWindow(m_hWnd));
705 
706         HWND hWndParent = m_hWnd;
707         HWND hWndTmp;
708         while ((hWndTmp = ::GetParent(hWndParent)) != NULL)
709             hWndParent = hWndTmp;
710 
711         return hWndParent;
712     }
713 
714     HWND GetTopLevelWindow() const
715     {
716         ATLASSERT(::IsWindow(m_hWnd));
717         return NULL;//FIXME stub
718     }
719 
720     HWND GetTopWindow() const
721     {
722         ATLASSERT(::IsWindow(m_hWnd));
723         return ::GetTopWindow(m_hWnd);
724     }
725 
726     BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE)
727     {
728         ATLASSERT(::IsWindow(m_hWnd));
729         return ::GetUpdateRect(m_hWnd, lpRect, bErase);
730     }
731 
732     int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE)
733     {
734         ATLASSERT(::IsWindow(m_hWnd));
735         return :: GetUpdateRgn(m_hWnd, hRgn, bErase);
736     }
737 
738     HWND GetWindow(UINT nCmd) const
739     {
740         ATLASSERT(::IsWindow(m_hWnd));
741         return ::GetWindow(m_hWnd, nCmd);
742     }
743 
744     DWORD GetWindowContextHelpId() const
745     {
746         ATLASSERT(::IsWindow(m_hWnd));
747         return ::GetWindowContextHelpId(m_hWnd);
748     }
749 
750     HDC GetWindowDC()
751     {
752         ATLASSERT(::IsWindow(m_hWnd));
753         return ::GetWindowDC(m_hWnd);
754     }
755 
756     LONG GetWindowLong(int nIndex) const
757     {
758         ATLASSERT(::IsWindow(m_hWnd));
759         return ::GetWindowLong(m_hWnd, nIndex);
760     }
761 
762     LONG_PTR GetWindowLongPtr(int nIndex) const
763     {
764         ATLASSERT(::IsWindow(m_hWnd));
765         return ::GetWindowLongPtr(m_hWnd, nIndex);
766     }
767 
768     BOOL GetWindowPlacement(WINDOWPLACEMENT* lpwndpl) const
769     {
770         ATLASSERT(::IsWindow(m_hWnd));
771         return ::GetWindowPlacement(m_hWnd, lpwndpl);
772     }
773 
774     DWORD GetWindowProcessID()
775     {
776         ATLASSERT(::IsWindow(m_hWnd));
777         DWORD processID;
778         ::GetWindowThreadProcessId(m_hWnd, &processID);
779         return processID;
780     }
781 
782     BOOL GetWindowRect(LPRECT lpRect) const
783     {
784         ATLASSERT(::IsWindow(m_hWnd));
785         return ::GetWindowRect(m_hWnd, lpRect);
786     }
787 
788     int GetWindowRgn(HRGN hRgn)
789     {
790         ATLASSERT(::IsWindow(m_hWnd));
791         return ::GetWindowRgn(m_hWnd, hRgn);
792     }
793 
794     int GetWindowText(
795         _Out_writes_to_(nMaxCount, return + 1) LPTSTR lpszStringBuf,
796         _In_ int nMaxCount) const
797     {
798         ATLASSERT(::IsWindow(m_hWnd));
799         return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount);
800     }
801 
802 #ifdef __ATLSTR_H__
803     int GetWindowText(_Inout_ CSimpleString& strText) const
804     {
805         int len = GetWindowTextLength();
806         len = GetWindowText(strText.GetBuffer(len + 1), len + 1);
807         strText.ReleaseBuffer(len);
808         return len;
809     }
810 #endif
811 
812     BOOL GetWindowText(
813         _Inout_ _Outref_result_maybenull_ _Post_z_ BSTR& bstrText) const
814     {
815         ATLASSERT(::IsWindow(m_hWnd));
816         INT length = ::GetWindowTextLengthW(m_hWnd);
817         if (!::SysReAllocStringLen(&bstrText, NULL, length))
818             return FALSE;
819         if (::GetWindowTextW(m_hWnd, bstrText, length + 1))
820             return TRUE;
821         ::SysFreeString(bstrText);
822         bstrText = NULL;
823         return FALSE;
824     }
825 
826     int GetWindowTextLength() const
827     {
828         ATLASSERT(::IsWindow(m_hWnd));
829         return ::GetWindowTextLength(m_hWnd);
830     }
831 
832     DWORD GetWindowThreadID()
833     {
834         ATLASSERT(::IsWindow(m_hWnd));
835         return ::GetWindowThreadProcessId(m_hWnd, NULL);
836     }
837 
838     WORD GetWindowWord(int nIndex) const
839     {
840         ATLASSERT(::IsWindow(m_hWnd));
841         return (WORD)::GetWindowLong(m_hWnd, nIndex);
842     }
843 
844     void GotoDlgCtrl(HWND hWndCtrl) const
845     {
846         ATLASSERT(::IsWindow(m_hWnd));
847         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0);
848     }
849 
850     BOOL HideCaret()
851     {
852         ATLASSERT(::IsWindow(m_hWnd));
853         return ::HideCaret(m_hWnd);
854     }
855 
856     BOOL HiliteMenuItem(HMENU hMenu, UINT uHiliteItem, UINT uHilite)
857     {
858         ATLASSERT(::IsWindow(m_hWnd));
859         return ::HiliteMenuItem(m_hWnd, hMenu, uHiliteItem, uHilite);
860     }
861 
862     BOOL Invalidate(BOOL bErase = TRUE)
863     {
864         ATLASSERT(::IsWindow(m_hWnd));
865         return ::InvalidateRect(m_hWnd, NULL, bErase);
866     }
867 
868     BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE)
869     {
870         ATLASSERT(::IsWindow(m_hWnd));
871         return ::InvalidateRect(m_hWnd, lpRect, bErase);
872     }
873 
874     void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE)
875     {
876         ATLASSERT(::IsWindow(m_hWnd));
877         ::InvalidateRgn(m_hWnd, hRgn, bErase);
878     }
879 
880     BOOL IsChild(const HWND hWnd) const
881     {
882         ATLASSERT(::IsWindow(m_hWnd));
883         return ::IsChild(m_hWnd, hWnd);
884     }
885 
886     BOOL IsDialogMessage(LPMSG lpMsg)
887     {
888         ATLASSERT(::IsWindow(m_hWnd));
889         return ::IsDialogMessage(m_hWnd, lpMsg);
890     }
891 
892     UINT IsDlgButtonChecked(int nIDButton) const
893     {
894         ATLASSERT(::IsWindow(m_hWnd));
895         return ::IsDlgButtonChecked(m_hWnd, nIDButton);
896     }
897 
898     BOOL IsIconic() const
899     {
900         ATLASSERT(::IsWindow(m_hWnd));
901         return ::IsIconic(m_hWnd);
902     }
903 
904     BOOL IsParentDialog()
905     {
906         ATLASSERT(::IsWindow(m_hWnd));
907         TCHAR pszType[10]; // Use sizeof("#32770")+3 so that extra characters can be detected.
908         if (!RealGetWindowClass(::GetParent(m_hWnd), pszType, _countof(pszType)))
909             return FALSE;
910         return !_tcscmp(pszType, _T("#32770"));
911     }
912 
913     BOOL IsWindow() const
914     {
915         return ::IsWindow(m_hWnd);
916     }
917 
918     BOOL IsWindowEnabled() const
919     {
920         ATLASSERT(::IsWindow(m_hWnd));
921         return ::IsWindowEnabled(m_hWnd);
922     }
923 
924     BOOL IsWindowVisible() const
925     {
926         ATLASSERT(::IsWindow(m_hWnd));
927         return ::IsWindowVisible(m_hWnd);
928     }
929 
930     BOOL IsWindowUnicode()
931     {
932         ATLASSERT(::IsWindow(m_hWnd));
933         return ::IsWindowUnicode(m_hWnd);
934     }
935 
936     BOOL IsZoomed() const
937     {
938         ATLASSERT(::IsWindow(m_hWnd));
939         return ::IsZoomed(m_hWnd);
940     }
941 
942     BOOL KillTimer(UINT_PTR nIDEvent)
943     {
944         ATLASSERT(::IsWindow(m_hWnd));
945         return ::KillTimer(m_hWnd, nIDEvent);
946     }
947 
948     BOOL LockWindowUpdate(BOOL bLock = TRUE)
949     {
950         ATLASSERT(::IsWindow(m_hWnd));
951         if (bLock)
952             return ::LockWindowUpdate(m_hWnd);
953         return ::LockWindowUpdate(NULL);
954     }
955 
956     int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const
957     {
958         ATLASSERT(::IsWindow(m_hWnd));
959         return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount);
960     }
961 
962     int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const
963     {
964         ATLASSERT(::IsWindow(m_hWnd));
965         return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, sizeof(RECT) / sizeof(POINT));
966     }
967 
968     int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK)
969     {
970         ATLASSERT(::IsWindow(m_hWnd));
971         return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType);
972     }
973 
974     BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
975     {
976         ATLASSERT(::IsWindow(m_hWnd));
977         ::SetWindowLong(m_hWnd, GWL_STYLE, (::GetWindowLong(m_hWnd, GWL_STYLE) & ~dwRemove) | dwAdd);
978         if (nFlags != 0)
979             return ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, nFlags | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
980         return TRUE;
981     }
982 
983     BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
984     {
985         ATLASSERT(::IsWindow(m_hWnd));
986         ::SetWindowLong(m_hWnd, GWL_EXSTYLE, (::GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~dwRemove) | dwAdd);
987         if (nFlags != 0)
988             return ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, nFlags | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
989         return TRUE;
990     }
991 
992     BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE)
993     {
994         ATLASSERT(::IsWindow(m_hWnd));
995         return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint);
996     }
997 
998     void NextDlgCtrl() const
999     {
1000         ATLASSERT(::IsWindow(m_hWnd));
1001         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0);
1002     }
1003 
1004     BOOL OpenClipboard()
1005     {
1006         ATLASSERT(::IsWindow(m_hWnd));
1007         return ::OpenClipboard(m_hWnd);
1008     }
1009 
1010     BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
1011     {
1012         ATLASSERT(::IsWindow(m_hWnd));
1013         return ::PostMessage(m_hWnd, message, wParam, lParam);
1014     }
1015 
1016     void PrevDlgCtrl() const
1017     {
1018         ATLASSERT(::IsWindow(m_hWnd));
1019         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0);
1020     }
1021 
1022     void Print(HDC hDC, DWORD dwFlags) const
1023     {
1024         ATLASSERT(::IsWindow(m_hWnd));
1025         ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, (LPARAM)dwFlags);
1026     }
1027 
1028     void PrintClient(HDC hDC, DWORD dwFlags) const
1029     {
1030         ATLASSERT(::IsWindow(m_hWnd));
1031         ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, (LPARAM)dwFlags);
1032     }
1033 
1034     BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE)
1035     {
1036         ATLASSERT(::IsWindow(m_hWnd));
1037         return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags);
1038     }
1039 
1040     int ReleaseDC(HDC hDC)
1041     {
1042         ATLASSERT(::IsWindow(m_hWnd));
1043         return ::ReleaseDC(m_hWnd, hDC);
1044     }
1045 
1046     BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = FALSE)
1047     {
1048         ATLASSERT(::IsWindow(m_hWnd));
1049         RECT clientRect, wndRect;
1050         ::GetClientRect(m_hWnd, &clientRect);
1051         ::GetWindowRect(m_hWnd, &wndRect);
1052         return ::MoveWindow(m_hWnd, wndRect.left, wndRect.top,
1053                             nWidth + (wndRect.right - wndRect.left) - (clientRect.right - clientRect.left),
1054                             nHeight + (wndRect.bottom - wndRect.top) - (clientRect.bottom - clientRect.top),
1055                             bRedraw);
1056     }
1057 
1058     BOOL ScreenToClient(LPPOINT lpPoint) const
1059     {
1060         ATLASSERT(::IsWindow(m_hWnd));
1061         return ::ScreenToClient(m_hWnd, lpPoint);
1062     }
1063 
1064     BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL)
1065     {
1066         ATLASSERT(::IsWindow(m_hWnd));
1067         return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
1068     }
1069 
1070     int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT flags)
1071     {
1072         ATLASSERT(::IsWindow(m_hWnd));
1073         return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, flags);
1074     }
1075 
1076     LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
1077     {
1078         ATLASSERT(::IsWindow(m_hWnd));
1079         return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam);
1080     }
1081 
1082     LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
1083     {
1084         ATLASSERT(::IsWindow(m_hWnd));
1085         return ::SendMessage(m_hWnd, message, wParam, lParam);
1086     }
1087 
1088     static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1089     {
1090         ATLASSERT(::IsWindow(hWnd));
1091         return ::SendMessage(hWnd, message, wParam, lParam);
1092     }
1093 
1094 private:
1095     static BOOL CALLBACK SendMessageToDescendantsCallback(HWND hWnd, LPARAM lParam)
1096     {
1097         ::SendMessage(hWnd, ((LPMSG)lParam)->message, ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam);
1098         return TRUE;
1099     }
1100 
1101     static BOOL CALLBACK SendMessageToDescendantsCallbackDeep(HWND hWnd, LPARAM lParam)
1102     {
1103         ::SendMessage(hWnd, ((LPMSG)lParam)->message, ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam);
1104         ::EnumChildWindows(hWnd, &SendMessageToDescendantsCallbackDeep, lParam);
1105         return TRUE;
1106     }
1107 
1108 public:
1109     void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE)
1110     {
1111         ATLASSERT(::IsWindow(m_hWnd));
1112         MSG msg;
1113         msg.message = message;
1114         msg.wParam = wParam;
1115         msg.lParam = lParam;
1116         if (bDeep)
1117             ::EnumChildWindows(m_hWnd, &SendMessageToDescendantsCallback, (LPARAM)&msg);
1118         else
1119             ::EnumChildWindows(m_hWnd, &SendMessageToDescendantsCallbackDeep, (LPARAM)&msg);
1120     }
1121 
1122     BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
1123     {
1124         ATLASSERT(::IsWindow(m_hWnd));
1125         return ::SendNotifyMessage(m_hWnd, message, wParam, lParam);
1126     }
1127 
1128     HWND SetActiveWindow()
1129     {
1130         ATLASSERT(::IsWindow(m_hWnd));
1131         return ::SetActiveWindow(m_hWnd);
1132     }
1133 
1134     HWND SetCapture()
1135     {
1136         ATLASSERT(::IsWindow(m_hWnd));
1137         return ::SetCapture(m_hWnd);
1138     }
1139 
1140     HWND SetClipboardViewer()
1141     {
1142         ATLASSERT(::IsWindow(m_hWnd));
1143         return ::SetClipboardViewer(m_hWnd);
1144     }
1145 
1146     int SetDlgCtrlID(int nID)
1147     {
1148         ATLASSERT(::IsWindow(m_hWnd));
1149         return ::SetWindowLong(m_hWnd, GWL_ID, nID);
1150     }
1151 
1152     BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE)
1153     {
1154         ATLASSERT(::IsWindow(m_hWnd));
1155         return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned);
1156     }
1157 
1158     BOOL SetDlgItemText(int nID, LPCTSTR lpszString)
1159     {
1160         ATLASSERT(::IsWindow(m_hWnd));
1161         return ::SetDlgItemText(m_hWnd, nID, lpszString);
1162     }
1163 
1164     HWND SetFocus()
1165     {
1166         ATLASSERT(::IsWindow(m_hWnd));
1167         return ::SetFocus(m_hWnd);
1168     }
1169 
1170     void SetFont(HFONT hFont, BOOL bRedraw = TRUE)
1171     {
1172         ATLASSERT(::IsWindow(m_hWnd));
1173         ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, (LPARAM)bRedraw);
1174     }
1175 
1176     int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers)
1177     {
1178         ATLASSERT(::IsWindow(m_hWnd));
1179         return ::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWPARAM(wVirtualKeyCode, wModifiers), 0);
1180     }
1181 
1182     HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE)
1183     {
1184         ATLASSERT(::IsWindow(m_hWnd));
1185         return (HICON)::SendMessage(m_hWnd, WM_SETICON, (WPARAM)bBigIcon, (LPARAM)hIcon);
1186     }
1187 
1188     BOOL SetMenu(HMENU hMenu)
1189     {
1190         ATLASSERT(::IsWindow(m_hWnd));
1191         return ::SetMenu(m_hWnd, hMenu);
1192     }
1193 
1194     HWND SetParent(HWND hWndNewParent)
1195     {
1196         ATLASSERT(::IsWindow(m_hWnd));
1197         return ::SetParent(m_hWnd, hWndNewParent);
1198     }
1199 
1200     void SetRedraw(BOOL bRedraw = TRUE)
1201     {
1202         ATLASSERT(::IsWindow(m_hWnd));
1203         ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0);
1204     }
1205 
1206     int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
1207     {
1208         ATLASSERT(::IsWindow(m_hWnd));
1209         return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw);
1210     }
1211 
1212     int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
1213     {
1214         ATLASSERT(::IsWindow(m_hWnd));
1215         return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
1216     }
1217 
1218     BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
1219     {
1220         ATLASSERT(::IsWindow(m_hWnd));
1221         return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
1222     }
1223 
1224     UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL)
1225     {
1226         ATLASSERT(::IsWindow(m_hWnd));
1227         return ::SetTimer(m_hWnd, nIDEvent, nElapse, reinterpret_cast<TIMERPROC>(lpfnTimer));
1228     }
1229 
1230     BOOL SetWindowContextHelpId(DWORD dwContextHelpId)
1231     {
1232         ATLASSERT(::IsWindow(m_hWnd));
1233         return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId);
1234     }
1235 
1236     LONG SetWindowLong(int nIndex, LONG dwNewLong)
1237     {
1238         ATLASSERT(::IsWindow(m_hWnd));
1239         return ::SetWindowLong(m_hWnd, nIndex, dwNewLong);
1240     }
1241 
1242     LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong)
1243     {
1244         ATLASSERT(::IsWindow(m_hWnd));
1245         return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong);
1246     }
1247 
1248     BOOL SetWindowPlacement(const WINDOWPLACEMENT* lpwndpl)
1249     {
1250         ATLASSERT(::IsWindow(m_hWnd));
1251         return ::SetWindowPlacement(m_hWnd, lpwndpl);
1252     }
1253 
1254     BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
1255     {
1256         ATLASSERT(::IsWindow(m_hWnd));
1257         return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
1258     }
1259 
1260     int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE)
1261     {
1262         ATLASSERT(::IsWindow(m_hWnd));
1263         return ::SetWindowRgn(m_hWnd, hRgn, bRedraw);
1264     }
1265 
1266     BOOL SetWindowText(LPCTSTR lpszString)
1267     {
1268         ATLASSERT(::IsWindow(m_hWnd));
1269         return ::SetWindowText(m_hWnd, lpszString);
1270     }
1271 
1272     WORD SetWindowWord(int nIndex, WORD wNewWord)
1273     {
1274         ATLASSERT(::IsWindow(m_hWnd));
1275         if (nIndex >= -4)
1276             return ::SetWindowLong(m_hWnd, nIndex - 2, MAKELONG(LOWORD(::GetWindowLong(m_hWnd, nIndex - 2)), wNewWord));
1277         else
1278             return ::SetWindowLong(m_hWnd, nIndex, MAKELONG(wNewWord, HIWORD(::GetWindowLong(m_hWnd, nIndex))));
1279     }
1280 
1281     BOOL ShowCaret()
1282     {
1283         ATLASSERT(::IsWindow(m_hWnd));
1284         return ::ShowCaret(m_hWnd);
1285     }
1286 
1287     BOOL ShowOwnedPopups(BOOL bShow = TRUE)
1288     {
1289         ATLASSERT(::IsWindow(m_hWnd));
1290         return ::ShowOwnedPopups(m_hWnd, bShow);
1291     }
1292 
1293     BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE)
1294     {
1295         ATLASSERT(::IsWindow(m_hWnd));
1296         return ::ShowScrollBar(m_hWnd, nBar, bShow);
1297     }
1298 
1299     BOOL ShowWindow(int nCmdShow)
1300     {
1301         ATLASSERT(::IsWindow(m_hWnd));
1302         return ::ShowWindow(m_hWnd, nCmdShow);
1303     }
1304 
1305     BOOL ShowWindowAsync(int nCmdShow)
1306     {
1307         ATLASSERT(::IsWindow(m_hWnd));
1308         return ::ShowWindowAsync(m_hWnd, nCmdShow);
1309     }
1310 
1311     BOOL UpdateWindow()
1312     {
1313         ATLASSERT(::IsWindow(m_hWnd));
1314         return ::UpdateWindow(m_hWnd);
1315     }
1316 
1317     BOOL ValidateRect(LPCRECT lpRect)
1318     {
1319         ATLASSERT(::IsWindow(m_hWnd));
1320         return ::ValidateRect(m_hWnd, lpRect);
1321     }
1322 
1323     BOOL ValidateRgn(HRGN hRgn)
1324     {
1325         ATLASSERT(::IsWindow(m_hWnd));
1326         return ::ValidateRgn(m_hWnd, hRgn);
1327     }
1328 
1329     BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0)
1330     {
1331         ATLASSERT(::IsWindow(m_hWnd));
1332         return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData);
1333     }
1334 };
1335 
1336 __declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
1337 
1338 template <class TBase = CWindow>
1339 class CWindowImplRoot : public TBase, public CMessageMap
1340 {
1341 public:
1342     enum { WINSTATE_DESTROYED = 0x00000001 };
1343 
1344 public:
1345     CWndProcThunk m_thunk;
1346     const _ATL_MSG *m_pCurrentMsg;
1347     DWORD m_dwState;
1348 
1349     CWindowImplRoot()
1350         : m_pCurrentMsg(NULL)
1351         , m_dwState(0)
1352     {
1353     }
1354 
1355     virtual ~CWindowImplRoot()
1356     {
1357     }
1358 };
1359 
1360 
1361 template <class TBase = CWindow>
1362 class CDialogImplBaseT : public CWindowImplRoot<TBase>
1363 {
1364 public:
1365     // + Hacks for gcc
1366     using CWindowImplRoot<TBase>::WINSTATE_DESTROYED;
1367     // - Hacks for gcc
1368 
1369     virtual ~CDialogImplBaseT()
1370     {
1371     }
1372     virtual DLGPROC GetDialogProc()
1373     {
1374         return DialogProc;
1375     }
1376 
1377     static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1378     {
1379         CDialogImplBaseT<TBase>* pThis;
1380         DLGPROC newDlgProc;
1381         DLGPROC GCCU(pOldProc);
1382 
1383         pThis = reinterpret_cast<CDialogImplBaseT<TBase>*>(_AtlWinModule.ExtractCreateWndData());
1384         ATLASSERT(pThis != NULL);
1385         if (pThis == NULL)
1386             return 0;
1387 
1388         pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis);
1389         newDlgProc = reinterpret_cast<DLGPROC>(pThis->m_thunk.GetWNDPROC());
1390         pOldProc = reinterpret_cast<DLGPROC>(::SetWindowLongPtr(hWnd, DWLP_DLGPROC, reinterpret_cast<LONG_PTR>(newDlgProc)));
1391         Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
1392         pThis->m_hWnd = hWnd;
1393         return newDlgProc(hWnd, uMsg, wParam, lParam);
1394     }
1395 
1396     static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1397     {
1398         CDialogImplBaseT<TBase>* pThis = reinterpret_cast<CDialogImplBaseT<TBase>*>(hWnd);
1399         _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1400         LRESULT lResult = 0;
1401         const _ATL_MSG *previousMessage;
1402         BOOL handled;
1403 
1404         hWnd = pThis->m_hWnd;
1405         previousMessage = pThis->m_pCurrentMsg;
1406         pThis->m_pCurrentMsg = &msg;
1407 
1408         handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
1409         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1410 
1411         if (handled)
1412         {
1413             if ((pThis->m_dwState & WINSTATE_DESTROYED) == 0)
1414             {
1415                 ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lResult);
1416             }
1417         }
1418         else
1419         {
1420             if (uMsg == WM_NCDESTROY)
1421             {
1422                 pThis->m_dwState |= WINSTATE_DESTROYED;
1423             }
1424         }
1425 
1426         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1427         pThis->m_pCurrentMsg = previousMessage;
1428 
1429         if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
1430         {
1431             pThis->m_dwState &= ~WINSTATE_DESTROYED;
1432             pThis->m_hWnd = NULL;
1433             pThis->OnFinalMessage(hWnd);
1434         }
1435         return lResult;
1436     }
1437 
1438     virtual void OnFinalMessage(HWND)
1439     {
1440     }
1441 };
1442 
1443 
1444 template <class T, class TBase = CWindow>
1445 class CDialogImpl : public CDialogImplBaseT<TBase>
1446 {
1447 public:
1448     // + Hacks for gcc
1449     using CWindowImplRoot<TBase>::m_thunk;
1450     using CWindowImplRoot<TBase>::m_hWnd;
1451     // - Hacks for gcc
1452 
1453     HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
1454     {
1455         BOOL result;
1456         HWND hWnd;
1457         T* pImpl;
1458 
1459         result = m_thunk.Init(NULL, NULL);
1460         if (result == FALSE)
1461             return NULL;
1462 
1463         _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
1464 
1465         pImpl = static_cast<T*>(this);
1466         hWnd = ::CreateDialogParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pImpl->IDD), hWndParent, T::StartDialogProc, dwInitParam);
1467         return hWnd;
1468     }
1469 
1470     INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
1471     {
1472         BOOL result;
1473         T* pImpl;
1474 
1475         result = m_thunk.Init(NULL, NULL);
1476         if (result == FALSE)
1477             return -1;
1478 
1479         _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
1480 
1481         pImpl = static_cast<T*>(this);
1482         return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pImpl->IDD), hWndParent, T::StartDialogProc, dwInitParam);
1483     }
1484 
1485     BOOL EndDialog(_In_ int nRetCode)
1486     {
1487         return ::EndDialog(m_hWnd, nRetCode);
1488     }
1489 
1490     BOOL DestroyWindow()
1491     {
1492         return ::DestroyWindow(m_hWnd);
1493     }
1494 };
1495 
1496 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
1497 class CWindowImplBaseT : public CWindowImplRoot<TBase>
1498 {
1499 public:
1500     // + Hacks for gcc
1501     using CWindowImplRoot<TBase>::WINSTATE_DESTROYED;
1502     using CWindowImplRoot<TBase>::m_thunk;
1503     using CWindowImplRoot<TBase>::m_hWnd;
1504     // - Hacks for gcc
1505 
1506     WNDPROC m_pfnSuperWindowProc;
1507 
1508 public:
1509     CWindowImplBaseT()
1510     {
1511         m_pfnSuperWindowProc = ::DefWindowProc;
1512     }
1513 
1514     virtual void OnFinalMessage(HWND /* hWnd */)
1515     {
1516     }
1517 
1518     BOOL SubclassWindow(HWND hWnd)
1519     {
1520         ATLASSERT(m_hWnd == NULL);
1521         ATLASSERT(::IsWindow(hWnd));
1522 
1523         CWindowImplBaseT<TBase, TWinTraits>* pThis;
1524         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
1525 
1526         BOOL result = m_thunk.Init(GetWindowProc(), this);
1527         if (result == FALSE)
1528             return FALSE;
1529 
1530         WNDPROC newWindowProc = m_thunk.GetWNDPROC();
1531         WNDPROC oldWindowProc = reinterpret_cast<WNDPROC>(
1532             ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1533         if (oldWindowProc == NULL)
1534             return FALSE;
1535 
1536         pThis->m_pfnSuperWindowProc = oldWindowProc;
1537         pThis->m_hWnd = hWnd;
1538         return TRUE;
1539     }
1540 
1541     HWND UnsubclassWindow(BOOL bForce = FALSE)
1542     {
1543         ATLASSERT(m_hWnd != NULL);
1544         ATLASSERT(::IsWindow(m_hWnd));
1545 
1546         CWindowImplBaseT<TBase, TWinTraits>* pThis;
1547         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
1548 
1549         HWND hwndOld = pThis->m_hWnd;
1550         WNDPROC oldWindowProc = m_thunk.GetWNDPROC();
1551         WNDPROC subclassedProc = reinterpret_cast<WNDPROC>(
1552             ::GetWindowLongPtr(hwndOld, GWLP_WNDPROC));
1553         if (!bForce && oldWindowProc != subclassedProc)
1554             return NULL;
1555 
1556         ::SetWindowLongPtr(hwndOld, GWLP_WNDPROC,
1557                            (LONG_PTR)pThis->m_pfnSuperWindowProc);
1558         pThis->m_pfnSuperWindowProc = ::DefWindowProc;
1559         pThis->m_hWnd = NULL;
1560         return hwndOld;
1561     }
1562 
1563     virtual WNDPROC GetWindowProc()
1564     {
1565         return WindowProc;
1566     }
1567 
1568     static DWORD GetWndStyle(DWORD dwStyle)
1569     {
1570         return TWinTraits::GetWndStyle(dwStyle);
1571     }
1572 
1573     static DWORD GetWndExStyle(DWORD dwExStyle)
1574     {
1575         return TWinTraits::GetWndExStyle(dwExStyle);
1576     }
1577 
1578     LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
1579     {
1580         CWindowImplBaseT<TBase, TWinTraits>* pThis;
1581         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
1582         return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
1583     }
1584 
1585     static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1586     {
1587         CWindowImplBaseT<TBase, TWinTraits>* pThis;
1588         WNDPROC newWindowProc;
1589         WNDPROC GCCU(pOldProc);
1590 
1591         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(_AtlWinModule.ExtractCreateWndData());
1592         ATLASSERT(pThis != NULL);
1593         if (pThis == NULL)
1594             return 0;
1595 
1596         pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
1597         newWindowProc = pThis->m_thunk.GetWNDPROC();
1598         pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1599         Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
1600         pThis->m_hWnd = hWnd;
1601         return newWindowProc(hWnd, uMsg, wParam, lParam);
1602     }
1603 
1604     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1605     {
1606         CWindowImplBaseT<TBase, TWinTraits>* pThis = reinterpret_cast<CWindowImplBaseT< TBase, TWinTraits>*>(hWnd);
1607         _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1608         LRESULT lResult;
1609         const _ATL_MSG *previousMessage;
1610         BOOL handled;
1611         LONG_PTR saveWindowProc;
1612 
1613         ATLASSERT(pThis != NULL);
1614         if (pThis == NULL)
1615             return 0;
1616 
1617         ATLASSERT((pThis->m_dwState & WINSTATE_DESTROYED) == 0);
1618         ATLASSERT(pThis->m_hWnd != NULL);
1619         if ((pThis->m_dwState & WINSTATE_DESTROYED) != 0 || pThis->m_hWnd == NULL)
1620             return 0;
1621 
1622         hWnd = pThis->m_hWnd;
1623         previousMessage = pThis->m_pCurrentMsg;
1624         pThis->m_pCurrentMsg = &msg;
1625 
1626         handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
1627         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1628 
1629         if (handled == FALSE)
1630         {
1631             if (uMsg == WM_NCDESTROY)
1632             {
1633                 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
1634                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1635                 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
1636                     ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
1637                 pThis->m_dwState |= WINSTATE_DESTROYED;
1638             }
1639             else
1640             {
1641                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1642             }
1643         }
1644         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1645         pThis->m_pCurrentMsg = previousMessage;
1646         if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
1647         {
1648             pThis->m_dwState &= ~WINSTATE_DESTROYED;
1649             pThis->m_hWnd = NULL;
1650             pThis->OnFinalMessage(hWnd);
1651         }
1652         return lResult;
1653     }
1654 
1655     HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle,
1656                 _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
1657     {
1658         HWND hWnd;
1659 
1660         ATLASSERT(m_hWnd == NULL);
1661         ATLASSERT(atom != 0);
1662         if (atom == 0)
1663             return NULL;
1664         if (m_thunk.Init(NULL, NULL) == FALSE)
1665         {
1666             SetLastError(ERROR_OUTOFMEMORY);
1667             return NULL;
1668         }
1669 
1670         _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
1671         if (MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD) != 0)
1672             MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
1673         if (rect.m_lpRect == NULL)
1674             rect.m_lpRect = &TBase::rcDefault;
1675 
1676         hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, dwStyle, rect.m_lpRect->left,
1677                     rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top,
1678                     hWndParent, MenuOrID.m_hMenu, _AtlBaseModule.GetModuleInstance(), lpCreateParam);
1679 
1680         ATLASSERT(m_hWnd == hWnd);
1681 
1682         return hWnd;
1683     }
1684 };
1685 
1686 
1687 template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
1688 class CWindowImpl : public CWindowImplBaseT<TBase, TWinTraits>
1689 {
1690 public:
1691     // + Hacks for gcc
1692     using CWindowImplRoot<TBase>::m_hWnd;
1693     // - Hacks for gcc
1694 
1695     static LPCTSTR GetWndCaption()
1696     {
1697         return NULL;
1698     }
1699 
1700     HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0,
1701                 DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
1702     {
1703         CWindowImplBaseT<TBase, TWinTraits>* pThis;
1704         ATOM atom;
1705 
1706         ATLASSERT(m_hWnd == NULL);
1707         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
1708 
1709         if (T::GetWndClassInfo().m_lpszOrigName == NULL)
1710             T::GetWndClassInfo().m_lpszOrigName = pThis->GetWndClassName();
1711         atom = T::GetWndClassInfo().Register(&pThis->m_pfnSuperWindowProc);
1712 
1713         if (szWindowName == NULL)
1714             szWindowName = T::GetWndCaption();
1715         dwStyle = T::GetWndStyle(dwStyle);
1716         dwExStyle = T::GetWndExStyle(dwExStyle);
1717 
1718         return CWindowImplBaseT<TBase, TWinTraits>::Create(hWndParent, rect, szWindowName, dwStyle,
1719                         dwExStyle, MenuOrID, atom, lpCreateParam);
1720     }
1721 };
1722 
1723 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
1724 class CContainedWindowT : public TBase
1725 {
1726 public:
1727     // + Hacks for gcc
1728     using TBase::m_hWnd;
1729     // - Hacks for gcc
1730 
1731     CWndProcThunk m_thunk;
1732     LPCTSTR m_lpszClassName;
1733     WNDPROC m_pfnSuperWindowProc;
1734     CMessageMap *m_pObject;
1735     DWORD m_dwMsgMapID;
1736     const _ATL_MSG *m_pCurrentMsg;
1737 
1738 public:
1739     CContainedWindowT(CMessageMap *pObject, DWORD dwMsgMapID = 0)
1740     {
1741         m_lpszClassName = TBase::GetWndClassName();
1742         m_pfnSuperWindowProc = ::DefWindowProc;
1743         m_pObject = pObject;
1744         m_dwMsgMapID = dwMsgMapID;
1745         m_pCurrentMsg = NULL;
1746     }
1747 
1748     CContainedWindowT(LPCTSTR lpszClassName, CMessageMap *pObject, DWORD dwMsgMapID = 0)
1749     {
1750         m_lpszClassName = lpszClassName;
1751         m_pfnSuperWindowProc = ::DefWindowProc;
1752         m_pObject = pObject;
1753         m_dwMsgMapID = dwMsgMapID;
1754         m_pCurrentMsg = NULL;
1755     }
1756 
1757     LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
1758     {
1759         return ::CallWindowProc(m_pfnSuperWindowProc, this->m_hWnd, uMsg, wParam, lParam);
1760     }
1761 
1762     BOOL SubclassWindow(HWND hWnd)
1763     {
1764         ATLASSERT(m_hWnd == NULL);
1765         ATLASSERT(::IsWindow(hWnd));
1766 
1767         CContainedWindowT<TBase>* pThis;
1768         pThis = reinterpret_cast<CContainedWindowT<TBase>*>(this);
1769 
1770         BOOL result = m_thunk.Init(WindowProc, pThis);
1771         if (result == FALSE)
1772             return FALSE;
1773 
1774         WNDPROC newWindowProc = m_thunk.GetWNDPROC();
1775         WNDPROC oldWindowProc = reinterpret_cast<WNDPROC>(
1776             ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1777         if (oldWindowProc == NULL)
1778             return FALSE;
1779 
1780         pThis->m_pfnSuperWindowProc = oldWindowProc;
1781         pThis->m_hWnd = hWnd;
1782         return TRUE;
1783     }
1784 
1785     HWND UnsubclassWindow(BOOL bForce = FALSE)
1786     {
1787         ATLASSERT(m_hWnd != NULL);
1788         ATLASSERT(::IsWindow(m_hWnd));
1789 
1790         CContainedWindowT<TBase>* pThis;
1791         pThis = reinterpret_cast<CContainedWindowT<TBase>*>(this);
1792         HWND hwndOld = pThis->m_hWnd;
1793 
1794         WNDPROC subclassedProc = reinterpret_cast<WNDPROC>(
1795             ::GetWindowLongPtr(hwndOld, GWLP_WNDPROC));
1796         if (!bForce && m_thunk.GetWNDPROC() != subclassedProc)
1797             return NULL;
1798 
1799         ::SetWindowLongPtr(hwndOld, GWLP_WNDPROC,
1800                            (LONG_PTR)pThis->m_pfnSuperWindowProc);
1801         pThis->m_pfnSuperWindowProc = ::DefWindowProc;
1802         pThis->m_hWnd = NULL;
1803         return hwndOld;
1804     }
1805 
1806     static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1807     {
1808         CContainedWindowT<TBase>* pThis;
1809         WNDPROC newWindowProc;
1810         WNDPROC GCCU(pOldProc);
1811 
1812         pThis = reinterpret_cast<CContainedWindowT<TBase>*>(_AtlWinModule.ExtractCreateWndData());
1813         ATLASSERT(pThis != NULL);
1814         if (pThis == NULL)
1815             return 0;
1816         pThis->m_thunk.Init(WindowProc, pThis);
1817         newWindowProc = pThis->m_thunk.GetWNDPROC();
1818         pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1819         Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
1820         pThis->m_hWnd = hWnd;
1821         return newWindowProc(hWnd, uMsg, wParam, lParam);
1822     }
1823 
1824     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1825     {
1826         CContainedWindowT<TBase>* pThis = reinterpret_cast<CContainedWindowT<TBase>*>(hWnd);
1827         _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1828         LRESULT lResult;
1829         const _ATL_MSG *previousMessage;
1830         BOOL handled;
1831         LONG_PTR saveWindowProc;
1832 
1833         ATLASSERT(pThis != NULL && pThis->m_hWnd != NULL && pThis->m_pObject != NULL);
1834         if (pThis == NULL || pThis->m_hWnd == NULL || pThis->m_pObject == NULL)
1835             return 0;
1836 
1837         hWnd = pThis->m_hWnd;
1838         previousMessage = pThis->m_pCurrentMsg;
1839         pThis->m_pCurrentMsg = &msg;
1840 
1841         handled = pThis->m_pObject->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, pThis->m_dwMsgMapID);
1842         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1843 
1844         pThis->m_pCurrentMsg = previousMessage;
1845         if (handled == FALSE)
1846         {
1847             if (uMsg == WM_NCDESTROY)
1848             {
1849                 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
1850                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1851                 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
1852                     ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
1853                 pThis->m_hWnd = NULL;
1854             }
1855             else
1856                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1857         }
1858         return lResult;
1859     }
1860 
1861 };
1862 typedef CContainedWindowT<CWindow> CContainedWindow;
1863 
1864 #define BEGIN_MSG_MAP(theClass)     \
1865 public:                             \
1866     BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
1867     {                               \
1868         BOOL GCCU(bHandled) = TRUE; \
1869         Unused(hWnd);               \
1870         Unused(uMsg);               \
1871         Unused(wParam);             \
1872         Unused(lParam);             \
1873         Unused(lResult);            \
1874         Unused(bHandled);           \
1875         switch(dwMsgMapID)          \
1876         {                           \
1877         case 0:
1878 
1879 #define ALT_MSG_MAP(map) \
1880             break;       \
1881         case map:
1882 
1883 #define END_MSG_MAP()   \
1884             break;      \
1885         default:        \
1886             ATLASSERT(FALSE); \
1887             break;      \
1888         }               \
1889         return FALSE;   \
1890     }
1891 
1892 #define MESSAGE_HANDLER(msg, func)  \
1893     if (uMsg == msg)                \
1894     {                               \
1895         bHandled = TRUE;            \
1896         lResult = func(uMsg, wParam, lParam, bHandled); \
1897         if (bHandled)               \
1898             return TRUE;            \
1899     }
1900 
1901 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func)  \
1902     if (uMsg >= msgFirst && uMsg <= msgLast)            \
1903     {                                                   \
1904         bHandled = TRUE;                                \
1905         lResult = func(uMsg, wParam, lParam, bHandled); \
1906         if (bHandled)                                   \
1907             return TRUE;                                \
1908     }
1909 
1910 #define COMMAND_HANDLER(id, code, func) \
1911     if (uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
1912     {                                   \
1913         bHandled = TRUE;                \
1914         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
1915         if (bHandled)                   \
1916             return TRUE;                \
1917     }
1918 
1919 #define COMMAND_ID_HANDLER(id, func)    \
1920     if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
1921     {                                   \
1922         bHandled = TRUE;                \
1923         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
1924         if (bHandled)                   \
1925             return TRUE;                \
1926     }
1927 
1928 #define COMMAND_CODE_HANDLER(code, func)    \
1929     if (uMsg == WM_COMMAND && code == HIWORD(wParam)) \
1930     {                                       \
1931         bHandled = TRUE;                    \
1932         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
1933         if (bHandled)                       \
1934             return TRUE;                    \
1935     }
1936 
1937 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func)    \
1938     if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
1939     {                                                   \
1940         bHandled = TRUE;                                \
1941         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
1942         if (bHandled)                                   \
1943             return TRUE;                                \
1944     }
1945 
1946 #define NOTIFY_CODE_HANDLER(cd, func)   \
1947     if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
1948     {                                   \
1949         bHandled = TRUE;                \
1950         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
1951         if (bHandled)                   \
1952             return TRUE;                \
1953     }
1954 
1955 #define NOTIFY_HANDLER(id, cd, func)    \
1956     if (uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
1957     {                                   \
1958         bHandled = TRUE;                \
1959         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
1960         if (bHandled)                   \
1961             return TRUE;                \
1962     }
1963 
1964 #define CHAIN_MSG_MAP(theChainClass)    \
1965     {                                   \
1966         if (theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
1967             return TRUE;                \
1968     }
1969 
1970 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd)    \
1971 static ATL::CWndClassInfo& GetWndClassInfo()                \
1972 {                                                           \
1973     static ATL::CWndClassInfo wc =                          \
1974     {                                                       \
1975         { sizeof(WNDCLASSEX), style, StartWindowProc,       \
1976           0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
1977         NULL, NULL, IDC_ARROW, TRUE, 0, _T("")              \
1978     };                                                      \
1979     return wc;                                              \
1980 }
1981 
1982 struct _ATL_WNDCLASSINFOW
1983 {
1984     WNDCLASSEX m_wc;
1985     LPCTSTR m_lpszOrigName;
1986     WNDPROC pWndProc;
1987     LPCTSTR m_lpszCursorID;
1988     BOOL m_bSystemCursor;
1989     ATOM m_atom;
1990     TCHAR m_szAutoName[sizeof("ATL:") + sizeof(void *) * 2]; // == 4 characters + NULL + number of hexadecimal digits describing a pointer.
1991 
1992     ATOM Register(WNDPROC *p)
1993     {
1994         if (m_wc.hInstance == NULL)
1995             m_wc.hInstance = _AtlBaseModule.GetModuleInstance();
1996         if (m_atom == 0)
1997         {
1998             if (m_bSystemCursor)
1999                 m_wc.hCursor = ::LoadCursor(NULL, m_lpszCursorID);
2000             else
2001                 m_wc.hCursor = ::LoadCursor(_AtlBaseModule.GetResourceInstance(), m_lpszCursorID);
2002 
2003             m_atom = RegisterClassEx(&m_wc);
2004         }
2005 
2006         return m_atom;
2007     }
2008 };
2009 
2010 }; // namespace ATL
2011 
2012 #pragma pop_macro("SubclassWindow")
2013 
2014