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