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