]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/timer.cpp
Fix broken and missing DataView interface items for Phoenix
[wxWidgets.git] / src / msw / timer.cpp
... / ...
CommitLineData
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)
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#if wxUSE_TIMER
20
21#include "wx/msw/private/timer.h"
22
23#ifndef WX_PRECOMP
24 #include "wx/list.h"
25 #include "wx/event.h"
26 #include "wx/app.h"
27 #include "wx/intl.h"
28 #include "wx/log.h"
29 #include "wx/hashmap.h"
30 #include "wx/module.h"
31#endif
32
33#include "wx/msw/private.h"
34#include "wx/msw/private/hiddenwin.h"
35
36// ----------------------------------------------------------------------------
37// private globals
38// ----------------------------------------------------------------------------
39
40// define a hash containing all the timers: it is indexed by timer id and
41// contains the corresponding timer
42WX_DECLARE_HASH_MAP(WPARAM, wxMSWTimerImpl *, wxIntegerHash, wxIntegerEqual,
43 wxTimerMap);
44
45// instead of using a global here, wrap it in a static function as otherwise it
46// could have been used before being initialized if a timer object were created
47// globally
48static wxTimerMap& TimerMap()
49{
50 static wxTimerMap s_timerMap;
51
52 return s_timerMap;
53}
54
55// This gets a unique, non-zero timer ID and creates an entry in the TimerMap
56UINT_PTR GetNewTimerId(wxMSWTimerImpl *t)
57{
58 static UINT_PTR lastTimerId = 0;
59
60 while (lastTimerId == 0 ||
61 TimerMap().find(lastTimerId) != TimerMap().end())
62 {
63 lastTimerId = lastTimerId + 1;
64 }
65
66 TimerMap()[lastTimerId] = t;
67
68 return lastTimerId;
69}
70
71
72
73// ----------------------------------------------------------------------------
74// private functions
75// ----------------------------------------------------------------------------
76
77LRESULT APIENTRY _EXPORT wxTimerWndProc(HWND hWnd, UINT message,
78 WPARAM wParam, LPARAM lParam);
79
80// ----------------------------------------------------------------------------
81// wxTimerHiddenWindowModule: used to manage the hidden window used for
82// catching timer messages (we need a module to ensure that the window is
83// always deleted)
84// ----------------------------------------------------------------------------
85
86class wxTimerHiddenWindowModule : public wxModule
87{
88public:
89 // module init/finalize
90 virtual bool OnInit();
91 virtual void OnExit();
92
93 // get the hidden window (creates on demand)
94 static HWND GetHWND();
95
96private:
97 // the HWND of the hidden window
98 static HWND ms_hwnd;
99
100 // the class used to create it
101 static const wxChar *ms_className;
102
103 DECLARE_DYNAMIC_CLASS(wxTimerHiddenWindowModule)
104};
105
106IMPLEMENT_DYNAMIC_CLASS(wxTimerHiddenWindowModule, wxModule)
107
108// ============================================================================
109// implementation
110// ============================================================================
111
112
113// ----------------------------------------------------------------------------
114// wxMSWTimerImpl class
115// ----------------------------------------------------------------------------
116
117bool wxMSWTimerImpl::Start(int milliseconds, bool oneShot)
118{
119 if ( !wxTimerImpl::Start(milliseconds, oneShot) )
120 return false;
121
122 m_id = GetNewTimerId(this);
123 // SetTimer() normally returns just idTimer but this might change in the
124 // future so use its return value to be safe
125 UINT_PTR ret = ::SetTimer
126 (
127 wxTimerHiddenWindowModule::GetHWND(), // window for WM_TIMER
128 m_id, // timer ID to create
129 (UINT)m_milli, // delay
130 NULL // timer proc (unused)
131 );
132
133 if ( ret == 0 )
134 {
135 wxLogSysError(_("Couldn't create a timer"));
136
137 return false;
138 }
139
140 return true;
141}
142
143void wxMSWTimerImpl::Stop()
144{
145 ::KillTimer(wxTimerHiddenWindowModule::GetHWND(), m_id);
146 TimerMap().erase(m_id);
147 m_id = 0;
148}
149
150// ----------------------------------------------------------------------------
151// private functions
152// ----------------------------------------------------------------------------
153
154void wxProcessTimer(wxMSWTimerImpl& timer)
155{
156 wxASSERT_MSG( timer.IsRunning(), wxT("bogus timer id") );
157
158 if ( timer.IsOneShot() )
159 timer.Stop();
160
161 timer.Notify();
162}
163
164
165LRESULT APIENTRY _EXPORT wxTimerWndProc(HWND hWnd, UINT message,
166 WPARAM wParam, LPARAM lParam)
167{
168 if ( message == WM_TIMER )
169 {
170 wxTimerMap::iterator node = TimerMap().find(wParam);
171
172 if ( node != TimerMap().end() )
173 {
174 wxProcessTimer(*(node->second));
175
176 return 0;
177 }
178 //else: Unknown timer, probably one of our timers that had fired just
179 // before being removed from the timers map by Stop().
180 }
181
182 return ::DefWindowProc(hWnd, message, wParam, lParam);
183}
184
185// ----------------------------------------------------------------------------
186// wxTimerHiddenWindowModule functions
187// ----------------------------------------------------------------------------
188
189
190HWND wxTimerHiddenWindowModule::ms_hwnd = NULL;
191
192const wxChar *wxTimerHiddenWindowModule::ms_className = NULL;
193
194bool wxTimerHiddenWindowModule::OnInit()
195{
196 // do not initialize ms_hwnd to ms_className to NULL here: it may happen
197 // that our GetHWND() is called before the modules are initialized if a
198 // timer is created from wxApp-derived class ctor and in this case we
199 // shouldn't overwrite it
200
201 return true;
202}
203
204void wxTimerHiddenWindowModule::OnExit()
205{
206 if ( ms_hwnd )
207 {
208 if ( !::DestroyWindow(ms_hwnd) )
209 {
210 wxLogLastError(wxT("DestroyWindow(wxTimerHiddenWindow)"));
211 }
212
213 ms_hwnd = NULL;
214 }
215
216 if ( ms_className )
217 {
218 if ( !::UnregisterClass(ms_className, wxGetInstance()) )
219 {
220 wxLogLastError(wxT("UnregisterClass(\"wxTimerHiddenWindow\")"));
221 }
222
223 ms_className = NULL;
224 }
225}
226
227/* static */
228HWND wxTimerHiddenWindowModule::GetHWND()
229{
230 static const wxChar *HIDDEN_WINDOW_CLASS = wxT("wxTimerHiddenWindow");
231 if ( !ms_hwnd )
232 {
233 ms_hwnd = wxCreateHiddenWindow(&ms_className, HIDDEN_WINDOW_CLASS,
234 wxTimerWndProc);
235 }
236
237 return ms_hwnd;
238}
239
240#endif // wxUSE_TIMER