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
25 #define GCCU(x) x __attribute__((unused))
29 #define Unused(x) (x);
32 #ifdef SetWindowLongPtr
33 #undef SetWindowLongPtr
34 inline LONG_PTR
SetWindowLongPtr(HWND hWnd
, int nIndex
, LONG_PTR dwNewLong
)
36 return SetWindowLong(hWnd
, nIndex
, (LONG
)dwNewLong
);
40 #ifdef GetWindowLongPtr
41 #undef GetWindowLongPtr
42 inline LONG_PTR
GetWindowLongPtr(HWND hWnd
, int nIndex
)
44 return (LONG_PTR
)GetWindowLong(hWnd
, nIndex
);
51 struct _ATL_WNDCLASSINFOW
;
52 typedef _ATL_WNDCLASSINFOW CWndClassInfo
;
54 template <DWORD t_dwStyle
= 0, DWORD t_dwExStyle
= 0>
58 static DWORD
GetWndStyle(DWORD dwStyle
)
65 static DWORD
GetWndExStyle(DWORD dwExStyle
)
73 typedef CWinTraits
<WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, 0> CControlWinTraits
;
74 typedef CWinTraits
<WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE
> CFrameWinTraits
;
75 typedef CWinTraits
<WS_OVERLAPPEDWINDOW
| WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, WS_EX_MDICHILD
> CMDIChildWinTraits
;
77 template <DWORD t_dwStyle
= 0, DWORD t_dwExStyle
= 0, class TWinTraits
= CControlWinTraits
>
81 static DWORD
GetWndStyle(DWORD dwStyle
)
83 return dwStyle
| t_dwStyle
| TWinTraits::GetWndStyle(dwStyle
);
86 static DWORD
GetWndExStyle(DWORD dwExStyle
)
88 return dwExStyle
| t_dwExStyle
| TWinTraits::GetWndExStyle(dwExStyle
);
97 _U_MENUorID(HMENU hMenu
)
102 _U_MENUorID(UINT nID
)
104 m_hMenu
= (HMENU
)(UINT_PTR
)nID
;
113 _U_RECT(LPRECT lpRect
)
124 struct _ATL_MSG
: public MSG
129 _ATL_MSG(HWND hWnd
, UINT uMsg
, WPARAM wParamIn
, LPARAM lParamIn
, BOOL bHandledIn
= TRUE
)
138 bHandled
= bHandledIn
;
158 _AtlCreateWndData cd
;
160 BOOL
Init(WNDPROC proc
, void *pThis
)
162 m_thunk
.m_mov
= 0x042444C7;
163 m_thunk
.m_this
= PtrToUlong(pThis
);
164 m_thunk
.m_jmp
= 0xe9;
165 m_thunk
.m_relproc
= DWORD(reinterpret_cast<char *>(proc
) - (reinterpret_cast<char *>(this) + sizeof(thunkCode
)));
171 return reinterpret_cast<WNDPROC
>(&m_thunk
);
175 #elif _AMD64_ //WARNING: NOT VERIFIED
190 _AtlCreateWndData cd
;
192 BOOL
Init(WNDPROC proc
, void *pThis
)
194 m_thunk
.m_mov
= 0xffff8000042444C7LL
;
195 m_thunk
.m_this
= (DWORD_PTR
)pThis
;
196 m_thunk
.m_jmp
= 0xe9;
197 m_thunk
.m_relproc
= DWORD_PTR(reinterpret_cast<char *>(proc
) - (reinterpret_cast<char *>(this) + sizeof(thunkCode
)));
203 return reinterpret_cast<WNDPROC
>(&m_thunk
);
207 #error ARCH not supported
213 virtual BOOL
ProcessWindowMessage(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
, DWORD dwMsgMapID
) = 0;
220 static RECT rcDefault
;
222 CWindow(HWND hWnd
= NULL
)
227 operator HWND() const
232 static LPCTSTR
GetWndClassName()
237 HDC
BeginPaint(LPPAINTSTRUCT lpPaint
)
239 ATLASSERT(::IsWindow(m_hWnd
));
240 return ::BeginPaint(m_hWnd
, lpPaint
);
245 ATLASSERT(::IsWindow(m_hWnd
));
247 if (!::DestroyWindow(m_hWnd
))
254 void EndPaint(LPPAINTSTRUCT lpPaint
)
256 ATLASSERT(::IsWindow(m_hWnd
));
257 ::EndPaint(m_hWnd
, lpPaint
);
260 BOOL
GetClientRect(LPRECT lpRect
) const
262 ATLASSERT(::IsWindow(m_hWnd
));
263 return ::GetClientRect(m_hWnd
, lpRect
);
266 CWindow
GetParent() const
268 ATLASSERT(::IsWindow(m_hWnd
));
269 return CWindow(::GetParent(m_hWnd
));
272 BOOL
Invalidate(BOOL bErase
= TRUE
)
274 ATLASSERT(::IsWindow(m_hWnd
));
275 return ::InvalidateRect(m_hWnd
, NULL
, bErase
);
278 BOOL
InvalidateRect(LPCRECT lpRect
, BOOL bErase
= TRUE
)
280 ATLASSERT(::IsWindow(m_hWnd
));
281 return ::InvalidateRect(m_hWnd
, lpRect
, bErase
);
284 BOOL
IsWindow() const
286 return ::IsWindow(m_hWnd
);
289 BOOL
KillTimer(UINT_PTR nIDEvent
)
291 ATLASSERT(::IsWindow(m_hWnd
));
292 return ::KillTimer(m_hWnd
, nIDEvent
);
295 BOOL
LockWindowUpdate(BOOL bLock
= TRUE
)
297 ATLASSERT(::IsWindow(m_hWnd
));
299 return ::LockWindowUpdate(m_hWnd
);
300 return ::LockWindowUpdate(NULL
);
303 BOOL
ScreenToClient(LPPOINT lpPoint
) const
305 ATLASSERT(::IsWindow(m_hWnd
));
306 return ::ScreenToClient(m_hWnd
, lpPoint
);
309 LRESULT
SendMessage(UINT message
, WPARAM wParam
= 0, LPARAM lParam
= 0)
311 ATLASSERT(::IsWindow(m_hWnd
));
312 return ::SendMessage(m_hWnd
, message
, wParam
, lParam
);
315 static LRESULT
SendMessage(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
317 ATLASSERT(::IsWindow(hWnd
));
318 return ::SendMessage(hWnd
, message
, wParam
, lParam
);
323 ATLASSERT(::IsWindow(m_hWnd
));
324 return ::SetCapture(m_hWnd
);
329 ATLASSERT(::IsWindow(m_hWnd
));
330 return ::SetFocus(m_hWnd
);
333 UINT_PTR
SetTimer(UINT_PTR nIDEvent
, UINT nElapse
, void (CALLBACK
*lpfnTimer
)(HWND
, UINT
, UINT_PTR
, DWORD
) = NULL
)
335 ATLASSERT(::IsWindow(m_hWnd
));
336 return ::SetTimer(m_hWnd
, nIDEvent
, nElapse
, reinterpret_cast<TIMERPROC
>(lpfnTimer
));
339 BOOL
SetWindowPos(HWND hWndInsertAfter
, int x
, int y
, int cx
, int cy
, UINT nFlags
)
341 ATLASSERT(::IsWindow(m_hWnd
));
342 return ::SetWindowPos(m_hWnd
, hWndInsertAfter
, x
, y
, cx
, cy
, nFlags
);
345 BOOL
SetWindowText(LPCTSTR lpszString
)
347 ATLASSERT(::IsWindow(m_hWnd
));
348 return ::SetWindowText(m_hWnd
, lpszString
);
351 BOOL
ShowWindow(int nCmdShow
)
353 ATLASSERT(::IsWindow(m_hWnd
));
354 return ::ShowWindow(m_hWnd
, nCmdShow
);
359 _declspec(selectany
) RECT
CWindow::rcDefault
= { CW_USEDEFAULT
, CW_USEDEFAULT
, 0, 0 };
361 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
362 class CWindowImplBaseT
: public TBase
, public CMessageMap
365 enum { WINSTATE_DESTROYED
= 0x00000001 };
367 const _ATL_MSG
*m_pCurrentMsg
;
368 CWndProcThunk m_thunk
;
369 WNDPROC m_pfnSuperWindowProc
;
374 m_pCurrentMsg
= NULL
;
375 m_pfnSuperWindowProc
= ::DefWindowProc
;
378 virtual void OnFinalMessage(HWND
/* hWnd */)
382 BOOL
SubclassWindow(HWND hWnd
)
384 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
385 WNDPROC newWindowProc
;
386 WNDPROC oldWindowProc
;
389 ATLASSERT(m_hWnd
== NULL
);
390 ATLASSERT(::IsWindow(hWnd
));
392 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
394 result
= m_thunk
.Init(GetWindowProc(), this);
397 newWindowProc
= m_thunk
.GetWNDPROC();
398 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
399 if (oldWindowProc
== NULL
)
401 m_pfnSuperWindowProc
= oldWindowProc
;
402 pThis
->m_hWnd
= hWnd
;
406 virtual WNDPROC
GetWindowProc()
411 static DWORD
GetWndStyle(DWORD dwStyle
)
413 return TWinTraits::GetWndStyle(dwStyle
);
416 static DWORD
GetWndExStyle(DWORD dwExStyle
)
418 return TWinTraits::GetWndExStyle(dwExStyle
);
421 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
423 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
425 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
426 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
429 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
431 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
432 WNDPROC newWindowProc
;
433 WNDPROC
GCCU(pOldProc
);
435 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(_AtlWinModule
.ExtractCreateWndData());
436 ATLASSERT(pThis
!= NULL
);
439 pThis
->m_thunk
.Init(pThis
->GetWindowProc(), pThis
);
440 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
441 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
442 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
443 pThis
->m_hWnd
= hWnd
;
444 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
447 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
449 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
= reinterpret_cast<CWindowImplBaseT
< TBase
, TWinTraits
> *>(hWnd
);
450 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
452 const _ATL_MSG
*previousMessage
;
454 LONG_PTR saveWindowProc
;
456 ATLASSERT(pThis
!= NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) == 0 && pThis
->m_hWnd
!= NULL
);
457 if (pThis
== NULL
|| (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0 || pThis
->m_hWnd
== NULL
)
460 hWnd
= pThis
->m_hWnd
;
461 previousMessage
= pThis
->m_pCurrentMsg
;
462 pThis
->m_pCurrentMsg
= &msg
;
464 handled
= pThis
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, 0);
465 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
467 if (handled
== FALSE
)
469 if (uMsg
== WM_NCDESTROY
)
471 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
472 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
473 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
474 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
475 pThis
->m_dwState
|= WINSTATE_DESTROYED
;
478 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
480 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
481 pThis
->m_pCurrentMsg
= previousMessage
;
482 if (previousMessage
== NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0)
484 pThis
->m_dwState
&= ~WINSTATE_DESTROYED
;
485 pThis
->m_hWnd
= NULL
;
486 pThis
->OnFinalMessage(hWnd
);
491 HWND
Create(HWND hWndParent
, _U_RECT rect
, LPCTSTR szWindowName
, DWORD dwStyle
, DWORD dwExStyle
,
492 _U_MENUorID MenuOrID
, ATOM atom
, LPVOID lpCreateParam
)
496 ATLASSERT(m_hWnd
== NULL
);
497 ATLASSERT(atom
!= 0);
500 if (m_thunk
.Init(NULL
, NULL
) == FALSE
)
502 SetLastError(ERROR_OUTOFMEMORY
);
506 _AtlWinModule
.AddCreateWndData(&m_thunk
.cd
, this);
507 if (MenuOrID
.m_hMenu
== NULL
&& (dwStyle
& WS_CHILD
) != 0)
508 MenuOrID
.m_hMenu
= (HMENU
)(UINT_PTR
)this;
509 if (rect
.m_lpRect
== NULL
)
510 rect
.m_lpRect
= &TBase::rcDefault
;
511 hWnd
= ::CreateWindowEx(dwExStyle
, reinterpret_cast<LPCWSTR
>(MAKEINTATOM(atom
)), szWindowName
, dwStyle
, rect
.m_lpRect
->left
,
512 rect
.m_lpRect
->top
, rect
.m_lpRect
->right
- rect
.m_lpRect
->left
, rect
.m_lpRect
->bottom
- rect
.m_lpRect
->top
,
513 hWndParent
, MenuOrID
.m_hMenu
, _AtlBaseModule
.GetModuleInstance(), lpCreateParam
);
515 ATLASSERT(m_hWnd
== hWnd
);
521 template <class T
, class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
522 class CWindowImpl
: public CWindowImplBaseT
<TBase
, TWinTraits
>
525 static LPCTSTR
GetWndCaption()
530 HWND
Create(HWND hWndParent
, _U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
, DWORD dwStyle
= 0,
531 DWORD dwExStyle
= 0, _U_MENUorID MenuOrID
= 0U, LPVOID lpCreateParam
= NULL
)
533 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
536 ATLASSERT(m_hWnd
== NULL
);
537 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
539 if (T::GetWndClassInfo().m_lpszOrigName
== NULL
)
540 T::GetWndClassInfo().m_lpszOrigName
= pThis
->GetWndClassName();
541 atom
= T::GetWndClassInfo().Register(&pThis
->m_pfnSuperWindowProc
);
543 if (szWindowName
== NULL
)
544 szWindowName
= T::GetWndCaption();
545 dwStyle
= T::GetWndStyle(dwStyle
);
546 dwExStyle
= T::GetWndExStyle(dwExStyle
);
548 return CWindowImplBaseT
<TBase
, TWinTraits
>::Create(hWndParent
, rect
, szWindowName
, dwStyle
,
549 dwExStyle
, MenuOrID
, atom
, lpCreateParam
);
553 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
554 class CContainedWindowT
: public TBase
557 CWndProcThunk m_thunk
;
558 LPCTSTR m_lpszClassName
;
559 WNDPROC m_pfnSuperWindowProc
;
560 CMessageMap
*m_pObject
;
562 const _ATL_MSG
*m_pCurrentMsg
;
564 CContainedWindowT(CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
566 m_lpszClassName
= TBase::GetWndClassName();
567 m_pfnSuperWindowProc
= ::DefWindowProc
;
569 m_dwMsgMapID
= dwMsgMapID
;
570 m_pCurrentMsg
= NULL
;
573 CContainedWindowT(LPTSTR lpszClassName
, CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
575 m_lpszClassName
= lpszClassName
;
576 m_pfnSuperWindowProc
= ::DefWindowProc
;
578 m_dwMsgMapID
= dwMsgMapID
;
579 m_pCurrentMsg
= NULL
;
582 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
584 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
586 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
587 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
590 BOOL
SubclassWindow(HWND hWnd
)
592 CContainedWindowT
<TBase
> *pThis
;
593 WNDPROC newWindowProc
;
594 WNDPROC oldWindowProc
;
597 ATLASSERT(m_hWnd
== NULL
);
598 ATLASSERT(::IsWindow(hWnd
));
600 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(this);
602 result
= m_thunk
.Init(WindowProc
, pThis
);
605 newWindowProc
= m_thunk
.GetWNDPROC();
606 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
607 if (oldWindowProc
== NULL
)
609 m_pfnSuperWindowProc
= oldWindowProc
;
610 pThis
->m_hWnd
= hWnd
;
614 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
616 CContainedWindowT
<TBase
> *pThis
;
617 WNDPROC newWindowProc
;
618 WNDPROC
GCCU(pOldProc
);
620 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(_AtlWinModule
.ExtractCreateWndData());
621 ATLASSERT(pThis
!= NULL
);
624 pThis
->m_thunk
.Init(WindowProc
, pThis
);
625 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
626 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
627 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
628 pThis
->m_hWnd
= hWnd
;
629 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
632 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
634 CContainedWindowT
<TBase
> *pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(hWnd
);
635 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
637 const _ATL_MSG
*previousMessage
;
639 LONG_PTR saveWindowProc
;
641 ATLASSERT(pThis
!= NULL
&& pThis
->m_hWnd
!= NULL
&& pThis
->m_pObject
!= NULL
);
642 if (pThis
== NULL
|| pThis
->m_hWnd
== NULL
|| pThis
->m_pObject
== NULL
)
645 hWnd
= pThis
->m_hWnd
;
646 previousMessage
= pThis
->m_pCurrentMsg
;
647 pThis
->m_pCurrentMsg
= &msg
;
649 handled
= pThis
->m_pObject
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, pThis
->m_dwMsgMapID
);
650 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
652 pThis
->m_pCurrentMsg
= previousMessage
;
653 if (handled
== FALSE
)
655 if (uMsg
== WM_NCDESTROY
)
657 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
658 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
659 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
660 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
661 pThis
->m_hWnd
= NULL
;
664 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
670 typedef CContainedWindowT
<CWindow
> CContainedWindow
;
672 #define BEGIN_MSG_MAP(theClass) \
674 BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
676 BOOL GCCU(bHandled) = TRUE; \
687 #define END_MSG_MAP() \
696 #define MESSAGE_HANDLER(msg, func) \
700 lResult = func(uMsg, wParam, lParam, bHandled); \
705 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
706 if (uMsg >= msgFirst && uMsg <= msgLast) \
709 lResult = func(uMsg, wParam, lParam, bHandled); \
714 #define COMMAND_ID_HANDLER(id, func) \
715 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
718 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
723 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
724 if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
727 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
732 #define NOTIFY_CODE_HANDLER(cd, func) \
733 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
736 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
741 #define NOTIFY_HANDLER(id, cd, func) \
742 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
745 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
750 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
751 static ATL::CWndClassInfo& GetWndClassInfo() \
753 static ATL::CWndClassInfo wc = \
755 { sizeof(WNDCLASSEX), style, StartWindowProc, \
756 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
757 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
762 struct _ATL_WNDCLASSINFOW
765 LPCWSTR m_lpszOrigName
;
767 LPCWSTR m_lpszCursorID
;
768 BOOL m_bSystemCursor
;
770 WCHAR m_szAutoName
[5 + sizeof(void *)];
772 ATOM
Register(WNDPROC
*p
)
775 m_atom
= RegisterClassEx(&m_wc
);