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