source: trunk/Common/alax.info/rowindows.h @ 77

Last change on this file since 77 was 77, checked in by roman, 12 years ago
  • Property svn:keywords set to Id
File size: 25.6 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2006-2012
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: rowindows.h 77 2012-07-24 09:37:18Z roman $
6//
7// A permission to use the source code is granted as long as reference to
8// source website http://alax.info is retained.
9
10#pragma once
11
12#include <atltypes.h>
13#include <atlcrack.h>
14#include "rores.h"
15#include "roatlcollections.h"
16
17////////////////////////////////////////////////////////////
18// CGdiSelector
19
20class CGdiSelector
21{
22public:
23        CDCHandle m_Dc;
24        HGDIOBJ m_hObject;
25
26public:
27// CGdiSelector
28        CGdiSelector(HDC hDc, HGDIOBJ hObject) throw()
29        {
30                m_Dc = hDc;
31                m_hObject = SelectObject(m_Dc, hObject);
32        }
33        ~CGdiSelector() throw()
34        {
35                SelectObject(m_Dc, m_hObject);
36        }
37        operator HDC () const throw()
38        {
39                return m_Dc;
40        }
41};
42
43////////////////////////////////////////////////////////////
44// _GdiHelper
45
46class _GdiHelper
47{
48public:
49// _GdiHelper
50        static SIZE_T GetDibSection(HBITMAP hBitmap, DIBSECTION& DibSection) throw()
51        {
52                _A(hBitmap);
53                ZeroMemory(&DibSection, sizeof DibSection);
54                return GetObject(hBitmap, sizeof DibSection, &DibSection);
55        }
56        static DIBSECTION GetDibSection(HBITMAP hBitmap)
57        {
58                DIBSECTION DibSection;
59                const SIZE_T nDibSectionSize = GetDibSection(hBitmap, DibSection);
60                __E(nDibSectionSize == sizeof DibSection || nDibSectionSize == sizeof (BITMAP));
61                return DibSection;
62        }
63        static ICONINFO GetIconInformation(HICON hIcon)
64        {
65                _A(hIcon);
66                ICONINFO IconInformation;
67                __E(CIconHandle(hIcon).GetIconInfo(&IconInformation));
68                return IconInformation;
69        }
70        static CIconHandle InternalOverlayIcon(CIconHandle BaseIcon, CIconHandle OverlayIcon, CDCHandle SampleDc, const ICONINFO& BaseIconInformation, CDCHandle Dc, CDCHandle SourceDc)
71        {
72                const ICONINFO OverlayIconInformation = GetIconInformation(OverlayIcon);
73                _A(BaseIconInformation.fIcon && OverlayIconInformation.fIcon);
74                const DIBSECTION BaseMaskDibSection = GetDibSection(BaseIconInformation.hbmMask);
75                const DIBSECTION BaseColorDibSection = GetDibSection(BaseIconInformation.hbmColor);
76#if defined(_DEBUG)
77                const DIBSECTION OverlayMaskDibSection = GetDibSection(OverlayIconInformation.hbmMask);
78                const DIBSECTION OverlayColorDibSection = GetDibSection(OverlayIconInformation.hbmColor);
79                CWindowDC DesktopDc(GetDesktopWindow());
80#endif // defined(_DEBUG)
81                const CSize Size(BaseColorDibSection.dsBm.bmWidth, BaseColorDibSection.dsBm.bmHeight);
82                _A(BaseMaskDibSection.dsBm.bmHeight == Size.cy); // Not a colorless icon
83                CBitmap MaskBitmap;
84                __E(MaskBitmap.CreateBitmap(Size.cx, Size.cy, 1, 1, NULL));
85                {
86                        CGdiSelector BitmapSelector(Dc, MaskBitmap);
87                        {
88                                CGdiSelector BitmapSelector(SourceDc, BaseIconInformation.hbmMask);
89                                __E(Dc.BitBlt(0, 0, Size.cx, Size.cy, SourceDc, 0, 0, SRCCOPY));
90                        }
91                        {
92                                CGdiSelector BitmapSelector(SourceDc, OverlayIconInformation.hbmMask);
93                                __E(Dc.BitBlt(0, 0, Size.cx, Size.cy, SourceDc, 0, 0, SRCAND));
94                        }
95                }
96#if defined(_DEBUG) && FALSE
97                _W(DesktopDc.StretchBlt(0, 0 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, BaseIconInformation.hbmMask), 0, 0, Size.cx, Size.cy, SRCCOPY));
98                _W(DesktopDc.StretchBlt(5 * Size.cx, 0 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, OverlayIconInformation.hbmMask), 0, 0, Size.cx, Size.cy, SRCCOPY));
99                _W(DesktopDc.StretchBlt(10 * Size.cx, 0 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, MaskBitmap), 0, 0, Size.cx, Size.cy, SRCCOPY));
100#endif // defined(_DEBUG)
101                CBitmap ColorBitmap;
102#if TRUE
103                BITMAPINFOHEADER ColorBitmapInfoHeader;
104                ZeroMemory(&ColorBitmapInfoHeader, sizeof ColorBitmapInfoHeader);
105                ColorBitmapInfoHeader.biSize = sizeof ColorBitmapInfoHeader;
106                ColorBitmapInfoHeader.biWidth = Size.cx;
107                ColorBitmapInfoHeader.biHeight = Size.cy;
108                ColorBitmapInfoHeader.biPlanes = 1;
109                ColorBitmapInfoHeader.biBitCount = 32;
110                ColorBitmapInfoHeader.biCompression = BI_RGB;
111                VOID* pvColorBits = NULL;
112                ColorBitmap = CreateDIBSection(SampleDc, (const BITMAPINFO*) &ColorBitmapInfoHeader, DIB_RGB_COLORS, &pvColorBits, NULL, 0);
113                __E(ColorBitmap);
114#else
115                __E(ColorBitmap.CreateBitmap(Size.cx, Size.cy, 1, 32, NULL)); //__E(ColorBitmap.CreateCompatibleBitmap(SampleDc, Size.cx, Size.cy));
116#endif
117                {
118                        CGdiSelector BitmapSelector(Dc, ColorBitmap);
119                        {
120                                CGdiSelector BitmapSelector(SourceDc, BaseIconInformation.hbmColor);
121                                __E(Dc.BitBlt(0, 0, Size.cx, Size.cy, SourceDc, 0, 0, SRCCOPY));
122                        }
123#if defined(_DEBUG) && FALSE
124                        _W(DesktopDc.StretchBlt(0, 5 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, BaseIconInformation.hbmColor), 0, 0, Size.cx, Size.cy, SRCCOPY));
125                        _W(DesktopDc.StretchBlt(5 * Size.cx, 5 * Size.cy, Size.cx * 4, Size.cy * 4, BitmapSelector, 0, 0, Size.cx, Size.cy, SRCCOPY));
126#endif // defined(_DEBUG)
127#if (WINVER >= 0x0400)
128                        // NOTE: Windows XP's DrawIconEx destroys Dc's alpha channel
129                        BOOL bHandled = FALSE;
130                        if(BaseColorDibSection.dsBm.bmBitsPixel >= 32)
131                        {
132                                // HOTFIX: Icons load from paletted formats (?) may have broken alpha channel
133                                if(BaseColorDibSection.dsBm.bmBitsPixel == 32)
134                                {
135                                        _A(pvColorBits);
136                                        BOOL bPositiveAlphaValueFound = FALSE;
137                                        for(SIZE_T nIndex = Size.cy * Size.cx; nIndex > 0; nIndex--)
138                                                if(((const RGBQUAD*) pvColorBits)[nIndex - 1].rgbReserved)
139                                                {
140                                                        bPositiveAlphaValueFound = TRUE;
141                                                        break;
142                                                }
143                                        if(!bPositiveAlphaValueFound)
144                                        {
145                                                _Z4(atlTraceWindowing, 4, _T("bPositiveAlphaValueFound %d\n"), bPositiveAlphaValueFound);
146                                                // WARN: GetPixel is slow
147                                                CGdiSelector BitmapSelector(SourceDc, BaseIconInformation.hbmMask);
148                                                RGBQUAD* pnPointer = (RGBQUAD*) pvColorBits;
149                                                for(LONG nY = Size.cy - 1; nY >= 0; nY--)
150                                                        for(LONG nX = 0; nX < Size.cx; nX++, pnPointer++)
151                                                                if(Dc.GetPixel(nX, nY))
152                                                                        pnPointer->rgbReserved = 0xFF;
153                                        }
154                                }
155                                CGdiSelector BitmapSelector(SourceDc, OverlayIconInformation.hbmColor);
156                                BLENDFUNCTION BlendFunction = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
157                                bHandled = AlphaBlend(Dc, 0, 0, Size.cx, Size.cy, SourceDc, 0, 0, Size.cx, Size.cy, BlendFunction);
158                                _A(bHandled);
159                        }
160                        if(!bHandled)
161#endif // (WINVER >= 0x0400)
162                                __E(OverlayIcon.DrawIconEx(Dc, CPoint(0, 0), Size));
163#if defined(_DEBUG) && FALSE
164                        _W(DesktopDc.StretchBlt(10 * Size.cx, 5 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, OverlayIconInformation.hbmColor), 0, 0, Size.cx, Size.cy, SRCCOPY));
165                        _W(DesktopDc.StretchBlt(15 * Size.cx, 5 * Size.cy, Size.cx * 4, Size.cy * 4, BitmapSelector, 0, 0, Size.cx, Size.cy, SRCCOPY));
166#endif // defined(_DEBUG)
167                }
168                ICONINFO IconInformation;
169                IconInformation = BaseIconInformation;
170                IconInformation.hbmMask = MaskBitmap;
171                IconInformation.hbmColor = ColorBitmap;
172                CIcon Icon;
173                __E(Icon.CreateIconIndirect(&IconInformation));
174#if defined(_DEBUG) && FALSE
175                _W(DesktopDc.StretchBlt(0, 10 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, MaskBitmap), 0, 0, Size.cx, Size.cy, SRCCOPY));
176                _W(DesktopDc.StretchBlt(5 * Size.cx, 10 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, ColorBitmap), 0, 0, Size.cx, Size.cy, SRCCOPY));
177                IconInformation = GetIconInformation(Icon);
178                _W(DesktopDc.StretchBlt(0, 15 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, IconInformation.hbmMask), 0, 0, Size.cx, Size.cy, SRCCOPY));
179                _W(DesktopDc.StretchBlt(5 * Size.cx, 15 * Size.cy, Size.cx * 4, Size.cy * 4, CGdiSelector(Dc, IconInformation.hbmColor), 0, 0, Size.cx, Size.cy, SRCCOPY));
180                _W(DesktopDc.DrawIcon(0, 20 * Size.cy, Icon));
181#endif // defined(_DEBUG)
182                return Icon.Detach();
183        }
184        static CIconHandle OverlayIcon(CIconHandle BaseIcon, CIconHandle OverlayIcon)
185        {
186                CClientDC SampleDc(NULL);
187                CDC Dc, SourceDc;
188                __E(Dc.CreateCompatibleDC(SampleDc));
189                __E(SourceDc.CreateCompatibleDC(Dc));
190                return InternalOverlayIcon(BaseIcon, OverlayIcon, (HDC) SampleDc, GetIconInformation(BaseIcon), (HDC) Dc, (HDC) SourceDc);
191        }
192        static VOID OverlayIcons(CIconHandle BaseIcon, CIconHandle* pOverlayIcons, SIZE_T nOverlayIconCount, CIcon* pIcons)
193        {
194                _A(!IsBadWritePtr(pIcons, sizeof *pIcons * nOverlayIconCount));
195                CClientDC SampleDc(NULL);
196                CDC Dc, SourceDc;
197                __E(Dc.CreateCompatibleDC(SampleDc));
198                __E(SourceDc.CreateCompatibleDC(Dc));
199                for(SIZE_T nIndex = 0; nIndex < nOverlayIconCount; nIndex++)
200                        pIcons[nIndex] = InternalOverlayIcon(BaseIcon, pOverlayIcons[nIndex], (HDC) SampleDc, GetIconInformation(BaseIcon), (HDC) Dc, (HDC) SourceDc);
201        }
202        static VOID OverlayIcons(CIconHandle BaseIcon, HICON* phOverlayIcons, SIZE_T nOverlayIconCount, CIcon* pIcons)
203        {
204                OverlayIcons(BaseIcon, reinterpret_cast<CIconHandle*>(phOverlayIcons), nOverlayIconCount, pIcons);
205        }
206        static VOID OverlayIcons(CIconHandle BaseIcon, CIcon* pOverlayIcons, SIZE_T nOverlayIconCount, CIcon* pIcons)
207        {
208                OverlayIcons(BaseIcon, reinterpret_cast<CIconHandle*>(pOverlayIcons), nOverlayIconCount, pIcons);
209        }
210};
211
212////////////////////////////////////////////////////////////
213// CWindowRedraw
214
215class CWindowRedraw
216{
217public:
218        CWindow m_Window;
219        LONG m_nCount;
220
221public:
222// CWindowRedraw
223        CWindowRedraw(HWND hWindow, LONG nSetCount = -1) throw() : 
224                m_Window(hWindow),
225                m_nCount(0)
226        {
227                // SUGG: Make more flexible on demand
228                _A(nSetCount == -1);
229                m_Window.SetRedraw(FALSE);
230                m_nCount = nSetCount;
231        }
232        ~CWindowRedraw() throw()
233        {
234                _A(m_nCount <= 0);
235                if(m_nCount == 0)
236                        return;
237                for(; m_nCount < 0; m_nCount++)
238                        m_Window.SetRedraw(TRUE);
239                // FIX: Workaround API GUI glitches
240                TCHAR pszClassName[64] = { 0 };
241                if(GetClassName(m_Window, pszClassName, DIM(pszClassName)))
242                {
243                        if(_tcsicmp(pszClassName, CComboBox::GetWndClassName()) == 0)
244                                m_Window.Invalidate();
245                }
246        }
247};
248
249////////////////////////////////////////////////////////////
250// BEGIN_MSG_MAP_EX, MESSAGE_TRACE_EX,
251// REGISTERED_MESSAGE_HANDLER_EX
252
253#undef BEGIN_MSG_MAP_EX
254
255#define BEGIN_MSG_MAP_EX(T) \
256public: \
257        BOOL m_bATL3MsgHandled; \
258        BOOL IsMsgHandled() const throw() \
259        { \
260                return m_bATL3MsgHandled; \
261        } \
262        VOID SetMsgHandled(BOOL bHandled) throw() \
263        { \
264                m_bATL3MsgHandled = bHandled; \
265        } \
266        __if_exists(T::m_hWnd) \
267        { \
268                INT_PTR AtlExceptionMessageBox(const CAtlException& Exception, UINT nType = MB_ICONERROR | MB_OK) \
269                { \
270                        return ::AtlExceptionMessageBox(static_cast<T*>(this)->m_hWnd, Exception, nType); \
271                } \
272        } \
273        BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) throw() \
274        { \
275                BOOL bHandled = m_bATL3MsgHandled; \
276                BOOL bResult = FALSE; \
277                _ATLTRY \
278                { \
279                        __if_exists(T::BeforeProcessWindowMessage) \
280                        { \
281                                static_cast<T*>(this)->BeforeProcessWindowMessage(); \
282                        } \
283                        bResult = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \
284                } \
285                _ATLCATCH(Exception) \
286                { \
287                        Exception; _Z_ATLEXCEPTION(Exception); \
288                        __if_exists(T::HandleException) \
289                        { \
290                                HandleException(Exception); \
291                        } \
292                        __if_not_exists(T::HandleException) \
293                        { \
294                                __if_exists(T::m_hWnd) \
295                                { \
296                                        AtlMessageBoxEx(static_cast<T*>(this)->m_hWnd, (LPCTSTR) AtlFormatSystemMessage(Exception.m_hr), IDS_ERROR, MB_ICONERROR | MB_OK); \
297                                } \
298                        } \
299                } \
300                _ATLCATCHALL() \
301                { \
302                        _Z_EXCEPTION(); \
303                        __if_exists(T::HandleException) \
304                        { \
305                                HandleException(CAtlException(E_UNEXPECTED)); \
306                        } \
307                        __if_not_exists(T::HandleException) \
308                        { \
309                                __if_exists(T::m_hWnd) \
310                                { \
311                                        AtlMessageBoxEx(static_cast<T*>(this)->m_hWnd, (LPCTSTR) AtlFormatSystemMessage(E_UNEXPECTED), IDS_ERROR, MB_ICONERROR | MB_OK); \
312                                } \
313                        } \
314                } \
315                m_bATL3MsgHandled = bHandled; \
316                return bResult; \
317        } \
318        BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \
319        { \
320                BOOL bHandled = TRUE; \
321                hWnd; \
322                uMsg; \
323                wParam; \
324                lParam; \
325                lResult; \
326                bHandled; \
327                switch(dwMsgMapID) \
328                { \
329                case 0:
330
331#define MESSAGE_TRACE_EX()      \
332        ATLTRACE(atlTraceWindowing, 4, _T("hWnd 0x%08x, uMsg %d (0x%x), wParam %d (0x%x), lParam %d (0x%x)\n"), hWnd, uMsg, uMsg, wParam, wParam, lParam, lParam);
333
334#define NOTIFY_TRACE_EX()       \
335        if(uMsg == WM_NOTIFY) \
336                ATLTRACE(atlTraceWindowing, 4, _T("hWnd 0x%08x, WM_NOTIFY, wParam %d (0x%x), lParam { hwndFrom 0x%08x, idFrom %d (0x%x), code %d (0x%x) }\n"), hWnd, wParam, wParam, ((NMHDR*) lParam)->hwndFrom, ((NMHDR*) lParam)->idFrom, ((NMHDR*) lParam)->idFrom, ((NMHDR*) lParam)->code, ((NMHDR*) lParam)->code);
337
338////////////////////////////////////////////////////////////
339// REGISTERED_MESSAGE_HANDLER_EX
340
341#define REGISTERED_MESSAGE_HANDLER_EX(msgname, func) \
342        if(uMsg >= 0xC000 && uMsg <= 0xFFFF && uMsg == RegisterWindowMessage(msgname)) \
343        { \
344                SetMsgHandled(TRUE); \
345                lResult = func(uMsg, wParam, lParam); \
346                if(IsMsgHandled()) \
347                        return TRUE; \
348        }
349
350////////////////////////////////////////////////////////////
351// CMessageOnlyWindowImpl
352
353template <typename T, typename _Window = CWindow, typename _WinTraits = CFrameWinTraits>
354class CMessageOnlyWindowImpl : 
355        public CWindowImpl<T, _Window, _WinTraits>
356{
357public:
358// CMessageOnlyWindowImpl
359        static HWND GetParentWindow() throw()
360        {
361#if WINVER >= 0x0500
362                OSVERSIONINFO VersionInformation = { sizeof VersionInformation };
363                ATLVERIFY(GetVersionEx(&VersionInformation));
364                if(VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT && VersionInformation.dwMajorVersion >= 5)
365                        return HWND_MESSAGE;
366#endif // WINVER >= 0x0500
367                return NULL;
368        }
369        HWND Create(HWND hParentWindow = GetParentWindow(), _U_RECT Position = NULL, LPCTSTR pszWindowName = NULL, DWORD nStyle = 0, DWORD nExStyle = 0, _U_MENUorID Menu = 0U, VOID* pvCreateParameter = NULL)
370        {
371                return __super::Create(hParentWindow, Position, pszWindowName, nStyle, nExStyle, Menu, pvCreateParameter);
372        }
373};
374
375////////////////////////////////////////////////////////////
376// CWindowMessageParameterMapT
377
378template <typename _Parameter>
379class CWindowMessageParameterMapT
380{
381private:
382        mutable CRoCriticalSection m_DataCriticalSection;
383        UINT_PTR m_nCounter;
384        CAtlMap<UINT_PTR, CAutoPtr<_Parameter> > m_ParameterMap;
385
386public:
387// CWindowMessageParameterMapT
388        CWindowMessageParameterMapT() throw() :
389                m_nCounter(0)
390        {
391        }
392        UINT_PTR AddParameter(CAutoPtr<_Parameter>& pParameter)
393        {
394                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
395                UINT_PTR nCookie = ++m_nCounter;
396                _A(!m_ParameterMap.Lookup((UINT) nCookie));
397                m_ParameterMap[(UINT) nCookie] = pParameter;
398                return nCookie;
399        }
400        UINT_PTR AddParameter(const _Parameter& Parameter)
401        {
402                CAutoPtr<_Parameter> pParameter(new _Parameter);
403                *pParameter = Parameter;
404                return AddParameter(pParameter);
405        }
406        CAutoPtr<_Parameter> RemoveParameter(UINT_PTR nCookie) throw()
407        {
408                CAutoPtr<_Parameter> pParameter;
409                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
410                POSITION Position = m_ParameterMap.Lookup((UINT) nCookie);
411                if(Position)
412                {
413                        pParameter = m_ParameterMap.GetValueAt(Position);
414                        m_ParameterMap.RemoveAtPos(Position);
415                }
416                return pParameter;
417        }
418        VOID RemoveAllParameters() throw()
419        {
420                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
421                m_ParameterMap.RemoveAll();
422        }
423};
424
425////////////////////////////////////////////////////////////
426// CWindowWithPrivateMessagesT
427
428template <typename T>
429class CWindowWithPrivateMessagesT
430{
431protected:
432        typedef CWindowWithPrivateMessagesT<T> CWindowWithPrivateMessages;
433
434public:
435
436BEGIN_MSG_MAP_EX(CWindowWithPrivateMessagesT<T>)
437        REGISTERED_MESSAGE_HANDLER_EX(T::GetPrivateMessageName(), OnPrivate)
438END_MSG_MAP()
439
440public:
441// CWindowWithPrivateMessagesT
442        static LPCTSTR GetPrivateMessageName() throw()
443        {
444                return _T("WM_PRIVATE");
445        }
446        static UINT GetPrivateMessageIdentifier() throw()
447        {
448                return RegisterWindowMessage(T::GetPrivateMessageName());
449        }
450        BOOL IsPrivateMessagePending() const throw()
451        {
452                const T* pT = static_cast<const T*>(this);
453                MSG Message;
454                UINT nPrivateMessageIdentifier = T::GetPrivateMessageIdentifier();
455                return PeekMessage(&Message, pT->m_hWnd, nPrivateMessageIdentifier, nPrivateMessageIdentifier, PM_NOREMOVE);
456        }
457        BOOL PostPrivateMessage(UINT nMessage, WPARAM wParam = 0) throw()
458        {
459                T* pT = static_cast<T*>(this);
460                return pT->PostMessage(T::GetPrivateMessageIdentifier(), (WPARAM) nMessage, (LPARAM) wParam);
461        }
462        SIZE_T RemovePrivateMessages(BOOL (T::*pMessageHandler)(const MSG& Message) = NULL) throw()
463        {
464                T* pT = static_cast<T*>(this);
465                MSG Message;
466                UINT nPrivateMessageIdentifier = T::GetPrivateMessageIdentifier();
467                SIZE_T nMessageCount = 0;
468                while(PeekMessage(&Message, pT->m_hWnd, nPrivateMessageIdentifier, nPrivateMessageIdentifier, PM_REMOVE))
469                {
470                        nMessageCount++;
471                        if(!pMessageHandler)
472                                continue;
473                        BOOL bContinue = (pT->*pMessageHandler)(Message);
474                        if(!bContinue)
475                                break;
476                }
477                return nMessageCount;
478        }
479        BOOL DispatchPrivateMessage(const MSG& Message) throw()
480        {
481                DispatchMessage(&Message);
482                return TRUE;
483        }
484        SIZE_T DispatchPrivateMessages() throw()
485        {
486                return RemovePrivateMessages(DispatchPrivateMessage);
487        }
488        LRESULT HandlePostedPrivateMessage(WPARAM wParam, LPARAM lParam) throw()
489        {
490                T* pT = static_cast<T*>(this);
491                return pT->SendMessage((UINT) wParam, (WPARAM) lParam);
492        }
493
494// Window message handlers
495        LRESULT OnPrivate(UINT, WPARAM wParam, LPARAM lParam) throw()
496        {
497                T* pT = static_cast<T*>(this);
498                return pT->HandlePostedPrivateMessage(wParam, lParam);
499        }
500};
501
502////////////////////////////////////////////////////////////
503// CWindowedTimedEventDaemonWindow
504
505class CWindowedTimedEventDaemonWindow :
506        public CMessageOnlyWindowImpl<CWindowedTimedEventDaemonWindow>//,
507        //public CWindowWithPrivateMessagesT<CWindowedTimedEventDaemonWindow>
508{
509        typedef VOID (*HANDLER)(UINT_PTR, DWORD_PTR);
510
511public:
512
513BEGIN_MSG_MAP_EX(CStubWindow)
514        //CHAIN_MSG_MAP(CWindowWithPrivateMessagesT<CWindowedTimedEventDaemonWindow>)
515        MSG_WM_TIMER(OnTimer)
516END_MSG_MAP()
517
518        ////////////////////////////////////////////////////////
519        // CTimedEvent
520
521        class CTimedEvent
522        {
523        public:
524                ULONG m_nDelay;
525                HANDLER m_pHandler;
526                DWORD_PTR m_nParameter;
527
528        public:
529        // CTimedEvent
530                CTimedEvent() throw()
531                {
532                }
533                CTimedEvent(ULONG nDelay, HANDLER pHandler, DWORD_PTR nParameter) throw() :
534                        m_nDelay(nDelay),
535                        m_pHandler(pHandler), 
536                        m_nParameter(nParameter)
537                {
538                }
539        };
540
541        ////////////////////////////////////////////////////////
542        // CTimedEventList
543
544        class CTimedEventList :
545                public CRoListT<CTimedEvent>
546        {
547        public:
548        // CTimedEventList
549                BOOL IsValidPosition(POSITION Position) const throw()
550                {
551                        for(POSITION CurrentPosition = GetHeadPosition(); CurrentPosition; GetNext(CurrentPosition))
552                                if(CurrentPosition == Position)
553                                        return TRUE;
554                        return FALSE;
555                }
556        };
557
558private:
559        static CRoListT<CWindowedTimedEventDaemonWindow> g_WindowList;
560        LONG m_nReferenceCount;
561        CTimedEventList m_TimedEventList;
562
563public:
564// CWindowedTimedEventDaemonWindow
565        static CWindowedTimedEventDaemonWindow* GetWindow(HWND hParentWindow)
566        {
567                _A(_pAtlModule);
568                CComCritSecLock<CComCriticalSection> GlobalLock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
569                CWindowedTimedEventDaemonWindow* pWindow = NULL;
570                for(POSITION Position = g_WindowList.GetHeadPosition(); Position; g_WindowList.GetNext(Position))
571                        if(g_WindowList.GetAt(Position).GetParent() == hParentWindow)
572                        {
573                                pWindow = &g_WindowList.GetAt(Position);
574                                break;
575                        }
576                if(!pWindow)
577                {
578                        const POSITION Position = g_WindowList.AddTail();
579                        _A(Position);
580                        pWindow = &g_WindowList.GetAt(Position);
581                        _ATLTRY
582                        {
583                                __E(pWindow->Create(hParentWindow));
584                        }
585                        _ATLCATCHALL()
586                        {
587                                g_WindowList.RemoveAt(Position);
588                                _ATLRETHROW;
589                        }
590                }
591                _A(pWindow->GetWindowThreadID() == GetCurrentThreadId());
592                pWindow->AddRef();
593                return pWindow;
594        }
595        static BOOL ReleaseWindow(CWindowedTimedEventDaemonWindow* pWindow) throw()
596        {
597                if(!pWindow)
598                        return FALSE;
599                _A(_pAtlModule);
600                CComCritSecLock<CComCriticalSection> GlobalLock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
601                for(POSITION Position = g_WindowList.GetHeadPosition(); Position; g_WindowList.GetNext(Position))
602                        if(&g_WindowList.GetAt(Position) == pWindow)
603                        {
604                                const LONG nReferenceCount = pWindow->Release();
605                                _A(nReferenceCount >= 0);
606                                if(nReferenceCount <= 0)
607                                {
608                                        if(pWindow->IsWindow())
609                                                _W(pWindow->DestroyWindow());
610                                        g_WindowList.RemoveAt(Position);
611                                }
612                                return TRUE;
613                        }
614                return FALSE;
615        }
616        CWindowedTimedEventDaemonWindow() throw() :
617                m_nReferenceCount(0)
618        {
619        }
620        LONG AddRef() throw()
621        {
622                return ++m_nReferenceCount;
623        }
624        LONG Release() throw()
625        {
626                return --m_nReferenceCount;
627        }
628        UINT_PTR SetEvent(ULONG nInterval, HANDLER pHandler, DWORD_PTR nParameter)
629        {
630                _A(IsWindow());
631                _A(GetWindowThreadID() == GetCurrentThreadId());
632                const POSITION Position = m_TimedEventList.AddTail(CTimedEvent(nInterval, pHandler, nParameter));
633                _A(Position);
634                const UINT_PTR nEvent = (UINT_PTR) Position;
635                _W(SetTimer(nEvent, nInterval));
636                return nEvent;
637        }
638        BOOL KillEvent(UINT_PTR nEvent) throw()
639        {
640                const POSITION Position = (POSITION) nEvent;
641                if(!m_TimedEventList.IsValidPosition(Position))
642                        return FALSE;
643                m_TimedEventList.RemoveAt(Position);
644                if(!IsWindow())
645                        return TRUE;
646                _A(GetWindowThreadID() == GetCurrentThreadId());
647                _W(KillTimer(nEvent));
648                return TRUE;
649        }
650
651// Window message handlers
652        LRESULT OnTimer(UINT_PTR nEvent) throw()
653        {
654                const POSITION Position = (POSITION) nEvent;
655                if(!m_TimedEventList.IsValidPosition(Position))
656                {
657                        SetMsgHandled(FALSE);
658                        return 0;
659                }
660                CTimedEvent& TimedEvent = m_TimedEventList.GetAt(Position);
661                _ATLTRY
662                {
663                        (*TimedEvent.m_pHandler)(nEvent, TimedEvent.m_nParameter);
664                }
665                _ATLCATCHALL()
666                {
667                        _Z_EXCEPTION();
668                }
669                return 0;
670        }
671};
672
673__declspec(selectany) CRoListT<CWindowedTimedEventDaemonWindow> CWindowedTimedEventDaemonWindow::g_WindowList;
674
675////////////////////////////////////////////////////////////
676// CWindowedTimedEventExT, CWindowedTimedEventT
677
678template <typename T, typename _Owner>
679class CWindowedTimedEventExT
680{
681        typedef VOID (_Owner::*HANDLER)(T*);
682
683public:
684        CWindowedTimedEventDaemonWindow* m_pWindowedTimedEventDaemonWindow;
685        UINT_PTR m_nEvent;
686        _Owner* m_pOwner;
687        HANDLER m_pHandler;
688        ULONG m_nOrdinalNumber;
689
690        VOID InternalHandler(UINT_PTR nEvent)
691        {
692                if(m_nEvent == nEvent)
693                {
694                        _A(m_pOwner && m_pHandler);
695                        m_nOrdinalNumber++;
696                        (m_pOwner->*m_pHandler)(static_cast<T*>(this));
697                }
698        }
699        static VOID InternalHandler(UINT_PTR nEvent, DWORD_PTR nUser)
700        {
701                _ATLTRY
702                {
703                        ((CWindowedTimedEventExT*) nUser)->InternalHandler(nEvent);
704                }
705                _ATLCATCHALL()
706                {
707                        _Z_EXCEPTION();
708                }
709        }
710
711public:
712// CWindowedTimedEventExT
713        CWindowedTimedEventExT() throw() :
714                m_pWindowedTimedEventDaemonWindow(NULL),
715                m_nEvent(0)
716        {
717        }
718        ~CWindowedTimedEventExT() throw()
719        {
720                Destroy();
721                if(m_pWindowedTimedEventDaemonWindow)
722                        _W(CWindowedTimedEventDaemonWindow::ReleaseWindow(m_pWindowedTimedEventDaemonWindow));
723        }
724        UINT_PTR GetEvent() const throw()
725        {
726                return m_nEvent;
727        }
728        BOOL IsActive() const throw()
729        {
730                return m_nEvent != 0;
731        }
732        CWindowedTimedEventDaemonWindow* GetEventDaemonWindow() const throw()
733        {
734                return m_pWindowedTimedEventDaemonWindow;
735        }
736        VOID CreateDaemonWindow(HWND hParentWindow)
737        {
738                if(m_pWindowedTimedEventDaemonWindow)
739                        return;
740                m_pWindowedTimedEventDaemonWindow = CWindowedTimedEventDaemonWindow::GetWindow(hParentWindow);
741                _A(m_pWindowedTimedEventDaemonWindow);
742                m_nEvent = 0;
743        }
744        VOID CreateDaemonWindow(_Owner* pOwner)
745        {
746                CreateDaemonWindow(pOwner->m_hWnd);
747        }
748        VOID Create(HWND hParentWindow, _Owner* pOwner, HANDLER pHandler, UINT nInterval)
749        {
750                _A(hParentWindow && pOwner && pHandler);
751                Destroy();
752                CreateDaemonWindow(hParentWindow);
753                m_nEvent = m_pWindowedTimedEventDaemonWindow->SetEvent(nInterval, InternalHandler, (DWORD_PTR) this);
754                m_pOwner = pOwner;
755                m_pHandler = pHandler;
756                m_nOrdinalNumber = 0;
757        }
758        VOID Create(_Owner* pOwner, HANDLER pHandler, UINT nInterval)
759        {
760                Create(pOwner->m_hWnd, pOwner, pHandler, nInterval);
761        }
762        VOID Destroy() throw()
763        {
764                if(m_pWindowedTimedEventDaemonWindow && m_nEvent)
765                {
766                        m_pWindowedTimedEventDaemonWindow->KillEvent(m_nEvent);
767                        m_nEvent = 0;
768                }
769        }
770        ULONG GetOrdinalNumber() const throw()
771        {
772                return m_nOrdinalNumber;
773        }
774};
775
776template <typename _Owner>
777class CWindowedTimedEventT :
778        public CWindowedTimedEventExT<CWindowedTimedEventT<_Owner>, _Owner>
779{
780public:
781// CWindowedTimedEventExT
782};
783
784////////////////////////////////////////////////////////////
785// CDeferWindowPos
786
787class CDeferWindowPos
788{
789private:
790        HDWP m_hWinPosInfo;
791
792public:
793// CDeferWindowPos
794        CDeferWindowPos() throw() :
795                m_hWinPosInfo(NULL)
796        {
797        }
798        CDeferWindowPos(INT nCapacity) throw() :
799                m_hWinPosInfo(NULL)
800        {
801                _W(Begin(nCapacity));
802        }
803        ~CDeferWindowPos() throw()
804        {
805                _A(!m_hWinPosInfo);
806        }
807        operator HDWP () const throw()
808        {
809                return m_hWinPosInfo;
810        }
811        BOOL Begin(INT nCapacity = 10) throw()
812        {
813                _A(!m_hWinPosInfo);
814                m_hWinPosInfo = BeginDeferWindowPos(nCapacity);
815                return m_hWinPosInfo != NULL;
816        }
817        BOOL SetWindowPos(HWND hWindow, HWND hWndInsertAfter, INT nX, INT nY, INT nWidth, INT nHeight, UINT nFlags) throw()
818        {
819                _A(m_hWinPosInfo);
820                m_hWinPosInfo = CWindow(hWindow).DeferWindowPos(m_hWinPosInfo, hWndInsertAfter, nX, nY, nWidth, nHeight, nFlags);
821                return m_hWinPosInfo != NULL;
822        }
823        BOOL SetWindowPos(HWND hWindow, HWND hWndInsertAfter, const RECT* pPosition, UINT nFlags) throw()
824        {
825                _A(pPosition);
826                const CRect& Position = reinterpret_cast<const CRect&>(*pPosition);
827                return SetWindowPos(hWindow, hWndInsertAfter, Position.left, Position.top, Position.Width(), Position.Height(), nFlags);
828        }
829        BOOL End() throw()
830        {
831                _A(m_hWinPosInfo);
832                const BOOL bResult = EndDeferWindowPos(m_hWinPosInfo);
833                m_hWinPosInfo = NULL;
834                return bResult;
835        }
836};
837
Note: See TracBrowser for help on using the repository browser.