]> git.saurik.com Git - wxWidgets.git/blame - src/msw/timer.cpp
Fix restoring the status bar help message after closing MSW menu from keyboard.
[wxWidgets.git] / src / msw / timer.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
8ecff181 2// Name: src/msw/timer.cpp
2bda0e17
KB
3// Purpose: wxTimer implementation
4// Author: Julian Smart
6d20f7ae 5// Modified by: Vadim Zeitlin (use hash map instead of list, global rewrite)
2bda0e17
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
2bda0e17
KB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
c085e333 16 #pragma hdrstop
2bda0e17
KB
17#endif
18
1e6feb95
VZ
19#if wxUSE_TIMER
20
c2ca375c 21#include "wx/msw/private/timer.h"
c0badb70 22
2bda0e17 23#ifndef WX_PRECOMP
c085e333 24 #include "wx/list.h"
2432b92d 25 #include "wx/event.h"
c085e333 26 #include "wx/app.h"
0470b1e6
VZ
27 #include "wx/intl.h"
28 #include "wx/log.h"
df69528b 29 #include "wx/hashmap.h"
0e16e5c3 30 #include "wx/module.h"
2bda0e17
KB
31#endif
32
0470b1e6 33#include "wx/msw/private.h"
b481194f 34#include "wx/msw/private/hiddenwin.h"
2bda0e17 35
c085e333 36// ----------------------------------------------------------------------------
97f278b4 37// private globals
c085e333
VZ
38// ----------------------------------------------------------------------------
39
97f278b4
VZ
40// define a hash containing all the timers: it is indexed by timer id and
41// contains the corresponding timer
491acfc7 42WX_DECLARE_HASH_MAP(WPARAM, wxMSWTimerImpl *, wxIntegerHash, wxIntegerEqual,
3f5c62f9 43 wxTimerMap);
5b6c8794 44
ee1025a7
VZ
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}
4676948b 54
1ed7a206
RD
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
c085e333 73// ----------------------------------------------------------------------------
97f278b4 74// private functions
eccd1992 75// ----------------------------------------------------------------------------
0e16e5c3 76
9cfc7f4f
RD
77LRESULT APIENTRY _EXPORT wxTimerWndProc(HWND hWnd, UINT message,
78 WPARAM wParam, LPARAM lParam);
eccd1992 79
9cfc7f4f
RD
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)
eccd1992 107
c085e333
VZ
108// ============================================================================
109// implementation
110// ============================================================================
111
9cfc7f4f 112
c085e333 113// ----------------------------------------------------------------------------
c2ca375c 114// wxMSWTimerImpl class
c085e333 115// ----------------------------------------------------------------------------
73974df1 116
c2ca375c 117bool wxMSWTimerImpl::Start(int milliseconds, bool oneShot)
2bda0e17 118{
c2ca375c
VZ
119 if ( !wxTimerImpl::Start(milliseconds, oneShot) )
120 return false;
caa36aab 121
b6ae7297 122 m_id = GetNewTimerId(this);
fe0c3289
VZ
123 // SetTimer() normally returns just idTimer but this might change in the
124 // future so use its return value to be safe
1ed7a206 125 UINT_PTR ret = ::SetTimer
fe0c3289
VZ
126 (
127 wxTimerHiddenWindowModule::GetHWND(), // window for WM_TIMER
1ed7a206 128 m_id, // timer ID to create
fe0c3289
VZ
129 (UINT)m_milli, // delay
130 NULL // timer proc (unused)
131 );
eccd1992 132
1ed7a206 133 if ( ret == 0 )
c085e333
VZ
134 {
135 wxLogSysError(_("Couldn't create a timer"));
136
04cd30de 137 return false;
c085e333 138 }
eccd1992 139
eccd1992 140 return true;
2bda0e17
KB
141}
142
c2ca375c 143void wxMSWTimerImpl::Stop()
2bda0e17 144{
9cfc7f4f 145 ::KillTimer(wxTimerHiddenWindowModule::GetHWND(), m_id);
b6ae7297
RD
146 TimerMap().erase(m_id);
147 m_id = 0;
2bda0e17
KB
148}
149
c085e333
VZ
150// ----------------------------------------------------------------------------
151// private functions
152// ----------------------------------------------------------------------------
73974df1 153
c2ca375c 154void wxProcessTimer(wxMSWTimerImpl& timer)
2bda0e17 155{
9a83f860 156 wxASSERT_MSG( timer.IsRunning(), wxT("bogus timer id") );
c085e333 157
0470b1e6 158 if ( timer.IsOneShot() )
c085e333
VZ
159 timer.Stop();
160
161 timer.Notify();
2bda0e17
KB
162}
163
9cfc7f4f
RD
164
165LRESULT APIENTRY _EXPORT wxTimerWndProc(HWND hWnd, UINT message,
166 WPARAM wParam, LPARAM lParam)
167{
168 if ( message == WM_TIMER )
169 {
491acfc7 170 wxTimerMap::iterator node = TimerMap().find(wParam);
9cfc7f4f 171
86c6fc77
VZ
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().
9cfc7f4f 180 }
86c6fc77
VZ
181
182 return ::DefWindowProc(hWnd, message, wParam, lParam);
9cfc7f4f
RD
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{
24a21a5f
VZ
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
9cfc7f4f
RD
200
201 return true;
202}
203
204void wxTimerHiddenWindowModule::OnExit()
c085e333 205{
9cfc7f4f
RD
206 if ( ms_hwnd )
207 {
208 if ( !::DestroyWindow(ms_hwnd) )
209 {
9a83f860 210 wxLogLastError(wxT("DestroyWindow(wxTimerHiddenWindow)"));
9cfc7f4f
RD
211 }
212
213 ms_hwnd = NULL;
214 }
c085e333 215
9cfc7f4f
RD
216 if ( ms_className )
217 {
218 if ( !::UnregisterClass(ms_className, wxGetInstance()) )
219 {
9a83f860 220 wxLogLastError(wxT("UnregisterClass(\"wxTimerHiddenWindow\")"));
9cfc7f4f
RD
221 }
222
223 ms_className = NULL;
224 }
225}
226
227/* static */
228HWND wxTimerHiddenWindowModule::GetHWND()
229{
9a83f860 230 static const wxChar *HIDDEN_WINDOW_CLASS = wxT("wxTimerHiddenWindow");
9cfc7f4f
RD
231 if ( !ms_hwnd )
232 {
233 ms_hwnd = wxCreateHiddenWindow(&ms_className, HIDDEN_WINDOW_CLASS,
234 wxTimerWndProc);
235 }
c085e333 236
9cfc7f4f 237 return ms_hwnd;
c085e333 238}
1e6feb95
VZ
239
240#endif // wxUSE_TIMER