]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/slider95.cpp
Clean up memory if have to exit early
[wxWidgets.git] / src / msw / slider95.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: slider95.cpp
3// Purpose: wxSlider95, using the Win95 trackbar control
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "slider95.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_SLIDER
24
25#ifndef WX_PRECOMP
26#include "wx/utils.h"
27#include "wx/brush.h"
28#include "wx/slider.h"
29#endif
30
31#ifdef __WIN95__
32
33#include "wx/msw/slider95.h"
34#include "wx/msw/private.h"
35
36#if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__)) && !defined(__CYGWIN10__))
37 #include <commctrl.h>
38#endif
39
40IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
41
42// Slider
43wxSlider95::wxSlider95()
44{
45 m_staticValue = (WXHWND) NULL;
46 m_staticMin = (WXHWND) NULL;
47 m_staticMax = (WXHWND) NULL;
48 m_pageSize = 1;
49 m_lineSize = 1;
50 m_rangeMax = 0;
51 m_rangeMin = 0;
52 m_tickFreq = 0;
53}
54
55bool wxSlider95::Create(wxWindow *parent, wxWindowID id,
56 int value, int minValue, int maxValue,
57 const wxPoint& pos,
58 const wxSize& size, long style,
59 const wxValidator& validator,
60 const wxString& name)
61{
62 SetName(name);
63#if wxUSE_VALIDATORS
64 SetValidator(validator);
65#endif // wxUSE_VALIDATORS
66
67 if (parent) parent->AddChild(this);
68
69 SetBackgroundColour(parent->GetBackgroundColour()) ;
70 SetForegroundColour(parent->GetForegroundColour()) ;
71
72 m_staticValue = (WXHWND) NULL;;
73 m_staticMin = (WXHWND) NULL;;
74 m_staticMax = (WXHWND) NULL;;
75 m_pageSize = 1;
76 m_lineSize = 1;
77 m_windowStyle = style;
78 m_tickFreq = 0;
79
80 if ( id == -1 )
81 m_windowId = (int)NewControlId();
82 else
83 m_windowId = id;
84
85 int x = pos.x;
86 int y = pos.y;
87 int width = size.x;
88 int height = size.y;
89
90 long msStyle = 0;
91 long wstyle = 0;
92
93 if ( m_windowStyle & wxCLIP_SIBLINGS )
94 msStyle |= WS_CLIPSIBLINGS;
95
96 if ( m_windowStyle & wxSL_LABELS )
97 {
98 msStyle |= WS_CHILD | WS_VISIBLE | WS_BORDER | SS_CENTER;
99
100 bool want3D;
101 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
102
103 m_staticValue = (WXHWND) CreateWindowEx
104 (
105 exStyle, wxT("STATIC"), NULL,
106 msStyle,
107 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)NewControlId(),
108 wxGetInstance(), NULL
109 );
110
111 // Now create min static control
112 wxString minLabel;
113 minLabel.Printf(wxT("%d"), minValue);
114 wstyle = STATIC_FLAGS;
115 if ( m_windowStyle & wxCLIP_SIBLINGS )
116 msStyle |= WS_CLIPSIBLINGS;
117 m_staticMin = (WXHWND) CreateWindowEx
118 (
119 0, wxT("STATIC"), minLabel,
120 wstyle,
121 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)NewControlId(),
122 wxGetInstance(), NULL
123 );
124 }
125
126 msStyle = 0;
127
128 if ( m_windowStyle & wxCLIP_SIBLINGS )
129 msStyle |= WS_CLIPSIBLINGS;
130
131 if (m_windowStyle & wxSL_VERTICAL)
132 msStyle = TBS_VERT | WS_CHILD | WS_VISIBLE | WS_TABSTOP ;
133 else
134 msStyle = TBS_HORZ | WS_CHILD | WS_VISIBLE | WS_TABSTOP ;
135
136 if ( m_windowStyle & wxSL_AUTOTICKS )
137 msStyle |= TBS_AUTOTICKS ;
138
139 if ( m_windowStyle & wxSL_LEFT )
140 msStyle |= TBS_LEFT;
141 else if ( m_windowStyle & wxSL_RIGHT )
142 msStyle |= TBS_RIGHT;
143 else if ( m_windowStyle & wxSL_TOP )
144 msStyle |= TBS_TOP;
145 else if ( m_windowStyle & wxSL_BOTTOM )
146 msStyle |= TBS_BOTTOM;
147 else if ( m_windowStyle & wxSL_BOTH )
148 msStyle |= TBS_BOTH;
149 else if ( ! (m_windowStyle & wxSL_AUTOTICKS) )
150 msStyle |= TBS_NOTICKS;
151
152 if ( m_windowStyle & wxSL_SELRANGE )
153 msStyle |= TBS_ENABLESELRANGE;
154
155 HWND scroll_bar = CreateWindowEx
156 (
157 MakeExtendedStyle(m_windowStyle), TRACKBAR_CLASS, wxT(""),
158 msStyle,
159 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)m_windowId,
160 wxGetInstance(), NULL
161 );
162
163 m_rangeMax = maxValue;
164 m_rangeMin = minValue;
165
166 m_pageSize = (int)((maxValue-minValue)/10);
167
168 ::SendMessage(scroll_bar, TBM_SETRANGE, TRUE, MAKELONG(minValue, maxValue));
169 ::SendMessage(scroll_bar, TBM_SETPOS, TRUE, (LPARAM)value);
170 ::SendMessage(scroll_bar, TBM_SETPAGESIZE, 0, (LPARAM)m_pageSize);
171
172 m_hWnd = (WXHWND)scroll_bar;
173
174 SubclassWin(GetHWND());
175
176 ::SetWindowText((HWND) m_hWnd, wxT(""));
177
178 SetFont(parent->GetFont());
179
180 if ( m_windowStyle & wxSL_LABELS )
181 {
182 // Finally, create max value static item
183 wxString maxLabel;
184 maxLabel.Printf(wxT("%d"), maxValue);
185 wstyle = STATIC_FLAGS;
186
187 if ( m_windowStyle & wxCLIP_SIBLINGS )
188 msStyle |= WS_CLIPSIBLINGS;
189
190 m_staticMax = (WXHWND) CreateWindowEx
191 (
192 0, wxT("STATIC"), maxLabel,
193 wstyle,
194 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)NewControlId(),
195 wxGetInstance(), NULL
196 );
197
198
199 if (GetFont().Ok())
200 {
201 if (GetFont().GetResourceHandle())
202 {
203 if ( m_staticMin )
204 ::SendMessage((HWND) m_staticMin, WM_SETFONT,
205 (WPARAM) GetFont().GetResourceHandle(), 0L);
206
207 if ( m_staticMax )
208 ::SendMessage((HWND) m_staticMax, WM_SETFONT,
209 (WPARAM) GetFont().GetResourceHandle(), 0L);
210
211 if (m_staticValue)
212 ::SendMessage((HWND) m_staticValue, WM_SETFONT,
213 (WPARAM) GetFont().GetResourceHandle(), 0L);
214 }
215 }
216 }
217
218 SetSize(x, y, width, height);
219 SetValue(value);
220
221 return TRUE;
222}
223
224bool wxSlider95::MSWOnScroll(int WXUNUSED(orientation), WXWORD wParam,
225 WXWORD WXUNUSED(pos), WXHWND control)
226{
227 wxEventType scrollEvent;
228 switch ( wParam )
229 {
230 case SB_TOP:
231 scrollEvent = wxEVT_SCROLL_TOP;
232 break;
233
234 case SB_BOTTOM:
235 scrollEvent = wxEVT_SCROLL_BOTTOM;
236 break;
237
238 case SB_LINEUP:
239 scrollEvent = wxEVT_SCROLL_LINEUP;
240 break;
241
242 case SB_LINEDOWN:
243 scrollEvent = wxEVT_SCROLL_LINEDOWN;
244 break;
245
246 case SB_PAGEUP:
247 scrollEvent = wxEVT_SCROLL_PAGEUP;
248 break;
249
250 case SB_PAGEDOWN:
251 scrollEvent = wxEVT_SCROLL_PAGEDOWN;
252 break;
253
254 case SB_THUMBTRACK:
255 scrollEvent = wxEVT_SCROLL_THUMBTRACK;
256 break;
257
258 case SB_THUMBPOSITION:
259 scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
260 break;
261
262 case SB_ENDSCROLL:
263 scrollEvent = wxEVT_SCROLL_ENDSCROLL;
264 break;
265
266 default:
267 // unknown scroll event?
268 return FALSE;
269 }
270
271 int newPos = (int) ::SendMessage((HWND) control, TBM_GETPOS, 0, 0);
272 if ( (newPos < GetMin()) || (newPos > GetMax()) )
273 {
274 // out of range - but we did process it
275 return TRUE;
276 }
277
278 SetValue(newPos);
279
280 wxScrollEvent event(scrollEvent, m_windowId);
281 event.SetPosition(newPos);
282 event.SetEventObject( this );
283 GetEventHandler()->ProcessEvent(event);
284
285 wxCommandEvent cevent( wxEVT_COMMAND_SLIDER_UPDATED, GetId() );
286 cevent.SetInt( newPos );
287 cevent.SetEventObject( this );
288
289 return GetEventHandler()->ProcessEvent( cevent );
290}
291
292wxSlider95::~wxSlider95()
293{
294 if (m_staticMin)
295 {
296 ::DestroyWindow((HWND) m_staticMin);
297 m_staticMin = (WXHWND) NULL;
298 }
299
300 if (m_staticMax)
301 {
302 ::DestroyWindow((HWND) m_staticMax);
303 m_staticMax = (WXHWND) NULL;
304 }
305
306 if (m_staticValue)
307 {
308 ::DestroyWindow((HWND) m_staticValue);
309 m_staticValue = (WXHWND) NULL;
310 }
311}
312
313int wxSlider95::GetValue() const
314{
315 return ::SendMessage(GetHwnd(), TBM_GETPOS, 0, 0);
316}
317
318void wxSlider95::SetValue(int value)
319{
320 ::SendMessage(GetHwnd(), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)value);
321
322 if (m_staticValue)
323 {
324 wxString str;
325 str.Printf(wxT("%d"), value);
326 ::SetWindowText((HWND) m_staticValue, str);
327 }
328}
329
330void wxSlider95::DoGetSize(int *width, int *height) const
331{
332 GetSize(width, height);
333}
334
335void wxSlider95::GetSize(int *width, int *height) const
336{
337 RECT rect;
338 rect.left = -1; rect.right = -1; rect.top = -1; rect.bottom = -1;
339
340 wxFindMaxSize(GetHWND(), &rect);
341
342 if (m_staticMin)
343 wxFindMaxSize(m_staticMin, &rect);
344
345 if (m_staticMax)
346 wxFindMaxSize(m_staticMax, &rect);
347
348 if (m_staticValue)
349 wxFindMaxSize(m_staticValue, &rect);
350
351 *width = rect.right - rect.left;
352 *height = rect.bottom - rect.top;
353}
354
355void wxSlider95::GetPosition(int *x, int *y) const
356{
357 wxWindow *parent = GetParent();
358 RECT rect;
359 rect.left = -1; rect.right = -1; rect.top = -1; rect.bottom = -1;
360
361 wxFindMaxSize(GetHWND(), &rect);
362
363 if (m_staticMin)
364 wxFindMaxSize(m_staticMin, &rect);
365 if (m_staticMax)
366 wxFindMaxSize(m_staticMax, &rect);
367 if (m_staticValue)
368 wxFindMaxSize(m_staticValue, &rect);
369
370 // Since we now have the absolute screen coords,
371 // if there's a parent we must subtract its top left corner
372 POINT point;
373 point.x = rect.left;
374 point.y = rect.top;
375 if (parent)
376 ::ScreenToClient((HWND) parent->GetHWND(), &point);
377
378 // We may be faking the client origin.
379 // So a window that's really at (0, 30) may appear
380 // (to wxWin apps) to be at (0, 0).
381 if (GetParent())
382 {
383 wxPoint pt(GetParent()->GetClientAreaOrigin());
384 point.x -= pt.x;
385 point.y -= pt.y;
386 }
387
388 *x = point.x;
389 *y = point.y;
390}
391
392// TODO one day, make sense of all this horros and replace it with a readable
393// DoGetBestSize()
394void wxSlider95::DoSetSize(int x, int y, int width, int height, int sizeFlags)
395{
396 int x1 = x;
397 int y1 = y;
398 int w1 = width;
399 int h1 = height;
400
401 int currentX, currentY;
402 GetPosition(&currentX, &currentY);
403 if (x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
404 x1 = currentX;
405 if (y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
406 y1 = currentY;
407
408 AdjustForParentClientOrigin(x1, y1, sizeFlags);
409
410 wxChar buf[300];
411
412 int x_offset = x;
413 int y_offset = y;
414
415 int cx; // slider,min,max sizes
416 int cy;
417 int cyf;
418
419 wxGetCharSize(GetHWND(), &cx, &cy, & this->GetFont());
420
421 if ((m_windowStyle & wxSL_VERTICAL) != wxSL_VERTICAL)
422 {
423 if ( m_windowStyle & wxSL_LABELS )
424 {
425 int min_len = 0;
426
427 ::GetWindowText((HWND) m_staticMin, buf, 300);
428 GetTextExtent(buf, &min_len, &cyf,NULL,NULL, & this->GetFont());
429
430 int max_len = 0;
431
432 ::GetWindowText((HWND) m_staticMax, buf, 300);
433 GetTextExtent(buf, &max_len, &cyf,NULL,NULL, & this->GetFont());
434 if (m_staticValue)
435 {
436 int new_width = (int)(wxMax(min_len, max_len));
437 int valueHeight = (int)cyf;
438#ifdef __WIN32__
439 // For some reason, under Win95, the text edit control has
440 // a lot of space before the first character
441 new_width += 3*cx;
442#endif
443 // The height needs to be a bit bigger under Win95 if
444 // using native 3D effects.
445 valueHeight = (int) (valueHeight * 1.5) ;
446 ::MoveWindow((HWND) m_staticValue, x_offset, y_offset,
447 new_width, valueHeight, TRUE);
448 x_offset += new_width + cx;
449 }
450
451 MoveWindow((HWND) m_staticMin, x_offset, y_offset,
452 (int) min_len, cy, TRUE);
453 x_offset += (int)(min_len + cx);
454
455 int slider_length = (int)(w1 - x_offset - max_len - cx);
456
457 int slider_height = h1;
458 if (slider_height < 0 )
459 slider_height = 20;
460
461 // Slider must have a minimum/default length/height
462 if (slider_length < 100)
463 slider_length = 100;
464
465 ::MoveWindow(GetHwnd(), x_offset, y_offset,
466 slider_length, slider_height, TRUE);
467 x_offset += slider_length + cx;
468
469 MoveWindow((HWND) m_staticMax, x_offset, y_offset,
470 (int) max_len, cy, TRUE);
471 }
472 else
473 {
474 // No labels
475 // If we're prepared to use the existing size, then...
476 if
477 (
478 width == -1
479 && height == -1
480 && ((sizeFlags & wxSIZE_AUTO) != wxSIZE_AUTO)
481 )
482 {
483 GetSize(&w1, &h1);
484 }
485
486 if ( w1 < 0 )
487 w1 = 200;
488 if ( h1 < 0 )
489 h1 = 20;
490
491 ::MoveWindow(GetHwnd(), x1, y1, w1, h1, TRUE);
492 }
493 }
494 else
495 {
496 if ( m_windowStyle & wxSL_LABELS )
497 {
498 int min_len;
499 ::GetWindowText((HWND) m_staticMin, buf, 300);
500 GetTextExtent(buf, &min_len, &cyf,NULL,NULL, & this->GetFont());
501
502 int max_len;
503 ::GetWindowText((HWND) m_staticMax, buf, 300);
504 GetTextExtent(buf, &max_len, &cyf,NULL,NULL, & this->GetFont());
505
506 if (m_staticValue)
507 {
508 int new_width = (int)(wxMax(min_len, max_len));
509 int valueHeight = (int)cyf;
510/*** Suggested change by George Tasker - remove this block...
511#ifdef __WIN32__
512 // For some reason, under Win95, the text edit control has
513 // a lot of space before the first character
514 new_width += 3*cx;
515#endif
516 ... and replace with following line: */
517 new_width += cx;
518
519 // The height needs to be a bit bigger under Win95 if
520 // using native 3D effects.
521 valueHeight = (int) (valueHeight * 1.5) ;
522
523 ::MoveWindow((HWND) m_staticValue, x_offset, y_offset,
524 new_width, valueHeight, TRUE);
525 y_offset += valueHeight;
526 }
527
528 ::MoveWindow((HWND) m_staticMin, x_offset, y_offset,
529 (int) min_len, cy, TRUE);
530 y_offset += cy;
531
532 int slider_length = (int)(h1 - y_offset - cy - cy);
533
534 int slider_width = w1;
535 if (slider_width < 0 )
536 slider_width = 20;
537
538 // Slider must have a minimum/default length
539 if (slider_length < 100)
540 slider_length = 100;
541
542 ::MoveWindow(GetHwnd(), x_offset, y_offset,
543 slider_width, slider_length, TRUE);
544 y_offset += slider_length;
545
546 ::MoveWindow((HWND) m_staticMax, x_offset, y_offset,
547 (int)max_len, cy, TRUE);
548 }
549 else
550 {
551 // No labels
552 // If we're prepared to use the existing size, then...
553 if
554 (
555 width == -1 && height == -1
556 && ((sizeFlags & wxSIZE_AUTO) != wxSIZE_AUTO)
557 )
558 {
559 GetSize(&w1, &h1);
560 }
561
562 if ( w1 < 0 )
563 w1 = 20;
564 if ( h1 < 0 )
565 h1 = 200;
566
567 ::MoveWindow(GetHwnd(), x1, y1, w1, h1, TRUE);
568 }
569 }
570}
571
572void wxSlider95::SetRange(int minValue, int maxValue)
573{
574 m_rangeMin = minValue;
575 m_rangeMax = maxValue;
576
577 ::SendMessage(GetHwnd(), TBM_SETRANGE, TRUE, MAKELONG(minValue, maxValue));
578
579 wxChar buf[40];
580 if ( m_staticMin )
581 {
582 wxSprintf(buf, wxT("%d"), m_rangeMin);
583 ::SetWindowText((HWND) m_staticMin, buf);
584 }
585
586 if ( m_staticMax )
587 {
588 wxSprintf(buf, wxT("%d"), m_rangeMax);
589 ::SetWindowText((HWND) m_staticMax, buf);
590 }
591}
592
593WXHBRUSH wxSlider95::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor,
594 WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
595{
596 if ( nCtlColor == CTLCOLOR_SCROLLBAR )
597 return 0;
598
599 // Otherwise, it's a static
600 return wxControl::OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
601}
602
603// For trackbars only
604void wxSlider95::SetTickFreq(int n, int pos)
605{
606 m_tickFreq = n;
607 ::SendMessage( GetHwnd(), TBM_SETTICFREQ, (WPARAM) n, (LPARAM) pos );
608}
609
610void wxSlider95::SetPageSize(int pageSize)
611{
612 ::SendMessage( GetHwnd(), TBM_SETPAGESIZE, (WPARAM) 0, (LPARAM) pageSize );
613 m_pageSize = pageSize;
614}
615
616int wxSlider95::GetPageSize() const
617{
618 return m_pageSize;
619}
620
621void wxSlider95::ClearSel()
622{
623 ::SendMessage( GetHwnd(), TBM_CLEARSEL, (WPARAM) TRUE, (LPARAM) 0 );
624}
625
626void wxSlider95::ClearTicks()
627{
628 ::SendMessage( GetHwnd(), TBM_CLEARTICS, (WPARAM) TRUE, (LPARAM) 0 );
629}
630
631void wxSlider95::SetLineSize(int lineSize)
632{
633 m_lineSize = lineSize;
634 ::SendMessage( GetHwnd(), TBM_SETLINESIZE, (WPARAM) 0, (LPARAM) lineSize );
635}
636
637int wxSlider95::GetLineSize() const
638{
639 return (int) ::SendMessage( GetHwnd(), TBM_GETLINESIZE,
640 (WPARAM) 0, (LPARAM) 0 );
641}
642
643int wxSlider95::GetSelEnd() const
644{
645 return (int) ::SendMessage( GetHwnd(), TBM_SETSELEND,
646 (WPARAM) 0, (LPARAM) 0 );
647}
648
649int wxSlider95::GetSelStart() const
650{
651 return (int) ::SendMessage( GetHwnd(), TBM_GETSELSTART,
652 (WPARAM) 0, (LPARAM) 0 );
653}
654
655void wxSlider95::SetSelection(int minPos, int maxPos)
656{
657 ::SendMessage(GetHwnd(), TBM_SETSEL,
658 (WPARAM) TRUE, (LPARAM) MAKELONG( minPos, maxPos) );
659}
660
661void wxSlider95::SetThumbLength(int len)
662{
663 ::SendMessage( GetHwnd(), TBM_SETTHUMBLENGTH, (WPARAM) len, (LPARAM) 0 );
664}
665
666int wxSlider95::GetThumbLength() const
667{
668 return (int) ::SendMessage( GetHwnd(), TBM_GETTHUMBLENGTH,
669 (WPARAM) 0, (LPARAM) 0 );
670}
671
672void wxSlider95::SetTick(int tickPos)
673{
674 ::SendMessage( GetHwnd(), TBM_SETTIC, (WPARAM) 0, (LPARAM) tickPos );
675}
676
677bool wxSlider95::ContainsHWND(WXHWND hWnd) const
678{
679 return
680 (
681 hWnd == GetStaticMin()
682 || hWnd == GetStaticMax()
683 || hWnd == GetEditValue()
684 );
685}
686
687void wxSlider95::Command (wxCommandEvent & event)
688{
689 SetValue (event.GetInt());
690 ProcessCommand (event);
691}
692
693bool wxSlider95::Show(bool show)
694{
695 wxWindow::Show(show);
696
697 int cshow;
698 if (show)
699 cshow = SW_SHOW;
700 else
701 cshow = SW_HIDE;
702
703 if(m_staticValue)
704 ShowWindow((HWND) m_staticValue, (BOOL)cshow);
705
706 if(m_staticMin)
707 ShowWindow((HWND) m_staticMin, (BOOL)cshow);
708
709 if(m_staticMax)
710 ShowWindow((HWND) m_staticMax, (BOOL)cshow);
711
712 return TRUE;
713}
714
715#endif
716 // __WIN95__
717
718#endif // wxUSE_SLIDER