]> git.saurik.com Git - wxWidgets.git/blob - src/msw/slider95.cpp
Some improvements to accessibility behaviour
[wxWidgets.git] / src / msw / slider95.cpp
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
40 IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
41
42 // Slider
43 wxSlider95::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
55 bool 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
224 bool 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
292 wxSlider95::~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
313 int wxSlider95::GetValue() const
314 {
315 return ::SendMessage(GetHwnd(), TBM_GETPOS, 0, 0);
316 }
317
318 void 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
330 void wxSlider95::DoGetSize(int *width, int *height) const
331 {
332 GetSize(width, height);
333 }
334
335 void 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
355 void 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()
394 void 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
572 void 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
593 WXHBRUSH 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
604 void wxSlider95::SetTickFreq(int n, int pos)
605 {
606 m_tickFreq = n;
607 ::SendMessage( GetHwnd(), TBM_SETTICFREQ, (WPARAM) n, (LPARAM) pos );
608 }
609
610 void wxSlider95::SetPageSize(int pageSize)
611 {
612 ::SendMessage( GetHwnd(), TBM_SETPAGESIZE, (WPARAM) 0, (LPARAM) pageSize );
613 m_pageSize = pageSize;
614 }
615
616 int wxSlider95::GetPageSize() const
617 {
618 return m_pageSize;
619 }
620
621 void wxSlider95::ClearSel()
622 {
623 ::SendMessage( GetHwnd(), TBM_CLEARSEL, (WPARAM) TRUE, (LPARAM) 0 );
624 }
625
626 void wxSlider95::ClearTicks()
627 {
628 ::SendMessage( GetHwnd(), TBM_CLEARTICS, (WPARAM) TRUE, (LPARAM) 0 );
629 }
630
631 void wxSlider95::SetLineSize(int lineSize)
632 {
633 m_lineSize = lineSize;
634 ::SendMessage( GetHwnd(), TBM_SETLINESIZE, (WPARAM) 0, (LPARAM) lineSize );
635 }
636
637 int wxSlider95::GetLineSize() const
638 {
639 return (int) ::SendMessage( GetHwnd(), TBM_GETLINESIZE,
640 (WPARAM) 0, (LPARAM) 0 );
641 }
642
643 int wxSlider95::GetSelEnd() const
644 {
645 return (int) ::SendMessage( GetHwnd(), TBM_SETSELEND,
646 (WPARAM) 0, (LPARAM) 0 );
647 }
648
649 int wxSlider95::GetSelStart() const
650 {
651 return (int) ::SendMessage( GetHwnd(), TBM_GETSELSTART,
652 (WPARAM) 0, (LPARAM) 0 );
653 }
654
655 void wxSlider95::SetSelection(int minPos, int maxPos)
656 {
657 ::SendMessage(GetHwnd(), TBM_SETSEL,
658 (WPARAM) TRUE, (LPARAM) MAKELONG( minPos, maxPos) );
659 }
660
661 void wxSlider95::SetThumbLength(int len)
662 {
663 ::SendMessage( GetHwnd(), TBM_SETTHUMBLENGTH, (WPARAM) len, (LPARAM) 0 );
664 }
665
666 int wxSlider95::GetThumbLength() const
667 {
668 return (int) ::SendMessage( GetHwnd(), TBM_GETTHUMBLENGTH,
669 (WPARAM) 0, (LPARAM) 0 );
670 }
671
672 void wxSlider95::SetTick(int tickPos)
673 {
674 ::SendMessage( GetHwnd(), TBM_SETTIC, (WPARAM) 0, (LPARAM) tickPos );
675 }
676
677 bool wxSlider95::ContainsHWND(WXHWND hWnd) const
678 {
679 return
680 (
681 hWnd == GetStaticMin()
682 || hWnd == GetStaticMax()
683 || hWnd == GetEditValue()
684 );
685 }
686
687 void wxSlider95::Command (wxCommandEvent & event)
688 {
689 SetValue (event.GetInt());
690 ProcessCommand (event);
691 }
692
693 bool 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