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 _declspec(selectany
) RECT
CWindow::rcDefault
= { CW_USEDEFAULT
, CW_USEDEFAULT
, 0, 0 };
360 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
361 class CWindowImplBaseT
: public TBase
, public CMessageMap
364 enum { WINSTATE_DESTROYED
= 0x00000001 };
366 const _ATL_MSG
*m_pCurrentMsg
;
367 CWndProcThunk m_thunk
;
368 WNDPROC m_pfnSuperWindowProc
;
373 m_pCurrentMsg
= NULL
;
374 m_pfnSuperWindowProc
= ::DefWindowProc
;
377 virtual void OnFinalMessage(HWND
/* hWnd */)
381 BOOL
SubclassWindow(HWND hWnd
)
383 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
384 WNDPROC newWindowProc
;
385 WNDPROC oldWindowProc
;
388 ATLASSERT(m_hWnd
== NULL
);
389 ATLASSERT(::IsWindow(hWnd
));
391 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
393 result
= m_thunk
.Init(GetWindowProc(), this);
396 newWindowProc
= m_thunk
.GetWNDPROC();
397 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
398 if (oldWindowProc
== NULL
)
400 m_pfnSuperWindowProc
= oldWindowProc
;
401 pThis
->m_hWnd
= hWnd
;
405 virtual WNDPROC
GetWindowProc()
410 static DWORD
GetWndStyle(DWORD dwStyle
)
412 return TWinTraits::GetWndStyle(dwStyle
);
415 static DWORD
GetWndExStyle(DWORD dwExStyle
)
417 return TWinTraits::GetWndExStyle(dwExStyle
);
420 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
422 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
424 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
425 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
428 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
430 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
431 WNDPROC newWindowProc
;
432 WNDPROC
GCCU(pOldProc
);
434 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(_AtlWinModule
.ExtractCreateWndData());
435 ATLASSERT(pThis
!= NULL
);
438 pThis
->m_thunk
.Init(pThis
->GetWindowProc(), pThis
);
439 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
440 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
441 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
442 pThis
->m_hWnd
= hWnd
;
443 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
446 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
448 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
= reinterpret_cast<CWindowImplBaseT
< TBase
, TWinTraits
> *>(hWnd
);
449 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
451 const _ATL_MSG
*previousMessage
;
453 LONG_PTR saveWindowProc
;
455 ATLASSERT(pThis
!= NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) == 0 && pThis
->m_hWnd
!= NULL
);
456 if (pThis
== NULL
|| (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0 || pThis
->m_hWnd
== NULL
)
459 hWnd
= pThis
->m_hWnd
;
460 previousMessage
= pThis
->m_pCurrentMsg
;
461 pThis
->m_pCurrentMsg
= &msg
;
463 handled
= pThis
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, 0);
464 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
466 if (handled
== FALSE
)
468 if (uMsg
== WM_NCDESTROY
)
470 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
471 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
472 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
473 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
474 pThis
->m_dwState
|= WINSTATE_DESTROYED
;
477 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
479 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
480 pThis
->m_pCurrentMsg
= previousMessage
;
481 if (previousMessage
== NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0)
483 pThis
->m_dwState
&= ~WINSTATE_DESTROYED
;
484 pThis
->m_hWnd
= NULL
;
485 pThis
->OnFinalMessage(hWnd
);
490 HWND
Create(HWND hWndParent
, _U_RECT rect
, LPCTSTR szWindowName
, DWORD dwStyle
, DWORD dwExStyle
,
491 _U_MENUorID MenuOrID
, ATOM atom
, LPVOID lpCreateParam
)
495 ATLASSERT(m_hWnd
== NULL
);
496 ATLASSERT(atom
!= 0);
499 if (m_thunk
.Init(NULL
, NULL
) == FALSE
)
501 SetLastError(ERROR_OUTOFMEMORY
);
505 _AtlWinModule
.AddCreateWndData(&m_thunk
.cd
, this);
506 if (MenuOrID
.m_hMenu
== NULL
&& (dwStyle
& WS_CHILD
) != 0)
507 MenuOrID
.m_hMenu
= (HMENU
)(UINT_PTR
)this;
508 if (rect
.m_lpRect
== NULL
)
509 rect
.m_lpRect
= &TBase::rcDefault
;
510 hWnd
= ::CreateWindowEx(dwExStyle
, reinterpret_cast<LPCWSTR
>(MAKEINTATOM(atom
)), szWindowName
, dwStyle
, rect
.m_lpRect
->left
,
511 rect
.m_lpRect
->top
, rect
.m_lpRect
->right
- rect
.m_lpRect
->left
, rect
.m_lpRect
->bottom
- rect
.m_lpRect
->top
,
512 hWndParent
, MenuOrID
.m_hMenu
, _AtlBaseModule
.GetModuleInstance(), lpCreateParam
);
514 ATLASSERT(m_hWnd
== hWnd
);
520 template <class T
, class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
521 class CWindowImpl
: public CWindowImplBaseT
<TBase
, TWinTraits
>
524 static LPCTSTR
GetWndCaption()
529 HWND
Create(HWND hWndParent
, _U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
, DWORD dwStyle
= 0,
530 DWORD dwExStyle
= 0, _U_MENUorID MenuOrID
= 0U, LPVOID lpCreateParam
= NULL
)
532 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
535 ATLASSERT(m_hWnd
== NULL
);
536 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
538 if (T::GetWndClassInfo().m_lpszOrigName
== NULL
)
539 T::GetWndClassInfo().m_lpszOrigName
= pThis
->GetWndClassName();
540 atom
= T::GetWndClassInfo().Register(&pThis
->m_pfnSuperWindowProc
);
542 if (szWindowName
== NULL
)
543 szWindowName
= T::GetWndCaption();
544 dwStyle
= T::GetWndStyle(dwStyle
);
545 dwExStyle
= T::GetWndExStyle(dwExStyle
);
547 return CWindowImplBaseT
<TBase
, TWinTraits
>::Create(hWndParent
, rect
, szWindowName
, dwStyle
,
548 dwExStyle
, MenuOrID
, atom
, lpCreateParam
);
552 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
553 class CContainedWindowT
: public TBase
556 CWndProcThunk m_thunk
;
557 LPCTSTR m_lpszClassName
;
558 WNDPROC m_pfnSuperWindowProc
;
559 CMessageMap
*m_pObject
;
561 const _ATL_MSG
*m_pCurrentMsg
;
563 CContainedWindowT(CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
565 m_lpszClassName
= TBase::GetWndClassName();
566 m_pfnSuperWindowProc
= ::DefWindowProc
;
568 m_dwMsgMapID
= dwMsgMapID
;
569 m_pCurrentMsg
= NULL
;
572 CContainedWindowT(LPTSTR lpszClassName
, CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
574 m_lpszClassName
= lpszClassName
;
575 m_pfnSuperWindowProc
= ::DefWindowProc
;
577 m_dwMsgMapID
= dwMsgMapID
;
578 m_pCurrentMsg
= NULL
;
581 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
583 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
585 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
586 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
589 BOOL
SubclassWindow(HWND hWnd
)
591 CContainedWindowT
<TBase
> *pThis
;
592 WNDPROC newWindowProc
;
593 WNDPROC oldWindowProc
;
596 ATLASSERT(m_hWnd
== NULL
);
597 ATLASSERT(::IsWindow(hWnd
));
599 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(this);
601 result
= m_thunk
.Init(WindowProc
, pThis
);
604 newWindowProc
= m_thunk
.GetWNDPROC();
605 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
606 if (oldWindowProc
== NULL
)
608 m_pfnSuperWindowProc
= oldWindowProc
;
609 pThis
->m_hWnd
= hWnd
;
613 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
615 CContainedWindowT
<TBase
> *pThis
;
616 WNDPROC newWindowProc
;
617 WNDPROC
GCCU(pOldProc
);
619 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(_AtlWinModule
.ExtractCreateWndData());
620 ATLASSERT(pThis
!= NULL
);
623 pThis
->m_thunk
.Init(WindowProc
, pThis
);
624 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
625 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
626 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
627 pThis
->m_hWnd
= hWnd
;
628 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
631 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
633 CContainedWindowT
<TBase
> *pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(hWnd
);
634 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
636 const _ATL_MSG
*previousMessage
;
638 LONG_PTR saveWindowProc
;
640 ATLASSERT(pThis
!= NULL
&& pThis
->m_hWnd
!= NULL
&& pThis
->m_pObject
!= NULL
);
641 if (pThis
== NULL
|| pThis
->m_hWnd
== NULL
|| pThis
->m_pObject
== NULL
)
644 hWnd
= pThis
->m_hWnd
;
645 previousMessage
= pThis
->m_pCurrentMsg
;
646 pThis
->m_pCurrentMsg
= &msg
;
648 handled
= pThis
->m_pObject
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, pThis
->m_dwMsgMapID
);
649 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
651 pThis
->m_pCurrentMsg
= previousMessage
;
652 if (handled
== FALSE
)
654 if (uMsg
== WM_NCDESTROY
)
656 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
657 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
658 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
659 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
660 pThis
->m_hWnd
= NULL
;
663 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
669 typedef CContainedWindowT
<CWindow
> CContainedWindow
;
671 #define BEGIN_MSG_MAP(theClass) \
673 BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
675 BOOL GCCU(bHandled) = TRUE; \
686 #define END_MSG_MAP() \
695 #define MESSAGE_HANDLER(msg, func) \
699 lResult = func(uMsg, wParam, lParam, bHandled); \
704 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
705 if (uMsg >= msgFirst && uMsg <= msgLast) \
708 lResult = func(uMsg, wParam, lParam, bHandled); \
713 #define COMMAND_ID_HANDLER(id, func) \
714 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
717 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
722 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
723 if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
726 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
731 #define NOTIFY_CODE_HANDLER(cd, func) \
732 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
735 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
740 #define NOTIFY_HANDLER(id, cd, func) \
741 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
744 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
749 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
750 static ATL::CWndClassInfo& GetWndClassInfo() \
752 static ATL::CWndClassInfo wc = \
754 { sizeof(WNDCLASSEX), style, StartWindowProc, \
755 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
756 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
761 struct _ATL_WNDCLASSINFOW
764 LPCWSTR m_lpszOrigName
;
766 LPCWSTR m_lpszCursorID
;
767 BOOL m_bSystemCursor
;
769 WCHAR m_szAutoName
[5 + sizeof(void *)];
771 ATOM
Register(WNDPROC
*p
)
774 m_atom
= RegisterClassEx(&m_wc
);