1 /*******************************************************************************
2 * Copyright (c) 2000, 2019 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 * Stefan Xenos (Google) - bug 468854 - Add a requestLayout method to Control
14 *******************************************************************************/
15 package org.eclipse.swt.widgets;
18 import org.eclipse.swt.*;
19 import org.eclipse.swt.accessibility.*;
20 import org.eclipse.swt.events.*;
21 import org.eclipse.swt.graphics.*;
22 import org.eclipse.swt.internal.*;
23 import org.eclipse.swt.internal.gdip.*;
24 import org.eclipse.swt.internal.win32.*;
27 * Control is the abstract superclass of all windowed user interface classes.
31 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT, FLIP_TEXT_DIRECTION</dd>
33 * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
34 * MouseExit, MouseHover, MouseUp, MouseMove, MouseWheel, MouseHorizontalWheel, MouseVerticalWheel, Move,
35 * Paint, Resize, Traverse</dd>
38 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
40 * IMPORTANT: This class is intended to be subclassed <em>only</em>
41 * within the SWT implementation.
44 * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a>
45 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
46 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
47 * @noextend This class is not intended to be subclassed by clients.
49 public abstract class Control extends Widget implements Drawable {
52 * the handle to the OS resource
53 * (Warning: This field is platform dependent)
55 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
56 * public API. It is marked public only so that it can be shared
57 * within the packages provided by SWT. It is not available on all
58 * platforms and should never be accessed from application code.
61 * @noreference This field is not intended to be referenced by clients.
66 Menu menu, activeMenu;
69 Accessible accessible;
70 Image backgroundImage;
73 int drawCount, foreground, background, backgroundAlpha = 255;
76 * Prevents uninitialized instances from being created outside the package.
82 * Constructs a new instance of this class given its parent
83 * and a style value describing its behavior and appearance.
85 * The style value is either one of the style constants defined in
86 * class <code>SWT</code> which is applicable to instances of this
87 * class, or must be built by <em>bitwise OR</em>'ing together
88 * (that is, using the <code>int</code> "|" operator) two or more
89 * of those <code>SWT</code> style constants. The class description
90 * lists the style constants that are applicable to the class.
91 * Style bits are also inherited from superclasses.
94 * @param parent a composite control which will be the parent of the new instance (cannot be null)
95 * @param style the style of control to construct
97 * @exception IllegalArgumentException <ul>
98 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
100 * @exception SWTException <ul>
101 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
102 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
106 * @see SWT#LEFT_TO_RIGHT
107 * @see SWT#RIGHT_TO_LEFT
108 * @see Widget#checkSubclass
109 * @see Widget#getStyle
111 public Control (Composite parent, int style) {
112 super (parent, style);
113 this.parent = parent;
118 * Adds the listener to the collection of listeners who will
119 * be notified when the control is moved or resized, by sending
120 * it one of the messages defined in the <code>ControlListener</code>
123 * @param listener the listener which should be notified
125 * @exception IllegalArgumentException <ul>
126 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
128 * @exception SWTException <ul>
129 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
130 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
133 * @see ControlListener
134 * @see #removeControlListener
136 public void addControlListener(ControlListener listener) {
138 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
139 TypedListener typedListener = new TypedListener (listener);
140 addListener (SWT.Resize,typedListener);
141 addListener (SWT.Move,typedListener);
145 * Adds the listener to the collection of listeners who will
146 * be notified when a drag gesture occurs, by sending it
147 * one of the messages defined in the <code>DragDetectListener</code>
150 * @param listener the listener which should be notified
152 * @exception IllegalArgumentException <ul>
153 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
155 * @exception SWTException <ul>
156 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
157 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
160 * @see DragDetectListener
161 * @see #removeDragDetectListener
165 public void addDragDetectListener (DragDetectListener listener) {
167 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
168 TypedListener typedListener = new TypedListener (listener);
169 addListener (SWT.DragDetect,typedListener);
173 * Adds the listener to the collection of listeners who will
174 * be notified when the control gains or loses focus, by sending
175 * it one of the messages defined in the <code>FocusListener</code>
178 * @param listener the listener which should be notified
180 * @exception IllegalArgumentException <ul>
181 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
183 * @exception SWTException <ul>
184 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
185 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
189 * @see #removeFocusListener
191 public void addFocusListener (FocusListener listener) {
193 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
194 TypedListener typedListener = new TypedListener (listener);
195 addListener (SWT.FocusIn,typedListener);
196 addListener (SWT.FocusOut,typedListener);
200 * Adds the listener to the collection of listeners who will
201 * be notified when gesture events are generated for the control,
202 * by sending it one of the messages defined in the
203 * <code>GestureListener</code> interface.
205 * NOTE: If <code>setTouchEnabled(true)</code> has previously been
206 * invoked on the receiver then <code>setTouchEnabled(false)</code>
207 * must be invoked on it to specify that gesture events should be
208 * sent instead of touch events.
211 * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
212 * SWT doesn't send Gesture or Touch events on GTK.
215 * @param listener the listener which should be notified
217 * @exception IllegalArgumentException <ul>
218 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
220 * @exception SWTException <ul>
221 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
222 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
225 * @see GestureListener
226 * @see #removeGestureListener
227 * @see #setTouchEnabled
231 public void addGestureListener (GestureListener listener) {
233 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
234 TypedListener typedListener = new TypedListener (listener);
235 addListener (SWT.Gesture, typedListener);
239 * Adds the listener to the collection of listeners who will
240 * be notified when help events are generated for the control,
241 * by sending it one of the messages defined in the
242 * <code>HelpListener</code> interface.
244 * @param listener the listener which should be notified
246 * @exception IllegalArgumentException <ul>
247 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
249 * @exception SWTException <ul>
250 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
251 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
255 * @see #removeHelpListener
257 public void addHelpListener (HelpListener listener) {
259 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
260 TypedListener typedListener = new TypedListener (listener);
261 addListener (SWT.Help, typedListener);
265 * Adds the listener to the collection of listeners who will
266 * be notified when keys are pressed and released on the system keyboard, by sending
267 * it one of the messages defined in the <code>KeyListener</code>
270 * When a key listener is added to a control, the control
271 * will take part in widget traversal. By default, all
272 * traversal keys (such as the tab key and so on) are
273 * delivered to the control. In order for a control to take
274 * part in traversal, it should listen for traversal events.
275 * Otherwise, the user can traverse into a control but not
276 * out. Note that native controls such as table and tree
277 * implement key traversal in the operating system. It is
278 * not necessary to add traversal listeners for these controls,
279 * unless you want to override the default traversal.
281 * @param listener the listener which should be notified
283 * @exception IllegalArgumentException <ul>
284 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
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>
292 * @see #removeKeyListener
294 public void addKeyListener (KeyListener listener) {
296 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
297 TypedListener typedListener = new TypedListener (listener);
298 addListener (SWT.KeyUp,typedListener);
299 addListener (SWT.KeyDown,typedListener);
303 * Adds the listener to the collection of listeners who will
304 * be notified when the platform-specific context menu trigger
305 * has occurred, by sending it one of the messages defined in
306 * the <code>MenuDetectListener</code> interface.
308 * @param listener the listener which should be notified
310 * @exception IllegalArgumentException <ul>
311 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
313 * @exception SWTException <ul>
314 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
315 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
318 * @see MenuDetectListener
319 * @see #removeMenuDetectListener
323 public void addMenuDetectListener (MenuDetectListener listener) {
325 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
326 TypedListener typedListener = new TypedListener (listener);
327 addListener (SWT.MenuDetect, typedListener);
331 * Adds the listener to the collection of listeners who will
332 * be notified when mouse buttons are pressed and released, by sending
333 * it one of the messages defined in the <code>MouseListener</code>
336 * @param listener the listener which should be notified
338 * @exception IllegalArgumentException <ul>
339 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
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>
347 * @see #removeMouseListener
349 public void addMouseListener (MouseListener listener) {
351 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
352 TypedListener typedListener = new TypedListener (listener);
353 addListener (SWT.MouseDown,typedListener);
354 addListener (SWT.MouseUp,typedListener);
355 addListener (SWT.MouseDoubleClick,typedListener);
359 * Adds the listener to the collection of listeners who will
360 * be notified when the mouse passes or hovers over controls, by sending
361 * it one of the messages defined in the <code>MouseTrackListener</code>
364 * @param listener the listener which should be notified
366 * @exception IllegalArgumentException <ul>
367 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
369 * @exception SWTException <ul>
370 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
371 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
374 * @see MouseTrackListener
375 * @see #removeMouseTrackListener
377 public void addMouseTrackListener (MouseTrackListener listener) {
379 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
380 TypedListener typedListener = new TypedListener (listener);
381 addListener (SWT.MouseEnter,typedListener);
382 addListener (SWT.MouseExit,typedListener);
383 addListener (SWT.MouseHover,typedListener);
387 * Adds the listener to the collection of listeners who will
388 * be notified when the mouse moves, by sending it one of the
389 * messages defined in the <code>MouseMoveListener</code>
392 * @param listener the listener which should be notified
394 * @exception IllegalArgumentException <ul>
395 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
397 * @exception SWTException <ul>
398 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
399 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
402 * @see MouseMoveListener
403 * @see #removeMouseMoveListener
405 public void addMouseMoveListener (MouseMoveListener listener) {
407 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
408 TypedListener typedListener = new TypedListener (listener);
409 addListener (SWT.MouseMove,typedListener);
413 * Adds the listener to the collection of listeners who will
414 * be notified when the mouse wheel is scrolled, by sending
415 * it one of the messages defined in the
416 * <code>MouseWheelListener</code> interface.
418 * @param listener the listener which should be notified
420 * @exception IllegalArgumentException <ul>
421 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
423 * @exception SWTException <ul>
424 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
425 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
428 * @see MouseWheelListener
429 * @see #removeMouseWheelListener
433 public void addMouseWheelListener (MouseWheelListener listener) {
435 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
436 TypedListener typedListener = new TypedListener (listener);
437 addListener (SWT.MouseWheel, typedListener);
441 * Adds the listener to the collection of listeners who will
442 * be notified when the receiver needs to be painted, by sending it
443 * one of the messages defined in the <code>PaintListener</code>
446 * @param listener the listener which should be notified
448 * @exception IllegalArgumentException <ul>
449 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
451 * @exception SWTException <ul>
452 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
453 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
457 * @see #removePaintListener
459 public void addPaintListener (PaintListener listener) {
461 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
462 TypedListener typedListener = new TypedListener (listener);
463 addListener (SWT.Paint,typedListener);
467 * Adds the listener to the collection of listeners who will
468 * be notified when touch events occur, by sending it
469 * one of the messages defined in the <code>TouchListener</code>
472 * NOTE: You must also call <code>setTouchEnabled(true)</code> to
473 * specify that touch events should be sent, which will cause gesture
474 * events to not be sent.
477 * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
478 * SWT doesn't send Gesture or Touch events on GTK.
481 * @param listener the listener which should be notified
483 * @exception IllegalArgumentException <ul>
484 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
486 * @exception SWTException <ul>
487 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
488 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
492 * @see #removeTouchListener
493 * @see #setTouchEnabled
497 public void addTouchListener (TouchListener listener) {
499 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
500 TypedListener typedListener = new TypedListener (listener);
501 addListener (SWT.Touch,typedListener);
505 * Adds the listener to the collection of listeners who will
506 * be notified when traversal events occur, by sending it
507 * one of the messages defined in the <code>TraverseListener</code>
510 * @param listener the listener which should be notified
512 * @exception IllegalArgumentException <ul>
513 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
515 * @exception SWTException <ul>
516 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
517 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
520 * @see TraverseListener
521 * @see #removeTraverseListener
523 public void addTraverseListener (TraverseListener listener) {
525 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
526 TypedListener typedListener = new TypedListener (listener);
527 addListener (SWT.Traverse,typedListener);
530 int binarySearch (int [] indices, int start, int end, int index) {
531 int low = start, high = end - 1;
532 while (low <= high) {
533 int mid = (low + high) >>> 1;
534 if (indices [mid] == index) return mid;
535 if (indices [mid] < index) {
544 long borderHandle () {
548 void checkBackground () {
549 Shell shell = getShell ();
550 if (this == shell) return;
551 state &= ~PARENT_BACKGROUND;
552 Composite composite = parent;
554 int mode = composite.backgroundMode;
555 if (mode != 0 || backgroundAlpha == 0) {
556 if (mode == SWT.INHERIT_DEFAULT || backgroundAlpha == 0) {
557 Control control = this;
559 if ((control.state & THEME_BACKGROUND) == 0) {
562 control = control.parent;
563 } while (control != composite);
565 state |= PARENT_BACKGROUND;
568 if (composite == shell) break;
569 composite = composite.parent;
573 void checkBorder () {
574 if (getBorderWidthInPixels () == 0) style &= ~SWT.BORDER;
577 void checkBuffered () {
578 style &= ~SWT.DOUBLE_BUFFERED;
581 void checkComposited () {
585 boolean checkHandle (long hwnd) {
586 return hwnd == handle;
589 void checkMirrored () {
590 if ((style & SWT.RIGHT_TO_LEFT) != 0) {
591 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
592 if ((bits & OS.WS_EX_LAYOUTRTL) != 0) style |= SWT.MIRRORED;
597 * Returns the preferred size (in points) of the receiver.
599 * The <em>preferred size</em> of a control is the size that it would
600 * best be displayed at. The width hint and height hint arguments
601 * allow the caller to ask a control questions such as "Given a particular
602 * width, how high does the control need to be to show all of the contents?"
603 * To indicate that the caller does not wish to constrain a particular
604 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
607 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
608 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
609 * @return the preferred size of the control
611 * @exception SWTException <ul>
612 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
613 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
617 * @see #getBorderWidth
620 * @see #pack(boolean)
621 * @see "computeTrim, getClientArea for controls that implement them"
623 public Point computeSize (int wHint, int hHint) {
624 return computeSize(wHint, hHint, true);
628 * Returns the preferred size (in points) of the receiver.
630 * The <em>preferred size</em> of a control is the size that it would
631 * best be displayed at. The width hint and height hint arguments
632 * allow the caller to ask a control questions such as "Given a particular
633 * width, how high does the control need to be to show all of the contents?"
634 * To indicate that the caller does not wish to constrain a particular
635 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
637 * If the changed flag is <code>true</code>, it indicates that the receiver's
638 * <em>contents</em> have changed, therefore any caches that a layout manager
639 * containing the control may have been keeping need to be flushed. When the
640 * control is resized, the changed flag will be <code>false</code>, so layout
641 * manager caches can be retained.
644 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
645 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
646 * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
647 * @return the preferred size of the control.
649 * @exception SWTException <ul>
650 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
651 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
655 * @see #getBorderWidth
658 * @see #pack(boolean)
659 * @see "computeTrim, getClientArea for controls that implement them"
661 public Point computeSize (int wHint, int hHint, boolean changed){
663 wHint = (wHint != SWT.DEFAULT ? DPIUtil.autoScaleUp(wHint) : wHint);
664 hHint = (hHint != SWT.DEFAULT ? DPIUtil.autoScaleUp(hHint) : hHint);
665 return DPIUtil.autoScaleDown(computeSizeInPixels(wHint, hHint, changed));
668 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
669 int width = DEFAULT_WIDTH;
670 int height = DEFAULT_HEIGHT;
671 if (wHint != SWT.DEFAULT) width = wHint;
672 if (hHint != SWT.DEFAULT) height = hHint;
673 int border = getBorderWidthInPixels ();
675 height += border * 2;
676 return new Point (width, height);
679 Widget computeTabGroup () {
680 if (isTabGroup ()) return this;
681 return parent.computeTabGroup ();
684 Control computeTabRoot () {
685 Control [] tabList = parent._getTabList ();
686 if (tabList != null) {
688 while (index < tabList.length) {
689 if (tabList [index] == this) break;
692 if (index == tabList.length) {
693 if (isTabGroup ()) return this;
696 return parent.computeTabRoot ();
699 Widget [] computeTabList () {
701 if (getVisible () && getEnabled ()) {
702 return new Widget [] {this};
705 return new Widget [0];
708 void createHandle () {
709 long hwndParent = widgetParent ();
710 handle = OS.CreateWindowEx (
715 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
718 OS.GetModuleHandle (null),
719 widgetCreateStruct ());
720 if (handle == 0) error (SWT.ERROR_NO_HANDLES);
721 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
722 if ((bits & OS.WS_CHILD) != 0) {
723 OS.SetWindowLongPtr (handle, OS.GWLP_ID, handle);
725 if (OS.IsDBLocale && hwndParent != 0) {
726 long hIMC = OS.ImmGetContext (hwndParent);
727 OS.ImmAssociateContext (handle, hIMC);
728 OS.ImmReleaseContext (hwndParent, hIMC);
733 void checkGesture () {
734 if (OS.WIN32_VERSION >= OS.VERSION (6, 1)) {
735 int value = OS.GetSystemMetrics (OS.SM_DIGITIZER);
736 if ((value & (OS.NID_READY | OS.NID_MULTI_INPUT)) != 0) {
738 * Feature in Windows 7: All gestures are enabled by default except GID_ROTATE.
739 * Enable it explicitly by calling SetGestureConfig.
741 long hHeap = OS.GetProcessHeap ();
742 long pConfigs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, GESTURECONFIG.sizeof);
744 GESTURECONFIG config = new GESTURECONFIG();
745 config.dwID = OS.GID_ROTATE;
748 OS.MoveMemory (pConfigs, config, GESTURECONFIG.sizeof);
749 OS.SetGestureConfig (handle, 0, 1, pConfigs, GESTURECONFIG.sizeof);
750 OS.HeapFree (hHeap, 0, pConfigs);
756 void createWidget () {
757 state |= DRAG_DETECT;
758 foreground = background = -1;
759 checkOrientation (parent);
770 if ((state & PARENT_BACKGROUND) != 0) {
775 int defaultBackground () {
776 return OS.GetSysColor (OS.COLOR_BTNFACE);
779 long defaultFont () {
780 return display.getSystemFont ().handle;
783 int defaultForeground () {
784 return OS.GetSysColor (OS.COLOR_WINDOWTEXT);
788 display.removeControl (handle);
792 void destroyWidget () {
793 long hwnd = topHandle ();
796 OS.DestroyWindow (hwnd);
801 * Detects a drag and drop gesture. This method is used
802 * to detect a drag gesture when called from within a mouse
805 * <p>By default, a drag is detected when the gesture
806 * occurs anywhere within the client area of a control.
807 * Some controls, such as tables and trees, override this
808 * behavior. In addition to the operating system specific
809 * drag gesture, they require the mouse to be inside an
810 * item. Custom widget writers can use <code>setDragDetect</code>
811 * to disable the default detection, listen for mouse down,
812 * and then call <code>dragDetect()</code> from within the
813 * listener to conditionally detect a drag.
816 * @param event the mouse down event
818 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
820 * @exception IllegalArgumentException <ul>
821 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
823 * @exception SWTException <ul>
824 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
825 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
828 * @see DragDetectListener
829 * @see #addDragDetectListener
831 * @see #getDragDetect
832 * @see #setDragDetect
836 public boolean dragDetect (Event event) {
838 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
839 Point loc = event.getLocationInPixels();
840 return dragDetect (event.button, event.count, event.stateMask, loc.x, loc.y);
844 * Detects a drag and drop gesture. This method is used
845 * to detect a drag gesture when called from within a mouse
848 * <p>By default, a drag is detected when the gesture
849 * occurs anywhere within the client area of a control.
850 * Some controls, such as tables and trees, override this
851 * behavior. In addition to the operating system specific
852 * drag gesture, they require the mouse to be inside an
853 * item. Custom widget writers can use <code>setDragDetect</code>
854 * to disable the default detection, listen for mouse down,
855 * and then call <code>dragDetect()</code> from within the
856 * listener to conditionally detect a drag.
859 * @param event the mouse down event
861 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
863 * @exception IllegalArgumentException <ul>
864 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
866 * @exception SWTException <ul>
867 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
868 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
871 * @see DragDetectListener
872 * @see #addDragDetectListener
874 * @see #getDragDetect
875 * @see #setDragDetect
879 public boolean dragDetect (MouseEvent event) {
881 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
882 return dragDetect (event.button, event.count, event.stateMask, DPIUtil.autoScaleUp(event.x), DPIUtil.autoScaleUp(event.y)); // To Pixels
885 boolean dragDetect (int button, int count, int stateMask, int x, int y) {
886 if (button != 1 || count != 1) return false;
887 boolean dragging = dragDetect (handle, x, y, false, null, null);
888 if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
889 if (OS.GetCapture () != handle) OS.SetCapture (handle);
893 * Feature in Windows. DragDetect() captures the mouse
894 * and tracks its movement until the user releases the
895 * left mouse button, presses the ESC key, or moves the
896 * mouse outside the drag rectangle. If the user moves
897 * the mouse outside of the drag rectangle, DragDetect()
898 * returns true and a drag and drop operation can be
899 * started. When the left mouse button is released or
900 * the ESC key is pressed, these events are consumed by
901 * DragDetect() so that application code that matches
902 * mouse down/up pairs or looks for the ESC key will not
903 * function properly. The fix is to send the missing
904 * events when the drag has not started.
906 * NOTE: For now, don't send a fake WM_KEYDOWN/WM_KEYUP
907 * events for the ESC key. This would require computing
908 * wParam (the key) and lParam (the repeat count, scan code,
909 * extended-key flag, context code, previous key-state flag,
910 * and transition-state flag) which is non-trivial.
912 if (button == 1 && OS.GetKeyState (OS.VK_ESCAPE) >= 0) {
914 if ((stateMask & SWT.CTRL) != 0) wParam |= OS.MK_CONTROL;
915 if ((stateMask & SWT.SHIFT) != 0) wParam |= OS.MK_SHIFT;
916 if ((stateMask & SWT.ALT) != 0) wParam |= OS.MK_ALT;
917 if ((stateMask & SWT.BUTTON1) != 0) wParam |= OS.MK_LBUTTON;
918 if ((stateMask & SWT.BUTTON2) != 0) wParam |= OS.MK_MBUTTON;
919 if ((stateMask & SWT.BUTTON3) != 0) wParam |= OS.MK_RBUTTON;
920 if ((stateMask & SWT.BUTTON4) != 0) wParam |= OS.MK_XBUTTON1;
921 if ((stateMask & SWT.BUTTON5) != 0) wParam |= OS.MK_XBUTTON2;
922 long lParam = OS.MAKELPARAM (x, y);
923 OS.SendMessage (handle, OS.WM_LBUTTONUP, wParam, lParam);
927 return sendDragEvent (button, stateMask, x, y);
930 void drawBackground (long hDC) {
931 RECT rect = new RECT ();
932 OS.GetClientRect (handle, rect);
933 drawBackground (hDC, rect);
936 void drawBackground (long hDC, RECT rect) {
937 drawBackground (hDC, rect, -1, 0, 0);
940 void drawBackground (long hDC, RECT rect, int pixel, int tx, int ty) {
941 Control control = findBackgroundControl ();
942 if (control != null) {
943 if (control.backgroundImage != null) {
944 fillImageBackground (hDC, control, rect, tx, ty);
947 pixel = control.getBackgroundPixel ();
950 if ((state & THEME_BACKGROUND) != 0) {
951 if (OS.IsAppThemed ()) {
952 control = findThemeControl ();
953 if (control != null) {
954 fillThemeBackground (hDC, control, rect);
960 if (pixel == -1) pixel = getBackgroundPixel ();
961 fillBackground (hDC, pixel, rect);
964 void drawImageBackground (long hDC, long hwnd, long hBitmap, RECT rect, int tx, int ty) {
965 RECT rect2 = new RECT ();
966 OS.GetClientRect (hwnd, rect2);
967 OS.MapWindowPoints (hwnd, handle, rect2, 2);
968 long hBrush = findBrush (hBitmap, OS.BS_PATTERN);
969 POINT lpPoint = new POINT ();
970 OS.GetWindowOrgEx (hDC, lpPoint);
971 OS.SetBrushOrgEx (hDC, -rect2.left - lpPoint.x - tx, -rect2.top - lpPoint.y - ty, lpPoint);
972 long hOldBrush = OS.SelectObject (hDC, hBrush);
973 OS.PatBlt (hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
974 OS.SetBrushOrgEx (hDC, lpPoint.x, lpPoint.y, null);
975 OS.SelectObject (hDC, hOldBrush);
978 void drawThemeBackground (long hDC, long hwnd, RECT rect) {
982 void enableDrag (boolean enabled) {
986 void enableWidget (boolean enabled) {
987 OS.EnableWindow (handle, enabled);
990 void fillBackground (long hDC, int pixel, RECT rect) {
991 if (rect.left > rect.right || rect.top > rect.bottom) return;
992 OS.FillRect (hDC, rect, findBrush (pixel, OS.BS_SOLID));
995 void fillImageBackground (long hDC, Control control, RECT rect, int tx, int ty) {
996 if (rect.left > rect.right || rect.top > rect.bottom) return;
997 if (control != null) {
998 Image image = control.backgroundImage;
1000 control.drawImageBackground (hDC, handle, image.handle, rect, tx, ty);
1005 void fillThemeBackground (long hDC, Control control, RECT rect) {
1006 if (rect.left > rect.right || rect.top > rect.bottom) return;
1007 if (control != null) {
1008 control.drawThemeBackground (hDC, handle, rect);
1012 Control findBackgroundControl () {
1013 if ((background != -1 || backgroundImage != null) && backgroundAlpha > 0) return this;
1014 return (parent != null && (state & PARENT_BACKGROUND) != 0) ? parent.findBackgroundControl () : null;
1017 long findBrush (long value, int lbStyle) {
1018 return parent.findBrush (value, lbStyle);
1021 Cursor findCursor () {
1022 if (cursor != null) return cursor;
1023 return parent.findCursor ();
1026 Control findImageControl () {
1027 Control control = findBackgroundControl ();
1028 return control != null && control.backgroundImage != null ? control : null;
1031 Control findThemeControl () {
1032 return background == -1 && backgroundImage == null ? parent.findThemeControl () : null;
1035 Menu [] findMenus (Control control) {
1036 if (menu != null && this != control) return new Menu [] {menu};
1037 return new Menu [0];
1040 char findMnemonic (String string) {
1042 int length = string.length ();
1044 while (index < length && string.charAt (index) != '&') index++;
1045 if (++index >= length) return '\0';
1046 if (string.charAt (index) != '&') return string.charAt (index);
1048 } while (index < length);
1052 void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
1053 oldShell.fixShell (newShell, this);
1054 oldDecorations.fixDecorations (newDecorations, this, menus);
1057 void fixFocus (Control focusControl) {
1058 Shell shell = getShell ();
1059 Control control = this;
1060 Display display = this.display;
1061 boolean oldFixFocus = display.fixFocus;
1062 display.fixFocus = true;
1064 while (control != shell && (control = control.parent) != null) {
1065 if (control.setFocus ()) return;
1068 display.fixFocus = oldFixFocus;
1070 shell.setSavedFocus (focusControl);
1075 * Forces the receiver to have the <em>keyboard focus</em>, causing
1076 * all keyboard events to be delivered to it.
1078 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
1080 * @exception SWTException <ul>
1081 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1082 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1087 public boolean forceFocus () {
1089 if (display.focusEvent == SWT.FocusOut) return false;
1090 Decorations shell = menuShell ();
1091 shell.setSavedFocus (this);
1092 if (!isEnabled () || !isVisible () || !isActive ()) return false;
1093 if (isFocusControl ()) return true;
1094 shell.setSavedFocus (null);
1096 * This code is intentionally commented.
1098 * When setting focus to a control, it is
1099 * possible that application code can set
1100 * the focus to another control inside of
1101 * WM_SETFOCUS. In this case, the original
1102 * control will no longer have the focus
1103 * and the call to setFocus() will return
1104 * false indicating failure.
1106 * We are still working on a solution at
1109 // if (OS.GetFocus () != OS.SetFocus (handle)) return false;
1110 OS.SetFocus (handle);
1111 if (isDisposed ()) return false;
1112 shell.setSavedFocus (this);
1113 return isFocusControl ();
1116 void forceResize () {
1117 if (parent == null) return;
1118 WINDOWPOS [] lpwp = parent.lpwp;
1119 if (lpwp == null) return;
1120 for (int i=0; i<lpwp.length; i++) {
1121 WINDOWPOS wp = lpwp [i];
1122 if (wp != null && wp.hwnd == handle) {
1124 * This code is intentionally commented. All widgets that
1125 * are created by SWT have WS_CLIPSIBLINGS to ensure that
1126 * application code does not draw outside of the control.
1128 // int count = parent.getChildrenCount ();
1130 // int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1131 // if ((bits & OS.WS_CLIPSIBLINGS) == 0) wp.flags |= OS.SWP_NOCOPYBITS;
1133 OS.SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
1141 * Returns the accessible object for the receiver.
1143 * If this is the first time this object is requested,
1144 * then the object is created and returned. The object
1145 * returned by getAccessible() does not need to be disposed.
1148 * @return the accessible object
1150 * @exception SWTException <ul>
1151 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1152 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1155 * @see Accessible#addAccessibleListener
1156 * @see Accessible#addAccessibleControlListener
1160 public Accessible getAccessible () {
1162 if (accessible == null) accessible = new_Accessible (this);
1167 * Returns the receiver's background color.
1169 * Note: This operation is a hint and may be overridden by the platform.
1170 * For example, on some versions of Windows the background of a TabFolder,
1171 * is a gradient rather than a solid color.
1173 * @return the background color
1175 * @exception SWTException <ul>
1176 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1177 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1180 public Color getBackground () {
1182 if (backgroundAlpha == 0) {
1183 Color color = Color.win32_new (display, background, 0);
1187 Control control = findBackgroundControl ();
1188 if (control == null) control = this;
1189 return Color.win32_new (display, control.getBackgroundPixel (), backgroundAlpha);
1194 * Returns the receiver's background image.
1196 * @return the background image
1198 * @exception SWTException <ul>
1199 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1200 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1205 public Image getBackgroundImage () {
1207 Control control = findBackgroundControl ();
1208 if (control == null) control = this;
1209 return control.backgroundImage;
1212 int getBackgroundPixel () {
1213 return background != -1 ? background : defaultBackground ();
1217 * Returns the receiver's border width in points.
1219 * @return the border width
1221 * @exception SWTException <ul>
1222 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1223 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1226 public int getBorderWidth () {
1228 return DPIUtil.autoScaleDown(getBorderWidthInPixels ());
1231 int getBorderWidthInPixels () {
1232 long borderHandle = borderHandle ();
1233 int bits1 = OS.GetWindowLong (borderHandle, OS.GWL_EXSTYLE);
1234 if ((bits1 & OS.WS_EX_CLIENTEDGE) != 0) return OS.GetSystemMetrics (OS.SM_CXEDGE);
1235 if ((bits1 & OS.WS_EX_STATICEDGE) != 0) return OS.GetSystemMetrics (OS.SM_CXBORDER);
1236 int bits2 = OS.GetWindowLong (borderHandle, OS.GWL_STYLE);
1237 if ((bits2 & OS.WS_BORDER) != 0) return OS.GetSystemMetrics (OS.SM_CXBORDER);
1242 * Returns a rectangle describing the receiver's size and location in points
1243 * relative to its parent (or its display if its parent is null),
1244 * unless the receiver is a shell. In this case, the location is
1245 * relative to the display.
1247 * @return the receiver's bounding rectangle
1249 * @exception SWTException <ul>
1250 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1251 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1254 public Rectangle getBounds (){
1256 return DPIUtil.autoScaleDown(getBoundsInPixels ());
1259 Rectangle getBoundsInPixels () {
1261 RECT rect = new RECT ();
1262 OS.GetWindowRect (topHandle (), rect);
1263 long hwndParent = parent == null ? 0 : parent.handle;
1264 OS.MapWindowPoints (0, hwndParent, rect, 2);
1265 int width = rect.right - rect.left;
1266 int height = rect.bottom - rect.top;
1267 return new Rectangle (rect.left, rect.top, width, height);
1270 int getCodePage () {
1274 String getClipboardText () {
1276 if (OS.OpenClipboard (0)) {
1277 long hMem = OS.GetClipboardData (OS.CF_UNICODETEXT);
1279 /* Ensure byteCount is a multiple of 2 bytes on UNICODE platforms */
1280 int byteCount = OS.GlobalSize (hMem) / TCHAR.sizeof * TCHAR.sizeof;
1281 long ptr = OS.GlobalLock (hMem);
1283 /* Use the character encoding for the default locale */
1284 TCHAR buffer = new TCHAR (0, byteCount / TCHAR.sizeof);
1285 OS.MoveMemory (buffer, ptr, byteCount);
1286 string = buffer.toString (0, buffer.strlen ());
1287 OS.GlobalUnlock (hMem);
1290 OS.CloseClipboard ();
1296 * Returns the receiver's cursor, or null if it has not been set.
1298 * When the mouse pointer passes over a control its appearance
1299 * is changed to match the control's cursor.
1302 * @return the receiver's cursor or <code>null</code>
1304 * @exception SWTException <ul>
1305 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1306 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1311 public Cursor getCursor () {
1317 * Returns <code>true</code> if the receiver is detecting
1318 * drag gestures, and <code>false</code> otherwise.
1320 * @return the receiver's drag detect state
1322 * @exception SWTException <ul>
1323 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1324 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1329 public boolean getDragDetect () {
1331 return (state & DRAG_DETECT) != 0;
1334 boolean getDrawing () {
1335 return drawCount <= 0;
1339 * Returns <code>true</code> if the receiver is enabled, and
1340 * <code>false</code> otherwise. A disabled control is typically
1341 * not selectable from the user interface and draws with an
1342 * inactive or "grayed" look.
1344 * @return the receiver's enabled state
1346 * @exception SWTException <ul>
1347 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1348 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1353 public boolean getEnabled () {
1355 return OS.IsWindowEnabled (handle);
1359 * Returns the font that the receiver will use to paint textual information.
1361 * @return the receiver's font
1363 * @exception SWTException <ul>
1364 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1365 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1368 public Font getFont () {
1370 if (font != null) return font;
1371 long hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
1372 if (hFont == 0) hFont = defaultFont ();
1373 return Font.win32_new (display, hFont);
1377 * Returns the foreground color that the receiver will use to draw.
1379 * @return the receiver's foreground color
1381 * @exception SWTException <ul>
1382 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1383 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1386 public Color getForeground () {
1388 return Color.win32_new (display, getForegroundPixel ());
1391 int getForegroundPixel () {
1392 return foreground != -1 ? foreground : defaultForeground ();
1396 * Returns layout data which is associated with the receiver.
1398 * @return the receiver's layout data
1400 * @exception SWTException <ul>
1401 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1402 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1405 public Object getLayoutData () {
1411 * Returns a point describing the receiver's location relative
1412 * to its parent in points (or its display if its parent is null), unless
1413 * the receiver is a shell. In this case, the point is
1414 * relative to the display.
1416 * @return the receiver's location
1418 * @exception SWTException <ul>
1419 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1420 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1423 public Point getLocation () {
1425 return DPIUtil.autoScaleDown(getLocationInPixels());
1428 Point getLocationInPixels () {
1430 RECT rect = new RECT ();
1431 OS.GetWindowRect (topHandle (), rect);
1432 long hwndParent = parent == null ? 0 : parent.handle;
1433 OS.MapWindowPoints (0, hwndParent, rect, 2);
1434 return new Point (rect.left, rect.top);
1438 * Returns the receiver's pop up menu if it has one, or null
1439 * if it does not. All controls may optionally have a pop up
1440 * menu that is displayed when the user requests one for
1441 * the control. The sequence of key strokes, button presses
1442 * and/or button releases that are used to request a pop up
1443 * menu is platform specific.
1445 * @return the receiver's menu
1447 * @exception SWTException <ul>
1448 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1449 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1453 public Menu getMenu () {
1459 * Returns the receiver's monitor.
1461 * @return the receiver's monitor
1463 * @exception SWTException <ul>
1464 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1465 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1470 public Monitor getMonitor () {
1472 long hmonitor = OS.MonitorFromWindow (handle, OS.MONITOR_DEFAULTTONEAREST);
1473 return display.getMonitor (hmonitor);
1477 * Returns the orientation of the receiver, which will be one of the
1478 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
1480 * @return the orientation style
1482 * @exception SWTException <ul>
1483 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1484 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1489 public int getOrientation () {
1491 return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
1495 * Returns the receiver's parent, which must be a <code>Composite</code>
1496 * or null when the receiver is a shell that was created with null or
1497 * a display for a parent.
1499 * @return the receiver's parent
1501 * @exception SWTException <ul>
1502 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1503 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1506 public Composite getParent () {
1511 Control [] getPath () {
1513 Shell shell = getShell ();
1514 Control control = this;
1515 while (control != shell) {
1517 control = control.parent;
1520 Control [] result = new Control [count];
1521 while (control != shell) {
1522 result [--count] = control;
1523 control = control.parent;
1529 * Returns the region that defines the shape of the control,
1530 * or null if the control has the default shape.
1532 * @return the region that defines the shape of the shell (or null)
1534 * @exception SWTException <ul>
1535 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1536 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1541 public Region getRegion () {
1547 * Returns the receiver's shell. For all controls other than
1548 * shells, this simply returns the control's nearest ancestor
1549 * shell. Shells return themselves, even if they are children
1552 * @return the receiver's shell
1554 * @exception SWTException <ul>
1555 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1556 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1561 public Shell getShell () {
1563 return parent.getShell ();
1567 * Returns a point describing the receiver's size in points. The
1568 * x coordinate of the result is the width of the receiver.
1569 * The y coordinate of the result is the height of the
1572 * @return the receiver's size
1574 * @exception SWTException <ul>
1575 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1576 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1579 public Point getSize (){
1581 return DPIUtil.autoScaleDown(getSizeInPixels ());
1584 Point getSizeInPixels () {
1586 RECT rect = new RECT ();
1587 OS.GetWindowRect (topHandle (), rect);
1588 int width = rect.right - rect.left;
1589 int height = rect.bottom - rect.top;
1590 return new Point (width, height);
1594 * Calculates a slightly different color, e.g. for the hot state of a button.
1595 * @param pixel the color to start with
1597 int getSlightlyDifferentColor(int pixel) {
1598 return getDifferentColor(pixel, 0.1);
1602 * Calculates a different color, e.g. for the checked state of a toggle button
1603 * or to highlight a selected button.
1604 * @param pixel the color to start with
1606 int getDifferentColor(int pixel) {
1607 return getDifferentColor(pixel, 0.2);
1611 * @param factor must be between [0..1]. The bounds are not checked
1613 int getDifferentColor(int pixel, double factor) {
1614 int red = pixel & 0xFF;
1615 int green = (pixel & 0xFF00) >> 8;
1616 int blue = (pixel & 0xFF0000) >> 16;
1617 red += calcDiff(red, factor);
1618 green += calcDiff(green, factor);
1619 blue += calcDiff(blue, factor);
1620 return (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
1623 long /* int */ calcDiff(int component, double factor) {
1624 if (component > 127) {
1625 return Math.round(component * -1 * factor);
1627 return Math.round((255 - component) * factor);
1632 * Calculates a slightly different background color, e.g. for highlighting the sort column
1633 * in a table or tree. This method produces less contrast that {@link #getSlightlyDifferentColor(int)}.
1634 * @param pixel the color to start with
1636 int getSlightlyDifferentBackgroundColor(int pixel) {
1638 int red = pixel & 0xFF;
1639 int green = (pixel & 0xFF00) >> 8;
1640 int blue = (pixel & 0xFF0000) >> 16;
1641 red = red > 127 ? red-offset : red+offset;
1642 green = green > 127 ? green-offset : green+offset;
1643 blue = blue > 127 ? blue-offset : blue+offset;
1644 return (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
1648 * Returns the text direction of the receiver, which will be one of the
1649 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
1651 * @return the text direction style
1653 * @exception SWTException <ul>
1654 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1655 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1660 public int getTextDirection() {
1662 int flags = OS.WS_EX_LAYOUTRTL | OS.WS_EX_RTLREADING;
1663 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE) & flags;
1664 return bits == 0 || bits == flags ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
1668 * Returns the receiver's tool tip text, or null if it has
1671 * @return the receiver's tool tip text
1673 * @exception SWTException <ul>
1674 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1675 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1678 public String getToolTipText () {
1684 * Returns <code>true</code> if this control is set to send touch events, or
1685 * <code>false</code> if it is set to send gesture events instead. This method
1686 * also returns <code>false</code> if a touch-based input device is not detected
1687 * (this can be determined with <code>Display#getTouchEnabled()</code>). Use
1688 * {@link #setTouchEnabled(boolean)} to switch the events that a control sends
1689 * between touch events and gesture events.
1691 * @return <code>true</code> if the control is set to send touch events, or <code>false</code> otherwise
1693 * @exception SWTException <ul>
1694 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1695 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1698 * @see #setTouchEnabled
1699 * @see Display#getTouchEnabled
1703 public boolean getTouchEnabled () {
1705 return OS.IsTouchWindow (handle, null);
1709 * Returns <code>true</code> if the receiver is visible, and
1710 * <code>false</code> otherwise.
1712 * If one of the receiver's ancestors is not visible or some
1713 * other condition makes the receiver not visible, this method
1714 * may still indicate that it is considered visible even though
1715 * it may not actually be showing.
1718 * @return the receiver's visibility state
1720 * @exception SWTException <ul>
1721 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1722 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1725 public boolean getVisible () {
1727 if (!getDrawing()) return (state & HIDDEN) == 0;
1728 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1729 return (bits & OS.WS_VISIBLE) != 0;
1732 boolean hasCursor () {
1733 RECT rect = new RECT ();
1734 if (!OS.GetClientRect (handle, rect)) return false;
1735 OS.MapWindowPoints (handle, 0, rect, 2);
1736 POINT pt = new POINT ();
1737 return OS.GetCursorPos (pt) && OS.PtInRect (rect, pt);
1740 boolean hasCustomBackground() {
1741 return background != -1;
1744 boolean hasCustomForeground() {
1745 return foreground != -1;
1748 boolean hasFocus () {
1750 * If a non-SWT child of the control has focus,
1751 * then this control is considered to have focus
1752 * even though it does not have focus in Windows.
1754 long hwndFocus = OS.GetFocus ();
1755 while (hwndFocus != 0) {
1756 if (hwndFocus == handle) return true;
1757 if (display.getControl (hwndFocus) != null) {
1760 hwndFocus = OS.GetParent (hwndFocus);
1766 * Invokes platform specific functionality to allocate a new GC handle.
1768 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1769 * API for <code>Control</code>. It is marked public only so that it
1770 * can be shared within the packages provided by SWT. It is not
1771 * available on all platforms, and should never be called from
1775 * @param data the platform specific GC data
1776 * @return the platform specific GC handle
1778 * @noreference This method is not intended to be referenced by clients.
1781 public long internal_new_GC (GCData data) {
1784 if (data != null && data.hwnd != 0) hwnd = data.hwnd;
1785 if (data != null) data.hwnd = hwnd;
1787 if (data == null || data.ps == null) {
1788 hDC = OS.GetDC (hwnd);
1790 hDC = OS.BeginPaint (hwnd, data.ps);
1792 if (hDC == 0) error(SWT.ERROR_NO_HANDLES);
1794 int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
1795 if ((data.style & mask) != 0) {
1796 data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0;
1798 int flags = OS.GetLayout (hDC);
1799 if ((flags & OS.LAYOUT_RTL) != 0) {
1800 data.style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
1802 data.style |= SWT.LEFT_TO_RIGHT;
1805 data.device = display;
1806 int foreground = getForegroundPixel ();
1807 if (foreground != OS.GetTextColor (hDC)) data.foreground = foreground;
1808 Control control = findBackgroundControl ();
1809 if (control == null) control = this;
1810 int background = control.getBackgroundPixel ();
1811 if (background != OS.GetBkColor (hDC)) data.background = background;
1812 data.font = font != null ? font : Font.win32_new (display, OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0));
1813 data.uiState = (int)OS.SendMessage (hwnd, OS.WM_QUERYUISTATE, 0, 0);
1819 * Invokes platform specific functionality to dispose a GC handle.
1821 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1822 * API for <code>Control</code>. It is marked public only so that it
1823 * can be shared within the packages provided by SWT. It is not
1824 * available on all platforms, and should never be called from
1828 * @param hDC the platform specific GC handle
1829 * @param data the platform specific GC data
1831 * @noreference This method is not intended to be referenced by clients.
1834 public void internal_dispose_GC (long hDC, GCData data) {
1837 if (data != null && data.hwnd != 0) {
1840 if (data == null || data.ps == null) {
1841 OS.ReleaseDC (hwnd, hDC);
1843 OS.EndPaint (hwnd, data.ps);
1847 boolean isActive () {
1848 Dialog dialog = display.getModalDialog ();
1849 if (dialog != null) {
1850 Shell dialogShell = dialog.parent;
1851 if (dialogShell != null && !dialogShell.isDisposed ()) {
1852 if (dialogShell != getShell ()) return false;
1856 Shell [] modalShells = display.modalShells;
1857 if (modalShells != null) {
1858 int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
1859 int index = modalShells.length;
1860 while (--index >= 0) {
1861 Shell modal = modalShells [index];
1862 if (modal != null) {
1863 if ((modal.style & bits) != 0) {
1864 Control control = this;
1865 while (control != null) {
1866 if (control == modal) break;
1867 control = control.parent;
1869 if (control != modal) return false;
1872 if ((modal.style & SWT.PRIMARY_MODAL) != 0) {
1873 if (shell == null) shell = getShell ();
1874 if (modal.parent == shell) return false;
1879 if (shell == null) shell = getShell ();
1880 return shell.getEnabled ();
1884 * Returns <code>true</code> if the receiver is enabled and all
1885 * ancestors up to and including the receiver's nearest ancestor
1886 * shell are enabled. Otherwise, <code>false</code> is returned.
1887 * A disabled control is typically not selectable from the user
1888 * interface and draws with an inactive or "grayed" look.
1890 * @return the receiver's enabled state
1892 * @exception SWTException <ul>
1893 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1894 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1899 public boolean isEnabled () {
1901 return getEnabled () && parent.isEnabled ();
1905 * Returns <code>true</code> if the receiver has the user-interface
1906 * focus, and <code>false</code> otherwise.
1908 * @return the receiver's focus state
1910 * @exception SWTException <ul>
1911 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1912 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1915 public boolean isFocusControl () {
1917 Control focusControl = display.focusControl;
1918 if (focusControl != null && !focusControl.isDisposed ()) {
1919 return this == focusControl;
1924 boolean isFocusAncestor (Control control) {
1925 while (control != null && control != this && !(control instanceof Shell)) {
1926 control = control.parent;
1928 return control == this;
1932 * Returns <code>true</code> if the underlying operating
1933 * system supports this reparenting, otherwise <code>false</code>
1935 * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code>
1937 * @exception SWTException <ul>
1938 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1939 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1942 public boolean isReparentable () {
1947 boolean isShowing () {
1949 * This is not complete. Need to check if the
1950 * widget is obscured by a parent or sibling.
1952 if (!isVisible ()) return false;
1953 Control control = this;
1954 while (control != null) {
1955 Point size = control.getSizeInPixels ();
1956 if (size.x == 0 || size.y == 0) {
1959 control = control.parent;
1963 * Check to see if current damage is included.
1965 // if (!OS.IsWindowVisible (handle)) return false;
1966 // int flags = OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS;
1967 // long hDC = OS.GetDCEx (handle, 0, flags);
1968 // int result = OS.GetClipBox (hDC, new RECT ());
1969 // OS.ReleaseDC (handle, hDC);
1970 // return result != OS.NULLREGION;
1973 boolean isTabGroup () {
1974 Control [] tabList = parent._getTabList ();
1975 if (tabList != null) {
1976 for (int i=0; i<tabList.length; i++) {
1977 if (tabList [i] == this) return true;
1980 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1981 return (bits & OS.WS_TABSTOP) != 0;
1984 boolean isTabItem () {
1985 Control [] tabList = parent._getTabList ();
1986 if (tabList != null) {
1987 for (int i=0; i<tabList.length; i++) {
1988 if (tabList [i] == this) return false;
1991 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1992 if ((bits & OS.WS_TABSTOP) != 0) return false;
1993 long code = OS.SendMessage (handle, OS.WM_GETDLGCODE, 0, 0);
1994 if ((code & OS.DLGC_STATIC) != 0) return false;
1995 if ((code & OS.DLGC_WANTALLKEYS) != 0) return false;
1996 if ((code & OS.DLGC_WANTARROWS) != 0) return false;
1997 if ((code & OS.DLGC_WANTTAB) != 0) return false;
2002 * Returns <code>true</code> if the receiver is visible and all
2003 * ancestors up to and including the receiver's nearest ancestor
2004 * shell are visible. Otherwise, <code>false</code> is returned.
2006 * @return the receiver's visibility state
2008 * @exception SWTException <ul>
2009 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2010 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2015 public boolean isVisible () {
2017 if (OS.IsWindowVisible (handle)) return true;
2018 return getVisible () && parent.isVisible ();
2022 void mapEvent (long hwnd, Event event) {
2023 if (hwnd != handle) {
2024 POINT point = new POINT ();
2025 Point loc = event.getLocationInPixels();
2028 OS.MapWindowPoints (hwnd, handle, point, 1);
2029 event.setLocationInPixels(point.x, point.y);
2033 void markLayout (boolean changed, boolean all) {
2037 Decorations menuShell () {
2038 return parent.menuShell ();
2041 boolean mnemonicHit (char key) {
2045 boolean mnemonicMatch (char key) {
2050 * Moves the receiver above the specified control in the
2051 * drawing order. If the argument is null, then the receiver
2052 * is moved to the top of the drawing order. The control at
2053 * the top of the drawing order will not be covered by other
2054 * controls even if they occupy intersecting areas.
2056 * @param control the sibling control (or null)
2058 * @exception IllegalArgumentException <ul>
2059 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
2061 * @exception SWTException <ul>
2062 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2063 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2066 * @see Control#moveBelow
2067 * @see Composite#getChildren
2069 public void moveAbove (Control control) {
2071 long topHandle = topHandle (), hwndAbove = OS.HWND_TOP;
2072 if (control != null) {
2073 if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
2074 if (parent != control.parent) return;
2075 long hwnd = control.topHandle ();
2076 if (hwnd == 0 || hwnd == topHandle) return;
2077 hwndAbove = OS.GetWindow (hwnd, OS.GW_HWNDPREV);
2079 * Bug in Windows. For some reason, when GetWindow ()
2080 * with GW_HWNDPREV is used to query the previous window
2081 * in the z-order with the first child, Windows returns
2082 * the first child instead of NULL. The fix is to detect
2083 * this case and move the control to the top.
2085 if (hwndAbove == 0 || hwndAbove == hwnd) {
2086 hwndAbove = OS.HWND_TOP;
2089 int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
2090 OS.SetWindowPos (topHandle, hwndAbove, 0, 0, 0, 0, flags);
2094 * Moves the receiver below the specified control in the
2095 * drawing order. If the argument is null, then the receiver
2096 * is moved to the bottom of the drawing order. The control at
2097 * the bottom of the drawing order will be covered by all other
2098 * controls which occupy intersecting areas.
2100 * @param control the sibling control (or null)
2102 * @exception IllegalArgumentException <ul>
2103 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
2105 * @exception SWTException <ul>
2106 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2107 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2110 * @see Control#moveAbove
2111 * @see Composite#getChildren
2113 public void moveBelow (Control control) {
2115 long topHandle = topHandle (), hwndAbove = OS.HWND_BOTTOM;
2116 if (control != null) {
2117 if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
2118 if (parent != control.parent) return;
2119 hwndAbove = control.topHandle ();
2122 * Bug in Windows. When SetWindowPos() is called
2123 * with HWND_BOTTOM on a dialog shell, the dialog
2124 * and the parent are moved to the bottom of the
2125 * desktop stack. The fix is to move the dialog
2126 * to the bottom of the dialog window stack by
2127 * moving behind the first dialog child.
2129 Shell shell = getShell ();
2130 if (this == shell && parent != null) {
2132 * Bug in Windows. For some reason, when GetWindow ()
2133 * with GW_HWNDPREV is used to query the previous window
2134 * in the z-order with the first child, Windows returns
2135 * the first child instead of NULL. The fix is to detect
2136 * this case and do nothing because the control is already
2139 long hwndParent = parent.handle, hwnd = hwndParent;
2140 hwndAbove = OS.GetWindow (hwnd, OS.GW_HWNDPREV);
2141 while (hwndAbove != 0 && hwndAbove != hwnd) {
2142 if (OS.GetWindow (hwndAbove, OS.GW_OWNER) == hwndParent) break;
2143 hwndAbove = OS.GetWindow (hwnd = hwndAbove, OS.GW_HWNDPREV);
2145 if (hwndAbove == hwnd) return;
2148 if (hwndAbove == 0 || hwndAbove == topHandle) return;
2149 int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
2150 OS.SetWindowPos (topHandle, hwndAbove, 0, 0, 0, 0, flags);
2153 Accessible new_Accessible (Control control) {
2154 return Accessible.internal_new_Accessible (this);
2158 GC new_GC (GCData data) {
2159 return GC.win32_new (this, data);
2163 * Causes the receiver to be resized to its preferred size.
2164 * For a composite, this involves computing the preferred size
2165 * from its layout, if there is one.
2167 * @exception SWTException <ul>
2168 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2169 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2172 * @see #computeSize(int, int, boolean)
2174 public void pack () {
2180 * Causes the receiver to be resized to its preferred size.
2181 * For a composite, this involves computing the preferred size
2182 * from its layout, if there is one.
2184 * If the changed flag is <code>true</code>, it indicates that the receiver's
2185 * <em>contents</em> have changed, therefore any caches that a layout manager
2186 * containing the control may have been keeping need to be flushed. When the
2187 * control is resized, the changed flag will be <code>false</code>, so layout
2188 * manager caches can be retained.
2191 * @param changed whether or not the receiver's contents have changed
2193 * @exception SWTException <ul>
2194 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2195 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2198 * @see #computeSize(int, int, boolean)
2200 public void pack (boolean changed) {
2203 * Since computeSize is overridden by Custom classes like CCombo
2204 * etc... hence we cannot call computeSizeInPixels directly.
2206 setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed));
2210 * Prints the receiver and all children.
2212 * @param gc the gc where the drawing occurs
2213 * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
2215 * @exception IllegalArgumentException <ul>
2216 * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
2217 * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
2219 * @exception SWTException <ul>
2220 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2221 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2226 public boolean print (GC gc) {
2228 if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
2229 if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
2230 long topHandle = topHandle ();
2231 long hdc = gc.handle;
2233 long gdipGraphics = gc.getGCData().gdipGraphics;
2234 if (gdipGraphics != 0) {
2236 Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
2237 long rgn = Gdip.Region_new();
2238 if (rgn == 0) error(SWT.ERROR_NO_HANDLES);
2239 Gdip.Graphics_GetClip(gdipGraphics, rgn);
2240 if (!Gdip.Region_IsInfinite(rgn, gdipGraphics)) {
2241 clipRgn = Gdip.Region_GetHRGN(rgn, gdipGraphics);
2243 Gdip.Region_delete(rgn);
2244 Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
2245 float[] lpXform = null;
2246 long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
2247 if (matrix == 0) error(SWT.ERROR_NO_HANDLES);
2248 Gdip.Graphics_GetTransform(gdipGraphics, matrix);
2249 if (!Gdip.Matrix_IsIdentity(matrix)) {
2250 lpXform = new float[6];
2251 Gdip.Matrix_GetElements(matrix, lpXform);
2253 Gdip.Matrix_delete(matrix);
2254 hdc = Gdip.Graphics_GetHDC(gdipGraphics);
2255 state = OS.SaveDC(hdc);
2256 if (lpXform != null) {
2257 OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
2258 OS.SetWorldTransform(hdc, lpXform);
2261 OS.SelectClipRgn(hdc, clipRgn);
2262 OS.DeleteObject(clipRgn);
2265 int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
2266 OS.RedrawWindow (topHandle, null, 0, flags);
2267 printWidget (topHandle, hdc, gc);
2268 if (gdipGraphics != 0) {
2269 OS.RestoreDC(hdc, state);
2270 Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
2275 void printWidget (long hwnd, long hdc, GC gc) {
2277 * Bug in Windows. For some reason, PrintWindow()
2278 * returns success but does nothing when it is called
2279 * on a printer. The fix is to just go directly to
2280 * WM_PRINT in this case.
2282 boolean success = false;
2283 if (!(OS.GetDeviceCaps(gc.handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER)) {
2285 * Bug in Windows. When PrintWindow() will only draw that
2286 * portion of a control that is not obscured by the shell.
2287 * The fix is temporarily reparent the window to the desktop,
2288 * call PrintWindow() then reparent the window back.
2290 long hwndParent = OS.GetParent (hwnd);
2291 long hwndShell = hwndParent;
2292 while (OS.GetParent (hwndShell) != 0) {
2293 if (OS.GetWindow (hwndShell, OS.GW_OWNER) != 0) break;
2294 hwndShell = OS.GetParent (hwndShell);
2296 RECT rect1 = new RECT ();
2297 OS.GetWindowRect (hwnd, rect1);
2298 boolean fixPrintWindow = !OS.IsWindowVisible(hwnd);
2299 if (!fixPrintWindow) {
2300 RECT rect2 = new RECT ();
2301 OS.GetWindowRect (hwndShell, rect2);
2302 OS.IntersectRect (rect2, rect1, rect2);
2303 fixPrintWindow = !OS.EqualRect (rect2, rect1);
2306 * Bug in Windows. PrintWindow() does not print portions
2307 * of the receiver that are clipped out using SetWindowRgn()
2308 * in a parent. The fix is temporarily reparent the window
2309 * to the desktop, call PrintWindow() then reparent the window
2312 if (!fixPrintWindow) {
2313 long rgn = OS.CreateRectRgn(0, 0, 0, 0);
2314 long parent = OS.GetParent(hwnd);
2315 while (parent != hwndShell && !fixPrintWindow) {
2316 if (OS.GetWindowRgn(parent, rgn) != 0) {
2317 fixPrintWindow = true;
2319 parent = OS.GetParent(parent);
2321 OS.DeleteObject(rgn);
2323 int bits1 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
2324 int bits2 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
2325 long hwndInsertAfter = OS.GetWindow (hwnd, OS.GW_HWNDPREV);
2327 * Bug in Windows. For some reason, when GetWindow ()
2328 * with GW_HWNDPREV is used to query the previous window
2329 * in the z-order with the first child, Windows returns
2330 * the first child instead of NULL. The fix is to detect
2331 * this case and move the control to the top.
2333 if (hwndInsertAfter == 0 || hwndInsertAfter == hwnd) {
2334 hwndInsertAfter = OS.HWND_TOP;
2336 if (fixPrintWindow) {
2337 int x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
2338 int y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
2339 int width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
2340 int height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
2341 int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE | OS.SWP_DRAWFRAME;
2342 if ((bits1 & OS.WS_VISIBLE) != 0) {
2343 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 0, 0);
2345 OS.SetWindowPos (hwnd, 0, x + width, y + height, 0, 0, flags);
2346 OS.SetWindowLong (hwnd, OS.GWL_STYLE, (bits1 & ~OS.WS_CHILD) | OS.WS_POPUP);
2347 OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits2 | OS.WS_EX_TOOLWINDOW);
2348 Shell shell = getShell ();
2349 Control savedFocus = shell.savedFocus;
2350 OS.SetParent (hwnd, 0);
2351 shell.setSavedFocus (savedFocus);
2352 if ((bits1 & OS.WS_VISIBLE) != 0) {
2353 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 1, 0);
2356 if ((bits1 & OS.WS_VISIBLE) == 0) {
2357 OS.ShowWindow (hwnd, OS.SW_SHOW);
2359 success = OS.PrintWindow (hwnd, hdc, 0);
2360 if ((bits1 & OS.WS_VISIBLE) == 0) {
2361 OS.ShowWindow (hwnd, OS.SW_HIDE);
2363 if (fixPrintWindow) {
2364 if ((bits1 & OS.WS_VISIBLE) != 0) {
2365 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 0, 0);
2367 OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits1);
2368 OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits2);
2369 OS.SetParent (hwnd, hwndParent);
2370 OS.MapWindowPoints (0, hwndParent, rect1, 2);
2371 int flags = OS.SWP_NOSIZE | OS.SWP_NOACTIVATE | OS.SWP_DRAWFRAME;
2372 OS.SetWindowPos (hwnd, hwndInsertAfter, rect1.left, rect1.top, rect1.right - rect1.left, rect1.bottom - rect1.top, flags);
2373 if ((bits1 & OS.WS_VISIBLE) != 0) {
2374 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 1, 0);
2380 * Bug in Windows. For some reason, PrintWindow() fails
2381 * when it is called on a push button. The fix is to
2382 * detect the failure and use WM_PRINT instead. Note
2383 * that WM_PRINT cannot be used all the time because it
2384 * fails for browser controls when the browser has focus.
2387 int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND | OS.PRF_CHILDREN;
2388 OS.SendMessage (hwnd, OS.WM_PRINT, hdc, flags);
2393 * Requests that this control and all of its ancestors be repositioned by
2394 * their layouts at the earliest opportunity. This should be invoked after
2395 * modifying the control in order to inform any dependent layouts of
2398 * The control will not be repositioned synchronously. This method is
2399 * fast-running and only marks the control for future participation in
2400 * a deferred layout.
2402 * Invoking this method multiple times before the layout occurs is an
2403 * inexpensive no-op.
2407 public void requestLayout () {
2408 getShell ().layout (new Control[] {this}, SWT.DEFER);
2412 * Causes the entire bounds of the receiver to be marked
2413 * as needing to be redrawn. The next time a paint request
2414 * is processed, the control will be completely painted,
2415 * including the background.
2417 * Schedules a paint request if the invalidated area is visible
2418 * or becomes visible later. It is not necessary for the caller
2419 * to explicitly call {@link #update()} after calling this method,
2420 * but depending on the platform, the automatic repaints may be
2421 * delayed considerably.
2424 * @exception SWTException <ul>
2425 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2426 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2430 * @see PaintListener
2432 * @see SWT#NO_BACKGROUND
2433 * @see SWT#NO_REDRAW_RESIZE
2434 * @see SWT#NO_MERGE_PAINTS
2435 * @see SWT#DOUBLE_BUFFERED
2437 public void redraw () {
2442 void redraw (boolean all) {
2444 if (!OS.IsWindowVisible (handle)) return;
2445 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
2446 if (all) flags |= OS.RDW_ALLCHILDREN;
2447 OS.RedrawWindow (handle, null, 0, flags);
2450 * Causes the rectangular area of the receiver specified by
2451 * the arguments to be marked as needing to be redrawn.
2452 * The next time a paint request is processed, that area of
2453 * the receiver will be painted, including the background.
2454 * If the <code>all</code> flag is <code>true</code>, any
2455 * children of the receiver which intersect with the specified
2456 * area will also paint their intersecting areas. If the
2457 * <code>all</code> flag is <code>false</code>, the children
2458 * will not be painted.
2460 * Schedules a paint request if the invalidated area is visible
2461 * or becomes visible later. It is not necessary for the caller
2462 * to explicitly call {@link #update()} after calling this method,
2463 * but depending on the platform, the automatic repaints may be
2464 * delayed considerably.
2467 * @param x the x coordinate of the area to draw
2468 * @param y the y coordinate of the area to draw
2469 * @param width the width of the area to draw
2470 * @param height the height of the area to draw
2471 * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
2473 * @exception SWTException <ul>
2474 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2475 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2479 * @see PaintListener
2481 * @see SWT#NO_BACKGROUND
2482 * @see SWT#NO_REDRAW_RESIZE
2483 * @see SWT#NO_MERGE_PAINTS
2484 * @see SWT#DOUBLE_BUFFERED
2486 public void redraw (int x, int y, int width, int height, boolean all) {
2488 x = DPIUtil.autoScaleUp(x);
2489 y = DPIUtil.autoScaleUp(y);
2490 width = DPIUtil.autoScaleUp(width);
2491 height = DPIUtil.autoScaleUp(height);
2492 redrawInPixels(x, y, width, height, all);
2495 void redrawInPixels (int x, int y, int width, int height, boolean all) {
2496 if (width <= 0 || height <= 0) return;
2497 if (!OS.IsWindowVisible (handle)) return;
2498 RECT rect = new RECT ();
2499 OS.SetRect (rect, x, y, x + width, y + height);
2500 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
2501 if (all) flags |= OS.RDW_ALLCHILDREN;
2502 OS.RedrawWindow (handle, rect, 0, flags);
2505 boolean redrawChildren () {
2506 if (!OS.IsWindowVisible (handle)) return false;
2507 Control control = findBackgroundControl ();
2508 if (control == null) {
2509 if ((state & THEME_BACKGROUND) != 0) {
2510 if (OS.IsAppThemed ()) {
2511 OS.InvalidateRect (handle, null, true);
2516 if (control.backgroundImage != null) {
2517 OS.InvalidateRect (handle, null, true);
2525 display.addControl (handle, this);
2529 void releaseHandle () {
2530 super.releaseHandle ();
2536 void releaseParent () {
2537 parent.removeControl (this);
2541 void releaseWidget () {
2542 super.releaseWidget ();
2543 if (OS.IsDBLocale) {
2544 OS.ImmAssociateContext (handle, 0);
2546 if (toolTipText != null) {
2547 setToolTipText (getShell (), null);
2550 if (menu != null && !menu.isDisposed ()) {
2553 backgroundImage = null;
2559 if (accessible != null) {
2560 accessible.internal_dispose_Accessible ();
2568 * Removes the listener from the collection of listeners who will
2569 * be notified when the control is moved or resized.
2571 * @param listener the listener which should no longer be notified
2573 * @exception IllegalArgumentException <ul>
2574 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2576 * @exception SWTException <ul>
2577 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2578 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2581 * @see ControlListener
2582 * @see #addControlListener
2584 public void removeControlListener (ControlListener listener) {
2586 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2587 if (eventTable == null) return;
2588 eventTable.unhook (SWT.Move, listener);
2589 eventTable.unhook (SWT.Resize, listener);
2593 * Removes the listener from the collection of listeners who will
2594 * be notified when a drag gesture occurs.
2596 * @param listener the listener which should no longer be notified
2598 * @exception IllegalArgumentException <ul>
2599 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2601 * @exception SWTException <ul>
2602 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2603 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2606 * @see DragDetectListener
2607 * @see #addDragDetectListener
2611 public void removeDragDetectListener(DragDetectListener listener) {
2613 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2614 if (eventTable == null) return;
2615 eventTable.unhook (SWT.DragDetect, listener);
2619 * Removes the listener from the collection of listeners who will
2620 * be notified when the control gains or loses focus.
2622 * @param listener the listener which should no longer be notified
2624 * @exception IllegalArgumentException <ul>
2625 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2627 * @exception SWTException <ul>
2628 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2629 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2632 * @see FocusListener
2633 * @see #addFocusListener
2635 public void removeFocusListener(FocusListener listener) {
2637 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2638 if (eventTable == null) return;
2639 eventTable.unhook (SWT.FocusIn, listener);
2640 eventTable.unhook (SWT.FocusOut, listener);
2644 * Removes the listener from the collection of listeners who will
2645 * be notified when gesture events are generated for the control.
2647 * @param listener the listener which should no longer be notified
2649 * @exception IllegalArgumentException <ul>
2650 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2652 * @exception SWTException <ul>
2653 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2654 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2657 * @see GestureListener
2658 * @see #addGestureListener
2662 public void removeGestureListener (GestureListener listener) {
2664 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2665 if (eventTable == null) return;
2666 eventTable.unhook (SWT.Gesture, listener);
2670 * Removes the listener from the collection of listeners who will
2671 * be notified when the help events are generated for the control.
2673 * @param listener the listener which should no longer be notified
2675 * @exception IllegalArgumentException <ul>
2676 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2678 * @exception SWTException <ul>
2679 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2680 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2684 * @see #addHelpListener
2686 public void removeHelpListener (HelpListener listener) {
2688 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2689 if (eventTable == null) return;
2690 eventTable.unhook (SWT.Help, listener);
2694 * Removes the listener from the collection of listeners who will
2695 * be notified when keys are pressed and released on the system keyboard.
2697 * @param listener the listener which should no longer be notified
2699 * @exception IllegalArgumentException <ul>
2700 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2702 * @exception SWTException <ul>
2703 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2704 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2708 * @see #addKeyListener
2710 public void removeKeyListener(KeyListener listener) {
2712 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2713 if (eventTable == null) return;
2714 eventTable.unhook (SWT.KeyUp, listener);
2715 eventTable.unhook (SWT.KeyDown, listener);
2719 * Removes the listener from the collection of listeners who will
2720 * be notified when the platform-specific context menu trigger has
2723 * @param listener the listener which should no longer be notified
2725 * @exception IllegalArgumentException <ul>
2726 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2728 * @exception SWTException <ul>
2729 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2730 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2733 * @see MenuDetectListener
2734 * @see #addMenuDetectListener
2738 public void removeMenuDetectListener (MenuDetectListener listener) {
2740 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2741 if (eventTable == null) return;
2742 eventTable.unhook (SWT.MenuDetect, listener);
2746 * Removes the listener from the collection of listeners who will
2747 * be notified when the mouse passes or hovers over controls.
2749 * @param listener the listener which should no longer be notified
2751 * @exception IllegalArgumentException <ul>
2752 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2754 * @exception SWTException <ul>
2755 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2756 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2759 * @see MouseTrackListener
2760 * @see #addMouseTrackListener
2762 public void removeMouseTrackListener(MouseTrackListener listener) {
2764 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2765 if (eventTable == null) return;
2766 eventTable.unhook (SWT.MouseEnter, listener);
2767 eventTable.unhook (SWT.MouseExit, listener);
2768 eventTable.unhook (SWT.MouseHover, listener);
2772 * Removes the listener from the collection of listeners who will
2773 * be notified when mouse buttons are pressed and released.
2775 * @param listener the listener which should no longer be notified
2777 * @exception IllegalArgumentException <ul>
2778 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2780 * @exception SWTException <ul>
2781 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2782 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2785 * @see MouseListener
2786 * @see #addMouseListener
2788 public void removeMouseListener (MouseListener listener) {
2790 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2791 if (eventTable == null) return;
2792 eventTable.unhook (SWT.MouseDown, listener);
2793 eventTable.unhook (SWT.MouseUp, listener);
2794 eventTable.unhook (SWT.MouseDoubleClick, listener);
2798 * Removes the listener from the collection of listeners who will
2799 * be notified when the mouse moves.
2801 * @param listener the listener which should no longer be notified
2803 * @exception IllegalArgumentException <ul>
2804 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2806 * @exception SWTException <ul>
2807 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2808 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2811 * @see MouseMoveListener
2812 * @see #addMouseMoveListener
2814 public void removeMouseMoveListener(MouseMoveListener listener) {
2816 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2817 if (eventTable == null) return;
2818 eventTable.unhook (SWT.MouseMove, listener);
2822 * Removes the listener from the collection of listeners who will
2823 * be notified when the mouse wheel is scrolled.
2825 * @param listener the listener which should no longer be notified
2827 * @exception IllegalArgumentException <ul>
2828 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2830 * @exception SWTException <ul>
2831 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2832 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2835 * @see MouseWheelListener
2836 * @see #addMouseWheelListener
2840 public void removeMouseWheelListener (MouseWheelListener listener) {
2842 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2843 if (eventTable == null) return;
2844 eventTable.unhook (SWT.MouseWheel, listener);
2848 * Removes the listener from the collection of listeners who will
2849 * be notified when the receiver needs to be painted.
2851 * @param listener the listener which should no longer be notified
2853 * @exception IllegalArgumentException <ul>
2854 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2856 * @exception SWTException <ul>
2857 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2858 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2861 * @see PaintListener
2862 * @see #addPaintListener
2864 public void removePaintListener(PaintListener listener) {
2866 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2867 if (eventTable == null) return;
2868 eventTable.unhook(SWT.Paint, listener);
2872 * Removes the listener from the collection of listeners who will
2873 * be notified when touch events occur.
2875 * @param listener the listener which should no longer be notified
2877 * @exception IllegalArgumentException <ul>
2878 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2880 * @exception SWTException <ul>
2881 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2882 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2885 * @see TouchListener
2886 * @see #addTouchListener
2890 public void removeTouchListener(TouchListener listener) {
2892 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2893 if (eventTable == null) return;
2894 eventTable.unhook (SWT.Touch, listener);
2898 * Removes the listener from the collection of listeners who will
2899 * be notified when traversal events occur.
2901 * @param listener the listener which should no longer be notified
2903 * @exception IllegalArgumentException <ul>
2904 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2906 * @exception SWTException <ul>
2907 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2908 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2911 * @see TraverseListener
2912 * @see #addTraverseListener
2914 public void removeTraverseListener(TraverseListener listener) {
2916 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2917 if (eventTable == null) return;
2918 eventTable.unhook (SWT.Traverse, listener);
2921 int resolveTextDirection() {
2923 * For generic Controls do nothing here. Text-enabled Controls will resolve
2924 * AUTO text direction according to their text content.
2929 void showWidget (boolean visible) {
2930 long topHandle = topHandle ();
2931 OS.ShowWindow (topHandle, visible ? OS.SW_SHOW : OS.SW_HIDE);
2932 if (handle != topHandle) OS.ShowWindow (handle, visible ? OS.SW_SHOW : OS.SW_HIDE);
2936 boolean sendFocusEvent (int type) {
2937 Shell shell = getShell ();
2940 * Feature in Windows. During the processing of WM_KILLFOCUS,
2941 * when the focus window is queried using GetFocus(), it has
2942 * already been assigned to the new window. The fix is to
2943 * remember the control that is losing or gaining focus and
2944 * answer it during WM_KILLFOCUS. If a WM_SETFOCUS occurs
2945 * during WM_KILLFOCUS, the focus control needs to be updated
2946 * to the current control. At any other time, the focus
2947 * control matches Windows.
2949 Display display = this.display;
2950 display.focusEvent = type;
2951 display.focusControl = this;
2953 // widget could be disposed at this point
2954 display.focusEvent = SWT.None;
2955 display.focusControl = null;
2958 * It is possible that the shell may be
2959 * disposed at this point. If this happens
2960 * don't send the activate and deactivate
2963 if (!shell.isDisposed ()) {
2966 shell.setActiveControl (this);
2969 if (shell != display.getActiveShell ()) {
2970 shell.setActiveControl (null);
2978 boolean sendGestureEvent (GESTUREINFO gi) {
2980 * Feature in Windows 7. GID_BEGIN and GID_END events bubble up through the window
2981 * hierarchy for legacy support. Ignore events not targeted for this control.
2983 if (gi.hwndTarget != handle) return true;
2984 Event event = new Event ();
2986 Point globalPt = new Point(gi.x, gi.y);
2987 Point point = toControlInPixels(globalPt.x, globalPt.y);
2988 event.setLocationInPixels(point.x, point.y);
2992 event.detail = SWT.GESTURE_MAGNIFY;
2993 int fingerDistance = OS.LODWORD (gi.ullArguments);
2994 if ((gi.dwFlags & OS.GF_BEGIN) != 0) {
2995 event.detail = SWT.GESTURE_BEGIN;
2996 display.magStartDistance = display.lastDistance = fingerDistance;
2997 } else if ((gi.dwFlags & OS.GF_END) != 0) {
2998 event.detail = SWT.GESTURE_END;
3002 * The gi.ullArguments is the distance between the fingers.
3003 * Scale factor is relative to that original value.
3005 if (fingerDistance == display.lastDistance && event.detail == SWT.GESTURE_MAGNIFY) return true;
3006 if (fingerDistance != 0) event.magnification = fingerDistance / display.magStartDistance;
3007 display.lastDistance = fingerDistance;
3011 event.detail = SWT.GESTURE_PAN;
3012 if ((gi.dwFlags & OS.GF_BEGIN) != 0) {
3013 event.detail = SWT.GESTURE_BEGIN;
3014 display.lastX = point.x;
3015 display.lastY = point.y;
3016 } else if ((gi.dwFlags & OS.GF_END) != 0) {
3017 event.detail = SWT.GESTURE_END;
3019 if (display.lastX == point.x && display.lastY == point.y && event.detail == SWT.GESTURE_PAN) return true;
3020 event.xDirection = point.x - display.lastX;
3021 event.yDirection = point.y - display.lastY;
3022 display.lastX = point.x;
3023 display.lastY = point.y;
3027 event.detail = SWT.GESTURE_ROTATE;
3028 double rotationInRadians = OS.GID_ROTATE_ANGLE_FROM_ARGUMENT (OS.LODWORD (gi.ullArguments));
3029 if ((gi.dwFlags & OS.GF_BEGIN) != 0) {
3030 event.detail = SWT.GESTURE_BEGIN;
3031 display.rotationAngle = rotationInRadians;
3032 } else if ((gi.dwFlags & OS.GF_END) != 0) {
3033 event.detail = SWT.GESTURE_END;
3037 * Feature in Win32. Rotation events are sent even when the fingers are at rest.
3038 * If the current rotation is the same as the last one received don't send the event.
3040 if (display.rotationAngle == rotationInRadians && event.detail == SWT.GESTURE_ROTATE) return true;
3041 event.rotation = rotationInRadians * 180.0 / Math.PI;
3042 display.rotationAngle = rotationInRadians;
3045 // Unknown gesture -- ignore.
3049 if (type == 0) return true;
3050 setInputState (event, type);
3051 sendEvent (type, event);
3056 sendEvent (SWT.Move);
3059 void sendResize () {
3060 sendEvent (SWT.Resize);
3063 void sendTouchEvent (TOUCHINPUT touchInput []) {
3064 Event event = new Event ();
3065 POINT pt = new POINT ();
3066 OS.GetCursorPos (pt);
3067 OS.ScreenToClient (handle, pt);
3068 event.setLocationInPixels(pt.x, pt.y);
3069 Touch [] touches = new Touch [touchInput.length];
3070 Monitor monitor = getMonitor ();
3071 for (int i = 0; i < touchInput.length; i++) {
3072 TOUCHINPUT ti = touchInput [i];
3073 TouchSource inputSource = display.findTouchSource (ti.hSource, monitor);
3075 if ((ti.dwFlags & OS.TOUCHEVENTF_DOWN) != 0) state = SWT.TOUCHSTATE_DOWN;
3076 if ((ti.dwFlags & OS.TOUCHEVENTF_UP) != 0) state = SWT.TOUCHSTATE_UP;
3077 if ((ti.dwFlags & OS.TOUCHEVENTF_MOVE) != 0) state = SWT.TOUCHSTATE_MOVE;
3078 boolean primary = (ti.dwFlags & OS.TOUCHEVENTF_PRIMARY) != 0;
3079 int x = (int)OS.TOUCH_COORD_TO_PIXEL (ti.x);
3080 int y = (int)OS.TOUCH_COORD_TO_PIXEL (ti.y);
3081 touches [i] = new Touch (ti.dwID, inputSource, state, primary, x, y);
3083 event.touches = touches;
3084 setInputState (event, SWT.Touch);
3085 postEvent (SWT.Touch, event);
3088 void setBackground () {
3089 Control control = findBackgroundControl ();
3090 if (control == null) control = this;
3091 if (control.backgroundImage != null) {
3092 Shell shell = getShell ();
3093 shell.releaseBrushes ();
3094 setBackgroundImage (control.backgroundImage.handle);
3096 setBackgroundPixel (control.background == -1 ? control.defaultBackground() : control.background);
3101 * Sets the receiver's background color to the color specified
3102 * by the argument, or to the default system color for the control
3103 * if the argument is null.
3105 * Note: This operation is a hint and may be overridden by the platform.
3107 * @param color the new color (or null)
3109 * @exception IllegalArgumentException <ul>
3110 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3112 * @exception SWTException <ul>
3113 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3114 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3117 public void setBackground (Color color) {
3119 _setBackground (color);
3120 if (color != null) {
3121 this.updateBackgroundMode ();
3125 private void _setBackground (Color color) {
3128 if (color != null) {
3129 if (color.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
3130 pixel = color.handle;
3131 alpha = color.getAlpha();
3133 if (pixel == background && alpha == backgroundAlpha) return;
3135 backgroundAlpha = alpha;
3136 updateBackgroundColor ();
3141 * Sets the receiver's background image to the image specified
3142 * by the argument, or to the default system color for the control
3143 * if the argument is null. The background image is tiled to fill
3144 * the available space.
3146 * Note: This operation is a hint and may be overridden by the platform.
3147 * For example, on Windows the background of a Button cannot be changed.
3149 * @param image the new image (or null)
3151 * @exception IllegalArgumentException <ul>
3152 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3153 * <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li>
3155 * @exception SWTException <ul>
3156 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3157 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3162 public void setBackgroundImage (Image image) {
3164 if (image != null) {
3165 if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
3166 if (image.type != SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT);
3168 if (backgroundImage == image && backgroundAlpha > 0) return;
3169 backgroundAlpha = 255;
3170 backgroundImage = image;
3171 Shell shell = getShell ();
3172 shell.releaseBrushes ();
3173 updateBackgroundImage ();
3176 void setBackgroundImage (long hBitmap) {
3177 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
3178 OS.RedrawWindow (handle, null, 0, flags);
3181 void setBackgroundPixel (int pixel) {
3182 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
3183 OS.RedrawWindow (handle, null, 0, flags);
3187 * Sets the receiver's size and location in points to the rectangular
3188 * area specified by the arguments. The <code>x</code> and
3189 * <code>y</code> arguments are relative to the receiver's
3190 * parent (or its display if its parent is null), unless
3191 * the receiver is a shell. In this case, the <code>x</code>
3192 * and <code>y</code> arguments are relative to the display.
3194 * Note: Attempting to set the width or height of the
3195 * receiver to a negative number will cause that
3196 * value to be set to zero instead.
3199 * Note: On GTK, attempting to set the width or height of the
3200 * receiver to a number higher or equal 2^14 will cause them to be
3201 * set to (2^14)-1 instead.
3204 * @param x the new x coordinate for the receiver
3205 * @param y the new y coordinate for the receiver
3206 * @param width the new width for the receiver
3207 * @param height the new height for the receiver
3209 * @exception SWTException <ul>
3210 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3211 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3214 public void setBounds(int x, int y, int width, int height) {
3216 x = DPIUtil.autoScaleUp(x);
3217 y = DPIUtil.autoScaleUp(y);
3218 width = DPIUtil.autoScaleUp(width);
3219 height = DPIUtil.autoScaleUp(height);
3220 setBoundsInPixels(x, y, width, height);
3223 void setBoundsInPixels (int x, int y, int width, int height) {
3224 int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
3225 setBoundsInPixels (x, y, Math.max (0, width), Math.max (0, height), flags);
3228 void setBoundsInPixels (int x, int y, int width, int height, int flags) {
3229 setBoundsInPixels (x, y, width, height, flags, true);
3232 void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
3233 if (findImageControl () != null) {
3234 if (backgroundImage == null) flags |= OS.SWP_NOCOPYBITS;
3236 if (OS.GetWindow (handle, OS.GW_CHILD) == 0) {
3237 if (OS.IsAppThemed ()) {
3238 if (findThemeControl () != null) flags |= OS.SWP_NOCOPYBITS;
3242 long topHandle = topHandle ();
3243 if (defer && parent != null) {
3245 if (parent.lpwp != null) {
3247 WINDOWPOS [] lpwp = parent.lpwp;
3248 while (index < lpwp.length) {
3249 if (lpwp [index] == null) break;
3252 if (index == lpwp.length) {
3253 WINDOWPOS [] newLpwp = new WINDOWPOS [lpwp.length + 4];
3254 System.arraycopy (lpwp, 0, newLpwp, 0, lpwp.length);
3255 parent.lpwp = lpwp = newLpwp;
3257 WINDOWPOS wp = new WINDOWPOS ();
3258 wp.hwnd = topHandle;
3268 OS.SetWindowPos (topHandle, 0, x, y, width, height, flags);
3272 * Sets the receiver's size and location in points to the rectangular
3273 * area specified by the argument. The <code>x</code> and
3274 * <code>y</code> fields of the rectangle are relative to
3275 * the receiver's parent (or its display if its parent is null).
3277 * Note: Attempting to set the width or height of the
3278 * receiver to a negative number will cause that
3279 * value to be set to zero instead.
3282 * Note: On GTK, attempting to set the width or height of the
3283 * receiver to a number higher or equal 2^14 will cause them to be
3284 * set to (2^14)-1 instead.
3287 * @param rect the new bounds for the receiver
3289 * @exception SWTException <ul>
3290 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3291 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3294 public void setBounds (Rectangle rect) {
3296 if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
3297 setBoundsInPixels(DPIUtil.autoScaleUp(rect));
3300 void setBoundsInPixels (Rectangle rect) {
3301 setBoundsInPixels (rect.x, rect.y, rect.width, rect.height);
3305 * If the argument is <code>true</code>, causes the receiver to have
3306 * all mouse events delivered to it until the method is called with
3307 * <code>false</code> as the argument. Note that on some platforms,
3308 * a mouse button must currently be down for capture to be assigned.
3310 * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
3312 * @exception SWTException <ul>
3313 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3314 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3317 public void setCapture (boolean capture) {
3320 OS.SetCapture (handle);
3322 if (OS.GetCapture () == handle) {
3323 OS.ReleaseCapture ();
3329 long lParam = OS.MAKELPARAM (OS.HTCLIENT, OS.WM_MOUSEMOVE);
3330 OS.SendMessage (handle, OS.WM_SETCURSOR, handle, lParam);
3334 * Sets the receiver's cursor to the cursor specified by the
3335 * argument, or to the default cursor for that kind of control
3336 * if the argument is null.
3338 * When the mouse pointer passes over a control its appearance
3339 * is changed to match the control's cursor.
3342 * @param cursor the new cursor (or null)
3344 * @exception IllegalArgumentException <ul>
3345 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3347 * @exception SWTException <ul>
3348 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3349 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3352 public void setCursor (Cursor cursor) {
3354 if (cursor != null && cursor.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3355 this.cursor = cursor;
3356 long hwndCursor = OS.GetCapture ();
3357 if (hwndCursor == 0) {
3358 POINT pt = new POINT ();
3359 if (!OS.GetCursorPos (pt)) return;
3360 long hwnd = hwndCursor = OS.WindowFromPoint (pt);
3361 while (hwnd != 0 && hwnd != handle) {
3362 hwnd = OS.GetParent (hwnd);
3364 if (hwnd == 0) return;
3366 Control control = display.getControl (hwndCursor);
3367 if (control == null) control = this;
3368 control.setCursor ();
3371 void setDefaultFont () {
3372 long hFont = display.getSystemFont ().handle;
3373 OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
3377 * Sets the receiver's drag detect state. If the argument is
3378 * <code>true</code>, the receiver will detect drag gestures,
3379 * otherwise these gestures will be ignored.
3381 * @param dragDetect the new drag detect state
3383 * @exception SWTException <ul>
3384 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3385 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3390 public void setDragDetect (boolean dragDetect) {
3393 state |= DRAG_DETECT;
3395 state &= ~DRAG_DETECT;
3397 enableDrag (dragDetect);
3401 * Enables the receiver if the argument is <code>true</code>,
3402 * and disables it otherwise. A disabled control is typically
3403 * not selectable from the user interface and draws with an
3404 * inactive or "grayed" look.
3406 * @param enabled the new enabled state
3408 * @exception SWTException <ul>
3409 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3410 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3413 public void setEnabled (boolean enabled) {
3416 * Feature in Windows. If the receiver has focus, disabling
3417 * the receiver causes no window to have focus. The fix is
3418 * to assign focus to the first ancestor window that takes
3419 * focus. If no window will take focus, set focus to the
3422 Control control = null;
3423 boolean fixFocus = false;
3425 if (display.focusEvent != SWT.FocusOut) {
3426 control = display.getFocusControl ();
3427 fixFocus = isFocusAncestor (control);
3430 enableWidget (enabled);
3431 if (fixFocus) fixFocus (control);
3435 * Causes the receiver to have the <em>keyboard focus</em>,
3436 * such that all keyboard events will be delivered to it. Focus
3437 * reassignment will respect applicable platform constraints.
3439 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
3441 * @exception SWTException <ul>
3442 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3443 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3448 public boolean setFocus () {
3450 if ((style & SWT.NO_FOCUS) != 0) return false;
3451 return forceFocus ();
3455 * Sets the font that the receiver will use to paint textual information
3456 * to the font specified by the argument, or to the default font for that
3457 * kind of control if the argument is null.
3459 * @param font the new font (or null)
3461 * @exception IllegalArgumentException <ul>
3462 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3464 * @exception SWTException <ul>
3465 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3466 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3469 public void setFont (Font font) {
3473 if (font.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3474 hFont = font.handle;
3477 if (hFont == 0) hFont = defaultFont ();
3478 OS.SendMessage (handle, OS.WM_SETFONT, hFont, 1);
3482 * Sets the receiver's foreground color to the color specified
3483 * by the argument, or to the default system color for the control
3484 * if the argument is null.
3486 * Note: This operation is a hint and may be overridden by the platform.
3488 * @param color the new color (or null)
3490 * @exception IllegalArgumentException <ul>
3491 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3493 * @exception SWTException <ul>
3494 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3495 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3498 public void setForeground (Color color) {
3501 if (color != null) {
3502 if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3503 pixel = color.handle;
3505 if (pixel == foreground) return;
3507 setForegroundPixel (pixel);
3510 void setForegroundPixel (int pixel) {
3511 OS.InvalidateRect (handle, null, true);
3515 * Sets the layout data associated with the receiver to the argument.
3517 * @param layoutData the new layout data for the receiver.
3519 * @exception SWTException <ul>
3520 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3521 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3524 public void setLayoutData (Object layoutData) {
3526 this.layoutData = layoutData;
3530 * Sets the receiver's location to the point specified by
3531 * the arguments which are relative to the receiver's
3532 * parent (or its display if its parent is null), unless
3533 * the receiver is a shell. In this case, the point is
3534 * relative to the display.
3536 * @param x the new x coordinate for the receiver
3537 * @param y the new y coordinate for the receiver
3539 * @exception SWTException <ul>
3540 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3541 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3544 public void setLocation (int x, int y) {
3546 x = DPIUtil.autoScaleUp(x);
3547 y = DPIUtil.autoScaleUp(y);
3548 setLocationInPixels(x, y);
3551 void setLocationInPixels (int x, int y) {
3552 int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE | OS.SWP_DRAWFRAME;
3553 setBoundsInPixels (x, y, 0, 0, flags);
3557 * Sets the receiver's location to the point specified by
3558 * the arguments which are relative to the receiver's
3559 * parent (or its display if its parent is null), unless
3560 * the receiver is a shell. In this case, the point is
3561 * relative to the display.
3563 * @param location the new location for the receiver
3565 * @exception SWTException <ul>
3566 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3567 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3570 public void setLocation (Point location) {
3572 if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
3573 location = DPIUtil.autoScaleUp(location);
3574 setLocationInPixels(location.x, location.y);
3578 * Sets the receiver's pop up menu to the argument.
3579 * All controls may optionally have a pop up
3580 * menu that is displayed when the user requests one for
3581 * the control. The sequence of key strokes, button presses
3582 * and/or button releases that are used to request a pop up
3583 * menu is platform specific.
3585 * Note: Disposing of a control that has a pop up menu will
3586 * dispose of the menu. To avoid this behavior, set the
3587 * menu to null before the control is disposed.
3590 * @param menu the new pop up menu
3592 * @exception IllegalArgumentException <ul>
3593 * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
3594 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
3595 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
3597 * @exception SWTException <ul>
3598 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3599 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3602 public void setMenu (Menu menu) {
3605 if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3606 if ((menu.style & SWT.POP_UP) == 0) {
3607 error (SWT.ERROR_MENU_NOT_POP_UP);
3609 if (menu.parent != menuShell ()) {
3610 error (SWT.ERROR_INVALID_PARENT);
3617 * Sets the orientation of the receiver, which must be one
3618 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
3621 * @param orientation new orientation style
3623 * @exception SWTException <ul>
3624 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3625 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3630 public void setOrientation (int orientation) {
3632 int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
3633 if ((orientation & flags) == 0 || (orientation & flags) == flags) return;
3634 style &= ~SWT.MIRRORED;
3636 style |= orientation & flags;
3637 style &= ~SWT.FLIP_TEXT_DIRECTION;
3638 updateOrientation ();
3642 boolean setRadioFocus (boolean tabbing) {
3646 boolean setRadioSelection (boolean value) {
3651 * If the argument is <code>false</code>, causes subsequent drawing
3652 * operations in the receiver to be ignored. No drawing of any kind
3653 * can occur in the receiver until the flag is set to true.
3654 * Graphics operations that occurred while the flag was
3655 * <code>false</code> are lost. When the flag is set to <code>true</code>,
3656 * the entire widget is marked as needing to be redrawn. Nested calls
3657 * to this method are stacked.
3659 * Note: This operation is a hint and may not be supported on some
3660 * platforms or for some widgets.
3663 * @param redraw the new redraw state
3665 * @exception SWTException <ul>
3666 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3667 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3670 * @see #redraw(int, int, int, int, boolean)
3673 public void setRedraw (boolean redraw) {
3676 * Feature in Windows. When WM_SETREDRAW is used to turn
3677 * off drawing in a widget, it clears the WS_VISIBLE bits
3678 * and then sets them when redraw is turned back on. This
3679 * means that WM_SETREDRAW will make a widget unexpectedly
3680 * visible. The fix is to track the visibility state while
3681 * drawing is turned off and restore it when drawing is
3684 if (drawCount == 0) {
3685 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
3686 if ((bits & OS.WS_VISIBLE) == 0) state |= HIDDEN;
3689 if (--drawCount == 0) {
3690 long topHandle = topHandle ();
3691 OS.SendMessage (topHandle, OS.WM_SETREDRAW, 1, 0);
3692 if (handle != topHandle) OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
3693 if ((state & HIDDEN) != 0) {
3695 OS.ShowWindow (topHandle, OS.SW_HIDE);
3696 if (handle != topHandle) OS.ShowWindow (handle, OS.SW_HIDE);
3698 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
3699 OS.RedrawWindow (topHandle, null, 0, flags);
3703 if (drawCount++ == 0) {
3704 long topHandle = topHandle ();
3705 OS.SendMessage (topHandle, OS.WM_SETREDRAW, 0, 0);
3706 if (handle != topHandle) OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
3712 * Sets the shape of the control to the region specified
3713 * by the argument. When the argument is null, the
3714 * default shape of the control is restored.
3716 * @param region the region that defines the shape of the control (or null)
3718 * @exception IllegalArgumentException <ul>
3719 * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
3721 * @exception SWTException <ul>
3722 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3723 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3728 public void setRegion (Region region) {
3730 if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
3732 if (region != null) {
3733 hRegion = OS.CreateRectRgn (0, 0, 0, 0);
3734 OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR);
3736 OS.SetWindowRgn (handle, hRegion, true);
3737 this.region = region;
3741 * Sets the receiver's size to the point specified by the arguments.
3743 * Note: Attempting to set the width or height of the
3744 * receiver to a negative number will cause that
3745 * value to be set to zero instead.
3748 * Note: On GTK, attempting to set the width or height of the
3749 * receiver to a number higher or equal 2^14 will cause them to be
3750 * set to (2^14)-1 instead.
3753 * @param width the new width in points for the receiver
3754 * @param height the new height in points for the receiver
3756 * @exception SWTException <ul>
3757 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3758 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3761 public void setSize (int width, int height) {
3763 width = DPIUtil.autoScaleUp(width);
3764 height = DPIUtil.autoScaleUp(height);
3765 setSizeInPixels(width, height);
3768 void setSizeInPixels (int width, int height) {
3769 int flags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
3770 setBoundsInPixels (0, 0, Math.max (0, width), Math.max (0, height), flags);
3774 * Sets the receiver's size to the point specified by the argument.
3776 * Note: Attempting to set the width or height of the
3777 * receiver to a negative number will cause them to be
3778 * set to zero instead.
3781 * Note: On GTK, attempting to set the width or height of the
3782 * receiver to a number higher or equal 2^14 will cause them to be
3783 * set to (2^14)-1 instead.
3786 * @param size the new size in points for the receiver
3788 * @exception IllegalArgumentException <ul>
3789 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
3791 * @exception SWTException <ul>
3792 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3793 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3796 public void setSize (Point size) {
3798 if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
3799 size = DPIUtil.autoScaleUp(size);
3800 setSizeInPixels(size.x, size.y);
3804 boolean setTabItemFocus () {
3805 if (!isShowing ()) return false;
3806 return forceFocus ();
3810 * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
3811 * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code>,
3812 * <code>SWT.RIGHT_TO_LEFT</code>, or <code>SWT.AUTO_TEXT_DIRECTION</code>.
3814 * <code>setOrientation</code> would override this value with the text direction
3815 * that is consistent with the new orientation.
3818 * <b>Warning</b>: This API is currently only implemented on Windows.
3819 * It doesn't set the base text direction on GTK and Cocoa.
3822 * @param textDirection the base text direction style
3824 * @exception SWTException <ul>
3825 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3826 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3829 * @see SWT#LEFT_TO_RIGHT
3830 * @see SWT#RIGHT_TO_LEFT
3831 * @see SWT#AUTO_TEXT_DIRECTION
3832 * @see SWT#FLIP_TEXT_DIRECTION
3836 public void setTextDirection(int textDirection) {
3838 textDirection &= (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
3839 updateTextDirection (textDirection);
3840 if (textDirection == AUTO_TEXT_DIRECTION) {
3841 state |= HAS_AUTO_DIRECTION;
3843 state &= ~HAS_AUTO_DIRECTION;
3848 * Sets the receiver's tool tip text to the argument, which
3849 * may be null indicating that the default tool tip for the
3850 * control will be shown. For a control that has a default
3851 * tool tip, such as the Tree control on Windows, setting
3852 * the tool tip text to an empty string replaces the default,
3853 * causing no tool tip text to be shown.
3855 * The mnemonic indicator (character '&') is not displayed in a tool tip.
3856 * To display a single '&' in the tool tip, the character '&' can be
3857 * escaped by doubling it in the string.
3860 * NOTE: This operation is a hint and behavior is platform specific, on Windows
3861 * for CJK-style mnemonics of the form " (&C)" at the end of the tooltip text
3862 * are not shown in tooltip.
3865 * @param string the new tool tip text (or null)
3867 * @exception SWTException <ul>
3868 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3869 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3872 public void setToolTipText (String string) {
3874 toolTipText = string;
3875 setToolTipText (getShell (), string);
3878 void setToolTipText (Shell shell, String string) {
3879 shell.setToolTipText (handle, string);
3883 * Sets whether this control should send touch events (by default controls do not).
3884 * Setting this to <code>false</code> causes the receiver to send gesture events
3885 * instead. No exception is thrown if a touch-based input device is not
3886 * detected (this can be determined with <code>Display#getTouchEnabled()</code>).
3888 * @param enabled the new touch-enabled state
3890 * @exception SWTException <ul>
3891 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3892 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3895 * @see Display#getTouchEnabled
3899 public void setTouchEnabled(boolean enabled) {
3902 OS.RegisterTouchWindow(handle, 0);
3904 OS.UnregisterTouchWindow(handle);
3909 * Marks the receiver as visible if the argument is <code>true</code>,
3910 * and marks it invisible otherwise.
3912 * If one of the receiver's ancestors is not visible or some
3913 * other condition makes the receiver not visible, marking
3914 * it visible may not actually cause it to be displayed.
3917 * @param visible the new visibility state
3919 * @exception SWTException <ul>
3920 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3921 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3924 public void setVisible (boolean visible) {
3926 if (!getDrawing()) {
3927 if (((state & HIDDEN) == 0) == visible) return;
3929 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
3930 if (((bits & OS.WS_VISIBLE) != 0) == visible) return;
3933 sendEvent (SWT.Show);
3934 if (isDisposed ()) return;
3938 * Feature in Windows. If the receiver has focus, hiding
3939 * the receiver causes no window to have focus. The fix is
3940 * to assign focus to the first ancestor window that takes
3941 * focus. If no window will take focus, set focus to the
3944 Control control = null;
3945 boolean fixFocus = false;
3947 if (display.focusEvent != SWT.FocusOut) {
3948 control = display.getFocusControl ();
3949 fixFocus = isFocusAncestor (control);
3952 if (!getDrawing()) {
3953 state = visible ? state & ~HIDDEN : state | HIDDEN;
3955 showWidget (visible);
3956 if (isDisposed ()) return;
3959 sendEvent (SWT.Hide);
3960 if (isDisposed ()) return;
3962 if (fixFocus) fixFocus (control);
3965 void sort (int [] items) {
3966 /* Shell Sort from K&R, pg 108 */
3967 int length = items.length;
3968 for (int gap=length/2; gap>0; gap/=2) {
3969 for (int i=gap; i<length; i++) {
3970 for (int j=i-gap; j>=0; j-=gap) {
3971 if (items [j] <= items [j + gap]) {
3972 int swap = items [j];
3973 items [j] = items [j + gap];
3974 items [j + gap] = swap;
3982 long oldProc = windowProc ();
3983 long newProc = display.windowProc;
3984 if (oldProc == newProc) return;
3985 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc);
3989 * Returns a point which is the result of converting the
3990 * argument, which is specified in display relative coordinates,
3991 * to coordinates relative to the receiver.
3993 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
3994 * {@link Display#map(Control, Control, Rectangle)}.
3997 * @param x the x coordinate in points to be translated
3998 * @param y the y coordinate in points to be translated
3999 * @return the translated coordinates
4001 * @exception SWTException <ul>
4002 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4003 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4008 public Point toControl (int x, int y) {
4010 return DPIUtil.autoScaleDown(toControlInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y)));
4013 Point toControlInPixels (int x, int y) {
4014 POINT pt = new POINT ();
4016 OS.ScreenToClient (handle, pt);
4017 return new Point (pt.x, pt.y);
4021 * Returns a point which is the result of converting the
4022 * argument, which is specified in display relative coordinates,
4023 * to coordinates relative to the receiver.
4025 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
4026 * {@link Display#map(Control, Control, Rectangle)}.
4029 * @param point the point to be translated (must not be null)
4030 * @return the translated coordinates
4032 * @exception IllegalArgumentException <ul>
4033 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
4035 * @exception SWTException <ul>
4036 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4037 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4040 public Point toControl (Point point) {
4042 if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
4043 point = DPIUtil.autoScaleUp(point);
4044 return DPIUtil.autoScaleDown(toControlInPixels(point.x, point.y));
4048 * Returns a point which is the result of converting the
4049 * argument, which is specified in coordinates relative to
4050 * the receiver, to display relative coordinates.
4052 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
4053 * {@link Display#map(Control, Control, Rectangle)}.
4056 * @param x the x coordinate to be translated
4057 * @param y the y coordinate to be translated
4058 * @return the translated coordinates
4060 * @exception SWTException <ul>
4061 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4062 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4067 public Point toDisplay (int x, int y) {
4069 return DPIUtil.autoScaleDown(toDisplayInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y)));
4072 Point toDisplayInPixels (int x, int y) {
4073 POINT pt = new POINT ();
4075 OS.ClientToScreen (handle, pt);
4076 return new Point (pt.x, pt.y);
4080 * Returns a point which is the result of converting the
4081 * argument, which is specified in coordinates relative to
4082 * the receiver, to display relative coordinates.
4084 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
4085 * {@link Display#map(Control, Control, Rectangle)}.
4088 * @param point the point to be translated (must not be null)
4089 * @return the translated coordinates
4091 * @exception IllegalArgumentException <ul>
4092 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
4094 * @exception SWTException <ul>
4095 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4096 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4099 public Point toDisplay (Point point) {
4101 if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
4102 point = DPIUtil.autoScaleUp(point);
4103 return DPIUtil.autoScaleDown(toDisplayInPixels(point.x, point.y));
4110 boolean translateAccelerator (MSG msg) {
4111 return menuShell ().translateAccelerator (msg);
4114 boolean translateMnemonic (Event event, Control control) {
4115 if (control == this) return false;
4116 if (!isVisible () || !isEnabled ()) return false;
4117 event.doit = mnemonicMatch (event.character);
4118 return traverse (event);
4121 boolean translateMnemonic (MSG msg) {
4122 if (msg.wParam < 0x20) return false;
4123 long hwnd = msg.hwnd;
4124 if (OS.GetKeyState (OS.VK_MENU) >= 0) {
4125 long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
4126 if ((code & OS.DLGC_WANTALLKEYS) != 0) return false;
4127 if ((code & OS.DLGC_BUTTON) == 0) return false;
4129 Decorations shell = menuShell ();
4130 if (shell.isVisible () && shell.isEnabled ()) {
4131 display.lastAscii = (int)msg.wParam;
4132 display.lastNull = display.lastDead = false;
4133 Event event = new Event ();
4134 event.detail = SWT.TRAVERSE_MNEMONIC;
4135 if (setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) {
4136 return translateMnemonic (event, null) || shell.translateMnemonic (event, this);
4142 boolean translateTraversal (MSG msg) {
4143 long hwnd = msg.hwnd;
4144 int key = (int)msg.wParam;
4145 if (key == OS.VK_MENU) {
4146 if ((msg.lParam & 0x40000000) == 0) {
4147 OS.SendMessage (hwnd, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
4151 int detail = SWT.TRAVERSE_NONE;
4152 boolean doit = true, all = false;
4153 boolean lastVirtual = false;
4154 int lastKey = key, lastAscii = 0;
4156 case OS.VK_ESCAPE: {
4159 long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
4160 if ((code & OS.DLGC_WANTALLKEYS) != 0) {
4162 * Use DLGC_HASSETSEL to determine that the control
4163 * is a text widget. A text widget normally wants
4164 * all keys except VK_ESCAPE. If this bit is not
4165 * set, then assume the control wants all keys,
4166 * including VK_ESCAPE.
4168 if ((code & OS.DLGC_HASSETSEL) == 0) doit = false;
4170 detail = SWT.TRAVERSE_ESCAPE;
4173 case OS.VK_RETURN: {
4176 long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
4177 if ((code & OS.DLGC_WANTALLKEYS) != 0) doit = false;
4178 detail = SWT.TRAVERSE_RETURN;
4183 boolean next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
4184 long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
4185 if ((code & (OS.DLGC_WANTTAB | OS.DLGC_WANTALLKEYS)) != 0) {
4187 * Use DLGC_HASSETSEL to determine that the control is a
4188 * text widget. If the control is a text widget, then
4189 * Ctrl+Tab and Shift+Tab should traverse out of the widget.
4190 * If the control is not a text widget, the correct behavior
4191 * is to give every character, including Tab, Ctrl+Tab and
4192 * Shift+Tab to the control.
4194 if ((code & OS.DLGC_HASSETSEL) != 0) {
4195 if (next && OS.GetKeyState (OS.VK_CONTROL) >= 0) {
4202 detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
4210 long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
4211 if ((code & (OS.DLGC_WANTARROWS /*| OS.DLGC_WANTALLKEYS*/)) != 0) doit = false;
4212 boolean next = key == OS.VK_DOWN || key == OS.VK_RIGHT;
4213 if (parent != null && (parent.style & SWT.MIRRORED) != 0) {
4214 if (key == OS.VK_LEFT || key == OS.VK_RIGHT) next = !next;
4216 detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS;
4223 if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
4224 long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
4225 if ((code & OS.DLGC_WANTALLKEYS) != 0) {
4227 * Use DLGC_HASSETSEL to determine that the control is a
4228 * text widget. If the control is a text widget, then
4229 * Ctrl+PgUp and Ctrl+PgDn should traverse out of the widget.
4231 if ((code & OS.DLGC_HASSETSEL) == 0) doit = false;
4233 detail = key == OS.VK_PRIOR ? SWT.TRAVERSE_PAGE_PREVIOUS : SWT.TRAVERSE_PAGE_NEXT;
4239 Event event = new Event ();
4241 event.detail = detail;
4242 display.lastKey = lastKey;
4243 display.lastAscii = lastAscii;
4244 display.lastVirtual = lastVirtual;
4245 display.lastNull = display.lastDead = false;
4246 if (!setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) return false;
4247 Shell shell = getShell ();
4248 Control control = this;
4250 if (control.traverse (event)) {
4251 OS.SendMessage (hwnd, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
4254 if (!event.doit && control.hooks (SWT.Traverse)) return false;
4255 if (control == shell) return false;
4256 control = control.parent;
4257 } while (all && control != null);
4261 boolean traverse (Event event) {
4263 * It is possible (but unlikely), that application
4264 * code could have disposed the widget in the traverse
4265 * event. If this happens, return true to stop further
4268 sendEvent (SWT.Traverse, event);
4269 if (isDisposed ()) return true;
4270 if (!event.doit) return false;
4271 switch (event.detail) {
4272 case SWT.TRAVERSE_NONE: return true;
4273 case SWT.TRAVERSE_ESCAPE: return traverseEscape ();
4274 case SWT.TRAVERSE_RETURN: return traverseReturn ();
4275 case SWT.TRAVERSE_TAB_NEXT: return traverseGroup (true);
4276 case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
4277 case SWT.TRAVERSE_ARROW_NEXT: return traverseItem (true);
4278 case SWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false);
4279 case SWT.TRAVERSE_MNEMONIC: return traverseMnemonic (event.character);
4280 case SWT.TRAVERSE_PAGE_NEXT: return traversePage (true);
4281 case SWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false);
4287 * Based on the argument, perform one of the expected platform
4288 * traversal action. The argument should be one of the constants:
4289 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
4290 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
4291 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
4292 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
4294 * @param traversal the type of traversal
4295 * @return true if the traversal succeeded
4297 * @exception SWTException <ul>
4298 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4299 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4302 public boolean traverse (int traversal) {
4304 Event event = new Event ();
4306 event.detail = traversal;
4307 return traverse (event);
4311 * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
4313 * <p>Valid traversal values are
4314 * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
4315 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
4316 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
4317 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
4318 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
4319 * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
4320 * event is created with standard values based on the KeyDown event. If
4321 * <code>traversal</code> is one of the other traversal constants then the Traverse
4322 * event is created with this detail, and its <code>doit</code> is taken from the
4326 * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
4327 * this from <code>event</code>
4328 * @param event the KeyDown event
4330 * @return <code>true</code> if the traversal succeeded
4332 * @exception IllegalArgumentException <ul>
4333 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
4335 * @exception SWTException <ul>
4336 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4337 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4342 public boolean traverse (int traversal, Event event) {
4344 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
4345 return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
4349 * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
4351 * <p>Valid traversal values are
4352 * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
4353 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
4354 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
4355 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
4356 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
4357 * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
4358 * event is created with standard values based on the KeyDown event. If
4359 * <code>traversal</code> is one of the other traversal constants then the Traverse
4360 * event is created with this detail, and its <code>doit</code> is taken from the
4364 * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
4365 * this from <code>event</code>
4366 * @param event the KeyDown event
4368 * @return <code>true</code> if the traversal succeeded
4370 * @exception IllegalArgumentException <ul>
4371 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
4373 * @exception SWTException <ul>
4374 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4375 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4380 public boolean traverse (int traversal, KeyEvent event) {
4382 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
4383 return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
4386 boolean traverse (int traversal, char character, int keyCode, int keyLocation, int stateMask, boolean doit) {
4387 if (traversal == SWT.TRAVERSE_NONE) {
4390 traversal = SWT.TRAVERSE_ESCAPE;
4395 traversal = SWT.TRAVERSE_RETURN;
4399 case SWT.ARROW_DOWN:
4400 case SWT.ARROW_RIGHT: {
4401 traversal = SWT.TRAVERSE_ARROW_NEXT;
4406 case SWT.ARROW_LEFT: {
4407 traversal = SWT.TRAVERSE_ARROW_PREVIOUS;
4412 traversal = (stateMask & SWT.SHIFT) != 0 ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT;
4416 case SWT.PAGE_DOWN: {
4417 if ((stateMask & SWT.CTRL) != 0) {
4418 traversal = SWT.TRAVERSE_PAGE_NEXT;
4424 if ((stateMask & SWT.CTRL) != 0) {
4425 traversal = SWT.TRAVERSE_PAGE_PREVIOUS;
4431 if (character != 0 && (stateMask & (SWT.ALT | SWT.CTRL)) == SWT.ALT) {
4432 traversal = SWT.TRAVERSE_MNEMONIC;
4440 Event event = new Event ();
4441 event.character = character;
4442 event.detail = traversal;
4444 event.keyCode = keyCode;
4445 event.keyLocation = keyLocation;
4446 event.stateMask = stateMask;
4448 Shell shell = getShell ();
4449 boolean all = false;
4450 switch (traversal) {
4451 case SWT.TRAVERSE_ESCAPE:
4452 case SWT.TRAVERSE_RETURN:
4453 case SWT.TRAVERSE_PAGE_NEXT:
4454 case SWT.TRAVERSE_PAGE_PREVIOUS: {
4458 case SWT.TRAVERSE_ARROW_NEXT:
4459 case SWT.TRAVERSE_ARROW_PREVIOUS:
4460 case SWT.TRAVERSE_TAB_NEXT:
4461 case SWT.TRAVERSE_TAB_PREVIOUS: {
4462 /* traversal is a valid traversal action */
4465 case SWT.TRAVERSE_MNEMONIC: {
4466 return translateMnemonic (event, null) || shell.translateMnemonic (event, this);
4469 /* traversal is not a valid traversal action */
4474 Control control = this;
4476 if (control.traverse (event)) {
4477 OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
4480 if (!event.doit && control.hooks (SWT.Traverse)) return false;
4481 if (control == shell) return false;
4482 control = control.parent;
4483 } while (all && control != null);
4487 boolean traverseEscape () {
4491 boolean traverseGroup (boolean next) {
4492 Control root = computeTabRoot ();
4493 Widget group = computeTabGroup ();
4494 Widget [] list = root.computeTabList ();
4495 int length = list.length;
4497 while (index < length) {
4498 if (list [index] == group) break;
4502 * It is possible (but unlikely), that application
4503 * code could have disposed the widget in focus in
4504 * or out events. Ensure that a disposed widget is
4507 if (index == length) return false;
4508 int start = index, offset = (next) ? 1 : -1;
4509 while ((index = ((index + offset + length) % length)) != start) {
4510 Widget widget = list [index];
4511 if (!widget.isDisposed () && widget.setTabGroupFocus ()) {
4515 if (group.isDisposed ()) return false;
4516 return group.setTabGroupFocus ();
4519 boolean traverseItem (boolean next) {
4520 Control [] children = parent._getChildren ();
4521 int length = children.length;
4523 while (index < length) {
4524 if (children [index] == this) break;
4528 * It is possible (but unlikely), that application
4529 * code could have disposed the widget in focus in
4530 * or out events. Ensure that a disposed widget is
4533 if (index == length) return false;
4534 int start = index, offset = (next) ? 1 : -1;
4535 while ((index = (index + offset + length) % length) != start) {
4536 Control child = children [index];
4537 if (!child.isDisposed () && child.isTabItem ()) {
4538 if (child.setTabItemFocus ()) return true;
4544 boolean traverseMnemonic (char key) {
4545 if (mnemonicHit (key)) {
4546 OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
4552 boolean traversePage (boolean next) {
4556 boolean traverseReturn () {
4560 void unsubclass () {
4561 long newProc = windowProc ();
4562 long oldProc = display.windowProc;
4563 if (oldProc == newProc) return;
4564 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc);
4568 * Forces all outstanding paint requests for the widget
4569 * to be processed before this method returns. If there
4570 * are no outstanding paint request, this method does
4573 * Note: This method does not cause a redraw.
4576 * @exception SWTException <ul>
4577 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4578 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4582 * @see #redraw(int, int, int, int, boolean)
4583 * @see PaintListener
4586 public void update () {
4591 void update (boolean all) {
4593 int flags = OS.RDW_UPDATENOW;
4594 if (all) flags |= OS.RDW_ALLCHILDREN;
4595 OS.RedrawWindow (handle, null, 0, flags);
4598 void updateBackgroundColor () {
4599 Control control = findBackgroundControl ();
4600 if (control == null) control = this;
4601 setBackgroundPixel (control.background);
4604 void updateBackgroundImage () {
4605 Control control = findBackgroundControl ();
4606 Image image = control != null ? control.backgroundImage : backgroundImage;
4607 setBackgroundImage (image != null ? image.handle : 0);
4610 void updateBackgroundMode () {
4611 int oldState = state & PARENT_BACKGROUND;
4613 if (oldState != (state & PARENT_BACKGROUND)) {
4618 void updateFont (Font oldFont, Font newFont) {
4619 if (getFont ().equals (oldFont)) setFont (newFont);
4622 void updateLayout (boolean resize, boolean all) {
4626 void updateOrientation () {
4627 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
4628 if ((style & SWT.RIGHT_TO_LEFT) != 0) {
4629 bits |= OS.WS_EX_LAYOUTRTL;
4631 bits &= ~OS.WS_EX_LAYOUTRTL;
4633 bits &= ~OS.WS_EX_RTLREADING;
4634 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
4635 OS.InvalidateRect (handle, null, true);
4638 boolean updateTextDirection (int textDirection) {
4639 if (textDirection == AUTO_TEXT_DIRECTION) {
4640 textDirection = resolveTextDirection();
4641 state |= HAS_AUTO_DIRECTION;
4643 state &= ~HAS_AUTO_DIRECTION;
4645 if (textDirection == 0) return false;
4646 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
4648 * OS.WS_EX_RTLREADING means that the text direction is opposite to the
4649 * natural one for the current layout. So text direction would be RTL when
4650 * one and only one of the flags OS.WS_EX_LAYOUTRTL | OS.WS_EX_RTLREADING is
4653 int flags = OS.WS_EX_LAYOUTRTL | OS.WS_EX_RTLREADING;
4654 boolean oldRtl = ((bits & flags) != 0 && (bits & flags) != flags);
4655 boolean newRtl = textDirection == SWT.RIGHT_TO_LEFT;
4656 if (newRtl == oldRtl) return false;
4657 oldRtl = (bits & OS.WS_EX_LAYOUTRTL) != 0;
4658 if (newRtl != oldRtl) {
4659 bits |= OS.WS_EX_RTLREADING;
4660 style |= SWT.FLIP_TEXT_DIRECTION;
4662 bits &= ~OS.WS_EX_RTLREADING;
4663 style &= ~SWT.FLIP_TEXT_DIRECTION;
4665 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
4666 OS.InvalidateRect (handle, null, true);
4670 CREATESTRUCT widgetCreateStruct () {
4674 int widgetExtStyle () {
4676 if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_CLIENTEDGE;
4677 // if ((style & SWT.BORDER) != 0) {
4678 // if ((style & SWT.FLAT) == 0) bits |= OS.WS_EX_CLIENTEDGE;
4680 bits |= OS.WS_EX_NOINHERITLAYOUT;
4681 if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL;
4682 if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) bits |= OS.WS_EX_RTLREADING;
4686 long widgetParent () {
4687 return parent.handle;
4690 int widgetStyle () {
4691 /* Force clipping of siblings by setting WS_CLIPSIBLINGS */
4692 int bits = OS.WS_CHILD | OS.WS_VISIBLE | OS.WS_CLIPSIBLINGS;
4693 // if ((style & SWT.BORDER) != 0) {
4694 // if ((style & SWT.FLAT) != 0) bits |= OS.WS_BORDER;
4699 * This code is intentionally commented. When clipping
4700 * of both siblings and children is not enforced, it is
4701 * possible for application code to draw outside of the
4704 // int bits = OS.WS_CHILD | OS.WS_VISIBLE;
4705 // if ((style & SWT.CLIP_SIBLINGS) != 0) bits |= OS.WS_CLIPSIBLINGS;
4706 // if ((style & SWT.CLIP_CHILDREN) != 0) bits |= OS.WS_CLIPCHILDREN;
4711 * Changes the parent of the widget to be the one provided.
4712 * Returns <code>true</code> if the parent is successfully changed.
4714 * @param parent the new parent for the control.
4715 * @return <code>true</code> if the parent is changed and <code>false</code> otherwise.
4717 * @exception IllegalArgumentException <ul>
4718 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
4719 * <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></li>
4721 * @exception SWTException <ul>
4722 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4723 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4726 public boolean setParent (Composite parent) {
4728 if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
4729 if (parent.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
4730 if (this.parent == parent) return true;
4731 if (!isReparentable ()) return false;
4733 Shell newShell = parent.getShell (), oldShell = getShell ();
4734 Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
4735 if (oldShell != newShell || oldDecorations != newDecorations) {
4736 Menu [] menus = oldShell.findMenus (this);
4737 fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
4739 long topHandle = topHandle ();
4740 if (OS.SetParent (topHandle, parent.handle) == 0) return false;
4741 this.parent = parent;
4742 int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
4743 OS.SetWindowPos (topHandle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
4748 abstract TCHAR windowClass ();
4750 abstract long windowProc ();
4752 long windowProc (long hwnd, int msg, long wParam, long lParam) {
4753 Display display = this.display;
4754 LRESULT result = null;
4756 case OS.WM_ACTIVATE: result = WM_ACTIVATE (wParam, lParam); break;
4757 case OS.WM_CAPTURECHANGED: result = WM_CAPTURECHANGED (wParam, lParam); break;
4758 case OS.WM_CHANGEUISTATE: result = WM_CHANGEUISTATE (wParam, lParam); break;
4759 case OS.WM_CHAR: result = WM_CHAR (wParam, lParam); break;
4760 case OS.WM_CLEAR: result = WM_CLEAR (wParam, lParam); break;
4761 case OS.WM_CLOSE: result = WM_CLOSE (wParam, lParam); break;
4762 case OS.WM_COMMAND: result = WM_COMMAND (wParam, lParam); break;
4763 case OS.WM_CONTEXTMENU: result = WM_CONTEXTMENU (wParam, lParam); break;
4764 case OS.WM_CTLCOLORBTN:
4765 case OS.WM_CTLCOLORDLG:
4766 case OS.WM_CTLCOLOREDIT:
4767 case OS.WM_CTLCOLORLISTBOX:
4768 case OS.WM_CTLCOLORMSGBOX:
4769 case OS.WM_CTLCOLORSCROLLBAR:
4770 case OS.WM_CTLCOLORSTATIC: result = WM_CTLCOLOR (wParam, lParam); break;
4771 case OS.WM_CUT: result = WM_CUT (wParam, lParam); break;
4772 case OS.WM_DESTROY: result = WM_DESTROY (wParam, lParam); break;
4773 case OS.WM_DRAWITEM: result = WM_DRAWITEM (wParam, lParam); break;
4774 case OS.WM_ENDSESSION: result = WM_ENDSESSION (wParam, lParam); break;
4775 case OS.WM_ENTERIDLE: result = WM_ENTERIDLE (wParam, lParam); break;
4776 case OS.WM_ERASEBKGND: result = WM_ERASEBKGND (wParam, lParam); break;
4777 case OS.WM_GESTURE: result = WM_GESTURE (wParam, lParam); break;
4778 case OS.WM_GETDLGCODE: result = WM_GETDLGCODE (wParam, lParam); break;
4779 case OS.WM_GETFONT: result = WM_GETFONT (wParam, lParam); break;
4780 case OS.WM_GETOBJECT: result = WM_GETOBJECT (wParam, lParam); break;
4781 case OS.WM_GETMINMAXINFO: result = WM_GETMINMAXINFO (wParam, lParam); break;
4782 case OS.WM_HELP: result = WM_HELP (wParam, lParam); break;
4783 case OS.WM_HSCROLL: result = WM_HSCROLL (wParam, lParam); break;
4784 case OS.WM_IME_CHAR: result = WM_IME_CHAR (wParam, lParam); break;
4785 case OS.WM_IME_COMPOSITION: result = WM_IME_COMPOSITION (wParam, lParam); break;
4786 case OS.WM_IME_COMPOSITION_START: result = WM_IME_COMPOSITION_START (wParam, lParam); break;
4787 case OS.WM_IME_ENDCOMPOSITION: result = WM_IME_ENDCOMPOSITION (wParam, lParam); break;
4788 case OS.WM_INITMENUPOPUP: result = WM_INITMENUPOPUP (wParam, lParam); break;
4789 case OS.WM_INPUTLANGCHANGE: result = WM_INPUTLANGCHANGE (wParam, lParam); break;
4790 case OS.WM_HOTKEY: result = WM_HOTKEY (wParam, lParam); break;
4791 case OS.WM_KEYDOWN: result = WM_KEYDOWN (wParam, lParam); break;
4792 case OS.WM_KEYUP: result = WM_KEYUP (wParam, lParam); break;
4793 case OS.WM_KILLFOCUS: result = WM_KILLFOCUS (wParam, lParam); break;
4794 case OS.WM_LBUTTONDBLCLK: result = WM_LBUTTONDBLCLK (wParam, lParam); break;
4795 case OS.WM_LBUTTONDOWN: result = WM_LBUTTONDOWN (wParam, lParam); break;
4796 case OS.WM_LBUTTONUP: result = WM_LBUTTONUP (wParam, lParam); break;
4797 case OS.WM_MBUTTONDBLCLK: result = WM_MBUTTONDBLCLK (wParam, lParam); break;
4798 case OS.WM_MBUTTONDOWN: result = WM_MBUTTONDOWN (wParam, lParam); break;
4799 case OS.WM_MBUTTONUP: result = WM_MBUTTONUP (wParam, lParam); break;
4800 case OS.WM_MEASUREITEM: result = WM_MEASUREITEM (wParam, lParam); break;
4801 case OS.WM_MENUCHAR: result = WM_MENUCHAR (wParam, lParam); break;
4802 case OS.WM_MENUSELECT: result = WM_MENUSELECT (wParam, lParam); break;
4803 case OS.WM_MOUSEACTIVATE: result = WM_MOUSEACTIVATE (wParam, lParam); break;
4804 case OS.WM_MOUSEHOVER: result = WM_MOUSEHOVER (wParam, lParam); break;
4805 case OS.WM_MOUSELEAVE: result = WM_MOUSELEAVE (wParam, lParam); break;
4806 case OS.WM_MOUSEMOVE: result = WM_MOUSEMOVE (wParam, lParam); break;
4807 case OS.WM_MOUSEWHEEL: result = WM_MOUSEWHEEL (wParam, lParam); break;
4808 case OS.WM_MOUSEHWHEEL: result = WM_MOUSEHWHEEL (wParam, lParam); break;
4809 case OS.WM_MOVE: result = WM_MOVE (wParam, lParam); break;
4810 case OS.WM_NCACTIVATE: result = WM_NCACTIVATE (wParam, lParam); break;
4811 case OS.WM_NCCALCSIZE: result = WM_NCCALCSIZE (wParam, lParam); break;
4812 case OS.WM_NCHITTEST: result = WM_NCHITTEST (wParam, lParam); break;
4813 case OS.WM_NCLBUTTONDOWN: result = WM_NCLBUTTONDOWN (wParam, lParam); break;
4814 case OS.WM_NCPAINT: result = WM_NCPAINT (wParam, lParam); break;
4815 case OS.WM_NOTIFY: result = WM_NOTIFY (wParam, lParam); break;
4816 case OS.WM_PAINT: result = WM_PAINT (wParam, lParam); break;
4817 case OS.WM_ENTERMENULOOP: result = WM_ENTERMENULOOP (wParam, lParam); break;
4818 case OS.WM_EXITMENULOOP: result = WM_EXITMENULOOP (wParam, lParam); break;
4819 case OS.WM_ENTERSIZEMOVE: result = WM_ENTERSIZEMOVE (wParam, lParam); break;
4820 case OS.WM_EXITSIZEMOVE: result = WM_EXITSIZEMOVE (wParam, lParam); break;
4821 case OS.WM_PARENTNOTIFY: result = WM_PARENTNOTIFY (wParam, lParam); break;
4822 case OS.WM_PASTE: result = WM_PASTE (wParam, lParam); break;
4823 case OS.WM_PRINT: result = WM_PRINT (wParam, lParam); break;
4824 case OS.WM_PRINTCLIENT: result = WM_PRINTCLIENT (wParam, lParam); break;
4825 case OS.WM_QUERYENDSESSION: result = WM_QUERYENDSESSION (wParam, lParam); break;
4826 case OS.WM_QUERYOPEN: result = WM_QUERYOPEN (wParam, lParam); break;
4827 case OS.WM_RBUTTONDBLCLK: result = WM_RBUTTONDBLCLK (wParam, lParam); break;
4828 case OS.WM_RBUTTONDOWN: result = WM_RBUTTONDOWN (wParam, lParam); break;
4829 case OS.WM_RBUTTONUP: result = WM_RBUTTONUP (wParam, lParam); break;
4830 case OS.WM_SETCURSOR: result = WM_SETCURSOR (wParam, lParam); break;
4831 case OS.WM_SETFOCUS: result = WM_SETFOCUS (wParam, lParam); break;
4832 case OS.WM_SETFONT: result = WM_SETFONT (wParam, lParam); break;
4833 case OS.WM_SETTINGCHANGE: result = WM_SETTINGCHANGE (wParam, lParam); break;
4834 case OS.WM_SETREDRAW: result = WM_SETREDRAW (wParam, lParam); break;
4835 case OS.WM_SHOWWINDOW: result = WM_SHOWWINDOW (wParam, lParam); break;
4836 case OS.WM_SIZE: result = WM_SIZE (wParam, lParam); break;
4837 case OS.WM_SYSCHAR: result = WM_SYSCHAR (wParam, lParam); break;
4838 case OS.WM_SYSCOLORCHANGE: result = WM_SYSCOLORCHANGE (wParam, lParam); break;
4839 case OS.WM_SYSCOMMAND: result = WM_SYSCOMMAND (wParam, lParam); break;
4840 case OS.WM_SYSKEYDOWN: result = WM_SYSKEYDOWN (wParam, lParam); break;
4841 case OS.WM_SYSKEYUP: result = WM_SYSKEYUP (wParam, lParam); break;
4842 case OS.WM_TABLET_FLICK: result = WM_TABLET_FLICK (wParam, lParam); break;
4843 case OS.WM_TIMER: result = WM_TIMER (wParam, lParam); break;
4844 case OS.WM_TOUCH: result = WM_TOUCH (wParam, lParam); break;
4845 case OS.WM_UNDO: result = WM_UNDO (wParam, lParam); break;
4846 case OS.WM_UNINITMENUPOPUP: result = WM_UNINITMENUPOPUP (wParam, lParam); break;
4847 case OS.WM_UPDATEUISTATE: result = WM_UPDATEUISTATE (wParam, lParam); break;
4848 case OS.WM_VSCROLL: result = WM_VSCROLL (wParam, lParam); break;
4849 case OS.WM_WINDOWPOSCHANGED: result = WM_WINDOWPOSCHANGED (wParam, lParam); break;
4850 case OS.WM_WINDOWPOSCHANGING: result = WM_WINDOWPOSCHANGING (wParam, lParam); break;
4851 case OS.WM_XBUTTONDBLCLK: result = WM_XBUTTONDBLCLK (wParam, lParam); break;
4852 case OS.WM_XBUTTONDOWN: result = WM_XBUTTONDOWN (wParam, lParam); break;
4853 case OS.WM_XBUTTONUP: result = WM_XBUTTONUP (wParam, lParam); break;
4854 case OS.WM_DPICHANGED: result = WM_DPICHANGED (wParam, lParam); break;
4856 if (result != null) return result.value;
4857 // widget could be disposed at this point
4858 display.sendPreExternalEventDispatchEvent ();
4860 return callWindowProc (hwnd, msg, wParam, lParam);
4862 // widget could be disposed at this point
4863 display.sendPostExternalEventDispatchEvent ();
4867 LRESULT WM_ACTIVATE (long wParam, long lParam) {
4871 LRESULT WM_CAPTURECHANGED (long wParam, long lParam) {
4872 return wmCaptureChanged (handle, wParam, lParam);
4875 LRESULT WM_CHANGEUISTATE (long wParam, long lParam) {
4876 if ((state & IGNORE_WM_CHANGEUISTATE) != 0) return LRESULT.ZERO;
4880 LRESULT WM_CHAR (long wParam, long lParam) {
4881 return wmChar (handle, wParam, lParam);
4884 LRESULT WM_CLEAR (long wParam, long lParam) {
4888 LRESULT WM_CLOSE (long wParam, long lParam) {
4892 LRESULT WM_COMMAND (long wParam, long lParam) {
4894 * When the WM_COMMAND message is sent from a
4895 * menu, the HWND parameter in LPARAM is zero.
4898 Decorations shell = menuShell ();
4899 if (shell.isEnabled ()) {
4900 int id = OS.LOWORD (wParam);
4901 MenuItem item = display.getMenuItem (id);
4902 if (item != null && item.isEnabled ()) {
4903 return item.wmCommandChild (wParam, lParam);
4908 Control control = display.getControl (lParam);
4909 if (control == null) return null;
4910 return control.wmCommandChild (wParam, lParam);
4913 LRESULT WM_CONTEXTMENU (long wParam, long lParam) {
4914 return wmContextMenu (handle, wParam, lParam);
4917 LRESULT WM_CTLCOLOR (long wParam, long lParam) {
4918 Control control = display.getControl (lParam);
4919 if (control == null) return null;
4920 return control.wmColorChild (wParam, lParam);
4923 LRESULT WM_CUT (long wParam, long lParam) {
4927 LRESULT WM_DESTROY (long wParam, long lParam) {
4928 OS.KillTimer (this.handle, Menu.ID_TOOLTIP_TIMER);
4932 LRESULT WM_DPICHANGED (long wParam, long lParam) {
4933 // Map DPI to Zoom and compare
4934 int nativeZoom = DPIUtil.mapDPIToZoom (OS.HIWORD (wParam));
4935 int newSWTZoom = DPIUtil.getZoomForAutoscaleProperty (nativeZoom);
4936 int oldSWTZoom = DPIUtil.getDeviceZoom();
4938 // Throw the DPI change event if zoom value changes
4939 if (newSWTZoom != oldSWTZoom) {
4940 Event event = new Event();
4941 event.type = SWT.ZoomChanged;
4942 event.widget = this;
4943 event.detail = newSWTZoom;
4945 notifyListeners(SWT.ZoomChanged, event);
4946 return LRESULT.ZERO;
4951 LRESULT WM_DRAWITEM (long wParam, long lParam) {
4952 DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
4953 OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
4954 if (struct.CtlType == OS.ODT_MENU) {
4955 MenuItem item = display.getMenuItem (struct.itemID);
4956 if (item == null) return null;
4957 return item.wmDrawChild (wParam, lParam);
4959 Control control = display.getControl (struct.hwndItem);
4960 if (control == null) return null;
4961 return control.wmDrawChild (wParam, lParam);
4964 LRESULT WM_ENDSESSION (long wParam, long lParam) {
4968 LRESULT WM_ENTERIDLE (long wParam, long lParam) {
4972 LRESULT WM_ENTERMENULOOP (long wParam, long lParam) {
4973 display.externalEventLoop = true;
4977 LRESULT WM_ENTERSIZEMOVE (long wParam, long lParam) {
4978 display.externalEventLoop = true;
4982 LRESULT WM_ERASEBKGND (long wParam, long lParam) {
4983 if ((state & DRAW_BACKGROUND) != 0) {
4984 if (findImageControl () != null) return LRESULT.ONE;
4986 if ((state & THEME_BACKGROUND) != 0) {
4987 if (OS.IsAppThemed ()) {
4988 if (findThemeControl () != null) return LRESULT.ONE;
4994 LRESULT WM_EXITMENULOOP (long wParam, long lParam) {
4995 display.externalEventLoop = false;
4999 LRESULT WM_EXITSIZEMOVE (long wParam, long lParam) {
5000 display.externalEventLoop = false;
5004 LRESULT WM_GESTURE (long wParam, long lParam) {
5005 if (hooks (SWT.Gesture) || filters (SWT.Gesture)) {
5006 GESTUREINFO gi = new GESTUREINFO ();
5007 gi.cbSize = GESTUREINFO.sizeof;
5008 if (OS.GetGestureInfo (lParam, gi)) {
5009 if (!sendGestureEvent (gi)) {
5010 OS.CloseGestureInfoHandle (lParam);
5011 return LRESULT.ZERO;
5018 LRESULT WM_GETDLGCODE (long wParam, long lParam) {
5022 LRESULT WM_GETFONT (long wParam, long lParam) {
5026 LRESULT WM_GETOBJECT (long wParam, long lParam) {
5027 if (accessible != null) {
5028 long result = accessible.internal_WM_GETOBJECT (wParam, lParam);
5029 if (result != 0) return new LRESULT (result);
5034 LRESULT WM_GETMINMAXINFO (long wParam, long lParam) {
5038 LRESULT WM_HOTKEY (long wParam, long lParam) {
5042 LRESULT WM_HELP (long wParam, long lParam) {
5043 HELPINFO lphi = new HELPINFO ();
5044 OS.MoveMemory (lphi, lParam, HELPINFO.sizeof);
5045 Decorations shell = menuShell ();
5046 if (!shell.isEnabled ()) return null;
5047 if (lphi.iContextType == OS.HELPINFO_MENUITEM) {
5048 MenuItem item = display.getMenuItem (lphi.iCtrlId);
5049 if (item != null && item.isEnabled ()) {
5050 Widget widget = null;
5051 if (item.hooks (SWT.Help)) {
5054 Menu menu = item.parent;
5055 if (menu.hooks (SWT.Help)) widget = menu;
5057 if (widget != null) {
5058 long hwndShell = shell.handle;
5059 OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
5060 widget.postEvent (SWT.Help);
5066 if (hooks (SWT.Help)) {
5067 postEvent (SWT.Help);
5073 LRESULT WM_HSCROLL (long wParam, long lParam) {
5074 Control control = display.getControl (lParam);
5075 if (control == null) return null;
5076 return control.wmScrollChild (wParam, lParam);
5079 LRESULT WM_IME_CHAR (long wParam, long lParam) {
5080 return wmIMEChar (handle, wParam, lParam);
5083 LRESULT WM_IME_COMPOSITION (long wParam, long lParam) {
5087 LRESULT WM_IME_COMPOSITION_START (long wParam, long lParam) {
5091 LRESULT WM_IME_ENDCOMPOSITION (long wParam, long lParam) {
5095 LRESULT WM_UNINITMENUPOPUP (long wParam, long lParam) {
5096 Menu hiddenMenu = menuShell ().findMenu (wParam);
5097 if (hiddenMenu != null) {
5098 Shell shell = getShell ();
5099 hiddenMenu.sendEvent (SWT.Hide);
5100 if (hiddenMenu == shell.activeMenu) shell.activeMenu = null;
5105 LRESULT WM_INITMENUPOPUP (long wParam, long lParam) {
5107 /* Ignore WM_INITMENUPOPUP for an accelerator */
5108 if (display.accelKeyHit) return null;
5111 * If the high order word of LPARAM is non-zero,
5112 * the menu is the system menu and we can ignore
5113 * WPARAM. Otherwise, use WPARAM to find the menu.
5115 Shell shell = getShell ();
5116 Menu oldMenu = shell.activeMenu, newMenu = null;
5117 if (OS.HIWORD (lParam) == 0) {
5118 newMenu = menuShell ().findMenu (wParam);
5119 if (newMenu != null) newMenu.update ();
5121 Menu menu = newMenu;
5122 while (menu != null && menu != oldMenu) {
5123 menu = menu.getParentMenu ();
5126 menu = shell.activeMenu;
5127 while (menu != null) {
5129 * It is possible (but unlikely), that application
5130 * code could have disposed the widget in the hide
5131 * event. If this happens, stop searching up the
5132 * ancestor list because there is no longer a link
5135 menu.sendEvent (SWT.Hide);
5136 if (menu.isDisposed ()) break;
5137 menu = menu.getParentMenu ();
5138 Menu ancestor = newMenu;
5139 while (ancestor != null && ancestor != menu) {
5140 ancestor = ancestor.getParentMenu ();
5142 if (ancestor != null) break;
5147 * The shell and the new menu may be disposed because of
5148 * sending the hide event to the ancestor menus but setting
5149 * a field to null in a disposed shell is not harmful.
5151 if (newMenu != null && newMenu.isDisposed ()) newMenu = null;
5152 shell.activeMenu = newMenu;
5154 /* Send the show event */
5155 if (newMenu != null && newMenu != oldMenu) {
5156 newMenu.sendEvent (SWT.Show);
5157 // widget could be disposed at this point
5162 LRESULT WM_INPUTLANGCHANGE (long wParam, long lParam) {
5163 menuShell().destroyAccelerators();
5167 LRESULT WM_KEYDOWN (long wParam, long lParam) {
5168 return wmKeyDown (handle, wParam, lParam);
5171 LRESULT WM_KEYUP (long wParam, long lParam) {
5172 return wmKeyUp (handle, wParam, lParam);
5175 LRESULT WM_KILLFOCUS (long wParam, long lParam) {
5176 return wmKillFocus (handle, wParam, lParam);
5179 LRESULT WM_LBUTTONDBLCLK (long wParam, long lParam) {
5180 return wmLButtonDblClk (handle, wParam, lParam);
5183 LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
5184 return wmLButtonDown (handle, wParam, lParam);
5187 LRESULT WM_LBUTTONUP (long wParam, long lParam) {
5188 return wmLButtonUp (handle, wParam, lParam);
5191 LRESULT WM_MBUTTONDBLCLK (long wParam, long lParam) {
5192 return wmMButtonDblClk (handle, wParam, lParam);
5195 LRESULT WM_MBUTTONDOWN (long wParam, long lParam) {
5196 return wmMButtonDown (handle, wParam, lParam);
5199 LRESULT WM_MBUTTONUP (long wParam, long lParam) {
5200 return wmMButtonUp (handle, wParam, lParam);
5203 LRESULT WM_MEASUREITEM (long wParam, long lParam) {
5204 MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT ();
5205 OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof);
5206 if (struct.CtlType == OS.ODT_MENU) {
5207 MenuItem item = display.getMenuItem (struct.itemID);
5208 if (item == null) return null;
5209 return item.wmMeasureChild (wParam, lParam);
5211 long hwnd = OS.GetDlgItem (handle, struct.CtlID);
5212 Control control = display.getControl (hwnd);
5213 if (control == null) return null;
5214 return control.wmMeasureChild (wParam, lParam);
5217 LRESULT WM_MENUCHAR (long wParam, long lParam) {
5219 * Feature in Windows. When the user types Alt+<key>
5220 * and <key> does not match a mnemonic in the System
5221 * menu or the menu bar, Windows beeps. This beep is
5222 * unexpected and unwanted by applications that look
5223 * for Alt+<key>. The fix is to detect the case and
5224 * stop Windows from beeping by closing the menu.
5226 int type = OS.HIWORD (wParam);
5227 if (type == 0 || type == OS.MF_SYSMENU) {
5228 display.mnemonicKeyHit = false;
5229 return new LRESULT (OS.MAKELRESULT (0, OS.MNC_CLOSE));
5234 LRESULT WM_MENUSELECT (long wParam, long lParam) {
5235 int code = OS.HIWORD (wParam);
5236 Shell shell = getShell ();
5237 OS.KillTimer (this.handle, Menu.ID_TOOLTIP_TIMER);
5238 if (activeMenu != null)
5239 activeMenu.hideCurrentToolTip ();
5240 if (code == 0xFFFF && lParam == 0) {
5241 Menu menu = shell.activeMenu;
5242 while (menu != null) {
5244 * When the user cancels any menu that is not the
5245 * menu bar, assume a mnemonic key was pressed to open
5246 * the menu from WM_SYSCHAR. When the menu was invoked
5247 * using the mouse, this assumption is wrong but not
5248 * harmful. This variable is only used in WM_SYSCHAR
5249 * and WM_SYSCHAR is only sent after the user has pressed
5252 display.mnemonicKeyHit = true;
5254 * It is possible (but unlikely), that application
5255 * code could have disposed the widget in the hide
5256 * event. If this happens, stop searching up the
5257 * parent list because there is no longer a link
5260 menu.sendEvent (SWT.Hide);
5261 if (menu.isDisposed ()) break;
5262 menu = menu.getParentMenu ();
5265 * The shell may be disposed because of sending the hide
5266 * event to the last active menu menu but setting a field
5267 * to null in a destroyed widget is not harmful.
5269 shell.activeMenu = null;
5272 if ((code & OS.MF_SYSMENU) != 0) return null;
5273 if ((code & OS.MF_HILITE) != 0) {
5274 MenuItem item = null;
5275 Decorations menuShell = menuShell ();
5276 if ((code & OS.MF_POPUP) != 0) {
5277 int index = OS.LOWORD (wParam);
5278 MENUITEMINFO info = new MENUITEMINFO ();
5279 info.cbSize = MENUITEMINFO.sizeof;
5280 info.fMask = OS.MIIM_SUBMENU;
5281 if (OS.GetMenuItemInfo (lParam, index, true, info)) {
5282 Menu newMenu = menuShell.findMenu (info.hSubMenu);
5283 if (newMenu != null) {
5284 item = newMenu.cascade;
5285 activeMenu = newMenu;
5286 activeMenu.selectedMenuItem = newMenu.cascade;
5287 OS.SetTimer (this.handle, Menu.ID_TOOLTIP_TIMER, OS.TTM_GETDELAYTIME, 0);
5291 Menu newMenu = menuShell.findMenu (lParam);
5292 if (newMenu != null) {
5293 int id = OS.LOWORD (wParam);
5294 item = display.getMenuItem (id);
5296 activeMenu = (newMenu == null) ? menu : newMenu;
5297 if (item != null && activeMenu != null) {
5298 activeMenu.selectedMenuItem = item;
5299 OS.SetTimer (this.handle, Menu.ID_TOOLTIP_TIMER, OS.TTM_GETDELAYTIME, 0);
5302 if (item != null) item.sendEvent (SWT.Arm);
5307 LRESULT WM_MOUSEACTIVATE (long wParam, long lParam) {
5311 LRESULT WM_MOUSEHOVER (long wParam, long lParam) {
5312 return wmMouseHover (handle, wParam, lParam);
5315 LRESULT WM_MOUSELEAVE (long wParam, long lParam) {
5316 getShell ().fixToolTip ();
5317 return wmMouseLeave (handle, wParam, lParam);
5320 LRESULT WM_MOUSEMOVE (long wParam, long lParam) {
5321 return wmMouseMove (handle, wParam, lParam);
5324 LRESULT WM_MOUSEWHEEL (long wParam, long lParam) {
5325 return wmMouseWheel (handle, wParam, lParam);
5328 LRESULT WM_MOUSEHWHEEL (long wParam, long lParam) {
5329 return wmMouseHWheel (handle, wParam, lParam);
5332 LRESULT WM_MOVE (long wParam, long lParam) {
5333 state |= MOVE_OCCURRED;
5334 if (findImageControl () != null) {
5335 if (this != getShell ()) redrawChildren ();
5337 if ((state & THEME_BACKGROUND) != 0) {
5338 if (OS.IsAppThemed ()) {
5339 if (OS.IsWindowVisible (handle)) {
5340 if (findThemeControl () != null) redrawChildren ();
5345 if ((state & MOVE_DEFERRED) == 0) sendEvent (SWT.Move);
5346 // widget could be disposed at this point
5350 LRESULT WM_NCACTIVATE (long wParam, long lParam) {
5354 LRESULT WM_NCCALCSIZE (long wParam, long lParam) {
5358 LRESULT WM_NCHITTEST (long wParam, long lParam) {
5359 if (!OS.IsWindowEnabled (handle)) return null;
5360 if (!isActive ()) return new LRESULT (OS.HTTRANSPARENT);
5364 LRESULT WM_NCLBUTTONDOWN (long wParam, long lParam) {
5368 LRESULT WM_NCPAINT (long wParam, long lParam) {
5369 return wmNCPaint (handle, wParam, lParam);
5372 LRESULT WM_NOTIFY (long wParam, long lParam) {
5373 NMHDR hdr = new NMHDR ();
5374 OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
5375 return wmNotify (hdr, wParam, lParam);
5378 LRESULT WM_PAINT (long wParam, long lParam) {
5379 if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
5380 return wmPaint (handle, wParam, lParam);
5383 LRESULT WM_PARENTNOTIFY (long wParam, long lParam) {
5387 LRESULT WM_PASTE (long wParam, long lParam) {
5391 LRESULT WM_PRINT (long wParam, long lParam) {
5392 return wmPrint (handle, wParam, lParam);
5395 LRESULT WM_PRINTCLIENT (long wParam, long lParam) {
5399 LRESULT WM_QUERYENDSESSION (long wParam, long lParam) {
5403 LRESULT WM_QUERYOPEN (long wParam, long lParam) {
5407 LRESULT WM_RBUTTONDBLCLK (long wParam, long lParam) {
5408 return wmRButtonDblClk (handle, wParam, lParam);
5411 LRESULT WM_RBUTTONDOWN (long wParam, long lParam) {
5412 return wmRButtonDown (handle, wParam, lParam);
5415 LRESULT WM_RBUTTONUP (long wParam, long lParam) {
5416 return wmRButtonUp (handle, wParam, lParam);
5419 LRESULT WM_SETCURSOR (long wParam, long lParam) {
5420 int hitTest = (short) OS.LOWORD (lParam);
5421 if (hitTest == OS.HTCLIENT) {
5422 Control control = display.getControl (wParam);
5423 if (control == null) return null;
5424 Cursor cursor = control.findCursor ();
5425 if (cursor != null) {
5426 OS.SetCursor (cursor.handle);
5433 LRESULT WM_SETFOCUS (long wParam, long lParam) {
5434 return wmSetFocus (handle, wParam, lParam);
5437 LRESULT WM_SETTINGCHANGE (long wParam, long lParam) {
5441 LRESULT WM_SETFONT (long wParam, long lParam) {
5445 LRESULT WM_SETREDRAW (long wParam, long lParam) {
5449 LRESULT WM_SHOWWINDOW (long wParam, long lParam) {
5453 LRESULT WM_SIZE (long wParam, long lParam) {
5454 state |= RESIZE_OCCURRED;
5455 if ((state & RESIZE_DEFERRED) == 0) sendEvent (SWT.Resize);
5456 // widget could be disposed at this point
5460 LRESULT WM_SYSCHAR (long wParam, long lParam) {
5461 return wmSysChar (handle, wParam, lParam);
5464 LRESULT WM_SYSCOLORCHANGE (long wParam, long lParam) {
5468 LRESULT WM_SYSCOMMAND (long wParam, long lParam) {
5470 * Check to see if the command is a system command or
5471 * a user menu item that was added to the System menu.
5472 * When a user item is added to the System menu,
5473 * WM_SYSCOMMAND must always return zero.
5475 * NOTE: This is undocumented.
5477 if ((wParam & 0xF000) == 0) {
5478 Decorations shell = menuShell ();
5479 if (shell.isEnabled ()) {
5480 MenuItem item = display.getMenuItem (OS.LOWORD (wParam));
5481 if (item != null) item.wmCommandChild (wParam, lParam);
5483 return LRESULT.ZERO;
5486 /* Process the System Command */
5487 int cmd = (int)wParam & 0xFFF0;
5491 * When lParam is zero, one of F10, Shift+F10, Ctrl+F10 or
5492 * Ctrl+Shift+F10 was pressed. If there is no menu bar and
5493 * the focus control is interested in keystrokes, give the
5494 * key to the focus control. Normally, F10 with no menu bar
5495 * moves focus to the System menu but this can be achieved
5496 * using Alt+Space. To allow the application to see F10,
5497 * avoid running the default window proc.
5499 * NOTE: When F10 is pressed, WM_SYSCOMMAND is sent to the
5500 * shell, not the focus control. This is undocumented Windows
5504 Decorations shell = menuShell ();
5505 Menu menu = shell.getMenuBar ();
5507 Control control = display._getFocusControl ();
5508 if (control != null) {
5509 if (control.hooks (SWT.KeyDown) || control.hooks (SWT.KeyUp)) {
5510 display.mnemonicKeyHit = false;
5511 return LRESULT.ZERO;
5517 * When lParam is not zero, Alt+<key> was pressed. If the
5518 * application is interested in keystrokes and there is a
5519 * menu bar, check to see whether the key that was pressed
5520 * matches a mnemonic on the menu bar. Normally, Windows
5521 * matches the first character of a menu item as well as
5522 * matching the mnemonic character. To allow the application
5523 * to see the keystrokes in this case, avoid running the default
5526 * NOTE: When the user types Alt+Space, the System menu is
5527 * activated. In this case the application should not see
5530 if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) {
5531 if (lParam != ' ') {
5532 Decorations shell = menuShell ();
5533 Menu menu = shell.getMenuBar ();
5535 char key = (char) lParam;
5537 key = Character.toUpperCase (key);
5538 MenuItem [] items = menu.getItems ();
5539 for (int i=0; i<items.length; i++) {
5540 MenuItem item = items [i];
5541 String text = item.getText ();
5542 char mnemonic = findMnemonic (text);
5543 if (text.length () > 0 && mnemonic == 0) {
5544 char ch = text.charAt (0);
5545 if (Character.toUpperCase (ch) == key) {
5546 display.mnemonicKeyHit = false;
5547 return LRESULT.ZERO;
5553 display.mnemonicKeyHit = false;
5562 * Do not allow keyboard traversal of the menu bar
5563 * or scrolling when the shell is not enabled.
5565 Decorations shell = menuShell ();
5566 if (!shell.isEnabled () || !shell.isActive ()) {
5567 return LRESULT.ZERO;
5570 case OS.SC_MINIMIZE:
5571 /* Save the focus widget when the shell is minimized */
5572 menuShell ().saveFocus ();
5578 LRESULT WM_SYSKEYDOWN (long wParam, long lParam) {
5579 return wmSysKeyDown (handle, wParam, lParam);
5582 LRESULT WM_SYSKEYUP (long wParam, long lParam) {
5583 return wmSysKeyUp (handle, wParam, lParam);
5586 LRESULT WM_TABLET_FLICK (long wParam, long lParam) {
5587 if (!hooks (SWT.Gesture) && !filters (SWT.Gesture)) return null;
5588 Event event = new Event ();
5589 FLICK_DATA fData = new FLICK_DATA ();
5590 long [] source = new long [1];
5592 OS.MoveMemory (fData, source, OS.FLICK_DATA_sizeof ());
5593 FLICK_POINT fPoint = new FLICK_POINT ();
5594 source [0] = lParam;
5595 OS.MoveMemory (fPoint, source, OS.FLICK_POINT_sizeof ());
5597 switch (fData.iFlickDirection) {
5598 case OS.FLICKDIRECTION_RIGHT:
5599 event.xDirection = 1;
5600 event.yDirection = 0;
5602 case OS.FLICKDIRECTION_UPRIGHT:
5603 event.xDirection = 1;
5604 event.yDirection = -1;
5606 case OS.FLICKDIRECTION_UP:
5607 event.xDirection = 0;
5608 event.yDirection = -1;
5610 case OS.FLICKDIRECTION_UPLEFT:
5611 event.xDirection = -1;
5612 event.yDirection = -1;
5614 case OS.FLICKDIRECTION_LEFT:
5615 event.xDirection = -1;
5616 event.yDirection = 0;
5618 case OS.FLICKDIRECTION_DOWNLEFT:
5619 event.xDirection = -1;
5620 event.yDirection = 1;
5622 case OS.FLICKDIRECTION_DOWN:
5623 event.xDirection = 0;
5624 event.yDirection = 1;
5626 case OS.FLICKDIRECTION_DOWNRIGHT:
5627 event.xDirection = 1;
5628 event.yDirection = 1;
5631 event.setLocationInPixels(fPoint.x, fPoint.y);
5632 event.type = SWT.Gesture;
5633 event.detail = SWT.GESTURE_SWIPE;
5634 setInputState (event, SWT.Gesture);
5635 sendEvent (SWT.Gesture, event);
5636 return event.doit ? null : LRESULT.ONE;
5639 LRESULT WM_TOUCH (long wParam, long lParam) {
5640 LRESULT result = null;
5641 if (hooks (SWT.Touch) || filters (SWT.Touch)) {
5642 int cInputs = OS.LOWORD (wParam);
5643 long hHeap = OS.GetProcessHeap ();
5644 long pInputs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, cInputs * TOUCHINPUT.sizeof);
5646 if (OS.GetTouchInputInfo (lParam, cInputs, pInputs, TOUCHINPUT.sizeof)) {
5647 TOUCHINPUT ti [] = new TOUCHINPUT [cInputs];
5648 for (int i = 0; i < cInputs; i++){
5649 ti [i] = new TOUCHINPUT ();
5650 OS.MoveMemory (ti [i], pInputs + i * TOUCHINPUT.sizeof, TOUCHINPUT.sizeof);
5652 sendTouchEvent (ti);
5653 OS.CloseTouchInputHandle (lParam);
5654 result = LRESULT.ZERO;
5656 OS.HeapFree (hHeap, 0, pInputs);
5662 LRESULT WM_TIMER (long wParam, long lParam) {
5663 if (wParam == Menu.ID_TOOLTIP_TIMER && activeMenu != null) {
5664 OS.KillTimer (this.handle, Menu.ID_TOOLTIP_TIMER);
5665 activeMenu.wmTimer (wParam, lParam);
5670 LRESULT WM_UNDO (long wParam, long lParam) {
5674 LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
5678 LRESULT WM_VSCROLL (long wParam, long lParam) {
5679 Control control = display.getControl (lParam);
5680 if (control == null) return null;
5681 return control.wmScrollChild (wParam, lParam);
5684 LRESULT WM_WINDOWPOSCHANGED (long wParam, long lParam) {
5686 display.resizeCount++;
5687 long code = callWindowProc (handle, OS.WM_WINDOWPOSCHANGED, wParam, lParam);
5688 return code == 0 ? LRESULT.ZERO : new LRESULT (code);
5690 --display.resizeCount;
5694 LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
5696 * Bug in Windows. When WM_SETREDRAW is used to turn off drawing
5697 * for a control and the control is moved or resized, Windows does
5698 * not redraw the area where the control once was in the parent.
5699 * The fix is to detect this case and redraw the area.
5701 if (!getDrawing()) {
5702 Shell shell = getShell ();
5703 if (shell != this) {
5704 WINDOWPOS lpwp = new WINDOWPOS ();
5705 OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
5706 if ((lpwp.flags & OS.SWP_NOMOVE) == 0 || (lpwp.flags & OS.SWP_NOSIZE) == 0) {
5707 RECT rect = new RECT ();
5708 OS.GetWindowRect (topHandle (), rect);
5709 int width = rect.right - rect.left;
5710 int height = rect.bottom - rect.top;
5711 if (width != 0 && height != 0) {
5712 long hwndParent = parent == null ? 0 : parent.handle;
5713 OS.MapWindowPoints (0, hwndParent, rect, 2);
5714 long rgn1 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
5715 long rgn2 = OS.CreateRectRgn (lpwp.x, lpwp.y, lpwp.x + lpwp.cx, lpwp.y + lpwp.cy);
5716 OS.CombineRgn (rgn1, rgn1, rgn2, OS.RGN_DIFF);
5717 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
5718 OS.RedrawWindow (hwndParent, null, rgn1, flags);
5719 OS.DeleteObject (rgn1);
5720 OS.DeleteObject (rgn2);
5728 LRESULT WM_XBUTTONDBLCLK (long wParam, long lParam) {
5729 return wmXButtonDblClk (handle, wParam, lParam);
5732 LRESULT WM_XBUTTONDOWN (long wParam, long lParam) {
5733 return wmXButtonDown (handle, wParam, lParam);
5736 LRESULT WM_XBUTTONUP (long wParam, long lParam) {
5737 return wmXButtonUp (handle, wParam, lParam);
5740 LRESULT wmColorChild (long wParam, long lParam) {
5741 Control control = findBackgroundControl ();
5742 if (control == null) {
5743 if ((state & THEME_BACKGROUND) != 0) {
5744 if (OS.IsAppThemed ()) {
5745 control = findThemeControl ();
5746 if (control != null) {
5747 RECT rect = new RECT ();
5748 OS.GetClientRect (handle, rect);
5749 OS.SetTextColor (wParam, getForegroundPixel ());
5750 OS.SetBkColor (wParam, getBackgroundPixel ());
5751 fillThemeBackground (wParam, control, rect);
5752 OS.SetBkMode (wParam, OS.TRANSPARENT);
5753 return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
5757 if (foreground == -1) return null;
5759 if (control == null) control = this;
5760 int forePixel = getForegroundPixel ();
5761 int backPixel = control.getBackgroundPixel ();
5762 OS.SetTextColor (wParam, forePixel);
5763 OS.SetBkColor (wParam, backPixel);
5764 if (control.backgroundImage != null) {
5765 RECT rect = new RECT ();
5766 OS.GetClientRect (handle, rect);
5767 long hwnd = control.handle;
5768 long hBitmap = control.backgroundImage.handle;
5769 OS.MapWindowPoints (handle, hwnd, rect, 2);
5770 POINT lpPoint = new POINT ();
5771 OS.GetWindowOrgEx (wParam, lpPoint);
5772 OS.SetBrushOrgEx (wParam, -rect.left - lpPoint.x, -rect.top - lpPoint.y, lpPoint);
5773 long hBrush = findBrush (hBitmap, OS.BS_PATTERN);
5774 if ((state & DRAW_BACKGROUND) != 0) {
5775 long hOldBrush = OS.SelectObject (wParam, hBrush);
5776 OS.MapWindowPoints (hwnd, handle, rect, 2);
5777 OS.PatBlt (wParam, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
5778 OS.SelectObject (wParam, hOldBrush);
5780 OS.SetBkMode (wParam, OS.TRANSPARENT);
5781 return new LRESULT (hBrush);
5783 long hBrush = findBrush (backPixel, OS.BS_SOLID);
5784 if ((state & DRAW_BACKGROUND) != 0) {
5785 RECT rect = new RECT ();
5786 OS.GetClientRect (handle, rect);
5787 long hOldBrush = OS.SelectObject (wParam, hBrush);
5788 OS.PatBlt (wParam, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
5789 OS.SelectObject (wParam, hOldBrush);
5791 return new LRESULT (hBrush);
5794 LRESULT wmCommandChild (long wParam, long lParam) {
5798 LRESULT wmDrawChild (long wParam, long lParam) {
5802 LRESULT wmMeasureChild (long wParam, long lParam) {
5806 LRESULT wmNotify (NMHDR hdr, long wParam, long lParam) {
5807 Control control = display.getControl (hdr.hwndFrom);
5808 if (control == null) return null;
5809 return control.wmNotifyChild (hdr, wParam, lParam);
5812 LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
5816 LRESULT wmScrollChild (long wParam, long lParam) {