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