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