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