comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Slider.d @ 0:6dd524f61e62

add dwt win and basic java stuff
author Frank Benoit <benoit@tionex.de>
date Mon, 02 Mar 2009 14:44:16 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:6dd524f61e62
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.swt.widgets.Slider;
14
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.SWTException;
17 import org.eclipse.swt.events.SelectionEvent;
18 import org.eclipse.swt.events.SelectionListener;
19 import org.eclipse.swt.graphics.Point;
20 import org.eclipse.swt.internal.win32.OS;
21
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Composite;
24 import org.eclipse.swt.widgets.TypedListener;
25 import org.eclipse.swt.widgets.Event;
26
27 import java.lang.all;
28
29 /**
30 * Instances of this class are selectable user interface
31 * objects that represent a range of positive, numeric values.
32 * <p>
33 * At any given moment, a given slider will have a
34 * single 'selection' that is considered to be its
35 * value, which is constrained to be within the range of
36 * values the slider represents (that is, between its
37 * <em>minimum</em> and <em>maximum</em> values).
38 * </p><p>
39 * Typically, sliders will be made up of five areas:
40 * <ol>
41 * <li>an arrow button for decrementing the value</li>
42 * <li>a page decrement area for decrementing the value by a larger amount</li>
43 * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
44 * <li>a page increment area for incrementing the value by a larger amount</li>
45 * <li>an arrow button for incrementing the value</li>
46 * </ol>
47 * Based on their style, sliders are either <code>HORIZONTAL</code>
48 * (which have a left facing button for decrementing the value and a
49 * right facing button for incrementing it) or <code>VERTICAL</code>
50 * (which have an upward facing button for decrementing the value
51 * and a downward facing buttons for incrementing it).
52 * </p><p>
53 * On some platforms, the size of the slider's thumb can be
54 * varied relative to the magnitude of the range of values it
55 * represents (that is, relative to the difference between its
56 * maximum and minimum values). Typically, this is used to
57 * indicate some proportional value such as the ratio of the
58 * visible area of a document to the total amount of space that
59 * it would take to display it. SWT supports setting the thumb
60 * size even if the underlying platform does not, but in this
61 * case the appearance of the slider will not change.
62 * </p>
63 * <dl>
64 * <dt><b>Styles:</b></dt>
65 * <dd>HORIZONTAL, VERTICAL</dd>
66 * <dt><b>Events:</b></dt>
67 * <dd>Selection</dd>
68 * </dl>
69 * <p>
70 * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
71 * </p><p>
72 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
73 * </p>
74 *
75 * @see ScrollBar
76 * @see <a href="http://www.eclipse.org/swt/snippets/#slider">Slider snippets</a>
77 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
78 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
79 */
80 public class Slider : Control {
81
82 alias Control.computeSize computeSize;
83 alias Control.setBounds setBounds;
84 alias Control.windowProc windowProc;
85
86 int increment, pageIncrement;
87 bool ignoreFocus;
88 static /+const+/ WNDPROC ScrollBarProc;
89 static const TCHAR[] ScrollBarClass = "SCROLLBAR";
90
91 private static bool static_this_completed = false;
92 private static void static_this() {
93 if( static_this_completed ){
94 return;
95 }
96 synchronized {
97 if( static_this_completed ){
98 return;
99 }
100 WNDCLASS lpWndClass;
101 OS.GetClassInfo (null, ScrollBarClass.ptr, &lpWndClass);
102 ScrollBarProc = lpWndClass.lpfnWndProc;
103 static_this_completed = true;
104 }
105 }
106
107 /**
108 * Constructs a new instance of this class given its parent
109 * and a style value describing its behavior and appearance.
110 * <p>
111 * The style value is either one of the style constants defined in
112 * class <code>SWT</code> which is applicable to instances of this
113 * class, or must be built by <em>bitwise OR</em>'ing together
114 * (that is, using the <code>int</code> "|" operator) two or more
115 * of those <code>SWT</code> style constants. The class description
116 * lists the style constants that are applicable to the class.
117 * Style bits are also inherited from superclasses.
118 * </p>
119 *
120 * @param parent a composite control which will be the parent of the new instance (cannot be null)
121 * @param style the style of control to construct
122 *
123 * @exception IllegalArgumentException <ul>
124 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
125 * </ul>
126 * @exception SWTException <ul>
127 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
128 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
129 * </ul>
130 *
131 * @see SWT#HORIZONTAL
132 * @see SWT#VERTICAL
133 * @see Widget#checkSubclass
134 * @see Widget#getStyle
135 */
136 public this (Composite parent, int style) {
137 static_this();
138 super (parent, checkStyle (style));
139 }
140
141 /**
142 * Adds the listener to the collection of listeners who will
143 * be notified when the user changes the receiver's value, by sending
144 * it one of the messages defined in the <code>SelectionListener</code>
145 * interface.
146 * <p>
147 * When <code>widgetSelected</code> is called, the event object detail field contains one of the following values:
148 * <code>SWT.NONE</code> - for the end of a drag.
149 * <code>SWT.DRAG</code>.
150 * <code>SWT.HOME</code>.
151 * <code>SWT.END</code>.
152 * <code>SWT.ARROW_DOWN</code>.
153 * <code>SWT.ARROW_UP</code>.
154 * <code>SWT.PAGE_DOWN</code>.
155 * <code>SWT.PAGE_UP</code>.
156 * <code>widgetDefaultSelected</code> is not called.
157 * </p>
158 *
159 * @param listener the listener which should be notified when the user changes the receiver's value
160 *
161 * @exception IllegalArgumentException <ul>
162 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
163 * </ul>
164 * @exception SWTException <ul>
165 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
166 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
167 * </ul>
168 *
169 * @see SelectionListener
170 * @see #removeSelectionListener
171 * @see SelectionEvent
172 */
173 public void addSelectionListener (SelectionListener listener) {
174 checkWidget ();
175 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
176 TypedListener typedListener = new TypedListener(listener);
177 addListener (SWT.Selection,typedListener);
178 addListener (SWT.DefaultSelection,typedListener);
179 }
180
181 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
182 if (handle is null) return 0;
183 /*
184 * Feature in Windows. Windows runs a modal message
185 * loop when the user drags a scroll bar. This means
186 * that mouse down events won't get delivered until
187 * after the loop finishes. The fix is to run any
188 * deferred messages, including mouse down messages
189 * before calling the scroll bar window proc.
190 */
191 switch (msg) {
192 case OS.WM_LBUTTONDOWN:
193 case OS.WM_LBUTTONDBLCLK:
194 display.runDeferredEvents ();
195 default:
196 }
197 return OS.CallWindowProc (ScrollBarProc, hwnd, msg, wParam, lParam);
198 }
199
200 static int checkStyle (int style) {
201 return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
202 }
203
204 override public Point computeSize (int wHint, int hHint, bool changed) {
205 checkWidget ();
206 int border = getBorderWidth ();
207 int width = border * 2, height = border * 2;
208 if ((style & SWT.HORIZONTAL) !is 0) {
209 width += OS.GetSystemMetrics (OS.SM_CXHSCROLL) * 10;
210 height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
211 } else {
212 width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
213 height += OS.GetSystemMetrics (OS.SM_CYVSCROLL) * 10;
214 }
215 if (wHint !is SWT.DEFAULT) width = wHint + (border * 2);
216 if (hHint !is SWT.DEFAULT) height = hHint + (border * 2);
217 return new Point (width, height);
218 }
219
220 override void createWidget () {
221 super.createWidget ();
222 increment = 1;
223 pageIncrement = 10;
224 /*
225 * Set the initial values of the maximum
226 * to 100 and the thumb to 10. Note that
227 * info.nPage needs to be 11 in order to
228 * get a thumb that is 10.
229 */
230 SCROLLINFO info;
231 info.cbSize = SCROLLINFO.sizeof;
232 info.fMask = OS.SIF_ALL;
233 info.nMax = 100;
234 info.nPage = 11;
235 OS.SetScrollInfo (handle, OS.SB_CTL, &info, true);
236 }
237
238 override int defaultBackground () {
239 return OS.GetSysColor (OS.COLOR_SCROLLBAR);
240 }
241
242 override int defaultForeground () {
243 return OS.GetSysColor (OS.COLOR_BTNFACE);
244 }
245
246 override void enableWidget (bool enabled) {
247 super.enableWidget (enabled);
248 static if (!OS.IsWinCE) {
249 int flags = enabled ? OS.ESB_ENABLE_BOTH : OS.ESB_DISABLE_BOTH;
250 OS.EnableScrollBar (handle, OS.SB_CTL, flags);
251 }
252 if (enabled) {
253 state &= ~DISABLED;
254 } else {
255 state |= DISABLED;
256 }
257 }
258
259 override public bool getEnabled () {
260 checkWidget ();
261 return (state & DISABLED) is 0;
262 }
263
264 /**
265 * Returns the amount that the receiver's value will be
266 * modified by when the up/down (or right/left) arrows
267 * are pressed.
268 *
269 * @return the increment
270 *
271 * @exception SWTException <ul>
272 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
273 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
274 * </ul>
275 */
276 public int getIncrement () {
277 checkWidget ();
278 return increment;
279 }
280
281 /**
282 * Returns the maximum value which the receiver will allow.
283 *
284 * @return the maximum
285 *
286 * @exception SWTException <ul>
287 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
288 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
289 * </ul>
290 */
291 public int getMaximum () {
292 checkWidget ();
293 SCROLLINFO info;
294 info.cbSize = SCROLLINFO.sizeof;
295 info.fMask = OS.SIF_RANGE;
296 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
297 return info.nMax;
298 }
299
300 /**
301 * Returns the minimum value which the receiver will allow.
302 *
303 * @return the minimum
304 *
305 * @exception SWTException <ul>
306 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
307 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
308 * </ul>
309 */
310 public int getMinimum () {
311 checkWidget ();
312 SCROLLINFO info;
313 info.cbSize = SCROLLINFO.sizeof;
314 info.fMask = OS.SIF_RANGE;
315 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
316 return info.nMin;
317 }
318
319 /**
320 * Returns the amount that the receiver's value will be
321 * modified by when the page increment/decrement areas
322 * are selected.
323 *
324 * @return the page increment
325 *
326 * @exception SWTException <ul>
327 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
328 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
329 * </ul>
330 */
331 public int getPageIncrement () {
332 checkWidget ();
333 return pageIncrement;
334 }
335
336 /**
337 * Returns the 'selection', which is the receiver's value.
338 *
339 * @return the selection
340 *
341 * @exception SWTException <ul>
342 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
343 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
344 * </ul>
345 */
346 public int getSelection () {
347 checkWidget ();
348 SCROLLINFO info;
349 info.cbSize = SCROLLINFO.sizeof;
350 info.fMask = OS.SIF_POS;
351 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
352 return info.nPos;
353 }
354
355 /**
356 * Returns the size of the receiver's thumb relative to the
357 * difference between its maximum and minimum values.
358 *
359 * @return the thumb value
360 *
361 * @exception SWTException <ul>
362 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
363 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
364 * </ul>
365 */
366 public int getThumb () {
367 checkWidget ();
368 SCROLLINFO info;
369 info.cbSize = SCROLLINFO.sizeof;
370 info.fMask = OS.SIF_PAGE;
371 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
372 if (info.nPage !is 0) --info.nPage;
373 return info.nPage;
374 }
375
376 /**
377 * Removes the listener from the collection of listeners who will
378 * be notified when the user changes the receiver's value.
379 *
380 * @param listener the listener which should no longer be notified
381 *
382 * @exception IllegalArgumentException <ul>
383 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
384 * </ul>
385 * @exception SWTException <ul>
386 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
387 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
388 * </ul>
389 *
390 * @see SelectionListener
391 * @see #addSelectionListener
392 */
393 public void removeSelectionListener (SelectionListener listener) {
394 checkWidget ();
395 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
396 if (eventTable is null) return;
397 eventTable.unhook (SWT.Selection, listener);
398 eventTable.unhook (SWT.DefaultSelection,listener);
399 }
400
401 override void setBounds (int x, int y, int width, int height, int flags) {
402 super.setBounds (x, y, width, height, flags);
403 /*
404 * Bug in Windows. If the scroll bar is resized when it has focus,
405 * the flashing cursor that is used to show that the scroll bar has
406 * focus is not moved. The fix is to send a fake WM_SETFOCUS to
407 * get the scroll bar to recompute the size of the flashing cursor.
408 */
409 if (OS.GetFocus () is handle) {
410 ignoreFocus = true;
411 OS.SendMessage (handle, OS.WM_SETFOCUS, 0, 0);
412 ignoreFocus = false;
413 }
414 }
415
416 /**
417 * Sets the amount that the receiver's value will be
418 * modified by when the up/down (or right/left) arrows
419 * are pressed to the argument, which must be at least
420 * one.
421 *
422 * @param value the new increment (must be greater than zero)
423 *
424 * @exception SWTException <ul>
425 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
426 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
427 * </ul>
428 */
429 public void setIncrement (int value) {
430 checkWidget ();
431 if (value < 1) return;
432 increment = value;
433 }
434
435 /**
436 * Sets the maximum. If this value is negative or less than or
437 * equal to the minimum, the value is ignored. If necessary, first
438 * the thumb and then the selection are adjusted to fit within the
439 * new range.
440 *
441 * @param value the new maximum, which must be greater than the current minimum
442 *
443 * @exception SWTException <ul>
444 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
445 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
446 * </ul>
447 */
448 public void setMaximum (int value) {
449 checkWidget ();
450 if (value < 0) return;
451 SCROLLINFO info;
452 info.cbSize = SCROLLINFO.sizeof;
453 info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
454 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
455 if (value - info.nMin - info.nPage < 1) return;
456 info.nMax = value;
457 SetScrollInfo (handle, OS.SB_CTL, &info, true);
458 }
459
460 /**
461 * Sets the minimum value. If this value is negative or greater
462 * than or equal to the maximum, the value is ignored. If necessary,
463 * first the thumb and then the selection are adjusted to fit within
464 * the new range.
465 *
466 * @param value the new minimum
467 *
468 * @exception SWTException <ul>
469 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
470 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
471 * </ul>
472 */
473 public void setMinimum (int value) {
474 checkWidget ();
475 if (value < 0) return;
476 SCROLLINFO info;
477 info.cbSize = SCROLLINFO.sizeof;
478 info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
479 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
480 if (info.nMax - value - info.nPage < 1) return;
481 info.nMin = value;
482 SetScrollInfo (handle, OS.SB_CTL, &info, true);
483 }
484
485 /**
486 * Sets the amount that the receiver's value will be
487 * modified by when the page increment/decrement areas
488 * are selected to the argument, which must be at least
489 * one.
490 *
491 * @param value the page increment (must be greater than zero)
492 *
493 * @exception SWTException <ul>
494 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
495 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
496 * </ul>
497 */
498 public void setPageIncrement (int value) {
499 checkWidget ();
500 if (value < 1) return;
501 pageIncrement = value;
502 }
503
504 bool SetScrollInfo (HWND hwnd, int flags, SCROLLINFO* info, bool fRedraw) {
505 /*
506 * Feature in Windows. Using SIF_DISABLENOSCROLL,
507 * SetScrollInfo () can change enabled and disabled
508 * state of the scroll bar causing a scroll bar that
509 * was disabled by the application to become enabled.
510 * The fix is to disable the scroll bar (again) when
511 * the application has disabled the scroll bar.
512 */
513 if ((state & DISABLED) !is 0) fRedraw = false;
514 bool result = cast(bool) OS.SetScrollInfo (hwnd, flags, info, fRedraw);
515 if ((state & DISABLED) !is 0) {
516 OS.EnableWindow (handle, false);
517 static if (!OS.IsWinCE) {
518 OS.EnableScrollBar (handle, OS.SB_CTL, OS.ESB_DISABLE_BOTH);
519 }
520 }
521
522 /*
523 * Bug in Windows. If the thumb is resized when it has focus,
524 * the flashing cursor that is used to show that the scroll bar
525 * has focus is not moved. The fix is to send a fake WM_SETFOCUS
526 * to get the scroll bar to recompute the size of the flashing
527 * cursor.
528 */
529 if (OS.GetFocus () is handle) {
530 ignoreFocus = true;
531 OS.SendMessage (handle, OS.WM_SETFOCUS, 0, 0);
532 ignoreFocus = false;
533 }
534 return result;
535 }
536
537 /**
538 * Sets the 'selection', which is the receiver's
539 * value, to the argument which must be greater than or equal
540 * to zero.
541 *
542 * @param value the new selection (must be zero or greater)
543 *
544 * @exception SWTException <ul>
545 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
546 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
547 * </ul>
548 */
549 public void setSelection (int value) {
550 checkWidget ();
551 SCROLLINFO info;
552 info.cbSize = SCROLLINFO.sizeof;
553 info.fMask = OS.SIF_POS;
554 info.nPos = value;
555 SetScrollInfo (handle, OS.SB_CTL, &info, true);
556 }
557
558 /**
559 * Sets the size of the receiver's thumb relative to the
560 * difference between its maximum and minimum values. This new
561 * value will be ignored if it is less than one, and will be
562 * clamped if it exceeds the receiver's current range.
563 *
564 * @param value the new thumb value, which must be at least one and not
565 * larger than the size of the current range
566 *
567 * @exception SWTException <ul>
568 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
569 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
570 * </ul>
571 */
572 public void setThumb (int value) {
573 checkWidget ();
574 if (value < 1) return;
575 SCROLLINFO info;
576 info.cbSize = SCROLLINFO.sizeof;
577 info.fMask = OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
578 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
579 info.nPage = value;
580 if (info.nPage !is 0) info.nPage++;
581 SetScrollInfo (handle, OS.SB_CTL, &info, true);
582 }
583
584 /**
585 * Sets the receiver's selection, minimum value, maximum
586 * value, thumb, increment and page increment all at once.
587 * <p>
588 * Note: This is similar to setting the values individually
589 * using the appropriate methods, but may be implemented in a
590 * more efficient fashion on some platforms.
591 * </p>
592 *
593 * @param selection the new selection value
594 * @param minimum the new minimum value
595 * @param maximum the new maximum value
596 * @param thumb the new thumb value
597 * @param increment the new increment value
598 * @param pageIncrement the new pageIncrement value
599 *
600 * @exception SWTException <ul>
601 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
602 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
603 * </ul>
604 */
605 public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
606 checkWidget ();
607 if (minimum < 0) return;
608 if (maximum < 0) return;
609 if (thumb < 1) return;
610 if (increment < 1) return;
611 if (pageIncrement < 1) return;
612 this.increment = increment;
613 this.pageIncrement = pageIncrement;
614 SCROLLINFO info;
615 info.cbSize = SCROLLINFO.sizeof;
616 info.fMask = OS.SIF_POS | OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
617 info.nPos = selection;
618 info.nMin = minimum;
619 info.nMax = maximum;
620 info.nPage = thumb;
621 if (info.nPage !is 0) info.nPage++;
622 SetScrollInfo (handle, OS.SB_CTL, &info, true);
623 }
624
625 override int widgetExtStyle () {
626 /*
627 * Bug in Windows. If a scroll bar control is given a border,
628 * dragging the scroll bar thumb eats away parts of the border
629 * while the thumb is dragged. The fix is to clear border for
630 * all scroll bars.
631 */
632 int bits = super.widgetExtStyle ();
633 if ((style & SWT.BORDER) !is 0) bits &= ~OS.WS_EX_CLIENTEDGE;
634 return bits;
635 }
636
637 override int widgetStyle () {
638 int bits = super.widgetStyle () | OS.WS_TABSTOP;
639 /*
640 * Bug in Windows. If a scroll bar control is given a border,
641 * dragging the scroll bar thumb eats away parts of the border
642 * while the thumb is dragged. The fix is to clear WS_BORDER.
643 */
644 if ((style & SWT.BORDER) !is 0) bits &= ~OS.WS_BORDER;
645 if ((style & SWT.HORIZONTAL) !is 0) return bits | OS.SBS_HORZ;
646 return bits | OS.SBS_VERT;
647 }
648
649 override String windowClass () {
650 return TCHARsToStr(ScrollBarClass);
651 }
652
653 override int windowProc () {
654 return cast(int) ScrollBarProc;
655 }
656
657 override LRESULT WM_KEYDOWN (int wParam, int lParam) {
658 LRESULT result = super.WM_KEYDOWN (wParam, lParam);
659 if (result !is null) return result;
660 if ((style & SWT.VERTICAL) !is 0) return result;
661 /*
662 * Bug in Windows. When a horizontal scroll bar is mirrored,
663 * the native control does not correctly swap the arrow keys.
664 * The fix is to swap them before calling the scroll bar window
665 * proc.
666 *
667 * NOTE: This fix is not ideal. It breaks when the bug is fixed
668 * in the operating system.
669 */
670 if ((style & SWT.MIRRORED) !is 0) {
671 switch (wParam) {
672 case OS.VK_LEFT:
673 case OS.VK_RIGHT: {
674 int key = wParam is OS.VK_LEFT ? OS.VK_RIGHT : OS.VK_LEFT;
675 int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam);
676 return new LRESULT (code);
677 }
678 default:
679 }
680 }
681 return result;
682 }
683
684 override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
685 /*
686 * Feature in Windows. Windows uses the WS_TABSTOP
687 * style for the scroll bar to decide that focus
688 * should be set during WM_LBUTTONDBLCLK. This is
689 * not the desired behavior. The fix is to clear
690 * and restore WS_TABSTOP so that Windows will not
691 * assign focus.
692 */
693 int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
694 int newBits = oldBits & ~OS.WS_TABSTOP;
695 OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
696 LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
697 if (isDisposed ()) return LRESULT.ZERO;
698 OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
699 if (result is LRESULT.ZERO) return result;
700
701 /*
702 * Feature in Windows. Windows runs a modal message loop
703 * when the user drags a scroll bar that terminates when
704 * it sees an WM_LBUTTONUP. Unfortunately the WM_LBUTTONUP
705 * is consumed. The fix is to send a fake mouse up and
706 * release the automatic capture.
707 */
708 static if (!OS.IsWinCE) {
709 if (OS.GetCapture () is handle) OS.ReleaseCapture ();
710 if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
711 return LRESULT.ZERO;
712 }
713 }
714 return result;
715 }
716
717 override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
718 /*
719 * Feature in Windows. Windows uses the WS_TABSTOP
720 * style for the scroll bar to decide that focus
721 * should be set during WM_LBUTTONDOWN. This is
722 * not the desired behavior. The fix is to clear
723 * and restore WS_TABSTOP so that Windows will not
724 * assign focus.
725 */
726 int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
727 int newBits = oldBits & ~OS.WS_TABSTOP;
728 OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
729 LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
730 if (isDisposed ()) return LRESULT.ZERO;
731 OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
732 if (result is LRESULT.ZERO) return result;
733
734 /*
735 * Feature in Windows. Windows runs a modal message loop
736 * when the user drags a scroll bar that terminates when
737 * it sees an WM_LBUTTONUP. Unfortunately the WM_LBUTTONUP
738 * is consumed. The fix is to send a fake mouse up and
739 * release the automatic capture.
740 */
741 static if (!OS.IsWinCE) {
742 if (OS.GetCapture () is handle) OS.ReleaseCapture ();
743 if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
744 return LRESULT.ONE;
745 }
746 }
747 return result;
748 }
749
750 override LRESULT WM_SETFOCUS (int wParam, int lParam) {
751 if (ignoreFocus) return null;
752 return super.WM_SETFOCUS (wParam, lParam);
753 }
754
755 override LRESULT wmScrollChild (int wParam, int lParam) {
756
757 /* Do nothing when scrolling is ending */
758 int code = OS.LOWORD (wParam);
759 if (code is OS.SB_ENDSCROLL) return null;
760
761 /* Move the thumb */
762 Event event = new Event ();
763 SCROLLINFO info;
764 info.cbSize = SCROLLINFO.sizeof;
765 info.fMask = OS.SIF_TRACKPOS | OS.SIF_POS | OS.SIF_RANGE;
766 OS.GetScrollInfo (handle, OS.SB_CTL, &info);
767 info.fMask = OS.SIF_POS;
768 switch (code) {
769 case OS.SB_THUMBPOSITION:
770 event.detail = SWT.NONE;
771 info.nPos = info.nTrackPos;
772 break;
773 case OS.SB_THUMBTRACK:
774 event.detail = SWT.DRAG;
775 info.nPos = info.nTrackPos;
776 break;
777 case OS.SB_TOP:
778 event.detail = SWT.HOME;
779 info.nPos = info.nMin;
780 break;
781 case OS.SB_BOTTOM:
782 event.detail = SWT.END;
783 info.nPos = info.nMax;
784 break;
785 case OS.SB_LINEDOWN:
786 event.detail = SWT.ARROW_DOWN;
787 info.nPos += increment;
788 break;
789 case OS.SB_LINEUP:
790 event.detail = SWT.ARROW_UP;
791 info.nPos = Math.max (info.nMin, info.nPos - increment);
792 break;
793 case OS.SB_PAGEDOWN:
794 event.detail = SWT.PAGE_DOWN;
795 info.nPos += pageIncrement;
796 break;
797 case OS.SB_PAGEUP:
798 event.detail = SWT.PAGE_UP;
799 info.nPos = Math.max (info.nMin, info.nPos - pageIncrement);
800 break;
801 default:
802 }
803 OS.SetScrollInfo (handle, OS.SB_CTL, &info, true);
804
805 /*
806 * Feature in Windows. Windows runs a modal message
807 * loop when the user drags a scroll bar. This means
808 * that selection event must be sent because WM_HSCROLL
809 * and WM_VSCROLL are sent from the modal message loop
810 * so that they are delivered during inside the loop.
811 */
812 sendEvent (SWT.Selection, event);
813 // the widget could be destroyed at this point
814 return null;
815 }
816
817 }