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
;
162 m_pthunk
= (thunkCode
*)VirtualAlloc(NULL
, sizeof(thunkCode
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
167 VirtualFree(m_pthunk
, 0, MEM_RELEASE
);
170 BOOL
Init(WNDPROC proc
, void *pThis
)
172 m_pthunk
->m_mov
= 0x042444C7;
173 m_pthunk
->m_this
= PtrToUlong(pThis
);
174 m_pthunk
->m_jmp
= 0xe9;
175 m_pthunk
->m_relproc
= DWORD(reinterpret_cast<char *>(proc
) - (reinterpret_cast<char *>(m_pthunk
) + sizeof(thunkCode
)));
181 return reinterpret_cast<WNDPROC
>(m_pthunk
);
185 #elif _AMD64_ //WARNING: NOT VERIFIED
200 _AtlCreateWndData cd
;
202 BOOL
Init(WNDPROC proc
, void *pThis
)
204 m_thunk
.m_mov
= 0xffff8000042444C7LL
;
205 m_thunk
.m_this
= (DWORD_PTR
)pThis
;
206 m_thunk
.m_jmp
= 0xe9;
207 m_thunk
.m_relproc
= DWORD_PTR(reinterpret_cast<char *>(proc
) - (reinterpret_cast<char *>(this) + sizeof(thunkCode
)));
213 return reinterpret_cast<WNDPROC
>(&m_thunk
);
217 #error ARCH not supported
223 virtual BOOL
ProcessWindowMessage(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
, DWORD dwMsgMapID
) = 0;
230 static RECT rcDefault
;
232 CWindow(HWND hWnd
= NULL
)
237 operator HWND() const
242 static LPCTSTR
GetWndClassName()
247 HDC
BeginPaint(LPPAINTSTRUCT lpPaint
)
249 ATLASSERT(::IsWindow(m_hWnd
));
250 return ::BeginPaint(m_hWnd
, lpPaint
);
255 ATLASSERT(::IsWindow(m_hWnd
));
257 if (!::DestroyWindow(m_hWnd
))
264 void EndPaint(LPPAINTSTRUCT lpPaint
)
266 ATLASSERT(::IsWindow(m_hWnd
));
267 ::EndPaint(m_hWnd
, lpPaint
);
270 BOOL
GetClientRect(LPRECT lpRect
) const
272 ATLASSERT(::IsWindow(m_hWnd
));
273 return ::GetClientRect(m_hWnd
, lpRect
);
276 CWindow
GetParent() const
278 ATLASSERT(::IsWindow(m_hWnd
));
279 return CWindow(::GetParent(m_hWnd
));
282 BOOL
Invalidate(BOOL bErase
= TRUE
)
284 ATLASSERT(::IsWindow(m_hWnd
));
285 return ::InvalidateRect(m_hWnd
, NULL
, bErase
);
288 BOOL
InvalidateRect(LPCRECT lpRect
, BOOL bErase
= TRUE
)
290 ATLASSERT(::IsWindow(m_hWnd
));
291 return ::InvalidateRect(m_hWnd
, lpRect
, bErase
);
294 BOOL
IsWindow() const
296 return ::IsWindow(m_hWnd
);
299 BOOL
KillTimer(UINT_PTR nIDEvent
)
301 ATLASSERT(::IsWindow(m_hWnd
));
302 return ::KillTimer(m_hWnd
, nIDEvent
);
305 BOOL
LockWindowUpdate(BOOL bLock
= TRUE
)
307 ATLASSERT(::IsWindow(m_hWnd
));
309 return ::LockWindowUpdate(m_hWnd
);
310 return ::LockWindowUpdate(NULL
);
313 BOOL
ScreenToClient(LPPOINT lpPoint
) const
315 ATLASSERT(::IsWindow(m_hWnd
));
316 return ::ScreenToClient(m_hWnd
, lpPoint
);
319 LRESULT
SendMessage(UINT message
, WPARAM wParam
= 0, LPARAM lParam
= 0)
321 ATLASSERT(::IsWindow(m_hWnd
));
322 return ::SendMessage(m_hWnd
, message
, wParam
, lParam
);
325 static LRESULT
SendMessage(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
327 ATLASSERT(::IsWindow(hWnd
));
328 return ::SendMessage(hWnd
, message
, wParam
, lParam
);
333 ATLASSERT(::IsWindow(m_hWnd
));
334 return ::SetCapture(m_hWnd
);
339 ATLASSERT(::IsWindow(m_hWnd
));
340 return ::SetFocus(m_hWnd
);
343 UINT_PTR
SetTimer(UINT_PTR nIDEvent
, UINT nElapse
, void (CALLBACK
*lpfnTimer
)(HWND
, UINT
, UINT_PTR
, DWORD
) = NULL
)
345 ATLASSERT(::IsWindow(m_hWnd
));
346 return ::SetTimer(m_hWnd
, nIDEvent
, nElapse
, reinterpret_cast<TIMERPROC
>(lpfnTimer
));
349 BOOL
SetWindowPos(HWND hWndInsertAfter
, int x
, int y
, int cx
, int cy
, UINT nFlags
)
351 ATLASSERT(::IsWindow(m_hWnd
));
352 return ::SetWindowPos(m_hWnd
, hWndInsertAfter
, x
, y
, cx
, cy
, nFlags
);
355 BOOL
SetWindowText(LPCTSTR lpszString
)
357 ATLASSERT(::IsWindow(m_hWnd
));
358 return ::SetWindowText(m_hWnd
, lpszString
);
361 BOOL
ShowWindow(int nCmdShow
)
363 ATLASSERT(::IsWindow(m_hWnd
));
364 return ::ShowWindow(m_hWnd
, nCmdShow
);
369 ATLASSERT(::IsWindow(m_hWnd
));
370 return ::UpdateWindow(m_hWnd
);
374 _declspec(selectany
) RECT
CWindow::rcDefault
= { CW_USEDEFAULT
, CW_USEDEFAULT
, 0, 0 };
376 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
377 class CWindowImplBaseT
: public TBase
, public CMessageMap
380 enum { WINSTATE_DESTROYED
= 0x00000001 };
382 const _ATL_MSG
*m_pCurrentMsg
;
383 CWndProcThunk m_thunk
;
384 WNDPROC m_pfnSuperWindowProc
;
389 m_pCurrentMsg
= NULL
;
390 m_pfnSuperWindowProc
= ::DefWindowProc
;
393 virtual void OnFinalMessage(HWND
/* hWnd */)
397 BOOL
SubclassWindow(HWND hWnd
)
399 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
400 WNDPROC newWindowProc
;
401 WNDPROC oldWindowProc
;
404 ATLASSERT(m_hWnd
== NULL
);
405 ATLASSERT(::IsWindow(hWnd
));
407 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
409 result
= m_thunk
.Init(GetWindowProc(), this);
412 newWindowProc
= m_thunk
.GetWNDPROC();
413 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
414 if (oldWindowProc
== NULL
)
416 m_pfnSuperWindowProc
= oldWindowProc
;
417 pThis
->m_hWnd
= hWnd
;
421 virtual WNDPROC
GetWindowProc()
426 static DWORD
GetWndStyle(DWORD dwStyle
)
428 return TWinTraits::GetWndStyle(dwStyle
);
431 static DWORD
GetWndExStyle(DWORD dwExStyle
)
433 return TWinTraits::GetWndExStyle(dwExStyle
);
436 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
438 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
440 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
441 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
444 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
446 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
447 WNDPROC newWindowProc
;
448 WNDPROC
GCCU(pOldProc
);
450 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(_AtlWinModule
.ExtractCreateWndData());
451 ATLASSERT(pThis
!= NULL
);
454 pThis
->m_thunk
.Init(pThis
->GetWindowProc(), pThis
);
455 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
456 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
457 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
458 pThis
->m_hWnd
= hWnd
;
459 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
462 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
464 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
= reinterpret_cast<CWindowImplBaseT
< TBase
, TWinTraits
> *>(hWnd
);
465 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
467 const _ATL_MSG
*previousMessage
;
469 LONG_PTR saveWindowProc
;
471 ATLASSERT(pThis
!= NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) == 0 && pThis
->m_hWnd
!= NULL
);
472 if (pThis
== NULL
|| (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0 || pThis
->m_hWnd
== NULL
)
475 hWnd
= pThis
->m_hWnd
;
476 previousMessage
= pThis
->m_pCurrentMsg
;
477 pThis
->m_pCurrentMsg
= &msg
;
479 handled
= pThis
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, 0);
480 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
482 if (handled
== FALSE
)
484 if (uMsg
== WM_NCDESTROY
)
486 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
487 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
488 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
489 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
490 pThis
->m_dwState
|= WINSTATE_DESTROYED
;
493 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
495 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
496 pThis
->m_pCurrentMsg
= previousMessage
;
497 if (previousMessage
== NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0)
499 pThis
->m_dwState
&= ~WINSTATE_DESTROYED
;
500 pThis
->m_hWnd
= NULL
;
501 pThis
->OnFinalMessage(hWnd
);
506 HWND
Create(HWND hWndParent
, _U_RECT rect
, LPCTSTR szWindowName
, DWORD dwStyle
, DWORD dwExStyle
,
507 _U_MENUorID MenuOrID
, ATOM atom
, LPVOID lpCreateParam
)
511 ATLASSERT(m_hWnd
== NULL
);
512 ATLASSERT(atom
!= 0);
515 if (m_thunk
.Init(NULL
, NULL
) == FALSE
)
517 SetLastError(ERROR_OUTOFMEMORY
);
521 _AtlWinModule
.AddCreateWndData(&m_thunk
.cd
, this);
522 if (MenuOrID
.m_hMenu
== NULL
&& (dwStyle
& WS_CHILD
) != 0)
523 MenuOrID
.m_hMenu
= (HMENU
)(UINT_PTR
)this;
524 if (rect
.m_lpRect
== NULL
)
525 rect
.m_lpRect
= &TBase::rcDefault
;
526 hWnd
= ::CreateWindowEx(dwExStyle
, reinterpret_cast<LPCWSTR
>(MAKEINTATOM(atom
)), szWindowName
, dwStyle
, rect
.m_lpRect
->left
,
527 rect
.m_lpRect
->top
, rect
.m_lpRect
->right
- rect
.m_lpRect
->left
, rect
.m_lpRect
->bottom
- rect
.m_lpRect
->top
,
528 hWndParent
, MenuOrID
.m_hMenu
, _AtlBaseModule
.GetModuleInstance(), lpCreateParam
);
530 ATLASSERT(m_hWnd
== hWnd
);
536 template <class T
, class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
537 class CWindowImpl
: public CWindowImplBaseT
<TBase
, TWinTraits
>
540 static LPCTSTR
GetWndCaption()
545 HWND
Create(HWND hWndParent
, _U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
, DWORD dwStyle
= 0,
546 DWORD dwExStyle
= 0, _U_MENUorID MenuOrID
= 0U, LPVOID lpCreateParam
= NULL
)
548 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
551 ATLASSERT(m_hWnd
== NULL
);
552 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
554 if (T::GetWndClassInfo().m_lpszOrigName
== NULL
)
555 T::GetWndClassInfo().m_lpszOrigName
= pThis
->GetWndClassName();
556 atom
= T::GetWndClassInfo().Register(&pThis
->m_pfnSuperWindowProc
);
558 if (szWindowName
== NULL
)
559 szWindowName
= T::GetWndCaption();
560 dwStyle
= T::GetWndStyle(dwStyle
);
561 dwExStyle
= T::GetWndExStyle(dwExStyle
);
563 return CWindowImplBaseT
<TBase
, TWinTraits
>::Create(hWndParent
, rect
, szWindowName
, dwStyle
,
564 dwExStyle
, MenuOrID
, atom
, lpCreateParam
);
568 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
569 class CContainedWindowT
: public TBase
572 CWndProcThunk m_thunk
;
573 LPCTSTR m_lpszClassName
;
574 WNDPROC m_pfnSuperWindowProc
;
575 CMessageMap
*m_pObject
;
577 const _ATL_MSG
*m_pCurrentMsg
;
579 CContainedWindowT(CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
581 m_lpszClassName
= TBase::GetWndClassName();
582 m_pfnSuperWindowProc
= ::DefWindowProc
;
584 m_dwMsgMapID
= dwMsgMapID
;
585 m_pCurrentMsg
= NULL
;
588 CContainedWindowT(LPTSTR lpszClassName
, CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
590 m_lpszClassName
= lpszClassName
;
591 m_pfnSuperWindowProc
= ::DefWindowProc
;
593 m_dwMsgMapID
= dwMsgMapID
;
594 m_pCurrentMsg
= NULL
;
597 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
599 return ::CallWindowProc(m_pfnSuperWindowProc
, this->m_hWnd
, uMsg
, wParam
, lParam
);
602 BOOL
SubclassWindow(HWND hWnd
)
604 CContainedWindowT
<TBase
> *pThis
;
605 WNDPROC newWindowProc
;
606 WNDPROC oldWindowProc
;
609 ATLASSERT(m_hWnd
== NULL
);
610 ATLASSERT(::IsWindow(hWnd
));
612 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(this);
614 result
= m_thunk
.Init(WindowProc
, pThis
);
617 newWindowProc
= m_thunk
.GetWNDPROC();
618 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
619 if (oldWindowProc
== NULL
)
621 m_pfnSuperWindowProc
= oldWindowProc
;
622 pThis
->m_hWnd
= hWnd
;
626 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
628 CContainedWindowT
<TBase
> *pThis
;
629 WNDPROC newWindowProc
;
630 WNDPROC
GCCU(pOldProc
);
632 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(_AtlWinModule
.ExtractCreateWndData());
633 ATLASSERT(pThis
!= NULL
);
636 pThis
->m_thunk
.Init(WindowProc
, pThis
);
637 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
638 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
639 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
640 pThis
->m_hWnd
= hWnd
;
641 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
644 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
646 CContainedWindowT
<TBase
> *pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(hWnd
);
647 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
649 const _ATL_MSG
*previousMessage
;
651 LONG_PTR saveWindowProc
;
653 ATLASSERT(pThis
!= NULL
&& pThis
->m_hWnd
!= NULL
&& pThis
->m_pObject
!= NULL
);
654 if (pThis
== NULL
|| pThis
->m_hWnd
== NULL
|| pThis
->m_pObject
== NULL
)
657 hWnd
= pThis
->m_hWnd
;
658 previousMessage
= pThis
->m_pCurrentMsg
;
659 pThis
->m_pCurrentMsg
= &msg
;
661 handled
= pThis
->m_pObject
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, pThis
->m_dwMsgMapID
);
662 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
664 pThis
->m_pCurrentMsg
= previousMessage
;
665 if (handled
== FALSE
)
667 if (uMsg
== WM_NCDESTROY
)
669 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
670 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
671 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
672 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
673 pThis
->m_hWnd
= NULL
;
676 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
682 typedef CContainedWindowT
<CWindow
> CContainedWindow
;
684 #define BEGIN_MSG_MAP(theClass) \
686 BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
688 BOOL GCCU(bHandled) = TRUE; \
699 #define END_MSG_MAP() \
708 #define MESSAGE_HANDLER(msg, func) \
712 lResult = func(uMsg, wParam, lParam, bHandled); \
717 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
718 if (uMsg >= msgFirst && uMsg <= msgLast) \
721 lResult = func(uMsg, wParam, lParam, bHandled); \
726 #define COMMAND_ID_HANDLER(id, func) \
727 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
730 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
735 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
736 if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
739 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
744 #define NOTIFY_CODE_HANDLER(cd, func) \
745 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
748 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
753 #define NOTIFY_HANDLER(id, cd, func) \
754 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
757 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
762 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
763 static ATL::CWndClassInfo& GetWndClassInfo() \
765 static ATL::CWndClassInfo wc = \
767 { sizeof(WNDCLASSEX), style, StartWindowProc, \
768 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
769 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
774 struct _ATL_WNDCLASSINFOW
777 LPCWSTR m_lpszOrigName
;
779 LPCWSTR m_lpszCursorID
;
780 BOOL m_bSystemCursor
;
782 WCHAR m_szAutoName
[5 + sizeof(void *)];
784 ATOM
Register(WNDPROC
*p
)
786 if (m_wc
.hInstance
== NULL
)
787 m_wc
.hInstance
= _AtlBaseModule
.GetModuleInstance();
789 m_atom
= RegisterClassEx(&m_wc
);