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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
);
176 #error Only X86 supported
182 virtual BOOL
ProcessWindowMessage(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
, DWORD dwMsgMapID
) = 0;
189 static RECT rcDefault
;
191 CWindow(HWND hWnd
= NULL
)
196 operator HWND() const
201 static LPCTSTR
GetWndClassName()
206 HDC
BeginPaint(LPPAINTSTRUCT lpPaint
)
208 ATLASSERT(::IsWindow(m_hWnd
));
209 return ::BeginPaint(m_hWnd
, lpPaint
);
214 ATLASSERT(::IsWindow(m_hWnd
));
216 if (!::DestroyWindow(m_hWnd
))
223 void EndPaint(LPPAINTSTRUCT lpPaint
)
225 ATLASSERT(::IsWindow(m_hWnd
));
226 ::EndPaint(m_hWnd
, lpPaint
);
229 BOOL
GetClientRect(LPRECT lpRect
) const
231 ATLASSERT(::IsWindow(m_hWnd
));
232 return ::GetClientRect(m_hWnd
, lpRect
);
235 CWindow
GetParent() const
237 ATLASSERT(::IsWindow(m_hWnd
));
238 return CWindow(::GetParent(m_hWnd
));
241 BOOL
Invalidate(BOOL bErase
= TRUE
)
243 ATLASSERT(::IsWindow(m_hWnd
));
244 return ::InvalidateRect(m_hWnd
, NULL
, bErase
);
247 BOOL
InvalidateRect(LPCRECT lpRect
, BOOL bErase
= TRUE
)
249 ATLASSERT(::IsWindow(m_hWnd
));
250 return ::InvalidateRect(m_hWnd
, lpRect
, bErase
);
253 BOOL
IsWindow() const
255 return ::IsWindow(m_hWnd
);
258 BOOL
KillTimer(UINT_PTR nIDEvent
)
260 ATLASSERT(::IsWindow(m_hWnd
));
261 return ::KillTimer(m_hWnd
, nIDEvent
);
264 BOOL
LockWindowUpdate(BOOL bLock
= TRUE
)
266 ATLASSERT(::IsWindow(m_hWnd
));
268 return ::LockWindowUpdate(m_hWnd
);
269 return ::LockWindowUpdate(NULL
);
272 BOOL
ScreenToClient(LPPOINT lpPoint
) const
274 ATLASSERT(::IsWindow(m_hWnd
));
275 return ::ScreenToClient(m_hWnd
, lpPoint
);
278 LRESULT
SendMessage(UINT message
, WPARAM wParam
= 0, LPARAM lParam
= 0)
280 ATLASSERT(::IsWindow(m_hWnd
));
281 return ::SendMessage(m_hWnd
, message
, wParam
, lParam
);
284 static LRESULT
SendMessage(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
286 ATLASSERT(::IsWindow(hWnd
));
287 return ::SendMessage(hWnd
, message
, wParam
, lParam
);
292 ATLASSERT(::IsWindow(m_hWnd
));
293 return ::SetCapture(m_hWnd
);
298 ATLASSERT(::IsWindow(m_hWnd
));
299 return ::SetFocus(m_hWnd
);
302 UINT_PTR
SetTimer(UINT_PTR nIDEvent
, UINT nElapse
, void (CALLBACK
*lpfnTimer
)(HWND
, UINT
, UINT_PTR
, DWORD
) = NULL
)
304 ATLASSERT(::IsWindow(m_hWnd
));
305 return ::SetTimer(m_hWnd
, nIDEvent
, nElapse
, reinterpret_cast<TIMERPROC
>(lpfnTimer
));
308 BOOL
SetWindowPos(HWND hWndInsertAfter
, int x
, int y
, int cx
, int cy
, UINT nFlags
)
310 ATLASSERT(::IsWindow(m_hWnd
));
311 return ::SetWindowPos(m_hWnd
, hWndInsertAfter
, x
, y
, cx
, cy
, nFlags
);
314 BOOL
SetWindowText(LPCTSTR lpszString
)
316 ATLASSERT(::IsWindow(m_hWnd
));
317 return ::SetWindowText(m_hWnd
, lpszString
);
320 BOOL
ShowWindow(int nCmdShow
)
322 ATLASSERT(::IsWindow(m_hWnd
));
323 return ::ShowWindow(m_hWnd
, nCmdShow
);
328 _declspec(selectany
) RECT
CWindow::rcDefault
= { CW_USEDEFAULT
, CW_USEDEFAULT
, 0, 0 };
330 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
331 class CWindowImplBaseT
: public TBase
, public CMessageMap
334 enum { WINSTATE_DESTROYED
= 0x00000001 };
336 const _ATL_MSG
*m_pCurrentMsg
;
337 CWndProcThunk m_thunk
;
338 WNDPROC m_pfnSuperWindowProc
;
343 m_pCurrentMsg
= NULL
;
344 m_pfnSuperWindowProc
= ::DefWindowProc
;
347 virtual void OnFinalMessage(HWND
/* hWnd */)
351 BOOL
SubclassWindow(HWND hWnd
)
353 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
354 WNDPROC newWindowProc
;
355 WNDPROC oldWindowProc
;
358 ATLASSERT(m_hWnd
== NULL
);
359 ATLASSERT(::IsWindow(hWnd
));
361 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
363 result
= m_thunk
.Init(GetWindowProc(), this);
366 newWindowProc
= m_thunk
.GetWNDPROC();
367 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
368 if (oldWindowProc
== NULL
)
370 m_pfnSuperWindowProc
= oldWindowProc
;
371 pThis
->m_hWnd
= hWnd
;
375 virtual WNDPROC
GetWindowProc()
380 static DWORD
GetWndStyle(DWORD dwStyle
)
382 return TWinTraits::GetWndStyle(dwStyle
);
385 static DWORD
GetWndExStyle(DWORD dwExStyle
)
387 return TWinTraits::GetWndExStyle(dwExStyle
);
390 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
392 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
394 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
395 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
398 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
400 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
401 WNDPROC newWindowProc
;
402 WNDPROC
GCCU(pOldProc
);
404 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(_AtlWinModule
.ExtractCreateWndData());
405 ATLASSERT(pThis
!= NULL
);
408 pThis
->m_thunk
.Init(pThis
->GetWindowProc(), pThis
);
409 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
410 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
411 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
412 pThis
->m_hWnd
= hWnd
;
413 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
416 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
418 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
= reinterpret_cast<CWindowImplBaseT
< TBase
, TWinTraits
> *>(hWnd
);
419 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
421 const _ATL_MSG
*previousMessage
;
423 LONG_PTR saveWindowProc
;
425 ATLASSERT(pThis
!= NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) == 0 && pThis
->m_hWnd
!= NULL
);
426 if (pThis
== NULL
|| (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0 || pThis
->m_hWnd
== NULL
)
429 hWnd
= pThis
->m_hWnd
;
430 previousMessage
= pThis
->m_pCurrentMsg
;
431 pThis
->m_pCurrentMsg
= &msg
;
433 handled
= pThis
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, 0);
434 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
436 if (handled
== FALSE
)
438 if (uMsg
== WM_NCDESTROY
)
440 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
441 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
442 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
443 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
444 pThis
->m_dwState
|= WINSTATE_DESTROYED
;
447 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
449 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
450 pThis
->m_pCurrentMsg
= previousMessage
;
451 if (previousMessage
== NULL
&& (pThis
->m_dwState
& WINSTATE_DESTROYED
) != 0)
453 pThis
->m_dwState
&= ~WINSTATE_DESTROYED
;
454 pThis
->m_hWnd
= NULL
;
455 pThis
->OnFinalMessage(hWnd
);
460 HWND
Create(HWND hWndParent
, _U_RECT rect
, LPCTSTR szWindowName
, DWORD dwStyle
, DWORD dwExStyle
,
461 _U_MENUorID MenuOrID
, ATOM atom
, LPVOID lpCreateParam
)
465 ATLASSERT(m_hWnd
== NULL
);
466 ATLASSERT(atom
!= 0);
469 if (m_thunk
.Init(NULL
, NULL
) == FALSE
)
471 SetLastError(ERROR_OUTOFMEMORY
);
475 _AtlWinModule
.AddCreateWndData(&m_thunk
.cd
, this);
476 if (MenuOrID
.m_hMenu
== NULL
&& (dwStyle
& WS_CHILD
) != 0)
477 MenuOrID
.m_hMenu
= (HMENU
)(UINT_PTR
)this;
478 if (rect
.m_lpRect
== NULL
)
479 rect
.m_lpRect
= &TBase::rcDefault
;
480 hWnd
= ::CreateWindowEx(dwExStyle
, reinterpret_cast<LPCWSTR
>(MAKEINTATOM(atom
)), szWindowName
, dwStyle
, rect
.m_lpRect
->left
,
481 rect
.m_lpRect
->top
, rect
.m_lpRect
->right
- rect
.m_lpRect
->left
, rect
.m_lpRect
->bottom
- rect
.m_lpRect
->top
,
482 hWndParent
, MenuOrID
.m_hMenu
, _AtlBaseModule
.GetModuleInstance(), lpCreateParam
);
484 ATLASSERT(m_hWnd
== hWnd
);
490 template <class T
, class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
491 class CWindowImpl
: public CWindowImplBaseT
<TBase
, TWinTraits
>
494 static LPCTSTR
GetWndCaption()
499 HWND
Create(HWND hWndParent
, _U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
, DWORD dwStyle
= 0,
500 DWORD dwExStyle
= 0, _U_MENUorID MenuOrID
= 0U, LPVOID lpCreateParam
= NULL
)
502 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
505 ATLASSERT(m_hWnd
== NULL
);
506 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
>*>(this);
508 if (T::GetWndClassInfo().m_lpszOrigName
== NULL
)
509 T::GetWndClassInfo().m_lpszOrigName
= pThis
->GetWndClassName();
510 atom
= T::GetWndClassInfo().Register(&pThis
->m_pfnSuperWindowProc
);
512 if (szWindowName
== NULL
)
513 szWindowName
= T::GetWndCaption();
514 dwStyle
= T::GetWndStyle(dwStyle
);
515 dwExStyle
= T::GetWndExStyle(dwExStyle
);
517 return CWindowImplBaseT
<TBase
, TWinTraits
>::Create(hWndParent
, rect
, szWindowName
, dwStyle
,
518 dwExStyle
, MenuOrID
, atom
, lpCreateParam
);
522 template <class TBase
= CWindow
, class TWinTraits
= CControlWinTraits
>
523 class CContainedWindowT
: public TBase
526 CWndProcThunk m_thunk
;
527 LPCTSTR m_lpszClassName
;
528 WNDPROC m_pfnSuperWindowProc
;
529 CMessageMap
*m_pObject
;
531 const _ATL_MSG
*m_pCurrentMsg
;
533 CContainedWindowT(CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
535 m_lpszClassName
= TBase::GetWndClassName();
536 m_pfnSuperWindowProc
= ::DefWindowProc
;
538 m_dwMsgMapID
= dwMsgMapID
;
539 m_pCurrentMsg
= NULL
;
542 CContainedWindowT(LPTSTR lpszClassName
, CMessageMap
*pObject
, DWORD dwMsgMapID
= 0)
544 m_lpszClassName
= lpszClassName
;
545 m_pfnSuperWindowProc
= ::DefWindowProc
;
547 m_dwMsgMapID
= dwMsgMapID
;
548 m_pCurrentMsg
= NULL
;
551 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
553 CWindowImplBaseT
<TBase
, TWinTraits
> *pThis
;
555 pThis
= reinterpret_cast<CWindowImplBaseT
<TBase
, TWinTraits
> *>(this);
556 return ::CallWindowProc(m_pfnSuperWindowProc
, pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
559 BOOL
SubclassWindow(HWND hWnd
)
561 CContainedWindowT
<TBase
> *pThis
;
562 WNDPROC newWindowProc
;
563 WNDPROC oldWindowProc
;
566 ATLASSERT(m_hWnd
== NULL
);
567 ATLASSERT(::IsWindow(hWnd
));
569 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(this);
571 result
= m_thunk
.Init(WindowProc
, pThis
);
574 newWindowProc
= m_thunk
.GetWNDPROC();
575 oldWindowProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
576 if (oldWindowProc
== NULL
)
578 m_pfnSuperWindowProc
= oldWindowProc
;
579 pThis
->m_hWnd
= hWnd
;
583 static LRESULT CALLBACK
StartWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
585 CContainedWindowT
<TBase
> *pThis
;
586 WNDPROC newWindowProc
;
587 WNDPROC
GCCU(pOldProc
);
589 pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(_AtlWinModule
.ExtractCreateWndData());
590 ATLASSERT(pThis
!= NULL
);
593 pThis
->m_thunk
.Init(WindowProc
, pThis
);
594 newWindowProc
= pThis
->m_thunk
.GetWNDPROC();
595 pOldProc
= reinterpret_cast<WNDPROC
>(::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(newWindowProc
)));
596 Unused(pOldProc
); // TODO: should generate trace message if overwriting another subclass
597 pThis
->m_hWnd
= hWnd
;
598 return newWindowProc(hWnd
, uMsg
, wParam
, lParam
);
601 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
603 CContainedWindowT
<TBase
> *pThis
= reinterpret_cast<CContainedWindowT
<TBase
> *>(hWnd
);
604 _ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
606 const _ATL_MSG
*previousMessage
;
608 LONG_PTR saveWindowProc
;
610 ATLASSERT(pThis
!= NULL
&& pThis
->m_hWnd
!= NULL
&& pThis
->m_pObject
!= NULL
);
611 if (pThis
== NULL
|| pThis
->m_hWnd
== NULL
|| pThis
->m_pObject
== NULL
)
614 hWnd
= pThis
->m_hWnd
;
615 previousMessage
= pThis
->m_pCurrentMsg
;
616 pThis
->m_pCurrentMsg
= &msg
;
618 handled
= pThis
->m_pObject
->ProcessWindowMessage(hWnd
, uMsg
, wParam
, lParam
, lResult
, pThis
->m_dwMsgMapID
);
619 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
621 pThis
->m_pCurrentMsg
= previousMessage
;
622 if (handled
== FALSE
)
624 if (uMsg
== WM_NCDESTROY
)
626 saveWindowProc
= ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
);
627 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
628 if (pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& saveWindowProc
== ::GetWindowLongPtr(hWnd
, GWLP_WNDPROC
))
629 ::SetWindowLongPtr(hWnd
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(pThis
->m_pfnSuperWindowProc
));
630 pThis
->m_hWnd
= NULL
;
633 lResult
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
639 typedef CContainedWindowT
<CWindow
> CContainedWindow
;
641 #define BEGIN_MSG_MAP(theClass) \
643 BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \
645 BOOL GCCU(bHandled) = TRUE; \
656 #define END_MSG_MAP() \
665 #define MESSAGE_HANDLER(msg, func) \
669 lResult = func(uMsg, wParam, lParam, bHandled); \
674 #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
675 if (uMsg >= msgFirst && uMsg <= msgLast) \
678 lResult = func(uMsg, wParam, lParam, bHandled); \
683 #define COMMAND_ID_HANDLER(id, func) \
684 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
687 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
692 #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
693 if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
696 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
701 #define NOTIFY_CODE_HANDLER(cd, func) \
702 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
705 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
710 #define NOTIFY_HANDLER(id, cd, func) \
711 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
714 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
719 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
720 static ATL::CWndClassInfo& GetWndClassInfo() \
722 static ATL::CWndClassInfo wc = \
724 { sizeof(WNDCLASSEX), style, StartWindowProc, \
725 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
726 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
731 struct _ATL_WNDCLASSINFOW
734 LPCWSTR m_lpszOrigName
;
736 LPCWSTR m_lpszCursorID
;
737 BOOL m_bSystemCursor
;
739 WCHAR m_szAutoName
[5 + sizeof(void *)];
741 ATOM
Register(WNDPROC
*p
)
744 m_atom
= RegisterClassEx(&m_wc
);