undid accidental change to assert in Start() during last commit
[wxWidgets.git] / src / msw / timer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/timer.cpp
3 // Purpose: wxTimer implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "timer.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_TIMER
24
25 #ifndef WX_PRECOMP
26 #include "wx/window.h"
27 #include "wx/list.h"
28 #include "wx/event.h"
29 #include "wx/app.h"
30 #include "wx/intl.h"
31 #include "wx/log.h"
32 #endif
33
34 #include "wx/hashmap.h"
35 #include "wx/module.h"
36
37 #include "wx/timer.h"
38
39 #include "wx/msw/private.h"
40
41 // from utils.cpp
42 extern "C" HWND
43 wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
44
45 // ----------------------------------------------------------------------------
46 // private functions
47 // ----------------------------------------------------------------------------
48
49 WX_DECLARE_HASH_MAP( long,
50 wxTimer *,
51 wxIntegerHash,
52 wxIntegerEqual,
53 wxTimerMap );
54
55 wxTimerMap wxTimerList;
56
57 void WINAPI wxTimerProc(HWND hwnd, WORD, int idTimer, DWORD);
58
59 // ----------------------------------------------------------------------------
60 // macros
61 // ----------------------------------------------------------------------------
62
63 IMPLEMENT_ABSTRACT_CLASS(wxTimer, wxObject)
64
65 // ----------------------------------------------------------------------------
66 // globals
67 // ----------------------------------------------------------------------------
68
69 // these variables are for timer shared hwnd management
70 static const wxChar *wxMSWTIMER_WNDCLASSNAME = wxT("_wxTimer_Internal_Class");
71 static LPCTSTR s_classnameTimerWnd = NULL;
72 static HWND s_hwndTimer = NULL;
73
74 // ----------------------------------------------------------------------------
75 // private classes
76 // ----------------------------------------------------------------------------
77
78 class wxTimerModule : public wxModule
79 {
80 public:
81 virtual bool OnInit() { return true; }
82 virtual void OnExit()
83 {
84 if ( s_hwndTimer )
85 {
86 ::DestroyWindow(s_hwndTimer);
87 s_hwndTimer = NULL;
88
89 if ( !::UnregisterClass(wxMSWTIMER_WNDCLASSNAME, wxGetInstance()) )
90 {
91 wxLogLastError(_T("UnregisterClass(wxTimerClass)"));
92 }
93
94 s_classnameTimerWnd = NULL;
95 }
96 }
97
98 private:
99 DECLARE_DYNAMIC_CLASS(wxTimerModule)
100 };
101
102 // ============================================================================
103 // implementation
104 // ============================================================================
105
106 // ----------------------------------------------------------------------------
107 // wxTimer class
108 // ----------------------------------------------------------------------------
109
110 void wxTimer::Init()
111 {
112 m_id = 0;
113 m_hwnd = NULL;
114 }
115
116 wxTimer::~wxTimer()
117 {
118 // save id as Stop() changes it
119 long id = m_id;
120
121 wxTimer::Stop();
122
123 wxTimerList.erase(id);
124 }
125
126 bool wxTimer::Start(int milliseconds, bool oneShot)
127 {
128 (void)wxTimerBase::Start(milliseconds, oneShot);
129
130 wxCHECK_MSG( m_milli > 0, false, wxT("invalid value for timer timeour") );
131
132 // find a window for SetTimer(): it should be a valid HWND owned by this
133 // thread (even if we had a non NULL m_hwnd before, reset it in case the
134 // owner has changed)
135 m_hwnd = NULL;
136
137 // first try the owner window
138 if ( m_owner )
139 {
140 wxWindow *win = wxDynamicCast(m_owner, wxWindow);
141 if ( win )
142 {
143 m_hwnd = win->GetHWND();
144 }
145 }
146
147 // if not, use a shared hidden window
148 if ( !m_hwnd )
149 {
150 if ( !s_hwndTimer )
151 {
152 s_hwndTimer = wxCreateHiddenWindow
153 (
154 &s_classnameTimerWnd,
155 wxMSWTIMER_WNDCLASSNAME,
156 ::DefWindowProc
157 );
158
159 if ( !s_hwndTimer )
160 {
161 wxASSERT_MSG( s_hwndTimer, wxT("can't create a HWND for wxTimer") );
162 return false;
163 }
164 }
165
166 m_hwnd = (WXHWND)s_hwndTimer;
167
168 }
169
170 m_id = ::SetTimer
171 (
172 (HWND)m_hwnd,
173 (UINT)(m_id ? m_id : 1),
174 (UINT)m_milli,
175 (TIMERPROC)wxTimerProc
176 );
177
178 if ( !m_id )
179 {
180 wxLogSysError(_("Couldn't create a timer"));
181
182 return false;
183 }
184
185 wxTimerList[m_id] = this;
186
187 return true;
188 }
189
190 void wxTimer::Stop()
191 {
192 if ( m_id )
193 {
194 ::KillTimer((HWND)m_hwnd, (UINT)m_id);
195 m_hwnd = NULL;
196
197 wxTimerList.erase(m_id);
198 }
199
200 m_id = 0;
201 }
202
203 // ----------------------------------------------------------------------------
204 // private functions
205 // ----------------------------------------------------------------------------
206
207 void wxProcessTimer(wxTimer& timer)
208 {
209 // Avoid to process spurious timer events
210 if ( timer.m_id == 0)
211 return;
212
213 if ( timer.IsOneShot() )
214 timer.Stop();
215
216 timer.Notify();
217 }
218
219 void WINAPI wxTimerProc(HWND WXUNUSED(hwnd), WORD, int idTimer, DWORD)
220 {
221 wxTimerMap::iterator node = wxTimerList.find((long)idTimer);
222
223 wxASSERT_MSG( node != wxTimerList.end(), wxT("bogus timer id in wxTimerProc") );
224
225 wxProcessTimer(*(node->second));
226 }
227
228 #endif // wxUSE_TIMER
229