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