4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
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.
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.
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
24 #define GCCU(x) x __attribute__((unused))
28 #define Unused(x) (x);
31 #ifdef SetWindowLongPtr
32 #undef SetWindowLongPtr
33 inline LONG_PTR
SetWindowLongPtr(HWND hWnd
, int nIndex
, LONG_PTR dwNewLong
)
35 return SetWindowLong(hWnd
, nIndex
, (LONG
)dwNewLong
);
39 #ifdef GetWindowLongPtr
40 #undef GetWindowLongPtr
41 inline LONG_PTR
GetWindowLongPtr(HWND hWnd
, int nIndex
)
43 return (LONG_PTR
)GetWindowLong(hWnd
, nIndex
);
50 struct _ATL_WNDCLASSINFOW
;
51 typedef _ATL_WNDCLASSINFOW CWndClassInfo
;
53 template <DWORD t_dwStyle
= 0, DWORD t_dwExStyle
= 0>
57 static DWORD
GetWndStyle(DWORD dwStyle
)
64 static DWORD
GetWndExStyle(DWORD dwExStyle
)
72 typedef CWinTraits
<WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, 0> CControlWinTraits
;
73 typedef CWinTraits
<WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE
> CFrameWinTraits
;
74 typedef CWinTraits
<WS_OVERLAPPEDWINDOW
| WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, WS_EX_MDICHILD
> CMDIChildWinTraits
;
76 template <DWORD t_dwStyle
= 0, DWORD t_dwExStyle
= 0, class TWinTraits
= CControlWinTraits
>
80 static DWORD
GetWndStyle(DWORD dwStyle
)
82 return dwStyle
| t_dwStyle
| TWinTraits::GetWndStyle(dwStyle
);
85 static DWORD
GetWndExStyle(DWORD dwExStyle
)
87 return dwExStyle
| t_dwExStyle
| TWinTraits::GetWndExStyle(dwExStyle
);
96 _U_MENUorID(HMENU hMenu
)
101 _U_MENUorID(UINT nID
)
103 m_hMenu
= (HMENU
)(UINT_PTR
)nID
;
112 _U_RECT(LPRECT lpRect
)
123 struct _ATL_MSG
: public MSG
128 _ATL_MSG(HWND hWnd
, UINT uMsg
, WPARAM wParamIn
, LPARAM lParamIn
, BOOL bHandledIn
= TRUE
)
137 bHandled
= bHandledIn
;
157 _AtlCreateWndData cd
;
159 BOOL
Init(WNDPROC proc
, void *pThis
)
161 m_thunk
.m_mov
= 0x042444C7;
162 m_thunk
.m_this
= PtrToUlong(pThis
);
163 m_thunk
.m_jmp
= 0xe9;
164 m_thunk
.m_relproc
= DWORD(reinterpret_cast<char *>(proc
) - (reinterpret_cast<char *>(this) + sizeof(thunkCode
)));
170 return reinterpret_cast<WNDPROC
>(&m_thunk
);
174 #elif _AMD64_ //WARNING: NOT VERIFIED
189 _AtlCreateWndData cd
;
191 BOOL
Init(WNDPROC proc
, void *pThis
)
193 m_thunk
.m_mov
= 0xffff8000042444C7LL
;
194 m_thunk
.m_this
= (DWORD_PTR
)pThis
;
195 m_thunk
.m_jmp
= 0xe9;
196 m_thunk
.m_relproc
= DWORD_PTR(reinterpret_cast<char *>(proc
) - (reinterpret_cast<char *>(this) + sizeof(thunkCode
)));
202 return reinterpret_cast<WNDPROC
>(&m_thunk
);
206 #error ARCH not supported
212 virtual BOOL
ProcessWindowMessage(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
, DWORD dwMsgMapID
) = 0;
219 static RECT rcDefault
;
221 CWindow(HWND hWnd
= NULL
)
226 operator HWND() const
231 static LPCTSTR
GetWndClassName()
236 HDC
BeginPaint(LPPAINTSTRUCT lpPaint
)
238 ATLASSERT(::IsWindow(m_hWnd
));
239 return ::BeginPaint(m_hWnd
, lpPaint
);
244 ATLASSERT(::IsWindow(m_hWnd
));
246 if (!::DestroyWindow(m_hWnd
))
253 void EndPaint(LPPAINTSTRUCT lpPaint
)
255 ATLASSERT(::IsWindow(m_hWnd
));
256 ::EndPaint(m_hWnd
, lpPaint
);
259 BOOL
GetClientRect(LPRECT lpRect
) const
261 ATLASSERT(::IsWindow(m_hWnd
));
262 return ::GetClientRect(m_hWnd
, lpRect
);
265 CWindow
GetParent() const
267 ATLASSERT(::IsWindow(m_hWnd
));
268 return CWindow(::GetParent(m_hWnd
));
271 BOOL
Invalidate(BOOL bErase
= TRUE
)
273 ATLASSERT(::IsWindow(m_hWnd
));
274 return ::InvalidateRect(m_hWnd
, NULL
, bErase
);
277 BOOL
InvalidateRect(LPCRECT lpRect
, BOOL bErase
= TRUE
)
279 ATLASSERT(::IsWindow(m_hWnd
));
280 return ::InvalidateRect(m_hWnd
, lpRect
, bErase
);
283 BOOL
IsWindow() const
285 return ::IsWindow(m_hWnd
);
288 BOOL
KillTimer(UINT_PTR nIDEvent
)
290 ATLASSERT(::IsWindow(m_hWnd
));
291 return ::KillTimer(m_hWnd
, nIDEvent
);
294 BOOL
LockWindowUpdate(BOOL bLock
= TRUE
)
296 ATLASSERT(::IsWindow(m_hWnd
));
298 return ::LockWindowUpdate(m_hWnd
);
299 return ::LockWindowUpdate(NULL
);
302 BOOL
ScreenToClient(LPPOINT lpPoint
) const
304 ATLASSERT(::IsWindow(m_hWnd
));
305 return ::ScreenToClient(m_hWnd
, lpPoint
);
308 LRESULT
SendMessage(UINT message
, WPARAM wParam
= 0, LPARAM lParam
= 0)
310 ATLASSERT(::IsWindow(m_hWnd
));
311 return ::SendMessage(m_hWnd
, message
, wParam
, lParam
);
314 static LRESULT
SendMessage(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
316 ATLASSERT(::IsWindow(hWnd
));
317 return ::SendMessage(hWnd
, message
, wParam
, lParam
);
322 ATLASSERT(::IsWindow(m_hWnd
));
323 return ::SetCapture(m_hWnd
);
328 ATLASSERT(::IsWindow(m_hWnd
));
329 return ::SetFocus(m_hWnd
);
332 UINT_PTR
SetTimer(UINT_PTR nIDEvent
, UINT nElapse
, void (CALLBACK
*lpfnTimer
)(HWND
, UINT
, UINT_PTR
, DWORD
) = NULL
)
334 ATLASSERT(::IsWindow(m_hWnd
));
335 return ::SetTimer(m_hWnd
, nIDEvent
, nElapse
, reinterpret_cast<TIMERPROC
>(lpfnTimer
));
338 BOOL
SetWindowPos(HWND hWndInsertAfter
, int x
, int y
, int cx
, int cy
, UINT nFlags
)
340 ATLASSERT(::IsWindow(m_hWnd
));
341 return ::SetWindowPos(m_hWnd
, hWndInsertAfter
, x
, y
, cx
, cy
, nFlags
);
344 BOOL
SetWindowText(LPCTSTR lpszString
)
346 ATLASSERT(::IsWindow(m_hWnd
));
347 return ::SetWindowText(m_hWnd
, lpszString
);
350 BOOL
ShowWindow(int nCmdShow
)
352 ATLASSERT(::IsWindow(m_hWnd
));
353 return ::ShowWindow(m_hWnd
, nCmdShow
);
358 ATLASSERT(::IsWindow(m_hWnd
));
359 return ::UpdateWindow(m_hWnd
);
363 _declspec(selectany
) RECT
CWindow::rcDefault
= { CW_USEDEFAULT
, CW_USEDEFAULT
, 0, 0 };
365 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
366 class CWindowImplBaseT
: public TBase
, public CMessageMap
369 enum { WINSTATE_DESTROYED
= 0x00000001 };
371 const _ATL_MSG
*m_pCurrentMsg
;
372 CWndProcThunk m_thunk
;
373 WNDPROC m_pfnSuperWindowProc
;
378 m_pCurrentMsg
= NULL
;
379 m_pfnSuperWindowProc
= ::DefWindowProc
;
382 virtual void OnFinalMessage(HWND
/* hWnd */)
386 BOOL
SubclassWindow(HWND hWnd
)
388 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
389 WNDPROC newWindowProc
;
390 WNDPROC oldWindowProc
;
393 ATLASSERT(m_hWnd
== NULL
);
394 ATLASSERT(::IsWindow(hWnd
));
396 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
398 result
= m_thunk
.Init(GetWindowProc(), this);
401 newWindowProc
= m_thunk
.GetWNDPROC();
402 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
403 if (oldWindowProc
== NULL
)
405 m_pfnSuperWindowProc
= oldWindowProc
;
406 pThis
->m_hWnd
= hWnd
;
410 virtual WNDPROC
GetWindowProc()
415 static DWORD
GetWndStyle(DWORD dwStyle
)
417 return TWinTraits::GetWndStyle(dwStyle
);
420 static DWORD
GetWndExStyle(DWORD dwExStyle
)
422 return TWinTraits::GetWndExStyle(dwExStyle
);
425 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
427 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
429 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
430 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
433 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
435 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
436 WNDPROC newWindowProc
;
437 WNDPROC
GCCU(pOldProc
);
439 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(_AtlWinModule
.ExtractCreateWndData());
440 ATLASSERT(pThis
!= NULL
);
443 pThis
->m_thunk
.Init(pThis
->GetWindowProc(), pThis
);
444 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
445 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
446 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
447 pThis
->m_hWnd
= hWnd
;
448 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
451 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
453 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
= reinterpret_cast<CWindowImplBaseT
< TBase
, TWinTraits
> *>(hWnd
);
454 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
456 const _ATL_MSG
*previousMessage
;
458 LONG_PTR saveWindowProc
;
460 ATLASSERT(pThis
!= NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) == 0 && pThis
->m_hWnd
!= NULL
);
461 if (pThis
== NULL
|| (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0 || pThis
->m_hWnd
== NULL
)
464 hWnd
= pThis
->m_hWnd
;
465 previousMessage
= pThis
->m_pCurrentMsg
;
466 pThis
->m_pCurrentMsg
= &msg
;
468 handled
= pThis
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, 0);
469 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
471 if (handled
== FALSE
)
473 if (uMsg
== WM_NCDESTROY
)
475 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
476 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
477 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
478 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
479 pThis
->m_dwState
|= WINSTATE_DESTROYED
;
482 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
484 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
485 pThis
->m_pCurrentMsg
= previousMessage
;
486 if (previousMessage
== NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0)
488 pThis
->m_dwState
&= ~WINSTATE_DESTROYED
;
489 pThis
->m_hWnd
= NULL
;
490 pThis
->OnFinalMessage(hWnd
);
495 HWND
Create(HWND hWndParent
, _U_RECT rect
, LPCTSTR szWindowName
, DWORD dwStyle
, DWORD dwExStyle
,
496 _U_MENUorID MenuOrID
, ATOM atom
, LPVOID lpCreateParam
)
500 ATLASSERT(m_hWnd
== NULL
);
501 ATLASSERT(atom
!= 0);
504 if (m_thunk
.Init(NULL
, NULL
) == FALSE
)
506 SetLastError(ERROR_OUTOFMEMORY
);
510 _AtlWinModule
.AddCreateWndData(&m_thunk
.cd
, this);
511 if (MenuOrID
.m_hMenu
== NULL
&& (dwStyle
& WS_CHILD
) != 0)
512 MenuOrID
.m_hMenu
= (HMENU
)(UINT_PTR
)this;
513 if (rect
.m_lpRect
== NULL
)
514 rect
.m_lpRect
= &TBase::rcDefault
;
515 hWnd
= ::CreateWindowEx(dwExStyle
, reinterpret_cast<LPCWSTR
>(MAKEINTATOM(atom
)), szWindowName
, dwStyle
, rect
.m_lpRect
->left
,
516 rect
.m_lpRect
->top
, rect
.m_lpRect
->right
- rect
.m_lpRect
->left
, rect
.m_lpRect
->bottom
- rect
.m_lpRect
->top
,
517 hWndParent
, MenuOrID
.m_hMenu
, _AtlBaseModule
.GetModuleInstance(), lpCreateParam
);
519 ATLASSERT(m_hWnd
== hWnd
);
525 template <class T
, class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
526 class CWindowImpl
: public CWindowImplBaseT
<TBase
, TWinTraits
>
529 static LPCTSTR
GetWndCaption()
534 HWND
Create(HWND hWndParent
, _U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
, DWORD dwStyle
= 0,
535 DWORD dwExStyle
= 0, _U_MENUorID MenuOrID
= 0U, LPVOID lpCreateParam
= NULL
)
537 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
540 ATLASSERT(m_hWnd
== NULL
);
541 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
543 if (T::GetWndClassInfo().m_lpszOrigName
== NULL
)
544 T::GetWndClassInfo().m_lpszOrigName
= pThis
->GetWndClassName();
545 atom
= T::GetWndClassInfo().Register(&pThis
->m_pfnSuperWindowProc
);
547 if (szWindowName
== NULL
)
548 szWindowName
= T::GetWndCaption();
549 dwStyle
= T::GetWndStyle(dwStyle
);
550 dwExStyle
= T::GetWndExStyle(dwExStyle
);
552 return CWindowImplBaseT
<TBase
, TWinTraits
>::Create(hWndParent
, rect
, szWindowName
, dwStyle
,
553 dwExStyle
, MenuOrID
, atom
, lpCreateParam
);
557 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
558 class CContainedWindowT
: public TBase
561 CWndProcThunk m_thunk
;
562 LPCTSTR m_lpszClassName
;
563 WNDPROC m_pfnSuperWindowProc
;
564 CMessageMap
*m_pObject
;
566 const _ATL_MSG
*m_pCurrentMsg
;
568 CContainedWindowT(CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
570 m_lpszClassName
= TBase::GetWndClassName();
571 m_pfnSuperWindowProc
= ::DefWindowProc
;
573 m_dwMsgMapID
= dwMsgMapID
;
574 m_pCurrentMsg
= NULL
;
577 CContainedWindowT(LPTSTR lpszClassName
, CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
579 m_lpszClassName
= lpszClassName
;
580 m_pfnSuperWindowProc
= ::DefWindowProc
;
582 m_dwMsgMapID
= dwMsgMapID
;
583 m_pCurrentMsg
= NULL
;
586 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
588 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
590 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
591 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
594 BOOL
SubclassWindow(HWND hWnd
)
596 CContainedWindowT
<TBase
> *pThis
;
597 WNDPROC newWindowProc
;
598 WNDPROC oldWindowProc
;
601 ATLASSERT(m_hWnd
== NULL
);
602 ATLASSERT(::IsWindow(hWnd
));
604 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(this);
606 result
= m_thunk
.Init(WindowProc
, pThis
);
609 newWindowProc
= m_thunk
.GetWNDPROC();
610 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
611 if (oldWindowProc
== NULL
)
613 m_pfnSuperWindowProc
= oldWindowProc
;
614 pThis
->m_hWnd
= hWnd
;
618 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
620 CContainedWindowT
<TBase
> *pThis
;
621 WNDPROC newWindowProc
;
622 WNDPROC
GCCU(pOldProc
);
624 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(_AtlWinModule
.ExtractCreateWndData());
625 ATLASSERT(pThis
!= NULL
);
628 pThis
->m_thunk
.Init(WindowProc
, pThis
);
629 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
630 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
631 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
632 pThis
->m_hWnd
= hWnd
;
633 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
636 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
638 CContainedWindowT
<TBase
> *pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(hWnd
);
639 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
641 const _ATL_MSG
*previousMessage
;
643 LONG_PTR saveWindowProc
;
645 ATLASSERT(pThis
!= NULL
&& pThis
->m_hWnd
!= NULL
&& pThis
->m_pObject
!= NULL
);
646 if (pThis
== NULL
|| pThis
->m_hWnd
== NULL
|| pThis
->m_pObject
== NULL
)
649 hWnd
= pThis
->m_hWnd
;
650 previousMessage
= pThis
->m_pCurrentMsg
;
651 pThis
->m_pCurrentMsg
= &msg
;
653 handled
= pThis
->m_pObject
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, pThis
->m_dwMsgMapID
);
654 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
656 pThis
->m_pCurrentMsg
= previousMessage
;
657 if (handled
== FALSE
)
659 if (uMsg
== WM_NCDESTROY
)
661 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
662 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
663 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
664 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
665 pThis
->m_hWnd
= NULL
;
668 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
674 typedef CContainedWindowT
<CWindow
> CContainedWindow
;
676 #define BEGIN_MSG_MAP(theClass) \
678 BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
680 BOOL GCCU(bHandled) = TRUE; \
691 #define END_MSG_MAP() \
700 #define MESSAGE_HANDLER(msg, func) \
704 lResult = func(uMsg, wParam, lParam, bHandled); \
709 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
710 if (uMsg >= msgFirst && uMsg <= msgLast) \
713 lResult = func(uMsg, wParam, lParam, bHandled); \
718 #define COMMAND_ID_HANDLER(id, func) \
719 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
722 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
727 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
728 if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
731 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
736 #define NOTIFY_CODE_HANDLER(cd, func) \
737 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
740 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
745 #define NOTIFY_HANDLER(id, cd, func) \
746 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
749 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
754 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
755 static ATL::CWndClassInfo& GetWndClassInfo() \
757 static ATL::CWndClassInfo wc = \
759 { sizeof(WNDCLASSEX), style, StartWindowProc, \
760 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
761 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
766 struct _ATL_WNDCLASSINFOW
769 LPCWSTR m_lpszOrigName
;
771 LPCWSTR m_lpszCursorID
;
772 BOOL m_bSystemCursor
;
774 WCHAR m_szAutoName
[5 + sizeof(void *)];
776 ATOM
Register(WNDPROC
*p
)
778 if (m_wc
.hInstance
== NULL
)
779 m_wc
.hInstance
= _AtlBaseModule
.GetModuleInstance();
781 m_atom
= RegisterClassEx(&m_wc
);