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"
32 #include "wx/msw/private.h"
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 // define a hash containing all the timers: it is indexed by timer id and
39 // contains the corresponding timer
40 WX_DECLARE_HASH_MAP(unsigned long, wxMSWTimerImpl
*, wxIntegerHash
, wxIntegerEqual
,
43 // instead of using a global here, wrap it in a static function as otherwise it
44 // could have been used before being initialized if a timer object were created
46 static wxTimerMap
& TimerMap()
48 static wxTimerMap s_timerMap
;
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 LRESULT APIENTRY _EXPORT
wxTimerWndProc(HWND hWnd
, UINT message
,
58 WPARAM wParam
, LPARAM lParam
);
60 // implemented in utils.cpp
61 extern "C" WXDLLIMPEXP_BASE HWND
62 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
);
65 // ----------------------------------------------------------------------------
66 // wxTimerHiddenWindowModule: used to manage the hidden window used for
67 // catching timer messages (we need a module to ensure that the window is
69 // ----------------------------------------------------------------------------
71 class wxTimerHiddenWindowModule
: public wxModule
74 // module init/finalize
75 virtual bool OnInit();
76 virtual void OnExit();
78 // get the hidden window (creates on demand)
79 static HWND
GetHWND();
82 // the HWND of the hidden window
85 // the class used to create it
86 static const wxChar
*ms_className
;
88 DECLARE_DYNAMIC_CLASS(wxTimerHiddenWindowModule
)
91 IMPLEMENT_DYNAMIC_CLASS(wxTimerHiddenWindowModule
, wxModule
)
93 // ============================================================================
95 // ============================================================================
98 // ----------------------------------------------------------------------------
99 // wxMSWTimerImpl class
100 // ----------------------------------------------------------------------------
102 bool wxMSWTimerImpl::Start(int milliseconds
, bool oneShot
)
104 if ( !wxTimerImpl::Start(milliseconds
, oneShot
) )
108 wxTimerHiddenWindowModule::GetHWND(), // window to send the messages to
110 (UINT
)m_milli
, // delay
111 NULL
// timer proc. Not used since we pass hwnd
116 wxLogSysError(_("Couldn't create a timer"));
121 // check that SetTimer() didn't reuse an existing id: according to the MSDN
122 // this can happen and this would be catastrophic to us as we rely on ids
123 // uniquely identifying the timers because we use them as keys in the hash
124 if ( TimerMap().find(m_id
) != TimerMap().end() )
126 wxLogError(_("Timer creation failed."));
128 ::KillTimer(wxTimerHiddenWindowModule::GetHWND(), m_id
);
134 TimerMap()[m_id
] = this;
139 void wxMSWTimerImpl::Stop()
141 wxASSERT_MSG( m_id
, _T("should be running") );
143 ::KillTimer(wxTimerHiddenWindowModule::GetHWND(), m_id
);
145 TimerMap().erase(m_id
);
150 // ----------------------------------------------------------------------------
152 // ----------------------------------------------------------------------------
154 void wxProcessTimer(wxMSWTimerImpl
& timer
)
156 wxASSERT_MSG( timer
.IsRunning(), _T("bogus timer id") );
158 if ( timer
.IsOneShot() )
165 LRESULT APIENTRY _EXPORT
wxTimerWndProc(HWND hWnd
, UINT message
,
166 WPARAM wParam
, LPARAM lParam
)
168 if ( message
== WM_TIMER
)
170 wxTimerMap::iterator node
= TimerMap().find((unsigned long)wParam
);
172 wxCHECK_MSG( node
!= TimerMap().end(), 0, wxT("bogus timer id in wxTimerProc") );
174 wxProcessTimer(*(node
->second
));
178 return ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
183 // ----------------------------------------------------------------------------
184 // wxTimerHiddenWindowModule functions
185 // ----------------------------------------------------------------------------
188 HWND
wxTimerHiddenWindowModule::ms_hwnd
= NULL
;
190 const wxChar
*wxTimerHiddenWindowModule::ms_className
= NULL
;
192 bool wxTimerHiddenWindowModule::OnInit()
200 void wxTimerHiddenWindowModule::OnExit()
204 if ( !::DestroyWindow(ms_hwnd
) )
206 wxLogLastError(_T("DestroyWindow(wxTimerHiddenWindow)"));
214 if ( !::UnregisterClass(ms_className
, wxGetInstance()) )
216 wxLogLastError(_T("UnregisterClass(\"wxTimerHiddenWindow\")"));
224 HWND
wxTimerHiddenWindowModule::GetHWND()
226 static const wxChar
*HIDDEN_WINDOW_CLASS
= _T("wxTimerHiddenWindow");
229 ms_hwnd
= wxCreateHiddenWindow(&ms_className
, HIDDEN_WINDOW_CLASS
,
236 #endif // wxUSE_TIMER