1 /*******************************************************************************
2 * Copyright (c) 2000, 2016 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 *******************************************************************************/
14 package org.eclipse.swt.widgets;
17 import org.eclipse.swt.*;
18 import org.eclipse.swt.events.*;
19 import org.eclipse.swt.graphics.*;
20 import org.eclipse.swt.internal.*;
21 import org.eclipse.swt.internal.win32.*;
24 * Instances of this class represent the "windows"
25 * which the desktop or "window manager" is managing.
26 * Instances that do not have a parent (that is, they
27 * are built using the constructor, which takes a
28 * <code>Display</code> as the argument) are described
29 * as <em>top level</em> shells. Instances that do have
30 * a parent are described as <em>secondary</em> or
31 * <em>dialog</em> shells.
33 * Instances are always displayed in one of the maximized,
34 * minimized or normal states:</p>
37 * When an instance is marked as <em>maximized</em>, the
38 * window manager will typically resize it to fill the
39 * entire visible area of the display, and the instance
40 * is usually put in a state where it can not be resized
41 * (even if it has style <code>RESIZE</code>) until it is
42 * no longer maximized.
44 * When an instance is in the <em>normal</em> state (neither
45 * maximized or minimized), its appearance is controlled by
46 * the style constants which were specified when it was created
47 * and the restrictions of the window manager (see below).
49 * When an instance has been marked as <em>minimized</em>,
50 * its contents (client area) will usually not be visible,
51 * and depending on the window manager, it may be
52 * "iconified" (that is, replaced on the desktop by a small
53 * simplified representation of itself), relocated to a
54 * distinguished area of the screen, or hidden. Combinations
55 * of these changes are also possible.
59 * The <em>modality</em> of an instance may be specified using
60 * style bits. The modality style bits are used to determine
61 * whether input is blocked for other shells on the display.
62 * The <code>PRIMARY_MODAL</code> style allows an instance to block
63 * input to its parent. The <code>APPLICATION_MODAL</code> style
64 * allows an instance to block input to every other shell in the
65 * display. The <code>SYSTEM_MODAL</code> style allows an instance
66 * to block input to all shells, including shells belonging to
67 * different applications.
69 * Note: The styles supported by this class are treated
70 * as <em>HINT</em>s, since the window manager for the
71 * desktop on which the instance is visible has ultimate
72 * control over the appearance and behavior of decorations
73 * and modality. For example, some window managers only
74 * support resizable windows and will always assume the
75 * RESIZE style, even if it is not set. In addition, if a
76 * modality style is not supported, it is "upgraded" to a
77 * more restrictive modality style that is supported. For
78 * example, if <code>PRIMARY_MODAL</code> is not supported,
79 * it would be upgraded to <code>APPLICATION_MODAL</code>.
80 * A modality style may also be "downgraded" to a less
81 * restrictive style. For example, most operating systems
82 * no longer support <code>SYSTEM_MODAL</code> because
83 * it can freeze up the desktop, so this is typically
84 * downgraded to <code>APPLICATION_MODAL</code>.</p>
86 * <dt><b>Styles:</b></dt>
87 * <dd>BORDER, CLOSE, MIN, MAX, NO_MOVE, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL, SHEET</dd>
88 * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
89 * <dt><b>Events:</b></dt>
90 * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
93 * Class <code>SWT</code> provides two "convenience constants"
94 * for the most commonly required style combinations:</p>
96 * <dt><code>SHELL_TRIM</code></dt>
98 * the result of combining the constants which are required
99 * to produce a typical application top level shell: (that
100 * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
102 * <dt><code>DIALOG_TRIM</code></dt>
104 * the result of combining the constants which are required
105 * to produce a typical application dialog shell: (that
106 * is, <code>TITLE | CLOSE | BORDER</code>)
110 * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
111 * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
113 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
118 * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell snippets</a>
119 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
120 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
121 * @noextend This class is not intended to be subclassed by clients.
123 public class Shell extends Decorations {
126 long hIMC, hwndMDIClient, lpstrTip, toolTipHandle, balloonTipHandle, menuItemToolTipHandle;
127 int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT;
129 boolean showWithParent, fullScreen, wasMaximized, modified, center;
130 String toolTitle, balloonTitle;
131 long toolIcon, balloonIcon;
134 static /*final*/ long ToolTipProc;
135 static final long DialogProc;
136 static final TCHAR DialogClass = new TCHAR (0, "#32770", true);
137 final static int [] SYSTEM_COLORS = {
145 final static int BRUSHES_SIZE = 32;
147 WNDCLASS lpWndClass = new WNDCLASS ();
148 OS.GetClassInfo (0, DialogClass, lpWndClass);
149 DialogProc = lpWndClass.lpfnWndProc;
153 * Constructs a new instance of this class. This is equivalent
154 * to calling <code>Shell((Display) null)</code>.
156 * @exception SWTException <ul>
157 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
158 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
162 this ((Display) null);
166 * Constructs a new instance of this class given only the style
167 * value describing its behavior and appearance. This is equivalent
168 * to calling <code>Shell((Display) null, style)</code>.
170 * The style value is either one of the style constants defined in
171 * class <code>SWT</code> which is applicable to instances of this
172 * class, or must be built by <em>bitwise OR</em>'ing together
173 * (that is, using the <code>int</code> "|" operator) two or more
174 * of those <code>SWT</code> style constants. The class description
175 * lists the style constants that are applicable to the class.
176 * Style bits are also inherited from superclasses.
179 * @param style the style of control to construct
181 * @exception SWTException <ul>
182 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
183 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
195 * @see SWT#SHELL_TRIM
196 * @see SWT#DIALOG_TRIM
199 * @see SWT#PRIMARY_MODAL
200 * @see SWT#APPLICATION_MODAL
201 * @see SWT#SYSTEM_MODAL
204 public Shell (int style) {
205 this ((Display) null, style);
209 * Constructs a new instance of this class given only the display
210 * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>.
212 * Note: Currently, null can be passed in for the display argument.
213 * This has the effect of creating the shell on the currently active
214 * display if there is one. If there is no current display, the
215 * shell is created on a "default" display. <b>Passing in null as
216 * the display argument is not considered to be good coding style,
217 * and may not be supported in a future release of SWT.</b>
220 * @param display the display to create the shell on
222 * @exception SWTException <ul>
223 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
224 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
227 public Shell (Display display) {
228 this (display, SWT.SHELL_TRIM);
232 * Constructs a new instance of this class given the display
233 * to create it on and a style value describing its behavior
236 * The style value is either one of the style constants defined in
237 * class <code>SWT</code> which is applicable to instances of this
238 * class, or must be built by <em>bitwise OR</em>'ing together
239 * (that is, using the <code>int</code> "|" operator) two or more
240 * of those <code>SWT</code> style constants. The class description
241 * lists the style constants that are applicable to the class.
242 * Style bits are also inherited from superclasses.
244 * Note: Currently, null can be passed in for the display argument.
245 * This has the effect of creating the shell on the currently active
246 * display if there is one. If there is no current display, the
247 * shell is created on a "default" display. <b>Passing in null as
248 * the display argument is not considered to be good coding style,
249 * and may not be supported in a future release of SWT.</b>
252 * @param display the display to create the shell on
253 * @param style the style of control to construct
255 * @exception SWTException <ul>
256 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
257 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
269 * @see SWT#SHELL_TRIM
270 * @see SWT#DIALOG_TRIM
273 * @see SWT#PRIMARY_MODAL
274 * @see SWT#APPLICATION_MODAL
275 * @see SWT#SYSTEM_MODAL
278 public Shell (Display display, int style) {
279 this (display, null, style, 0, false);
282 Shell (Display display, Shell parent, int style, long handle, boolean embedded) {
285 if (display == null) display = Display.getCurrent ();
286 if (display == null) display = Display.getDefault ();
287 if (!display.isValidThread ()) {
288 error (SWT.ERROR_THREAD_INVALID_ACCESS);
290 if (parent != null && parent.isDisposed ()) {
291 error (SWT.ERROR_INVALID_ARGUMENT);
293 this.center = parent != null && (style & SWT.SHEET) != 0;
294 this.style = checkStyle (parent, style);
295 this.parent = parent;
296 this.display = display;
297 this.handle = handle;
298 if (handle != 0 && !embedded) {
299 state |= FOREIGN_HANDLE;
306 * Constructs a new instance of this class given only its
307 * parent. It is created with style <code>SWT.DIALOG_TRIM</code>.
309 * Note: Currently, null can be passed in for the parent.
310 * This has the effect of creating the shell on the currently active
311 * display if there is one. If there is no current display, the
312 * shell is created on a "default" display. <b>Passing in null as
313 * the parent is not considered to be good coding style,
314 * and may not be supported in a future release of SWT.</b>
317 * @param parent a shell which will be the parent of the new instance
319 * @exception IllegalArgumentException <ul>
320 * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
322 * @exception SWTException <ul>
323 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
324 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
327 public Shell (Shell parent) {
328 this (parent, SWT.DIALOG_TRIM);
332 * Constructs a new instance of this class given its parent
333 * and a style value describing its behavior and appearance.
335 * The style value is either one of the style constants defined in
336 * class <code>SWT</code> which is applicable to instances of this
337 * class, or must be built by <em>bitwise OR</em>'ing together
338 * (that is, using the <code>int</code> "|" operator) two or more
339 * of those <code>SWT</code> style constants. The class description
340 * lists the style constants that are applicable to the class.
341 * Style bits are also inherited from superclasses.
343 * Note: Currently, null can be passed in for the parent.
344 * This has the effect of creating the shell on the currently active
345 * display if there is one. If there is no current display, the
346 * shell is created on a "default" display. <b>Passing in null as
347 * the parent is not considered to be good coding style,
348 * and may not be supported in a future release of SWT.</b>
351 * @param parent a shell which will be the parent of the new instance
352 * @param style the style of control to construct
354 * @exception IllegalArgumentException <ul>
355 * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
357 * @exception SWTException <ul>
358 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
359 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
370 * @see SWT#SHELL_TRIM
371 * @see SWT#DIALOG_TRIM
375 * @see SWT#PRIMARY_MODAL
376 * @see SWT#APPLICATION_MODAL
377 * @see SWT#SYSTEM_MODAL
380 public Shell (Shell parent, int style) {
381 this (parent != null ? parent.display : null, parent, style, 0, false);
385 * Invokes platform specific functionality to allocate a new shell
388 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
389 * API for <code>Shell</code>. It is marked public only so that it
390 * can be shared within the packages provided by SWT. It is not
391 * available on all platforms, and should never be called from
395 * @param display the display for the shell
396 * @param handle the handle for the shell
397 * @return a new shell object containing the specified display and handle
399 * @noreference This method is not intended to be referenced by clients.
401 public static Shell win32_new (Display display, long handle) {
402 return new Shell (display, null, SWT.NO_TRIM, handle, true);
406 * Invokes platform specific functionality to allocate a new shell
407 * that is not embedded.
409 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
410 * API for <code>Shell</code>. It is marked public only so that it
411 * can be shared within the packages provided by SWT. It is not
412 * available on all platforms, and should never be called from
416 * @param display the display for the shell
417 * @param handle the handle for the shell
418 * @return a new shell object containing the specified display and handle
420 * @noreference This method is not intended to be referenced by clients.
424 public static Shell internal_new (Display display, long handle) {
425 return new Shell (display, null, SWT.NO_TRIM, handle, false);
428 static int checkStyle (Shell parent, int style) {
429 style = Decorations.checkStyle (style);
430 style &= ~SWT.TRANSPARENT;
431 int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
432 if ((style & SWT.SHEET) != 0) {
434 style |= parent == null ? SWT.SHELL_TRIM : SWT.DIALOG_TRIM;
435 if ((style & mask) == 0) {
436 style |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL;
439 int bits = style & ~mask;
440 if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
441 if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
442 if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL;
447 * Adds the listener to the collection of listeners who will
448 * be notified when operations are performed on the receiver,
449 * by sending the listener one of the messages defined in the
450 * <code>ShellListener</code> interface.
452 * @param listener the listener which should be notified
454 * @exception IllegalArgumentException <ul>
455 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
457 * @exception SWTException <ul>
458 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
459 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
463 * @see #removeShellListener
465 public void addShellListener (ShellListener listener) {
467 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
468 TypedListener typedListener = new TypedListener (listener);
469 addListener (SWT.Close,typedListener);
470 addListener (SWT.Iconify,typedListener);
471 addListener (SWT.Deiconify,typedListener);
472 addListener (SWT.Activate, typedListener);
473 addListener (SWT.Deactivate, typedListener);
476 long balloonTipHandle () {
477 if (balloonTipHandle == 0) createBalloonTipHandle ();
478 return balloonTipHandle;
482 long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
483 if (handle == 0) return 0;
484 if (hwnd == toolTipHandle || hwnd == balloonTipHandle || hwnd == menuItemToolTipHandle) {
485 return OS.CallWindowProc (ToolTipProc, hwnd, msg, wParam, lParam);
487 if (hwndMDIClient != 0) {
488 return OS.DefFrameProc (hwnd, hwndMDIClient, msg, wParam, lParam);
490 if (windowProc != 0) {
491 return OS.CallWindowProc (windowProc, hwnd, msg, wParam, lParam);
493 if ((style & SWT.TOOL) != 0) {
494 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
495 if ((style & trim) == 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam);
497 if ((style & SWT.NO_MOVE) != 0) {
498 setItemEnabled (OS.SC_MOVE, false);
500 if (parent != null) {
502 case OS.WM_KILLFOCUS:
504 return OS.DefWindowProc (hwnd, msg, wParam, lParam);
506 return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam);
508 return OS.DefWindowProc (hwnd, msg, wParam, lParam);
512 if (parent == null) return;
513 Rectangle rect = getBoundsInPixels ();
514 Rectangle parentRect = display.mapInPixels (parent, null, parent.getClientAreaInPixels());
515 int x = Math.max (parentRect.x, parentRect.x + (parentRect.width - rect.width) / 2);
516 int y = Math.max (parentRect.y, parentRect.y + (parentRect.height - rect.height) / 2);
517 Rectangle monitorRect = parent.getMonitor ().getClientArea();
518 if (x + rect.width > monitorRect.x + monitorRect.width) {
519 x = Math.max (monitorRect.x, monitorRect.x + monitorRect.width - rect.width);
521 x = Math.max (x, monitorRect.x);
523 if (y + rect.height > monitorRect.y + monitorRect.height) {
524 y = Math.max (monitorRect.y, monitorRect.y + monitorRect.height - rect.height);
526 y = Math.max (y, monitorRect.y);
528 setLocationInPixels (x, y);
532 * Requests that the window manager close the receiver in
533 * the same way it would be closed when the user clicks on
534 * the "close box" or performs some other platform specific
535 * key or mouse combination that indicates the window
538 * @exception SWTException <ul>
539 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
540 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
546 public void close () {
551 void createBalloonTipHandle () {
552 balloonTipHandle = OS.CreateWindowEx (
554 new TCHAR (0, OS.TOOLTIPS_CLASS, true),
556 OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON,
557 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
560 OS.GetModuleHandle (null),
562 if (balloonTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
563 if (ToolTipProc == 0) {
564 ToolTipProc = OS.GetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC);
567 * Feature in Windows. Despite the fact that the
568 * tool tip text contains \r\n, the tooltip will
569 * not honour the new line unless TTM_SETMAXTIPWIDTH
570 * is set. The fix is to set TTM_SETMAXTIPWIDTH to
573 OS.SendMessage (balloonTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
574 display.addControl (balloonTipHandle, this);
575 OS.SetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC, display.windowProc);
579 void createHandle () {
580 boolean embedded = handle != 0 && (state & FOREIGN_HANDLE) == 0;
583 * On Windows 98 and NT, setting a window to be the
584 * top most window using HWND_TOPMOST can result in a
585 * parent dialog shell being moved behind its parent
586 * if the dialog has a sibling that is currently on top
587 * This only occurs using SetWindowPos (), not when the
591 * The following code is intentionally commented.
593 // if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = true;
594 if (handle == 0 || embedded) {
595 super.createHandle ();
598 if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
599 state |= THEME_BACKGROUND;
601 windowProc = OS.GetWindowLongPtr (handle, OS.GWL_WNDPROC);
605 * The following code is intentionally commented.
607 // if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = false;
610 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
611 bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION);
613 if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
614 if ((style & SWT.NO_TRIM) == 0) {
615 if ((style & (SWT.BORDER | SWT.RESIZE)) == 0) bits |= OS.WS_BORDER;
618 * Bug in Windows. When the WS_CAPTION bits are cleared using
619 * SetWindowLong(), Windows does not resize the client area of
620 * the window to get rid of the caption until the first resize.
621 * The fix is to use SetWindowPos() with SWP_DRAWFRAME to force
622 * the frame to be redrawn and resized.
624 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
625 int flags = OS.SWP_DRAWFRAME | OS.SWP_NOMOVE | OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
626 OS.SetWindowPos (handle, 0, 0, 0, 0, 0, flags);
629 hIMC = OS.ImmCreateContext ();
630 if (hIMC != 0) OS.ImmAssociateContext (handle, hIMC);
634 void createMenuItemToolTipHandle() {
635 menuItemToolTipHandle = createToolTipHandle (0);
638 void createToolTip (ToolTip toolTip) {
640 if (toolTips == null) toolTips = new ToolTip [4];
641 while (id < toolTips.length && toolTips [id] != null) id++;
642 if (id == toolTips.length) {
643 ToolTip [] newToolTips = new ToolTip [toolTips.length + 4];
644 System.arraycopy (toolTips, 0, newToolTips, 0, toolTips.length);
645 toolTips = newToolTips;
647 toolTips [id] = toolTip;
648 toolTip.id = id + Display.ID_START;
649 TOOLINFO lpti = new TOOLINFO ();
650 lpti.cbSize = TOOLINFO.sizeof;
652 lpti.uId = toolTip.id;
653 lpti.uFlags = OS.TTF_TRACK;
654 lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
655 OS.SendMessage (toolTip.hwndToolTip (), OS.TTM_ADDTOOL, 0, lpti);
658 void createToolTipHandle () {
659 toolTipHandle = createToolTipHandle (handle);
662 long createToolTipHandle (long parent) {
663 long toolTipHandle = OS.CreateWindowEx (
665 new TCHAR (0, OS.TOOLTIPS_CLASS, true),
667 OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX,
668 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
671 OS.GetModuleHandle (null),
673 if (toolTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
674 if (ToolTipProc == 0) {
675 ToolTipProc = OS.GetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC);
678 * Feature in Windows. Despite the fact that the
679 * tool tip text contains \r\n, the tooltip will
680 * not honour the new line unless TTM_SETMAXTIPWIDTH
681 * is set. The fix is to set TTM_SETMAXTIPWIDTH to
684 OS.SendMessage (toolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
685 display.addControl (toolTipHandle, this);
686 OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, display.windowProc);
687 return toolTipHandle;
693 if (toolTipHandle != 0) display.removeControl (toolTipHandle);
694 if (balloonTipHandle != 0) display.removeControl (balloonTipHandle);
695 if (menuItemToolTipHandle != 0) display.removeControl (menuItemToolTipHandle);
698 void destroyToolTip (ToolTip toolTip) {
699 if (toolTips == null) return;
700 toolTips [toolTip.id - Display.ID_START] = null;
701 if (balloonTipHandle != 0) {
702 TOOLINFO lpti = new TOOLINFO ();
703 lpti.cbSize = TOOLINFO.sizeof;
704 lpti.uId = toolTip.id;
706 OS.SendMessage (balloonTipHandle, OS.TTM_DELTOOL, 0, lpti);
712 void destroyWidget () {
714 super.destroyWidget ();
717 * Destroy context only after the controls that used it were destroyed.
718 * Technically, that shouldn't be necessary, because 'Control.releaseWidget'
719 * clears up association by calling 'OS.ImmAssociateContext (handle, 0)'.
720 * However, there's a bug in Windows 10 (see bug 526758), and this is the workaround.
723 if (hIMC != 0) OS.ImmDestroyContext (hIMC);
728 public void dispose () {
730 * This code is intentionally commented. On some
731 * platforms, the owner window is repainted right
732 * away when a dialog window exits. This behavior
733 * is currently unspecified.
736 // * Note: It is valid to attempt to dispose a widget
737 // * more than once. If this happens, fail silently.
739 // if (!isValidWidget ()) return;
740 // if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
741 // Display oldDisplay = display;
743 // widget is disposed at this point
744 // if (oldDisplay != null) oldDisplay.update ();
748 void enableWidget (boolean enabled) {
754 if (Display.TrimEnabled) {
755 if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled);
757 OS.EnableWindow (handle, enabled);
762 long findBrush (long value, int lbStyle) {
763 if (lbStyle == OS.BS_SOLID) {
764 for (int i=0; i<SYSTEM_COLORS.length; i++) {
765 if (value == OS.GetSysColor (SYSTEM_COLORS [i])) {
766 return OS.GetSysColorBrush (SYSTEM_COLORS [i]);
770 if (brushes == null) brushes = new long [BRUSHES_SIZE];
771 LOGBRUSH logBrush = new LOGBRUSH ();
772 for (int i=0; i<brushes.length; i++) {
773 long hBrush = brushes [i];
774 if (hBrush == 0) break;
775 OS.GetObject (hBrush, LOGBRUSH.sizeof, logBrush);
776 switch (logBrush.lbStyle) {
778 if (lbStyle == OS.BS_SOLID) {
779 if (logBrush.lbColor == value) return hBrush;
783 if (lbStyle == OS.BS_PATTERN) {
784 if (logBrush.lbHatch == value) return hBrush;
789 int length = brushes.length;
790 long hBrush = brushes [--length];
791 if (hBrush != 0) OS.DeleteObject (hBrush);
792 System.arraycopy (brushes, 0, brushes, 1, length);
795 hBrush = OS.CreateSolidBrush ((int)value);
798 hBrush = OS.CreatePatternBrush (value);
801 return brushes [0] = hBrush;
805 Control findBackgroundControl () {
806 return background != -1 || backgroundImage != null ? this : null;
810 Cursor findCursor () {
815 Control findThemeControl () {
819 ToolTip findToolTip (int id) {
820 if (toolTips == null) return null;
821 id = id - Display.ID_START;
822 return 0 <= id && id < toolTips.length ? toolTips [id] : null;
825 void fixActiveShell () {
827 * Feature in Windows. When the active shell is disposed
828 * or hidden, Windows normally makes the parent shell active
829 * and assigns focus. This does not happen when the parent
830 * shell is disabled. Instead, Windows assigns focus to the
831 * next shell on the desktop (possibly a shell in another
832 * application). The fix is to activate the disabled parent
833 * shell before disposing or hiding the active shell.
835 long hwndParent = OS.GetParent (handle);
836 if (hwndParent != 0 && handle == OS.GetActiveWindow ()) {
837 if (!OS.IsWindowEnabled (hwndParent) && OS.IsWindowVisible (hwndParent)) {
838 OS.SetActiveWindow (hwndParent);
843 void fixShell (Shell newShell, Control control) {
844 if (this == newShell) return;
845 if (control == lastActive) setActiveControl (null);
846 String toolTipText = control.toolTipText;
847 if (toolTipText != null) {
848 control.setToolTipText (this, null);
849 control.setToolTipText (newShell, toolTipText);
855 * Bug in Windows. On XP, when a tooltip is
856 * hidden due to a time out or mouse press,
857 * the tooltip remains active although no
858 * longer visible and won't show again until
859 * another tooltip becomes active. If there
860 * is only one tooltip in the window, it will
861 * never show again. The fix is to remove the
862 * current tooltip and add it again every time
863 * the mouse leaves the control.
865 if (toolTipHandle == 0) return;
866 TOOLINFO lpti = new TOOLINFO ();
867 lpti.cbSize = TOOLINFO.sizeof;
868 if (OS.SendMessage (toolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
869 if ((lpti.uFlags & OS.TTF_IDISHWND) != 0) {
870 OS.SendMessage (toolTipHandle, OS.TTM_DELTOOL, 0, lpti);
871 OS.SendMessage (toolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
874 TOOLINFO lptiMt = new TOOLINFO ();
875 lptiMt.cbSize = TOOLINFO.sizeof;
876 if (OS.SendMessage (menuItemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lptiMt) != 0) {
877 if ((lptiMt.uFlags & OS.TTF_IDISHWND) != 0) {
878 OS.SendMessage (menuItemToolTipHandle, OS.TTM_DELTOOL, 0, lptiMt);
879 OS.SendMessage (menuItemToolTipHandle, OS.TTM_ADDTOOL, 0, lptiMt);
885 * If the receiver is visible, moves it to the top of the
886 * drawing order for the display on which it was created
887 * (so that all other shells on that display, which are not
888 * the receiver's children will be drawn behind it) and forces
889 * the window manager to make the shell active.
891 * @exception SWTException <ul>
892 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
893 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
897 * @see Control#moveAbove
898 * @see Control#setFocus
899 * @see Control#setVisible
900 * @see Display#getActiveShell
901 * @see Decorations#setDefaultButton(Button)
903 * @see Shell#setActive
905 public void forceActive () {
907 if(!isVisible()) return;
908 OS.SetForegroundWindow (handle);
912 void forceResize () {
917 * Returns the receiver's alpha value. The alpha value
918 * is between 0 (transparent) and 255 (opaque).
920 * @return the alpha value
922 * @exception SWTException <ul>
923 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
924 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
929 public int getAlpha () {
931 byte [] pbAlpha = new byte [1];
932 if (OS.GetLayeredWindowAttributes (handle, null, pbAlpha, null)) {
933 return pbAlpha [0] & 0xFF;
938 @Override Rectangle getBoundsInPixels () {
939 if (OS.IsIconic (handle)) return super.getBoundsInPixels ();
940 RECT rect = new RECT ();
941 OS.GetWindowRect (handle, rect);
942 int width = rect.right - rect.left;
943 int height = rect.bottom - rect.top;
944 return new Rectangle (rect.left, rect.top, width, height);
947 ToolTip getCurrentToolTip () {
948 if (toolTipHandle != 0) {
949 ToolTip tip = getCurrentToolTip (toolTipHandle);
950 if (tip != null) return tip;
952 if (balloonTipHandle != 0) {
953 ToolTip tip = getCurrentToolTip (balloonTipHandle);
954 if (tip != null) return tip;
956 if (menuItemToolTipHandle != 0) {
957 ToolTip tip = getCurrentToolTip (menuItemToolTipHandle);
958 if (tip != null) return tip;
963 ToolTip getCurrentToolTip (long hwndToolTip) {
964 if (hwndToolTip == 0) return null;
965 if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
966 TOOLINFO lpti = new TOOLINFO ();
967 lpti.cbSize = TOOLINFO.sizeof;
968 if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
969 if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) return findToolTip ((int)lpti.uId);
976 public boolean getEnabled () {
978 return (state & DISABLED) == 0;
982 * Returns <code>true</code> if the receiver is currently
983 * in fullscreen state, and false otherwise.
986 * @return the fullscreen state
988 * @exception SWTException <ul>
989 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
990 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
995 public boolean getFullScreen () {
1001 * Returns the receiver's input method editor mode. This
1002 * will be the result of bitwise OR'ing together one or
1003 * more of the following constants defined in class
1005 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
1006 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
1008 * @return the IME mode
1010 * @exception SWTException <ul>
1011 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1012 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1017 public int getImeInputMode () {
1019 if (!OS.IsDBLocale) return 0;
1020 long hIMC = OS.ImmGetContext (handle);
1021 int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
1022 boolean open = OS.ImmGetOpenStatus (hIMC);
1023 if (open) open = OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence);
1024 OS.ImmReleaseContext (handle, hIMC);
1025 if (!open) return SWT.NONE;
1027 if ((lpfdwConversion [0] & OS.IME_CMODE_ROMAN) != 0) result |= SWT.ROMAN;
1028 if ((lpfdwConversion [0] & OS.IME_CMODE_FULLSHAPE) != 0) result |= SWT.DBCS;
1029 if ((lpfdwConversion [0] & OS.IME_CMODE_KATAKANA) != 0) return result | SWT.PHONETIC;
1030 if ((lpfdwConversion [0] & OS.IME_CMODE_NATIVE) != 0) return result | SWT.NATIVE;
1031 return result | SWT.ALPHA;
1034 @Override Point getLocationInPixels () {
1035 if (OS.IsIconic (handle)) return super.getLocationInPixels ();
1036 RECT rect = new RECT ();
1037 OS.GetWindowRect (handle, rect);
1038 return new Point (rect.left, rect.top);
1042 public boolean getMaximized () {
1044 return !fullScreen && super.getMaximized ();
1048 * Returns a point describing the minimum receiver's size. The
1049 * x coordinate of the result is the minimum width of the receiver.
1050 * The y coordinate of the result is the minimum height of the
1053 * @return the receiver's size
1055 * @exception SWTException <ul>
1056 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1057 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1062 public Point getMinimumSize () {
1064 return DPIUtil.autoScaleDown(getMinimumSizeInPixels());
1067 Point getMinimumSizeInPixels () {
1068 int width = Math.max (0, minWidth);
1069 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1070 if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
1071 width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
1073 int height = Math.max (0, minHeight);
1074 if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
1075 if ((style & SWT.RESIZE) != 0) {
1076 height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
1078 RECT rect = new RECT ();
1079 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
1080 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1081 OS.AdjustWindowRectEx (rect, bits1, false, bits2);
1082 height = Math.max (height, rect.bottom - rect.top);
1085 return new Point (width, height);
1089 * Gets the receiver's modified state.
1091 * @return <code>true</code> if the receiver is marked as modified, or <code>false</code> otherwise
1093 * @exception SWTException <ul>
1094 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1095 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1100 public boolean getModified () {
1106 * Returns the region that defines the shape of the shell,
1107 * or <code>null</code> if the shell has the default shape.
1109 * @return the region that defines the shape of the shell, or <code>null</code>
1111 * @exception SWTException <ul>
1112 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1113 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1120 public Region getRegion () {
1121 /* This method is needed for the @since 3.0 Javadoc */
1127 public Shell getShell () {
1132 @Override Point getSizeInPixels () {
1133 if (OS.IsIconic (handle)) return super.getSizeInPixels ();
1134 RECT rect = new RECT ();
1135 OS.GetWindowRect (handle, rect);
1136 int width = rect.right - rect.left;
1137 int height = rect.bottom - rect.top;
1138 return new Point (width, height);
1142 * Returns an array containing all shells which are
1143 * descendants of the receiver.
1145 * @return the dialog shells
1147 * @exception SWTException <ul>
1148 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1149 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1152 public Shell [] getShells () {
1155 Shell [] shells = display.getShells ();
1156 for (int i=0; i<shells.length; i++) {
1157 Control shell = shells [i];
1159 shell = shell.parent;
1160 } while (shell != null && shell != this);
1161 if (shell == this) count++;
1164 Shell [] result = new Shell [count];
1165 for (int i=0; i<shells.length; i++) {
1166 Control shell = shells [i];
1168 shell = shell.parent;
1169 } while (shell != null && shell != this);
1170 if (shell == this) {
1171 result [index++] = shells [i];
1178 * Returns a ToolBar object representing the tool bar that can be shown in the receiver's
1179 * trim. This will return <code>null</code> if the platform does not support tool bars that
1180 * are not part of the content area of the shell, or if the Shell's style does not support
1181 * having a tool bar.
1184 * @return a ToolBar object representing the Shell's tool bar, or <code>null</code>.
1186 * @exception SWTException <ul>
1187 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1188 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1193 public ToolBar getToolBar() {
1199 Composite findDeferredControl () {
1200 return layoutCount > 0 ? this : null;
1204 public boolean isEnabled () {
1206 return getEnabled ();
1210 public boolean isVisible () {
1212 return getVisible ();
1215 long hwndMDIClient () {
1216 if (hwndMDIClient == 0) {
1217 int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
1218 hwndMDIClient = OS.CreateWindowEx (
1220 new TCHAR (0, "MDICLIENT", true),
1226 OS.GetModuleHandle (null),
1227 new CREATESTRUCT ());
1228 // OS.ShowWindow (hwndMDIClient, OS.SW_SHOW);
1230 return hwndMDIClient;
1233 long menuItemToolTipHandle () {
1234 if (menuItemToolTipHandle == 0) createMenuItemToolTipHandle ();
1235 return menuItemToolTipHandle;
1239 * Moves the receiver to the top of the drawing order for
1240 * the display on which it was created (so that all other
1241 * shells on that display, which are not the receiver's
1242 * children will be drawn behind it), marks it visible,
1243 * sets the focus and asks the window manager to make the
1246 * @exception SWTException <ul>
1247 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1248 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1251 * @see Control#moveAbove
1252 * @see Control#setFocus
1253 * @see Control#setVisible
1254 * @see Display#getActiveShell
1255 * @see Decorations#setDefaultButton(Button)
1256 * @see Shell#setActive
1257 * @see Shell#forceActive
1259 public void open () {
1261 STARTUPINFO lpStartUpInfo = Display.lpStartupInfo;
1262 if (lpStartUpInfo == null || (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) == 0) {
1264 if (isDisposed ()) return;
1266 OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
1268 if (isDisposed ()) return;
1270 * Bug in Windows XP. Despite the fact that an icon has been
1271 * set for a window, the task bar displays the wrong icon the
1272 * first time the window is made visible with ShowWindow() after
1273 * a call to BringToTop(), when a long time elapses between the
1274 * ShowWindow() and the time the event queue is read. The icon
1275 * in the window trimming is correct but the one in the task
1276 * bar does not get updated. The fix is to call PeekMessage()
1277 * with the flag PM_NOREMOVE and PM_QS_SENDMESSAGE to respond
1278 * to a cross thread WM_GETICON.
1280 * NOTE: This allows other cross thread messages to be delivered,
1281 * most notably WM_ACTIVATE.
1283 MSG msg = new MSG ();
1284 int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
1285 OS.PeekMessage (msg, 0, 0, 0, flags);
1287 * When no widget has been given focus, or another push button has focus,
1288 * give focus to the default button. This avoids overriding the default
1291 boolean restored = restoreFocus ();
1293 restored = traverseGroup (true);
1296 Control focusControl = display.getFocusControl ();
1297 if (focusControl instanceof Button && (focusControl.style & SWT.PUSH) != 0) {
1302 if (saveDefault != null && !saveDefault.isDisposed ()) {
1303 saveDefault.setFocus ();
1311 public boolean print (GC gc) {
1313 if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
1314 if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
1321 if (toolTipHandle != 0) display.addControl (toolTipHandle, this);
1322 if (balloonTipHandle != 0) display.addControl (balloonTipHandle, this);
1323 if (menuItemToolTipHandle != 0) display.addControl (menuItemToolTipHandle, this);
1326 void releaseBrushes () {
1327 if (brushes != null) {
1328 for (int i=0; i<brushes.length; i++) {
1329 if (brushes [i] != 0) OS.DeleteObject (brushes [i]);
1336 void releaseChildren (boolean destroy) {
1337 Shell [] shells = getShells ();
1338 for (int i=0; i<shells.length; i++) {
1339 Shell shell = shells [i];
1340 if (shell != null && !shell.isDisposed ()) {
1341 shell.release (false);
1344 if (toolTips != null) {
1345 for (int i=0; i<toolTips.length; i++) {
1346 ToolTip toolTip = toolTips [i];
1347 if (toolTip != null && !toolTip.isDisposed ()) {
1348 toolTip.release (false);
1353 super.releaseChildren (destroy);
1357 void releaseHandle () {
1358 super.releaseHandle ();
1363 void releaseParent () {
1368 void releaseWidget () {
1369 super.releaseWidget ();
1372 display.clearModal (this);
1373 if (lpstrTip != 0) {
1374 long hHeap = OS.GetProcessHeap ();
1375 OS.HeapFree (hHeap, 0, lpstrTip);
1378 toolTipHandle = balloonTipHandle = menuItemToolTipHandle = 0;
1380 toolTitle = balloonTitle = null;
1384 void removeMenu (Menu menu) {
1385 super.removeMenu (menu);
1386 if (menu == activeMenu) activeMenu = null;
1390 * Removes the listener from the collection of listeners who will
1391 * be notified when operations are performed on the receiver.
1393 * @param listener the listener which should no longer be notified
1395 * @exception IllegalArgumentException <ul>
1396 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1398 * @exception SWTException <ul>
1399 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1400 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1403 * @see ShellListener
1404 * @see #addShellListener
1406 public void removeShellListener (ShellListener listener) {
1408 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1409 if (eventTable == null) return;
1410 eventTable.unhook (SWT.Close, listener);
1411 eventTable.unhook (SWT.Iconify,listener);
1412 eventTable.unhook (SWT.Deiconify,listener);
1413 eventTable.unhook (SWT.Activate, listener);
1414 eventTable.unhook (SWT.Deactivate, listener);
1418 public void requestLayout () {
1419 layout (null, SWT.DEFER);
1423 void reskinChildren (int flags) {
1424 Shell [] shells = getShells ();
1425 for (int i=0; i<shells.length; i++) {
1426 Shell shell = shells [i];
1427 if (shell != null) shell.reskin (flags);
1429 if (toolTips != null) {
1430 for (int i=0; i<toolTips.length; i++) {
1431 ToolTip toolTip = toolTips [i];
1432 if (toolTip != null) toolTip.reskin (flags);
1435 super.reskinChildren (flags);
1439 boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
1440 if (!isEnabled () || !isActive ()) return false;
1441 return super.sendKeyEvent (type, msg, wParam, lParam, event);
1445 * If the receiver is visible, moves it to the top of the
1446 * drawing order for the display on which it was created
1447 * (so that all other shells on that display, which are not
1448 * the receiver's children will be drawn behind it) and asks
1449 * the window manager to make the shell active
1451 * @exception SWTException <ul>
1452 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1453 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1457 * @see Control#moveAbove
1458 * @see Control#setFocus
1459 * @see Control#setVisible
1460 * @see Display#getActiveShell
1461 * @see Decorations#setDefaultButton(Button)
1463 * @see Shell#setActive
1465 public void setActive () {
1467 if (!isVisible ()) return;
1469 // widget could be disposed at this point
1472 void setActiveControl (Control control) {
1473 setActiveControl (control, SWT.None);
1476 void setActiveControl (Control control, int type) {
1477 if (control != null && control.isDisposed ()) control = null;
1478 if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
1479 if (lastActive == control) return;
1482 * Compute the list of controls to be activated and
1483 * deactivated by finding the first common parent
1486 Control [] activate = (control == null) ? new Control [0] : control.getPath ();
1487 Control [] deactivate = (lastActive == null) ? new Control [0] : lastActive.getPath ();
1488 lastActive = control;
1489 int index = 0, length = Math.min (activate.length, deactivate.length);
1490 while (index < length) {
1491 if (activate [index] != deactivate [index]) break;
1496 * It is possible (but unlikely), that application
1497 * code could have destroyed some of the widgets. If
1498 * this happens, keep processing those widgets that
1501 for (int i=deactivate.length-1; i>=index; --i) {
1502 if (!deactivate [i].isDisposed ()) {
1503 deactivate [i].sendEvent (SWT.Deactivate);
1506 for (int i=activate.length-1; i>=index; --i) {
1507 if (!activate [i].isDisposed ()) {
1508 Event event = new Event ();
1509 event.detail = type;
1510 activate [i].sendEvent (SWT.Activate, event);
1516 * Sets the receiver's alpha value which must be
1517 * between 0 (transparent) and 255 (opaque).
1519 * This operation requires the operating system's advanced
1520 * widgets subsystem which may not be available on some
1523 * @param alpha the alpha value
1525 * @exception SWTException <ul>
1526 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1527 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1532 public void setAlpha (int alpha) {
1535 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1536 if (alpha == 0xFF) {
1537 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits & ~OS.WS_EX_LAYERED);
1538 int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_FRAME | OS.RDW_ALLCHILDREN;
1539 OS.RedrawWindow (handle, null, 0, flags);
1541 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYERED);
1542 OS.SetLayeredWindowAttributes (handle, 0, (byte)alpha, OS.LWA_ALPHA);
1547 void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
1548 if (fullScreen) setFullScreen (false);
1550 * Bug in Windows. When a window has alpha and
1551 * SetWindowPos() is called with SWP_DRAWFRAME,
1552 * the contents of the window are copied rather
1553 * than allowing the windows underneath to draw.
1554 * This causes pixel corruption. The fix is to
1555 * clear the SWP_DRAWFRAME bits.
1557 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1558 if ((bits & OS.WS_EX_LAYERED) != 0) {
1559 flags &= ~OS.SWP_DRAWFRAME;
1561 super.setBoundsInPixels (x, y, width, height, flags, false);
1565 public void setEnabled (boolean enabled) {
1567 if (((state & DISABLED) == 0) == enabled) return;
1568 super.setEnabled (enabled);
1569 if (enabled && handle == OS.GetActiveWindow ()) {
1570 if (!restoreFocus ()) traverseGroup (true);
1575 * Sets the full screen state of the receiver.
1576 * If the argument is <code>true</code> causes the receiver
1577 * to switch to the full screen state, and if the argument is
1578 * <code>false</code> and the receiver was previously switched
1579 * into full screen state, causes the receiver to switch back
1580 * to either the maximized or normal states.
1582 * Note: The result of intermixing calls to <code>setFullScreen(true)</code>,
1583 * <code>setMaximized(true)</code> and <code>setMinimized(true)</code> will
1584 * vary by platform. Typically, the behavior will match the platform user's
1585 * expectations, but not always. This should be avoided if possible.
1588 * @param fullScreen the new fullscreen state
1590 * @exception SWTException <ul>
1591 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1592 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1597 public void setFullScreen (boolean fullScreen) {
1599 if (this.fullScreen == fullScreen) return;
1600 int stateFlags = fullScreen ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE;
1601 int styleFlags = OS.GetWindowLong (handle, OS.GWL_STYLE);
1602 int mask = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1603 if ((style & mask) != 0) {
1605 styleFlags &= ~(OS.WS_CAPTION | OS.WS_MAXIMIZEBOX | OS.WS_MINIMIZEBOX | OS.WS_THICKFRAME);
1607 styleFlags |= OS.WS_CAPTION;
1608 if ((style & SWT.MAX) != 0) styleFlags |= OS.WS_MAXIMIZEBOX;
1609 if ((style & SWT.MIN) != 0) styleFlags |= OS.WS_MINIMIZEBOX;
1610 if ((style & SWT.RESIZE) != 0) styleFlags |= OS.WS_THICKFRAME;
1613 if (fullScreen) wasMaximized = getMaximized ();
1614 boolean visible = isVisible ();
1615 OS.SetWindowLong (handle, OS.GWL_STYLE, styleFlags);
1617 OS.ShowWindow (handle, OS.SW_HIDE);
1618 stateFlags = OS.SW_SHOWMAXIMIZED;
1620 if (visible) OS.ShowWindow (handle, stateFlags);
1621 OS.UpdateWindow (handle);
1622 this.fullScreen = fullScreen;
1626 * Sets the input method editor mode to the argument which
1627 * should be the result of bitwise OR'ing together one or more
1628 * of the following constants defined in class <code>SWT</code>:
1629 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
1630 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
1632 * @param mode the new IME mode
1634 * @exception SWTException <ul>
1635 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1636 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1641 public void setImeInputMode (int mode) {
1643 if (!OS.IsDBLocale) return;
1644 boolean imeOn = mode != SWT.NONE;
1645 long hIMC = OS.ImmGetContext (handle);
1646 OS.ImmSetOpenStatus (hIMC, imeOn);
1648 int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
1649 if (OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence)) {
1651 int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA;
1652 if ((mode & SWT.PHONETIC) != 0) {
1653 newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE;
1656 if ((mode & SWT.NATIVE) != 0) {
1657 newBits = OS.IME_CMODE_NATIVE;
1658 oldBits = OS.IME_CMODE_KATAKANA;
1661 boolean fullShape = (mode & SWT.DBCS) != 0;
1662 if ((mode & SWT.NATIVE) != 0) {
1663 long hkl = OS.GetKeyboardLayout (0);
1664 int langid = OS.PRIMARYLANGID (OS.LOWORD (hkl));
1665 if (langid == OS.LANG_JAPANESE) {
1670 newBits |= OS.IME_CMODE_FULLSHAPE;
1672 oldBits |= OS.IME_CMODE_FULLSHAPE;
1674 if ((mode & SWT.ROMAN) != 0) {
1675 newBits |= OS.IME_CMODE_ROMAN;
1677 oldBits |= OS.IME_CMODE_ROMAN;
1679 lpfdwConversion [0] |= newBits;
1680 lpfdwConversion [0] &= ~oldBits;
1681 OS.ImmSetConversionStatus (hIMC, lpfdwConversion [0], lpfdwSentence [0]);
1684 OS.ImmReleaseContext (handle, hIMC);
1688 * Sets the receiver's minimum size to the size specified by the arguments.
1689 * If the new minimum size is larger than the current size of the receiver,
1690 * the receiver is resized to the new minimum size.
1692 * @param width the new minimum width for the receiver
1693 * @param height the new minimum height for the receiver
1695 * @exception SWTException <ul>
1696 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1697 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1702 public void setMinimumSize (int width, int height) {
1704 setMinimumSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
1707 void setMinimumSizeInPixels (int width, int height) {
1708 int widthLimit = 0, heightLimit = 0;
1709 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1710 if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
1711 widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK);
1712 if ((style & SWT.RESIZE) != 0) {
1713 heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK);
1715 RECT rect = new RECT ();
1716 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
1717 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1718 OS.AdjustWindowRectEx (rect, bits1, false, bits2);
1719 heightLimit = rect.bottom - rect.top;
1722 minWidth = Math.max (widthLimit, width);
1723 minHeight = Math.max (heightLimit, height);
1724 Point size = getSizeInPixels ();
1725 int newWidth = Math.max (size.x, minWidth);
1726 int newHeight = Math.max (size.y, minHeight);
1727 if (minWidth <= widthLimit) minWidth = SWT.DEFAULT;
1728 if (minHeight <= heightLimit) minHeight = SWT.DEFAULT;
1729 if (newWidth != size.x || newHeight != size.y) setSizeInPixels (newWidth, newHeight);
1733 * Sets the receiver's minimum size to the size specified by the argument.
1734 * If the new minimum size is larger than the current size of the receiver,
1735 * the receiver is resized to the new minimum size.
1737 * @param size the new minimum size for the receiver
1739 * @exception IllegalArgumentException <ul>
1740 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
1742 * @exception SWTException <ul>
1743 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1744 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1749 public void setMinimumSize (Point size) {
1751 if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
1752 size = DPIUtil.autoScaleUp(size);
1753 setMinimumSizeInPixels(size.x, size.y);
1757 * Sets the receiver's modified state as specified by the argument.
1759 * @param modified the new modified state for the receiver
1761 * @exception SWTException <ul>
1762 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1763 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1768 public void setModified (boolean modified) {
1770 this.modified = modified;
1773 void setItemEnabled (int cmd, boolean enabled) {
1774 long hMenu = OS.GetSystemMenu (handle, false);
1775 if (hMenu == 0) return;
1776 int flags = OS.MF_ENABLED;
1777 if (!enabled) flags = OS.MF_DISABLED | OS.MF_GRAYED;
1778 OS.EnableMenuItem (hMenu, cmd, OS.MF_BYCOMMAND | flags);
1783 /* Do nothing. Not necessary for Shells */
1787 * Sets the shape of the shell to the region specified
1788 * by the argument. When the argument is null, the
1789 * default shape of the shell is restored. The shell
1790 * must be created with the style SWT.NO_TRIM in order
1791 * to specify a region.
1793 * NOTE: This method also sets the size of the shell. Clients should
1794 * not call {@link #setSize} or {@link #setBounds} on this shell.
1795 * Furthermore, the passed region should not be modified any more.
1798 * @param region the region that defines the shape of the shell (or null)
1800 * @exception IllegalArgumentException <ul>
1801 * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
1803 * @exception SWTException <ul>
1804 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1805 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1811 public void setRegion (Region region) {
1813 if ((style & SWT.NO_TRIM) == 0) return;
1814 if (region != null) {
1815 Rectangle bounds = region.getBounds ();
1816 setSize (bounds.x + bounds.width, bounds.y + bounds.height);
1818 super.setRegion (region);
1821 void setToolTipText (long hwnd, String text) {
1822 TOOLINFO lpti = new TOOLINFO ();
1823 lpti.cbSize = TOOLINFO.sizeof;
1826 long hwndToolTip = toolTipHandle ();
1828 OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, lpti);
1830 if (OS.SendMessage (hwndToolTip, OS.TTM_GETTOOLINFO, 0, lpti) != 0) {
1831 OS.SendMessage (hwndToolTip, OS.TTM_UPDATE, 0, 0);
1833 lpti.uFlags = OS.TTF_IDISHWND | OS.TTF_SUBCLASS;
1834 lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
1835 OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, lpti);
1840 void setToolTipText (NMTTDISPINFO lpnmtdi, char [] buffer) {
1842 * Ensure that the current position of the mouse
1843 * is inside the client area of the shell. This
1844 * prevents tool tips from popping up over the
1847 if (!hasCursor ()) return;
1848 long hHeap = OS.GetProcessHeap ();
1849 if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip);
1850 int byteCount = buffer.length * 2;
1851 lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
1852 OS.MoveMemory (lpstrTip, buffer, byteCount);
1853 lpnmtdi.lpszText = lpstrTip;
1856 void setToolTipTitle (long hwndToolTip, String text, int icon) {
1858 * Bug in Windows. For some reason, when TTM_SETTITLE
1859 * is used to set the title of a tool tip, Windows leaks
1860 * GDI objects. This happens even when TTM_SETTITLE is
1861 * called with TTI_NONE and NULL. The documentation
1862 * states that Windows copies the icon and that the
1863 * programmer must free the copy but does not provide
1864 * API to get the icon. For example, when TTM_SETTITLE
1865 * is called with ICON_ERROR, when TTM_GETTITLE is used
1866 * to query the title and the icon, the uTitleBitmap
1867 * field in the TTGETTITLE struct is zero. The fix
1868 * is to remember these values, only set them when then
1869 * change and leak less.
1871 * NOTE: This only happens on Vista.
1873 if (hwndToolTip != toolTipHandle && hwndToolTip != balloonTipHandle && hwndToolTip != menuItemToolTipHandle) {
1876 if (hwndToolTip == toolTipHandle || hwndToolTip == menuItemToolTipHandle) {
1877 if (text == toolTitle || (toolTitle != null && toolTitle.equals (text))) {
1878 if (icon == toolIcon) return;
1883 if (hwndToolTip == balloonTipHandle) {
1884 if (text == balloonTitle || (balloonTitle != null && balloonTitle.equals (text))) {
1885 if (icon == toolIcon) return;
1887 balloonTitle = text;
1893 * Feature in Windows. The text point to by pszTitle
1894 * must not exceed 100 characters in length, including
1895 * the null terminator.
1897 if (text.length () > 99) text = text.substring (0, 99);
1898 TCHAR pszTitle = new TCHAR (getCodePage (), text, true);
1899 OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, pszTitle);
1901 OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0);
1906 public void setVisible (boolean visible) {
1909 * Feature in Windows. When ShowWindow() is called used to hide
1910 * a window, Windows attempts to give focus to the parent. If the
1911 * parent is disabled by EnableWindow(), focus is assigned to
1912 * another windows on the desktop. This means that if you hide
1913 * a modal window before the parent is enabled, the parent will
1914 * not come to the front. The fix is to change the modal state
1915 * before hiding or showing a window so that this does not occur.
1917 int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
1918 if ((style & mask) != 0) {
1920 display.setModalShell (this);
1921 if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
1922 display.setModalDialog (null);
1924 Control control = display._getFocusControl ();
1925 if (control != null && !control.isActive ()) {
1927 if (isDisposed ()) return;
1929 long hwndShell = OS.GetActiveWindow ();
1930 if (hwndShell == 0) {
1931 if (parent != null) hwndShell = parent.handle;
1933 if (hwndShell != 0) {
1934 OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
1936 OS.ReleaseCapture ();
1938 display.clearModal (this);
1945 * Bug in Windows. Calling ShowOwnedPopups() to hide the
1946 * child windows of a hidden window causes the application
1947 * to be deactivated. The fix is to call ShowOwnedPopups()
1948 * to hide children before hiding the parent.
1950 if (showWithParent && !visible) {
1951 OS.ShowOwnedPopups (handle, false);
1953 if (!visible) fixActiveShell ();
1954 if (visible && center && !moved) {
1956 if (isDisposed ()) return;
1958 super.setVisible (visible);
1959 if (isDisposed ()) return;
1960 if (showWithParent != visible) {
1961 showWithParent = visible;
1963 OS.ShowOwnedPopups (handle, true);
1967 /* Make the foreign window parent appear in the task bar */
1969 if (parent != null && (parent.state & FOREIGN_HANDLE) != 0) {
1970 long hwndParent = parent.handle;
1971 int style = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
1972 if ((style & OS.WS_EX_TOOLWINDOW) != 0) {
1973 OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, style & ~OS.WS_EX_TOOLWINDOW);
1975 * Bug in Windows. The window does not show in the task bar when
1976 * WS_EX_TOOLWINDOW is removed after the window has already been shown.
1977 * The fix is to hide and shown the shell.
1979 OS.ShowWindow (hwndParent, OS.SW_HIDE);
1980 OS.ShowWindow (hwndParent, OS.SW_RESTORE);
1989 if (ToolTipProc != 0) {
1990 long newProc = display.windowProc;
1991 if (toolTipHandle != 0) {
1992 OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, newProc);
1994 if (balloonTipHandle != 0) {
1995 OS.SetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC, newProc);
1997 if (menuItemToolTipHandle != 0) {
1998 OS.SetWindowLongPtr (menuItemToolTipHandle, OS.GWLP_WNDPROC, newProc);
2003 long toolTipHandle () {
2004 if (toolTipHandle == 0) createToolTipHandle ();
2005 return toolTipHandle;
2009 boolean translateAccelerator (MSG msg) {
2010 if (!isEnabled () || !isActive ()) return false;
2011 if (menuBar != null && !menuBar.isEnabled ()) return false;
2012 return translateMDIAccelerator (msg) || translateMenuAccelerator (msg);
2016 boolean traverseEscape () {
2017 if (parent == null) return false;
2018 if (!isVisible () || !isEnabled ()) return false;
2024 void unsubclass () {
2025 super.unsubclass ();
2026 if (ToolTipProc != 0) {
2027 if (toolTipHandle != 0) {
2028 OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
2030 if (toolTipHandle != 0) {
2031 OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
2033 if (menuItemToolTipHandle != 0) {
2034 OS.SetWindowLongPtr (menuItemToolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
2039 void updateModal () {
2040 if (Display.TrimEnabled) {
2041 setItemEnabled (OS.SC_CLOSE, isActive ());
2043 OS.EnableWindow (handle, isActive ());
2048 CREATESTRUCT widgetCreateStruct () {
2053 long widgetParent () {
2054 if (handle != 0) return handle;
2055 return parent != null ? parent.handle : 0;
2059 int widgetExtStyle () {
2060 int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD;
2061 if ((style & SWT.TOOL) != 0) bits |= OS.WS_EX_TOOLWINDOW;
2064 * Feature in Windows. When a window that does not have a parent
2065 * is created, it is automatically added to the Windows Task Bar,
2066 * even when it has no title. The fix is to use WS_EX_TOOLWINDOW
2067 * which does not cause the window to appear in the Task Bar.
2069 if (parent == null) {
2070 if ((style & SWT.ON_TOP) != 0) {
2071 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
2072 if ((style & SWT.NO_TRIM) != 0 || (style & trim) == 0) {
2073 bits |= OS.WS_EX_TOOLWINDOW;
2078 if ((style & SWT.ON_TOP) != 0) bits |= OS.WS_EX_TOPMOST;
2083 TCHAR windowClass () {
2084 if ((style & SWT.TOOL) != 0) {
2085 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
2086 if ((style & trim) == 0) return display.windowShadowClass;
2088 return parent != null ? DialogClass : super.windowClass ();
2092 long windowProc () {
2093 if (windowProc != 0) return windowProc;
2094 if ((style & SWT.TOOL) != 0) {
2095 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
2096 if ((style & trim) == 0) return super.windowProc ();
2098 return parent != null ? DialogProc : super.windowProc ();
2102 long windowProc (long hwnd, int msg, long wParam, long lParam) {
2103 if (handle == 0) return 0;
2104 if((style & SWT.NO_MOVE) != 0 && msg == OS.WM_NCLBUTTONDOWN && wParam == OS.HTCAPTION) return 0;
2105 if (hwnd == toolTipHandle || hwnd == balloonTipHandle || hwnd == menuItemToolTipHandle) {
2108 if (wParam != ToolTip.TIMER_ID) break;
2109 ToolTip tip = getCurrentToolTip (hwnd);
2110 if (tip != null && tip.autoHide) {
2111 tip.setVisible (false);
2115 case OS.WM_LBUTTONDOWN: {
2116 ToolTip tip = getCurrentToolTip (hwnd);
2118 tip.setVisible (false);
2119 tip.sendSelectionEvent (SWT.Selection);
2124 return callWindowProc (hwnd, msg, wParam, lParam);
2126 if (hwnd == handle) {
2127 if ((int)msg == Display.TASKBARBUTTONCREATED) {
2128 if (display.taskBar != null) {
2129 for (TaskItem item : display.taskBar.items) {
2130 if (item != null && item.shell == this) {
2138 return super.windowProc (hwnd, msg, wParam, lParam);
2142 int widgetStyle () {
2143 int bits = super.widgetStyle ();
2144 if (handle != 0) return bits | OS.WS_CHILD;
2145 bits &= ~OS.WS_CHILD;
2148 * Use WS_OVERLAPPED for all windows, either dialog or top level
2149 * so that CreateWindowEx () will respect CW_USEDEFAULT and set
2150 * the default window location and size.
2152 * NOTE: When a WS_OVERLAPPED window is created, Windows gives
2153 * the new window WS_CAPTION style bits. These two constants are
2157 * WS_CAPTION = WS_BORDER | WS_DLGFRAME
2160 return bits | OS.WS_OVERLAPPED | OS.WS_CAPTION;
2164 LRESULT WM_ACTIVATE (long wParam, long lParam) {
2166 * Bug in Windows XP. When a Shell is deactivated, the
2167 * IME composition window does not go away. This causes
2168 * repaint issues. The fix is to commit the composition
2171 if (OS.LOWORD (wParam) == 0 && OS.IsDBLocale && hIMC != 0) {
2172 if (OS.ImmGetOpenStatus (hIMC)) {
2173 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0);
2177 /* Process WM_ACTIVATE */
2178 LRESULT result = super.WM_ACTIVATE (wParam, lParam);
2179 if (OS.LOWORD (wParam) == 0) {
2180 if (lParam == 0 || (lParam != toolTipHandle && lParam != balloonTipHandle
2181 && lParam != menuItemToolTipHandle)) {
2182 ToolTip tip = getCurrentToolTip ();
2183 if (tip != null) tip.setVisible (false);
2186 return parent != null ? LRESULT.ZERO : result;
2190 LRESULT WM_DESTROY (long wParam, long lParam) {
2191 LRESULT result = super.WM_DESTROY (wParam, lParam);
2193 * When the shell is a WS_CHILD window of a non-SWT
2194 * window, the destroy code does not get called because
2195 * the non-SWT window does not call dispose (). Instead,
2196 * the destroy code is called here in WM_DESTROY.
2198 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2199 if ((bits & OS.WS_CHILD) != 0) {
2207 LRESULT WM_ERASEBKGND (long wParam, long lParam) {
2208 LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
2209 if (result != null) return result;
2211 * Feature in Windows. When a shell is resized by dragging
2212 * the resize handles, Windows temporarily fills in black
2213 * rectangles where the new contents of the shell should
2214 * draw. The fix is to always draw the background of shells.
2216 * NOTE: This only happens on Vista.
2218 if (OS.WIN32_VERSION == OS.VERSION (6, 0)) {
2219 drawBackground (wParam);
2226 LRESULT WM_ENTERIDLE (long wParam, long lParam) {
2227 LRESULT result = super.WM_ENTERIDLE (wParam, lParam);
2228 if (result != null) return result;
2229 Display display = this.display;
2230 if (display.runAsyncMessages (false)) display.wakeThread ();
2235 LRESULT WM_GETMINMAXINFO (long wParam, long lParam) {
2236 LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam);
2237 if (result != null) return result;
2238 if (minWidth != SWT.DEFAULT || minHeight != SWT.DEFAULT) {
2239 MINMAXINFO info = new MINMAXINFO ();
2240 OS.MoveMemory (info, lParam, MINMAXINFO.sizeof);
2241 if (minWidth != SWT.DEFAULT) info.ptMinTrackSize_x = minWidth;
2242 if (minHeight != SWT.DEFAULT) info.ptMinTrackSize_y = minHeight;
2243 OS.MoveMemory (lParam, info, MINMAXINFO.sizeof);
2244 return LRESULT.ZERO;
2250 LRESULT WM_MOUSEACTIVATE (long wParam, long lParam) {
2251 LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam);
2252 if (result != null) return result;
2255 * Check for WM_MOUSEACTIVATE when an MDI shell is active
2256 * and stop the normal shell activation but allow the mouse
2257 * down to be delivered.
2259 int hittest = (short) OS.LOWORD (lParam);
2262 case OS.HTTRANSPARENT:
2266 Control control = display._getFocusControl ();
2267 if (control != null) {
2268 Decorations decorations = control.menuShell ();
2269 if (decorations.getShell () == this && decorations != this) {
2270 display.ignoreRestoreFocus = true;
2271 display.lastHittest = hittest;
2272 display.lastHittestControl = null;
2273 if (hittest == OS.HTMENU || hittest == OS.HTSYSMENU) {
2274 display.lastHittestControl = control;
2277 return new LRESULT (OS.MA_NOACTIVATE);
2282 if (hittest == OS.HTMENU) return null;
2285 * Get the current location of the cursor,
2286 * not the location of the cursor when the
2287 * WM_MOUSEACTIVATE was generated. This is
2288 * strictly incorrect but is necessary in
2289 * order to support Activate and Deactivate
2290 * events for embedded widgets that have
2291 * their own event loop. In that case, the
2292 * cursor location reported by GetMessagePos()
2293 * is the one for our event loop, not the
2294 * embedded widget's event loop.
2296 POINT pt = new POINT ();
2297 if (!OS.GetCursorPos (pt)) {
2298 int pos = OS.GetMessagePos ();
2299 OS.POINTSTOPOINT (pt, pos);
2301 long hwnd = OS.WindowFromPoint (pt);
2302 if (hwnd == 0) return null;
2303 Control control = display.findControl (hwnd);
2306 * When a shell is created with SWT.ON_TOP and SWT.NO_FOCUS,
2307 * do not activate the shell when the user clicks on the
2308 * the client area or on the border or a control within the
2309 * shell that does not take focus.
2311 if (control != null && (control.state & CANVAS) != 0) {
2312 if ((control.style & SWT.NO_FOCUS) != 0) {
2313 int bits = SWT.ON_TOP | SWT.NO_FOCUS;
2314 if ((style & bits) == bits) {
2315 if (hittest == OS.HTBORDER || hittest == OS.HTCLIENT) {
2316 return new LRESULT (OS.MA_NOACTIVATE);
2322 long code = callWindowProc (handle, OS.WM_MOUSEACTIVATE, wParam, lParam);
2323 setActiveControl (control, SWT.MouseDown);
2324 return new LRESULT (code);
2328 LRESULT WM_MOVE (long wParam, long lParam) {
2329 LRESULT result = super.WM_MOVE (wParam, lParam);
2330 if (result != null) return result;
2331 ToolTip tip = getCurrentToolTip ();
2332 if (tip != null) tip.setVisible (false);
2337 LRESULT WM_NCHITTEST (long wParam, long lParam) {
2338 if (!OS.IsWindowEnabled (handle)) return null;
2339 if (!isEnabled () || !isActive ()) {
2340 if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE);
2341 long hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
2342 if (hittest == OS.HTCLIENT || hittest == OS.HTMENU) hittest = OS.HTBORDER;
2343 return new LRESULT (hittest);
2345 if (menuBar != null && !menuBar.getEnabled ()) {
2346 long hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
2347 if (hittest == OS.HTMENU) hittest = OS.HTBORDER;
2348 return new LRESULT (hittest);
2354 LRESULT WM_NCLBUTTONDOWN (long wParam, long lParam) {
2355 LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam);
2356 if (result != null) return result;
2358 * When the normal activation was interrupted in WM_MOUSEACTIVATE
2359 * because the active shell was an MDI shell, set the active window
2360 * to the top level shell but lock the active window and stop focus
2361 * changes. This allows the user to interact the top level shell
2362 * in the normal manner.
2364 if (!display.ignoreRestoreFocus) return result;
2365 Display display = this.display;
2366 display.lockActiveWindow = true;
2367 long code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
2368 display.lockActiveWindow = false;
2369 Control focusControl = display.lastHittestControl;
2370 if (focusControl != null && !focusControl.isDisposed ()) {
2371 focusControl.setFocus ();
2373 display.lastHittestControl = null;
2374 display.ignoreRestoreFocus = false;
2375 return new LRESULT (code);
2379 LRESULT WM_SETCURSOR (long wParam, long lParam) {
2381 * Feature in Windows. When the shell is disabled
2382 * by a Windows standard dialog (like a MessageBox
2383 * or FileDialog), clicking in the shell does not
2384 * bring the shell or the dialog to the front. The
2385 * fix is to detect this case and bring the shell
2388 int msg = OS.HIWORD (lParam);
2389 if (msg == OS.WM_LBUTTONDOWN) {
2390 if (!Display.TrimEnabled) {
2391 Shell modalShell = display.getModalShell ();
2392 if (modalShell != null && !isActive ()) {
2393 long hwndModal = modalShell.handle;
2394 if (OS.IsWindowEnabled (hwndModal)) {
2395 OS.SetActiveWindow (hwndModal);
2399 if (!OS.IsWindowEnabled (handle)) {
2400 long hwndPopup = OS.GetLastActivePopup (handle);
2401 if (hwndPopup != 0 && hwndPopup != handle) {
2402 if (display.getControl (hwndPopup) == null) {
2403 if (OS.IsWindowEnabled (hwndPopup)) {
2404 OS.SetActiveWindow (hwndPopup);
2411 * When the shell that contains a cursor is disabled,
2412 * WM_SETCURSOR is called with HTERROR. Normally,
2413 * when a control is disabled, the parent will get
2414 * mouse and cursor events. In the case of a disabled
2415 * shell, there is no enabled parent. In order to
2416 * show the cursor when a shell is disabled, it is
2417 * necessary to override WM_SETCURSOR when called
2418 * with HTERROR to set the cursor but only when the
2419 * mouse is in the client area of the shell.
2421 int hitTest = (short) OS.LOWORD (lParam);
2422 if (hitTest == OS.HTERROR) {
2423 if (!getEnabled ()) {
2424 Control control = display.getControl (wParam);
2425 if (control == this && cursor != null) {
2426 POINT pt = new POINT ();
2427 int pos = OS.GetMessagePos ();
2428 OS.POINTSTOPOINT (pt, pos);
2429 OS.ScreenToClient (handle, pt);
2430 RECT rect = new RECT ();
2431 OS.GetClientRect (handle, rect);
2432 if (OS.PtInRect (rect, pt)) {
2433 OS.SetCursor (cursor.handle);
2435 case OS.WM_LBUTTONDOWN:
2436 case OS.WM_RBUTTONDOWN:
2437 case OS.WM_MBUTTONDOWN:
2438 case OS.WM_XBUTTONDOWN:
2439 OS.MessageBeep (OS.MB_OK);
2446 return super.WM_SETCURSOR (wParam, lParam);
2450 LRESULT WM_SHOWWINDOW (long wParam, long lParam) {
2451 LRESULT result = super.WM_SHOWWINDOW (wParam, lParam);
2452 if (result != null) return result;
2454 * Bug in Windows. If the shell is hidden while the parent
2455 * is iconic, Windows shows the shell when the parent is
2456 * deiconified. This does not happen if the shell is hidden
2457 * while the parent is not an icon. The fix is to track
2458 * visible state for the shell and refuse to show the shell
2459 * when the parent is shown.
2461 if (lParam == OS.SW_PARENTOPENING) {
2462 Control control = this;
2463 while (control != null) {
2464 Shell shell = control.getShell ();
2465 if (!shell.showWithParent) return LRESULT.ZERO;
2466 control = control.parent;
2473 LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
2474 LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam);
2475 if (result != null) return result;
2476 WINDOWPOS lpwp = new WINDOWPOS ();
2477 OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
2478 if ((lpwp.flags & OS.SWP_NOSIZE) == 0) {
2479 lpwp.cx = Math.max (lpwp.cx, minWidth);
2480 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
2481 if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
2482 lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
2484 lpwp.cy = Math.max (lpwp.cy, minHeight);
2485 if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
2486 if ((style & SWT.RESIZE) != 0) {
2487 lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
2489 RECT rect = new RECT ();
2490 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
2491 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
2492 OS.AdjustWindowRectEx (rect, bits1, false, bits2);
2493 lpwp.cy = Math.max (lpwp.cy, rect.bottom - rect.top);
2496 OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);