xref: /reactos/sdk/lib/atl/atlwin.h (revision 019f21ee)
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 = ::GetWindowTextLength(m_hWnd);
786         if (!SysReAllocStringLen(&bstrText, NULL, length))
787             return FALSE;
788         ::GetWindowText(m_hWnd, (LPTSTR)&bstrText[2], length);
789         return TRUE;
790     }
791 
792     int GetWindowTextLength() const
793     {
794         ATLASSERT(::IsWindow(m_hWnd));
795         return ::GetWindowTextLength(m_hWnd);
796     }
797 
798     DWORD GetWindowThreadID()
799     {
800         ATLASSERT(::IsWindow(m_hWnd));
801         return ::GetWindowThreadProcessId(m_hWnd, NULL);
802     }
803 
804     WORD GetWindowWord(int nIndex) const
805     {
806         ATLASSERT(::IsWindow(m_hWnd));
807         return (WORD)::GetWindowLong(m_hWnd, nIndex);
808     }
809 
810     void GotoDlgCtrl(HWND hWndCtrl) const
811     {
812         ATLASSERT(::IsWindow(m_hWnd));
813         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0);
814     }
815 
816     BOOL HideCaret()
817     {
818         ATLASSERT(::IsWindow(m_hWnd));
819         return ::HideCaret(m_hWnd);
820     }
821 
822     BOOL HiliteMenuItem(HMENU hMenu, UINT uHiliteItem, UINT uHilite)
823     {
824         ATLASSERT(::IsWindow(m_hWnd));
825         return ::HiliteMenuItem(m_hWnd, hMenu, uHiliteItem, uHilite);
826     }
827 
828     BOOL Invalidate(BOOL bErase = TRUE)
829     {
830         ATLASSERT(::IsWindow(m_hWnd));
831         return ::InvalidateRect(m_hWnd, NULL, bErase);
832     }
833 
834     BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE)
835     {
836         ATLASSERT(::IsWindow(m_hWnd));
837         return ::InvalidateRect(m_hWnd, lpRect, bErase);
838     }
839 
840     void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE)
841     {
842         ATLASSERT(::IsWindow(m_hWnd));
843         ::InvalidateRgn(m_hWnd, hRgn, bErase);
844     }
845 
846     BOOL IsChild(const HWND hWnd) const
847     {
848         ATLASSERT(::IsWindow(m_hWnd));
849         return ::IsChild(m_hWnd, hWnd);
850     }
851 
852     BOOL IsDialogMessage(LPMSG lpMsg)
853     {
854         ATLASSERT(::IsWindow(m_hWnd));
855         return ::IsDialogMessage(m_hWnd, lpMsg);
856     }
857 
858     UINT IsDlgButtonChecked(int nIDButton) const
859     {
860         ATLASSERT(::IsWindow(m_hWnd));
861         return ::IsDlgButtonChecked(m_hWnd, nIDButton);
862     }
863 
864     BOOL IsIconic() const
865     {
866         ATLASSERT(::IsWindow(m_hWnd));
867         return ::IsIconic(m_hWnd);
868     }
869 
870     BOOL IsParentDialog()
871     {
872         ATLASSERT(::IsWindow(m_hWnd));
873         TCHAR pszType[10];
874         if (!RealGetWindowClass(::GetParent(m_hWnd), pszType, sizeof(pszType) / sizeof(pszType[0])))
875             return FALSE;
876         return !_tcscmp(pszType, _T("#32770"));
877     }
878 
879     BOOL IsWindow() const
880     {
881         return ::IsWindow(m_hWnd);
882     }
883 
884     BOOL IsWindowEnabled() const
885     {
886         ATLASSERT(::IsWindow(m_hWnd));
887         return ::IsWindowEnabled(m_hWnd);
888     }
889 
890     BOOL IsWindowVisible() const
891     {
892         ATLASSERT(::IsWindow(m_hWnd));
893         return ::IsWindowVisible(m_hWnd);
894     }
895 
896     BOOL IsWindowUnicode()
897     {
898         ATLASSERT(::IsWindow(m_hWnd));
899         return ::IsWindowUnicode(m_hWnd);
900     }
901 
902     BOOL IsZoomed() const
903     {
904         ATLASSERT(::IsWindow(m_hWnd));
905         return ::IsZoomed(m_hWnd);
906     }
907 
908     BOOL KillTimer(UINT_PTR nIDEvent)
909     {
910         ATLASSERT(::IsWindow(m_hWnd));
911         return ::KillTimer(m_hWnd, nIDEvent);
912     }
913 
914     BOOL LockWindowUpdate(BOOL bLock = TRUE)
915     {
916         ATLASSERT(::IsWindow(m_hWnd));
917         if (bLock)
918             return ::LockWindowUpdate(m_hWnd);
919         return ::LockWindowUpdate(NULL);
920     }
921 
922     int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const
923     {
924         ATLASSERT(::IsWindow(m_hWnd));
925         return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount);
926     }
927 
928     int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const
929     {
930         ATLASSERT(::IsWindow(m_hWnd));
931         return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, sizeof(RECT) / sizeof(POINT));
932     }
933 
934     int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK)
935     {
936         ATLASSERT(::IsWindow(m_hWnd));
937         return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType);
938     }
939 
940     BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
941     {
942         ATLASSERT(::IsWindow(m_hWnd));
943         ::SetWindowLong(m_hWnd, GWL_STYLE, (::GetWindowLong(m_hWnd, GWL_STYLE) & ~dwRemove) | dwAdd);
944         if (nFlags != 0)
945             return ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, nFlags | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
946         return TRUE;
947     }
948 
949     BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
950     {
951         ATLASSERT(::IsWindow(m_hWnd));
952         ::SetWindowLong(m_hWnd, GWL_EXSTYLE, (::GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~dwRemove) | dwAdd);
953         if (nFlags != 0)
954             return ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, nFlags | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
955         return TRUE;
956     }
957 
958     BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE)
959     {
960         ATLASSERT(::IsWindow(m_hWnd));
961         return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint);
962     }
963 
964     void NextDlgCtrl() const
965     {
966         ATLASSERT(::IsWindow(m_hWnd));
967         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0);
968     }
969 
970     BOOL OpenClipboard()
971     {
972         ATLASSERT(::IsWindow(m_hWnd));
973         return ::OpenClipboard(m_hWnd);
974     }
975 
976     BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
977     {
978         ATLASSERT(::IsWindow(m_hWnd));
979         return ::PostMessage(m_hWnd, message, wParam, lParam);
980     }
981 
982     void PrevDlgCtrl() const
983     {
984         ATLASSERT(::IsWindow(m_hWnd));
985         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0);
986     }
987 
988     void Print(HDC hDC, DWORD dwFlags) const
989     {
990         ATLASSERT(::IsWindow(m_hWnd));
991         ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, (LPARAM)dwFlags);
992     }
993 
994     void PrintClient(HDC hDC, DWORD dwFlags) const
995     {
996         ATLASSERT(::IsWindow(m_hWnd));
997         ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, (LPARAM)dwFlags);
998     }
999 
1000     BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE)
1001     {
1002         ATLASSERT(::IsWindow(m_hWnd));
1003         return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags);
1004     }
1005 
1006     int ReleaseDC(HDC hDC)
1007     {
1008         ATLASSERT(::IsWindow(m_hWnd));
1009         return ::ReleaseDC(m_hWnd, hDC);
1010     }
1011 
1012     BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = FALSE)
1013     {
1014         ATLASSERT(::IsWindow(m_hWnd));
1015         RECT clientRect, wndRect;
1016         ::GetClientRect(m_hWnd, &clientRect);
1017         ::GetWindowRect(m_hWnd, &wndRect);
1018         return ::MoveWindow(m_hWnd, wndRect.left, wndRect.top,
1019                             nWidth + (wndRect.right - wndRect.left) - (clientRect.right - clientRect.left),
1020                             nHeight + (wndRect.bottom - wndRect.top) - (clientRect.bottom - clientRect.top),
1021                             bRedraw);
1022     }
1023 
1024     BOOL ScreenToClient(LPPOINT lpPoint) const
1025     {
1026         ATLASSERT(::IsWindow(m_hWnd));
1027         return ::ScreenToClient(m_hWnd, lpPoint);
1028     }
1029 
1030     BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL)
1031     {
1032         ATLASSERT(::IsWindow(m_hWnd));
1033         return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
1034     }
1035 
1036     int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT flags)
1037     {
1038         ATLASSERT(::IsWindow(m_hWnd));
1039         return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, flags);
1040     }
1041 
1042     LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
1043     {
1044         ATLASSERT(::IsWindow(m_hWnd));
1045         return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam);
1046     }
1047 
1048     LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
1049     {
1050         ATLASSERT(::IsWindow(m_hWnd));
1051         return ::SendMessage(m_hWnd, message, wParam, lParam);
1052     }
1053 
1054     static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1055     {
1056         ATLASSERT(::IsWindow(hWnd));
1057         return ::SendMessage(hWnd, message, wParam, lParam);
1058     }
1059 
1060 private:
1061     static BOOL CALLBACK SendMessageToDescendantsCallback(HWND hWnd, LPARAM lParam)
1062     {
1063         ::SendMessage(hWnd, ((LPMSG)lParam)->message, ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam);
1064         return TRUE;
1065     }
1066 
1067     static BOOL CALLBACK SendMessageToDescendantsCallbackDeep(HWND hWnd, LPARAM lParam)
1068     {
1069         ::SendMessage(hWnd, ((LPMSG)lParam)->message, ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam);
1070         ::EnumChildWindows(hWnd, &SendMessageToDescendantsCallbackDeep, lParam);
1071         return TRUE;
1072     }
1073 
1074 public:
1075     void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE)
1076     {
1077         ATLASSERT(::IsWindow(m_hWnd));
1078         MSG msg;
1079         msg.message = message;
1080         msg.wParam = wParam;
1081         msg.lParam = lParam;
1082         if (bDeep)
1083             ::EnumChildWindows(m_hWnd, &SendMessageToDescendantsCallback, (LPARAM)&msg);
1084         else
1085             ::EnumChildWindows(m_hWnd, &SendMessageToDescendantsCallbackDeep, (LPARAM)&msg);
1086     }
1087 
1088     BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
1089     {
1090         ATLASSERT(::IsWindow(m_hWnd));
1091         return ::SendNotifyMessage(m_hWnd, message, wParam, lParam);
1092     }
1093 
1094     HWND SetActiveWindow()
1095     {
1096         ATLASSERT(::IsWindow(m_hWnd));
1097         return ::SetActiveWindow(m_hWnd);
1098     }
1099 
1100     HWND SetCapture()
1101     {
1102         ATLASSERT(::IsWindow(m_hWnd));
1103         return ::SetCapture(m_hWnd);
1104     }
1105 
1106     HWND SetClipboardViewer()
1107     {
1108         ATLASSERT(::IsWindow(m_hWnd));
1109         return ::SetClipboardViewer(m_hWnd);
1110     }
1111 
1112     int SetDlgCtrlID(int nID)
1113     {
1114         ATLASSERT(::IsWindow(m_hWnd));
1115         return ::SetWindowLong(m_hWnd, GWL_ID, nID);
1116     }
1117 
1118     BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE)
1119     {
1120         ATLASSERT(::IsWindow(m_hWnd));
1121         return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned);
1122     }
1123 
1124     BOOL SetDlgItemText(int nID, LPCTSTR lpszString)
1125     {
1126         ATLASSERT(::IsWindow(m_hWnd));
1127         return ::SetDlgItemText(m_hWnd, nID, lpszString);
1128     }
1129 
1130     HWND SetFocus()
1131     {
1132         ATLASSERT(::IsWindow(m_hWnd));
1133         return ::SetFocus(m_hWnd);
1134     }
1135 
1136     void SetFont(HFONT hFont, BOOL bRedraw = TRUE)
1137     {
1138         ATLASSERT(::IsWindow(m_hWnd));
1139         ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, (LPARAM)bRedraw);
1140     }
1141 
1142     int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers)
1143     {
1144         ATLASSERT(::IsWindow(m_hWnd));
1145         return ::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWPARAM(wVirtualKeyCode, wModifiers), 0);
1146     }
1147 
1148     HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE)
1149     {
1150         ATLASSERT(::IsWindow(m_hWnd));
1151         return (HICON)::SendMessage(m_hWnd, WM_SETICON, (WPARAM)bBigIcon, (LPARAM)hIcon);
1152     }
1153 
1154     BOOL SetMenu(HMENU hMenu)
1155     {
1156         ATLASSERT(::IsWindow(m_hWnd));
1157         return ::SetMenu(m_hWnd, hMenu);
1158     }
1159 
1160     HWND SetParent(HWND hWndNewParent)
1161     {
1162         ATLASSERT(::IsWindow(m_hWnd));
1163         return ::SetParent(m_hWnd, hWndNewParent);
1164     }
1165 
1166     void SetRedraw(BOOL bRedraw = TRUE)
1167     {
1168         ATLASSERT(::IsWindow(m_hWnd));
1169         ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0);
1170     }
1171 
1172     int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
1173     {
1174         ATLASSERT(::IsWindow(m_hWnd));
1175         return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw);
1176     }
1177 
1178     int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
1179     {
1180         ATLASSERT(::IsWindow(m_hWnd));
1181         return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
1182     }
1183 
1184     BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
1185     {
1186         ATLASSERT(::IsWindow(m_hWnd));
1187         return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
1188     }
1189 
1190     UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL)
1191     {
1192         ATLASSERT(::IsWindow(m_hWnd));
1193         return ::SetTimer(m_hWnd, nIDEvent, nElapse, reinterpret_cast<TIMERPROC>(lpfnTimer));
1194     }
1195 
1196     BOOL SetWindowContextHelpId(DWORD dwContextHelpId)
1197     {
1198         ATLASSERT(::IsWindow(m_hWnd));
1199         return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId);
1200     }
1201 
1202     LONG SetWindowLong(int nIndex, LONG dwNewLong)
1203     {
1204         ATLASSERT(::IsWindow(m_hWnd));
1205         return ::SetWindowLong(m_hWnd, nIndex, dwNewLong);
1206     }
1207 
1208     LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong)
1209     {
1210         ATLASSERT(::IsWindow(m_hWnd));
1211         return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong);
1212     }
1213 
1214     BOOL SetWindowPlacement(const WINDOWPLACEMENT* lpwndpl)
1215     {
1216         ATLASSERT(::IsWindow(m_hWnd));
1217         return ::SetWindowPlacement(m_hWnd, lpwndpl);
1218     }
1219 
1220     BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
1221     {
1222         ATLASSERT(::IsWindow(m_hWnd));
1223         return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
1224     }
1225 
1226     int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE)
1227     {
1228         ATLASSERT(::IsWindow(m_hWnd));
1229         return ::SetWindowRgn(m_hWnd, hRgn, bRedraw);
1230     }
1231 
1232     BOOL SetWindowText(LPCTSTR lpszString)
1233     {
1234         ATLASSERT(::IsWindow(m_hWnd));
1235         return ::SetWindowText(m_hWnd, lpszString);
1236     }
1237 
1238     WORD SetWindowWord(int nIndex, WORD wNewWord)
1239     {
1240         ATLASSERT(::IsWindow(m_hWnd));
1241         if (nIndex >= -4)
1242             return ::SetWindowLong(m_hWnd, nIndex - 2, MAKELONG(LOWORD(::GetWindowLong(m_hWnd, nIndex - 2)), wNewWord));
1243         else
1244             return ::SetWindowLong(m_hWnd, nIndex, MAKELONG(wNewWord, HIWORD(::GetWindowLong(m_hWnd, nIndex))));
1245     }
1246 
1247     BOOL ShowCaret()
1248     {
1249         ATLASSERT(::IsWindow(m_hWnd));
1250         return ::ShowCaret(m_hWnd);
1251     }
1252 
1253     BOOL ShowOwnedPopups(BOOL bShow = TRUE)
1254     {
1255         ATLASSERT(::IsWindow(m_hWnd));
1256         return ::ShowOwnedPopups(m_hWnd, bShow);
1257     }
1258 
1259     BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE)
1260     {
1261         ATLASSERT(::IsWindow(m_hWnd));
1262         return ::ShowScrollBar(m_hWnd, nBar, bShow);
1263     }
1264 
1265     BOOL ShowWindow(int nCmdShow)
1266     {
1267         ATLASSERT(::IsWindow(m_hWnd));
1268         return ::ShowWindow(m_hWnd, nCmdShow);
1269     }
1270 
1271     BOOL ShowWindowAsync(int nCmdShow)
1272     {
1273         ATLASSERT(::IsWindow(m_hWnd));
1274         return ::ShowWindowAsync(m_hWnd, nCmdShow);
1275     }
1276 
1277     BOOL UpdateWindow()
1278     {
1279         ATLASSERT(::IsWindow(m_hWnd));
1280         return ::UpdateWindow(m_hWnd);
1281     }
1282 
1283     BOOL ValidateRect(LPCRECT lpRect)
1284     {
1285         ATLASSERT(::IsWindow(m_hWnd));
1286         return ::ValidateRect(m_hWnd, lpRect);
1287     }
1288 
1289     BOOL ValidateRgn(HRGN hRgn)
1290     {
1291         ATLASSERT(::IsWindow(m_hWnd));
1292         return ::ValidateRgn(m_hWnd, hRgn);
1293     }
1294 
1295     BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0)
1296     {
1297         ATLASSERT(::IsWindow(m_hWnd));
1298         return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData);
1299     }
1300 };
1301 
1302 __declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
1303 
1304 template <class TBase = CWindow>
1305 class CWindowImplRoot : public TBase, public CMessageMap
1306 {
1307 public:
1308     enum { WINSTATE_DESTROYED = 0x00000001 };
1309 
1310 public:
1311     CWndProcThunk m_thunk;
1312     const _ATL_MSG *m_pCurrentMsg;
1313     DWORD m_dwState;
1314 
1315     CWindowImplRoot()
1316         : m_pCurrentMsg(NULL)
1317         , m_dwState(0)
1318     {
1319     }
1320 
1321     virtual ~CWindowImplRoot()
1322     {
1323     }
1324 };
1325 
1326 
1327 template <class TBase = CWindow>
1328 class CDialogImplBaseT : public CWindowImplRoot<TBase>
1329 {
1330 public:
1331     // + Hacks for gcc
1332     using CWindowImplRoot<TBase>::WINSTATE_DESTROYED;
1333     // - Hacks for gcc
1334 
1335     virtual ~CDialogImplBaseT()
1336     {
1337     }
1338     virtual DLGPROC GetDialogProc()
1339     {
1340         return DialogProc;
1341     }
1342 
1343     static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1344     {
1345         CDialogImplBaseT<TBase> *pThis;
1346         DLGPROC newDlgProc;
1347         DLGPROC GCCU(pOldProc);
1348 
1349         pThis = reinterpret_cast<CDialogImplBaseT<TBase>*>(_AtlWinModule.ExtractCreateWndData());
1350         ATLASSERT(pThis != NULL);
1351         if (pThis == NULL)
1352             return 0;
1353         pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis);
1354         newDlgProc = reinterpret_cast<DLGPROC>(pThis->m_thunk.GetWNDPROC());
1355         pOldProc = reinterpret_cast<DLGPROC>(::SetWindowLongPtr(hWnd, DWLP_DLGPROC, reinterpret_cast<LONG_PTR>(newDlgProc)));
1356         Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
1357         pThis->m_hWnd = hWnd;
1358         return newDlgProc(hWnd, uMsg, wParam, lParam);
1359     }
1360 
1361     static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1362     {
1363         CDialogImplBaseT<TBase> *pThis = reinterpret_cast<CDialogImplBaseT<TBase>*>(hWnd);
1364         _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1365         LRESULT lResult = 0;
1366         const _ATL_MSG *previousMessage;
1367         BOOL handled;
1368 
1369         hWnd = pThis->m_hWnd;
1370         previousMessage = pThis->m_pCurrentMsg;
1371         pThis->m_pCurrentMsg = &msg;
1372 
1373         handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
1374         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1375 
1376         if (handled)
1377         {
1378             if ((pThis->m_dwState & WINSTATE_DESTROYED) == 0)
1379             {
1380                 ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lResult);
1381             }
1382         }
1383         else
1384         {
1385             if (uMsg == WM_NCDESTROY)
1386             {
1387                 pThis->m_dwState |= WINSTATE_DESTROYED;
1388             }
1389         }
1390 
1391         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1392         pThis->m_pCurrentMsg = previousMessage;
1393 
1394         if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
1395         {
1396             pThis->m_dwState &= ~WINSTATE_DESTROYED;
1397             pThis->m_hWnd = NULL;
1398             pThis->OnFinalMessage(hWnd);
1399         }
1400         return lResult;
1401     }
1402 
1403     virtual void OnFinalMessage(HWND)
1404     {
1405     }
1406 };
1407 
1408 
1409 template <class T, class TBase = CWindow>
1410 class CDialogImpl : public CDialogImplBaseT< TBase >
1411 {
1412 public:
1413     // + Hacks for gcc
1414     using CWindowImplRoot<TBase>::m_thunk;
1415     using CWindowImplRoot<TBase>::m_hWnd;
1416     // - Hacks for gcc
1417 
1418     HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
1419     {
1420         BOOL result;
1421         HWND hWnd;
1422         T* pImpl;
1423 
1424         result = m_thunk.Init(NULL, NULL);
1425         if (result == FALSE)
1426             return NULL;
1427 
1428         _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
1429 
1430         pImpl = static_cast<T*>(this);
1431         hWnd = ::CreateDialogParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pImpl->IDD), hWndParent, T::StartDialogProc, dwInitParam);
1432         return hWnd;
1433     }
1434 
1435     INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
1436     {
1437         BOOL result;
1438         T* pImpl;
1439 
1440         result = m_thunk.Init(NULL, NULL);
1441         if (result == FALSE)
1442             return -1;
1443 
1444         _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
1445 
1446         pImpl = static_cast<T*>(this);
1447         return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pImpl->IDD), hWndParent, T::StartDialogProc, dwInitParam);
1448     }
1449 
1450     BOOL EndDialog(_In_ int nRetCode)
1451     {
1452         return ::EndDialog(m_hWnd, nRetCode);
1453     }
1454 
1455     BOOL DestroyWindow()
1456     {
1457         return ::DestroyWindow(m_hWnd);
1458     }
1459 };
1460 
1461 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
1462 class CWindowImplBaseT : public CWindowImplRoot<TBase>
1463 {
1464 public:
1465     // + Hacks for gcc
1466     using CWindowImplRoot<TBase>::WINSTATE_DESTROYED;
1467     using CWindowImplRoot<TBase>::m_thunk;
1468     using CWindowImplRoot<TBase>::m_hWnd;
1469     // - Hacks for gcc
1470 
1471     WNDPROC m_pfnSuperWindowProc;
1472 
1473 public:
1474     CWindowImplBaseT()
1475     {
1476         m_pfnSuperWindowProc = ::DefWindowProc;
1477     }
1478 
1479     virtual void OnFinalMessage(HWND /* hWnd */)
1480     {
1481     }
1482 
1483     BOOL SubclassWindow(HWND hWnd)
1484     {
1485         CWindowImplBaseT<TBase, TWinTraits> *pThis;
1486         WNDPROC newWindowProc;
1487         WNDPROC oldWindowProc;
1488         BOOL result;
1489 
1490         ATLASSERT(m_hWnd == NULL);
1491         ATLASSERT(::IsWindow(hWnd));
1492 
1493         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
1494 
1495         result = m_thunk.Init(GetWindowProc(), this);
1496         if (result == FALSE)
1497             return FALSE;
1498         newWindowProc = m_thunk.GetWNDPROC();
1499         oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1500         if (oldWindowProc == NULL)
1501             return FALSE;
1502         m_pfnSuperWindowProc = oldWindowProc;
1503         pThis->m_hWnd = hWnd;
1504         return TRUE;
1505     }
1506 
1507     virtual WNDPROC GetWindowProc()
1508     {
1509         return WindowProc;
1510     }
1511 
1512     static DWORD GetWndStyle(DWORD dwStyle)
1513     {
1514         return TWinTraits::GetWndStyle(dwStyle);
1515     }
1516 
1517     static DWORD GetWndExStyle(DWORD dwExStyle)
1518     {
1519         return TWinTraits::GetWndExStyle(dwExStyle);
1520     }
1521 
1522     LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
1523     {
1524         CWindowImplBaseT<TBase, TWinTraits>    *pThis;
1525 
1526         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(this);
1527         return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
1528     }
1529 
1530     static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1531     {
1532         CWindowImplBaseT<TBase, TWinTraits> *pThis;
1533         WNDPROC newWindowProc;
1534         WNDPROC GCCU(pOldProc);
1535 
1536         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(_AtlWinModule.ExtractCreateWndData());
1537         ATLASSERT(pThis != NULL);
1538         if (pThis == NULL)
1539             return 0;
1540         pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
1541         newWindowProc = pThis->m_thunk.GetWNDPROC();
1542         pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1543         Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
1544         pThis->m_hWnd = hWnd;
1545         return newWindowProc(hWnd, uMsg, wParam, lParam);
1546     }
1547 
1548     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1549     {
1550         CWindowImplBaseT<TBase, TWinTraits> *pThis = reinterpret_cast<CWindowImplBaseT< TBase, TWinTraits> *>(hWnd);
1551         _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1552         LRESULT lResult;
1553         const _ATL_MSG *previousMessage;
1554         BOOL handled;
1555         LONG_PTR saveWindowProc;
1556 
1557         ATLASSERT(pThis != NULL && (pThis->m_dwState & WINSTATE_DESTROYED) == 0 && pThis->m_hWnd != NULL);
1558         if (pThis == NULL || (pThis->m_dwState & WINSTATE_DESTROYED) != 0 || pThis->m_hWnd == NULL)
1559             return 0;
1560 
1561         hWnd = pThis->m_hWnd;
1562         previousMessage = pThis->m_pCurrentMsg;
1563         pThis->m_pCurrentMsg = &msg;
1564 
1565         handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
1566         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1567 
1568         if (handled == FALSE)
1569         {
1570             if (uMsg == WM_NCDESTROY)
1571             {
1572                 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
1573                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1574                 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
1575                     ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
1576                 pThis->m_dwState |= WINSTATE_DESTROYED;
1577             }
1578             else
1579                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1580         }
1581         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1582         pThis->m_pCurrentMsg = previousMessage;
1583         if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
1584         {
1585             pThis->m_dwState &= ~WINSTATE_DESTROYED;
1586             pThis->m_hWnd = NULL;
1587             pThis->OnFinalMessage(hWnd);
1588         }
1589         return lResult;
1590     }
1591 
1592     HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle,
1593                     _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
1594     {
1595         HWND                                hWnd;
1596 
1597         ATLASSERT(m_hWnd == NULL);
1598         ATLASSERT(atom != 0);
1599         if (atom == 0)
1600             return NULL;
1601         if (m_thunk.Init(NULL, NULL) == FALSE)
1602         {
1603             SetLastError(ERROR_OUTOFMEMORY);
1604             return NULL;
1605         }
1606 
1607         _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
1608         if (MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD) != 0)
1609             MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
1610         if (rect.m_lpRect == NULL)
1611             rect.m_lpRect = &TBase::rcDefault;
1612         hWnd = ::CreateWindowEx(dwExStyle, reinterpret_cast<LPCWSTR>(MAKEINTATOM(atom)), szWindowName, dwStyle, rect.m_lpRect->left,
1613                     rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top,
1614                     hWndParent, MenuOrID.m_hMenu, _AtlBaseModule.GetModuleInstance(), lpCreateParam);
1615 
1616         ATLASSERT(m_hWnd == hWnd);
1617 
1618         return hWnd;
1619     }
1620 };
1621 
1622 
1623 template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
1624 class CWindowImpl : public CWindowImplBaseT<TBase, TWinTraits>
1625 {
1626 public:
1627     // + Hacks for gcc
1628     using CWindowImplRoot<TBase>::m_hWnd;
1629     // - Hacks for gcc
1630 
1631 
1632     static LPCTSTR GetWndCaption()
1633     {
1634         return NULL;
1635     }
1636 
1637     HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0,
1638                     DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
1639     {
1640         CWindowImplBaseT<TBase, TWinTraits> *pThis;
1641         ATOM atom;
1642 
1643         ATLASSERT(m_hWnd == NULL);
1644         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
1645 
1646         if (T::GetWndClassInfo().m_lpszOrigName == NULL)
1647             T::GetWndClassInfo().m_lpszOrigName = pThis->GetWndClassName();
1648         atom = T::GetWndClassInfo().Register(&pThis->m_pfnSuperWindowProc);
1649 
1650         if (szWindowName == NULL)
1651             szWindowName = T::GetWndCaption();
1652         dwStyle = T::GetWndStyle(dwStyle);
1653         dwExStyle = T::GetWndExStyle(dwExStyle);
1654 
1655         return CWindowImplBaseT<TBase, TWinTraits>::Create(hWndParent, rect, szWindowName, dwStyle,
1656                         dwExStyle, MenuOrID, atom, lpCreateParam);
1657     }
1658 };
1659 
1660 template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
1661 class CContainedWindowT : public TBase
1662 {
1663 public:
1664     // + Hacks for gcc
1665     using TBase::m_hWnd;
1666     // - Hacks for gcc
1667 
1668     CWndProcThunk m_thunk;
1669     LPCTSTR m_lpszClassName;
1670     WNDPROC m_pfnSuperWindowProc;
1671     CMessageMap *m_pObject;
1672     DWORD m_dwMsgMapID;
1673     const _ATL_MSG *m_pCurrentMsg;
1674 public:
1675     CContainedWindowT(CMessageMap *pObject, DWORD dwMsgMapID = 0)
1676     {
1677         m_lpszClassName = TBase::GetWndClassName();
1678         m_pfnSuperWindowProc = ::DefWindowProc;
1679         m_pObject = pObject;
1680         m_dwMsgMapID = dwMsgMapID;
1681         m_pCurrentMsg = NULL;
1682     }
1683 
1684     CContainedWindowT(LPTSTR lpszClassName, CMessageMap *pObject, DWORD dwMsgMapID = 0)
1685     {
1686         m_lpszClassName = lpszClassName;
1687         m_pfnSuperWindowProc = ::DefWindowProc;
1688         m_pObject = pObject;
1689         m_dwMsgMapID = dwMsgMapID;
1690         m_pCurrentMsg = NULL;
1691     }
1692 
1693     LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
1694     {
1695         return ::CallWindowProc(m_pfnSuperWindowProc, this->m_hWnd, uMsg, wParam, lParam);
1696     }
1697 
1698     BOOL SubclassWindow(HWND hWnd)
1699     {
1700         CContainedWindowT<TBase> *pThis;
1701         WNDPROC newWindowProc;
1702         WNDPROC oldWindowProc;
1703         BOOL result;
1704 
1705         ATLASSERT(m_hWnd == NULL);
1706         ATLASSERT(::IsWindow(hWnd));
1707 
1708         pThis = reinterpret_cast<CContainedWindowT<TBase> *>(this);
1709 
1710         result = m_thunk.Init(WindowProc, pThis);
1711         if (result == FALSE)
1712             return FALSE;
1713         newWindowProc = m_thunk.GetWNDPROC();
1714         oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1715         if (oldWindowProc == NULL)
1716             return FALSE;
1717         m_pfnSuperWindowProc = oldWindowProc;
1718         pThis->m_hWnd = hWnd;
1719         return TRUE;
1720     }
1721 
1722     static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1723     {
1724         CContainedWindowT<TBase> *pThis;
1725         WNDPROC newWindowProc;
1726         WNDPROC GCCU(pOldProc);
1727 
1728         pThis = reinterpret_cast<CContainedWindowT<TBase> *>(_AtlWinModule.ExtractCreateWndData());
1729         ATLASSERT(pThis != NULL);
1730         if (pThis == NULL)
1731             return 0;
1732         pThis->m_thunk.Init(WindowProc, pThis);
1733         newWindowProc = pThis->m_thunk.GetWNDPROC();
1734         pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
1735         Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
1736         pThis->m_hWnd = hWnd;
1737         return newWindowProc(hWnd, uMsg, wParam, lParam);
1738     }
1739 
1740     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1741     {
1742         CContainedWindowT<TBase> *pThis = reinterpret_cast<CContainedWindowT<TBase> *>(hWnd);
1743         _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1744         LRESULT lResult;
1745         const _ATL_MSG *previousMessage;
1746         BOOL handled;
1747         LONG_PTR saveWindowProc;
1748 
1749         ATLASSERT(pThis != NULL && pThis->m_hWnd != NULL && pThis->m_pObject != NULL);
1750         if (pThis == NULL || pThis->m_hWnd == NULL || pThis->m_pObject == NULL)
1751             return 0;
1752 
1753         hWnd = pThis->m_hWnd;
1754         previousMessage = pThis->m_pCurrentMsg;
1755         pThis->m_pCurrentMsg = &msg;
1756 
1757         handled = pThis->m_pObject->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, pThis->m_dwMsgMapID);
1758         ATLASSERT(pThis->m_pCurrentMsg == &msg);
1759 
1760         pThis->m_pCurrentMsg = previousMessage;
1761         if (handled == FALSE)
1762         {
1763             if (uMsg == WM_NCDESTROY)
1764             {
1765                 saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
1766                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1767                 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
1768                     ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
1769                 pThis->m_hWnd = NULL;
1770             }
1771             else
1772                 lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1773         }
1774         return lResult;
1775     }
1776 
1777 };
1778 typedef CContainedWindowT<CWindow> CContainedWindow;
1779 
1780 #define BEGIN_MSG_MAP(theClass)                                                                                                \
1781 public:                                                                                                                        \
1782     BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0)    \
1783     {                                                                                                                        \
1784         BOOL GCCU(bHandled) = TRUE;                                                                                            \
1785         Unused(hWnd);                                                                                                        \
1786         Unused(uMsg);                                                                                                        \
1787         Unused(wParam);                                                                                                        \
1788         Unused(lParam);                                                                                                        \
1789         Unused(lResult);                                                                                                    \
1790         Unused(bHandled);                                                                                                    \
1791         switch(dwMsgMapID)                                                                                                    \
1792         {                                                                                                                    \
1793         case 0:
1794 
1795 #define ALT_MSG_MAP(map)                                                                        \
1796             break;                                                                                \
1797         case map:
1798 
1799 #define END_MSG_MAP()                                                                            \
1800             break;                                                                                \
1801         default:                                                                                \
1802             ATLASSERT(FALSE);                                                                    \
1803             break;                                                                                \
1804         }                                                                                        \
1805         return FALSE;                                                                            \
1806     }
1807 
1808 #define MESSAGE_HANDLER(msg, func)                                                                \
1809     if (uMsg == msg)                                                                            \
1810     {                                                                                            \
1811         bHandled = TRUE;                                                                        \
1812         lResult = func(uMsg, wParam, lParam, bHandled);                                            \
1813         if (bHandled)                                                                            \
1814             return TRUE;                                                                        \
1815     }
1816 
1817 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func)                                            \
1818     if (uMsg >= msgFirst && uMsg <= msgLast)                                                    \
1819     {                                                                                            \
1820         bHandled = TRUE;                                                                        \
1821         lResult = func(uMsg, wParam, lParam, bHandled);                                            \
1822         if (bHandled)                                                                            \
1823             return TRUE;                                                                        \
1824     }
1825 
1826 #define COMMAND_HANDLER(id, code, func)                                                         \
1827     if (uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam))                   \
1828     {                                                                                           \
1829         bHandled = TRUE;                                                                        \
1830         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);                 \
1831         if (bHandled)                                                                           \
1832             return TRUE;                                                                        \
1833     }
1834 
1835 #define COMMAND_ID_HANDLER(id, func)                                                            \
1836     if (uMsg == WM_COMMAND && id == LOWORD(wParam))                                                \
1837     {                                                                                            \
1838         bHandled = TRUE;                                                                        \
1839         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);                    \
1840         if (bHandled)                                                                            \
1841             return TRUE;                                                                        \
1842     }
1843 
1844 #define COMMAND_CODE_HANDLER(code, func)                                                            \
1845     if (uMsg == WM_COMMAND && code == HIWORD(wParam))                                                \
1846     {                                                                                            \
1847         bHandled = TRUE;                                                                        \
1848         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);                    \
1849         if (bHandled)                                                                            \
1850             return TRUE;                                                                        \
1851     }
1852 
1853 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func)                                            \
1854     if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst  && LOWORD(wParam) <= idLast)            \
1855     {                                                                                            \
1856         bHandled = TRUE;                                                                        \
1857         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);                    \
1858         if (bHandled)                                                                            \
1859             return TRUE;                                                                        \
1860     }
1861 
1862 #define NOTIFY_CODE_HANDLER(cd, func)                                                            \
1863     if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code)                                        \
1864     {                                                                                            \
1865         bHandled = TRUE;                                                                        \
1866         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled);                                    \
1867         if (bHandled)                                                                            \
1868             return TRUE;                                                                        \
1869     }
1870 
1871 #define NOTIFY_HANDLER(id, cd, func)                                                            \
1872     if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code)    \
1873     {                                                                                            \
1874         bHandled = TRUE;                                                                        \
1875         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled);                                    \
1876         if (bHandled)                                                                            \
1877             return TRUE;                                                                        \
1878     }
1879 
1880 #define CHAIN_MSG_MAP(theChainClass) \
1881     { \
1882         if (theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
1883             return TRUE; \
1884     }
1885 
1886 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd)                                        \
1887 static ATL::CWndClassInfo& GetWndClassInfo()                                                    \
1888 {                                                                                                \
1889     static ATL::CWndClassInfo wc =                                                                \
1890     {                                                                                            \
1891         { sizeof(WNDCLASSEX), style, StartWindowProc,                                            \
1892           0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL },                \
1893         NULL, NULL, IDC_ARROW, TRUE, 0, _T("")                                                    \
1894     };                                                                                            \
1895     return wc;                                                                                    \
1896 }
1897 
1898 struct _ATL_WNDCLASSINFOW
1899 {
1900     WNDCLASSEXW m_wc;
1901     LPCWSTR m_lpszOrigName;
1902     WNDPROC pWndProc;
1903     LPCWSTR m_lpszCursorID;
1904     BOOL m_bSystemCursor;
1905     ATOM m_atom;
1906     WCHAR m_szAutoName[sizeof("ATL:") + sizeof(void *) * 2]; // == 4 characters + NULL + number of hexadecimal digits describing a pointer.
1907 
1908     ATOM Register(WNDPROC *p)
1909     {
1910         if (m_wc.hInstance == NULL)
1911             m_wc.hInstance = _AtlBaseModule.GetModuleInstance();
1912         if (m_atom == 0)
1913         {
1914             if (m_bSystemCursor)
1915                 m_wc.hCursor = ::LoadCursor(NULL, m_lpszCursorID);
1916             else
1917                 m_wc.hCursor = ::LoadCursor(_AtlBaseModule.GetResourceInstance(), m_lpszCursorID);
1918 
1919             m_atom = RegisterClassEx(&m_wc);
1920         }
1921 
1922         return m_atom;
1923     }
1924 };
1925 
1926 }; // namespace ATL
1927 
1928 #pragma pop_macro("SubclassWindow")
1929 
1930