1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/timer.cpp
3 // Purpose: wxTimer implementation
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin (use hash map instead of list, global rewrite)
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/msw/private/timer.h"
29 #include "wx/hashmap.h"
30 #include "wx/module.h"
33 #include "wx/msw/private.h"
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
39 // define a hash containing all the timers: it is indexed by timer id and
40 // contains the corresponding timer
41 WX_DECLARE_HASH_MAP(WPARAM
, wxMSWTimerImpl
*, wxIntegerHash
, wxIntegerEqual
,
44 // instead of using a global here, wrap it in a static function as otherwise it
45 // could have been used before being initialized if a timer object were created
47 static wxTimerMap
& TimerMap()
49 static wxTimerMap s_timerMap
;
54 // This gets a unique, non-zero timer ID and creates an entry in the TimerMap
55 UINT_PTR
GetNewTimerId(wxMSWTimerImpl
*t
)
57 static UINT_PTR lastTimerId
= 0;
59 while (lastTimerId
== 0 ||
60 TimerMap().find(lastTimerId
) != TimerMap().end())
62 lastTimerId
= lastTimerId
+ 1;
65 TimerMap()[lastTimerId
] = t
;
72 // ----------------------------------------------------------------------------
74 // ----------------------------------------------------------------------------
76 LRESULT APIENTRY _EXPORT
wxTimerWndProc(HWND hWnd
, UINT message
,
77 WPARAM wParam
, LPARAM lParam
);
79 // implemented in utils.cpp
80 extern "C" WXDLLIMPEXP_BASE HWND
81 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
);
84 // ----------------------------------------------------------------------------
85 // wxTimerHiddenWindowModule: used to manage the hidden window used for
86 // catching timer messages (we need a module to ensure that the window is
88 // ----------------------------------------------------------------------------
90 class wxTimerHiddenWindowModule
: public wxModule
93 // module init/finalize
94 virtual bool OnInit();
95 virtual void OnExit();
97 // get the hidden window (creates on demand)
98 static HWND
GetHWND();
101 // the HWND of the hidden window
104 // the class used to create it
105 static const wxChar
*ms_className
;
107 DECLARE_DYNAMIC_CLASS(wxTimerHiddenWindowModule
)
110 IMPLEMENT_DYNAMIC_CLASS(wxTimerHiddenWindowModule
, wxModule
)
112 // ============================================================================
114 // ============================================================================
117 // ----------------------------------------------------------------------------
118 // wxMSWTimerImpl class
119 // ----------------------------------------------------------------------------
121 wxMSWTimerImpl::wxMSWTimerImpl(wxTimer
*timer
)
124 m_id
= GetNewTimerId(this);
127 wxMSWTimerImpl::~wxMSWTimerImpl()
129 TimerMap().erase(m_id
);
132 bool wxMSWTimerImpl::Start(int milliseconds
, bool oneShot
)
134 if ( !wxTimerImpl::Start(milliseconds
, oneShot
) )
137 // SetTimer() normally returns just idTimer but this might change in the
138 // future so use its return value to be safe
139 UINT_PTR ret
= ::SetTimer
141 wxTimerHiddenWindowModule::GetHWND(), // window for WM_TIMER
142 m_id
, // timer ID to create
143 (UINT
)m_milli
, // delay
144 NULL
// timer proc (unused)
149 wxLogSysError(_("Couldn't create a timer"));
157 void wxMSWTimerImpl::Stop()
159 ::KillTimer(wxTimerHiddenWindowModule::GetHWND(), m_id
);
162 // ----------------------------------------------------------------------------
164 // ----------------------------------------------------------------------------
166 void wxProcessTimer(wxMSWTimerImpl
& timer
)
168 wxASSERT_MSG( timer
.IsRunning(), wxT("bogus timer id") );
170 if ( timer
.IsOneShot() )
177 LRESULT APIENTRY _EXPORT
wxTimerWndProc(HWND hWnd
, UINT message
,
178 WPARAM wParam
, LPARAM lParam
)
180 if ( message
== WM_TIMER
)
182 wxTimerMap::iterator node
= TimerMap().find(wParam
);
184 wxCHECK_MSG( node
!= TimerMap().end(), 0, wxT("bogus timer id in wxTimerProc") );
186 wxProcessTimer(*(node
->second
));
190 return ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
195 // ----------------------------------------------------------------------------
196 // wxTimerHiddenWindowModule functions
197 // ----------------------------------------------------------------------------
200 HWND
wxTimerHiddenWindowModule::ms_hwnd
= NULL
;
202 const wxChar
*wxTimerHiddenWindowModule::ms_className
= NULL
;
204 bool wxTimerHiddenWindowModule::OnInit()
206 // do not initialize ms_hwnd to ms_className to NULL here: it may happen
207 // that our GetHWND() is called before the modules are initialized if a
208 // timer is created from wxApp-derived class ctor and in this case we
209 // shouldn't overwrite it
214 void wxTimerHiddenWindowModule::OnExit()
218 if ( !::DestroyWindow(ms_hwnd
) )
220 wxLogLastError(wxT("DestroyWindow(wxTimerHiddenWindow)"));
228 if ( !::UnregisterClass(ms_className
, wxGetInstance()) )
230 wxLogLastError(wxT("UnregisterClass(\"wxTimerHiddenWindow\")"));
238 HWND
wxTimerHiddenWindowModule::GetHWND()
240 static const wxChar
*HIDDEN_WINDOW_CLASS
= wxT("wxTimerHiddenWindow");
243 ms_hwnd
= wxCreateHiddenWindow(&ms_className
, HIDDEN_WINDOW_CLASS
,
250 #endif // wxUSE_TIMER