KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > widgets > Shell


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.widgets;
12
13
14 import org.eclipse.swt.internal.win32.*;
15 import org.eclipse.swt.*;
16 import org.eclipse.swt.graphics.*;
17 import org.eclipse.swt.events.*;
18
19 /**
20  * Instances of this class represent the "windows"
21  * which the desktop or "window manager" is managing.
22  * Instances that do not have a parent (that is, they
23  * are built using the constructor, which takes a
24  * <code>Display</code> as the argument) are described
25  * as <em>top level</em> shells. Instances that do have
26  * a parent are described as <em>secondary</em> or
27  * <em>dialog</em> shells.
28  * <p>
29  * Instances are always displayed in one of the maximized,
30  * minimized or normal states:
31  * <ul>
32  * <li>
33  * When an instance is marked as <em>maximized</em>, the
34  * window manager will typically resize it to fill the
35  * entire visible area of the display, and the instance
36  * is usually put in a state where it can not be resized
37  * (even if it has style <code>RESIZE</code>) until it is
38  * no longer maximized.
39  * </li><li>
40  * When an instance is in the <em>normal</em> state (neither
41  * maximized or minimized), its appearance is controlled by
42  * the style constants which were specified when it was created
43  * and the restrictions of the window manager (see below).
44  * </li><li>
45  * When an instance has been marked as <em>minimized</em>,
46  * its contents (client area) will usually not be visible,
47  * and depending on the window manager, it may be
48  * "iconified" (that is, replaced on the desktop by a small
49  * simplified representation of itself), relocated to a
50  * distinguished area of the screen, or hidden. Combinations
51  * of these changes are also possible.
52  * </li>
53  * </ul>
54  * </p><p>
55  * The <em>modality</em> of an instance may be specified using
56  * style bits. The modality style bits are used to determine
57  * whether input is blocked for other shells on the display.
58  * The <code>PRIMARY_MODAL</code> style allows an instance to block
59  * input to its parent. The <code>APPLICATION_MODAL</code> style
60  * allows an instance to block input to every other shell in the
61  * display. The <code>SYSTEM_MODAL</code> style allows an instance
62  * to block input to all shells, including shells belonging to
63  * different applications.
64  * </p><p>
65  * Note: The styles supported by this class are treated
66  * as <em>HINT</em>s, since the window manager for the
67  * desktop on which the instance is visible has ultimate
68  * control over the appearance and behavior of decorations
69  * and modality. For example, some window managers only
70  * support resizable windows and will always assume the
71  * RESIZE style, even if it is not set. In addition, if a
72  * modality style is not supported, it is "upgraded" to a
73  * more restrictive modality style that is supported. For
74  * example, if <code>PRIMARY_MODAL</code> is not supported,
75  * it would be upgraded to <code>APPLICATION_MODAL</code>.
76  * A modality style may also be "downgraded" to a less
77  * restrictive style. For example, most operating systems
78  * no longer support <code>SYSTEM_MODAL</code> because
79  * it can freeze up the desktop, so this is typically
80  * downgraded to <code>APPLICATION_MODAL</code>.
81  * <dl>
82  * <dt><b>Styles:</b></dt>
83  * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd>
84  * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
85  * <dt><b>Events:</b></dt>
86  * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
87  * </dl>
88  * Class <code>SWT</code> provides two "convenience constants"
89  * for the most commonly required style combinations:
90  * <dl>
91  * <dt><code>SHELL_TRIM</code></dt>
92  * <dd>
93  * the result of combining the constants which are required
94  * to produce a typical application top level shell: (that
95  * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
96  * </dd>
97  * <dt><code>DIALOG_TRIM</code></dt>
98  * <dd>
99  * the result of combining the constants which are required
100  * to produce a typical application dialog shell: (that
101  * is, <code>TITLE | CLOSE | BORDER</code>)
102  * </dd>
103  * </dl>
104  * </p>
105  * <p>
106  * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
107  * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
108  * </p><p>
109  * IMPORTANT: This class is not intended to be subclassed.
110  * </p>
111  *
112  * @see Decorations
113  * @see SWT
114  */

115 public class Shell extends Decorations {
116     Menu activeMenu;
117     ToolTip [] toolTips;
118     int hIMC, hwndMDIClient, lpstrTip, toolTipHandle, balloonTipHandle;
119     int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT;
120     int [] brushes;
121     boolean showWithParent;
122     String JavaDoc toolTitle, balloonTitle;
123     int toolIcon, balloonIcon;
124     int windowProc;
125     Control lastActive, lockToolTipControl;
126     SHACTIVATEINFO psai;
127     Region region;
128     static /*final*/ int ToolTipProc;
129     static final int DialogProc;
130     static final TCHAR DialogClass = new TCHAR (0, OS.IsWinCE ? "Dialog" : "#32770", true);
131     final static int [] SYSTEM_COLORS = {
132         OS.COLOR_BTNFACE,
133         OS.COLOR_WINDOW,
134         OS.COLOR_BTNTEXT,
135         OS.COLOR_WINDOWTEXT,
136         OS.COLOR_HIGHLIGHT,
137         OS.COLOR_SCROLLBAR,
138     };
139     final static int BRUSHES_SIZE = 32;
140     static {
141         WNDCLASS lpWndClass = new WNDCLASS ();
142         OS.GetClassInfo (0, DialogClass, lpWndClass);
143         DialogProc = lpWndClass.lpfnWndProc;
144     }
145
146 /**
147  * Constructs a new instance of this class. This is equivalent
148  * to calling <code>Shell((Display) null)</code>.
149  *
150  * @exception SWTException <ul>
151  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
152  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
153  * </ul>
154  */

155 public Shell () {
156     this ((Display) null);
157 }
158
159 /**
160  * Constructs a new instance of this class given only the style
161  * value describing its behavior and appearance. This is equivalent
162  * to calling <code>Shell((Display) null, style)</code>.
163  * <p>
164  * The style value is either one of the style constants defined in
165  * class <code>SWT</code> which is applicable to instances of this
166  * class, or must be built by <em>bitwise OR</em>'ing together
167  * (that is, using the <code>int</code> "|" operator) two or more
168  * of those <code>SWT</code> style constants. The class description
169  * lists the style constants that are applicable to the class.
170  * Style bits are also inherited from superclasses.
171  * </p>
172  *
173  * @param style the style of control to construct
174  *
175  * @exception SWTException <ul>
176  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
177  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
178  * </ul>
179  *
180  * @see SWT#BORDER
181  * @see SWT#CLOSE
182  * @see SWT#MIN
183  * @see SWT#MAX
184  * @see SWT#RESIZE
185  * @see SWT#TITLE
186  * @see SWT#NO_TRIM
187  * @see SWT#SHELL_TRIM
188  * @see SWT#DIALOG_TRIM
189  * @see SWT#MODELESS
190  * @see SWT#PRIMARY_MODAL
191  * @see SWT#APPLICATION_MODAL
192  * @see SWT#SYSTEM_MODAL
193  */

194 public Shell (int style) {
195     this ((Display) null, style);
196 }
197
198 /**
199  * Constructs a new instance of this class given only the display
200  * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>.
201  * <p>
202  * Note: Currently, null can be passed in for the display argument.
203  * This has the effect of creating the shell on the currently active
204  * display if there is one. If there is no current display, the
205  * shell is created on a "default" display. <b>Passing in null as
206  * the display argument is not considered to be good coding style,
207  * and may not be supported in a future release of SWT.</b>
208  * </p>
209  *
210  * @param display the display to create the shell on
211  *
212  * @exception SWTException <ul>
213  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
214  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
215  * </ul>
216  */

217 public Shell (Display display) {
218     this (display, OS.IsWinCE ? SWT.NONE : SWT.SHELL_TRIM);
219 }
220
221 /**
222  * Constructs a new instance of this class given the display
223  * to create it on and a style value describing its behavior
224  * and appearance.
225  * <p>
226  * The style value is either one of the style constants defined in
227  * class <code>SWT</code> which is applicable to instances of this
228  * class, or must be built by <em>bitwise OR</em>'ing together
229  * (that is, using the <code>int</code> "|" operator) two or more
230  * of those <code>SWT</code> style constants. The class description
231  * lists the style constants that are applicable to the class.
232  * Style bits are also inherited from superclasses.
233  * </p><p>
234  * Note: Currently, null can be passed in for the display argument.
235  * This has the effect of creating the shell on the currently active
236  * display if there is one. If there is no current display, the
237  * shell is created on a "default" display. <b>Passing in null as
238  * the display argument is not considered to be good coding style,
239  * and may not be supported in a future release of SWT.</b>
240  * </p>
241  *
242  * @param display the display to create the shell on
243  * @param style the style of control to construct
244  *
245  * @exception SWTException <ul>
246  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
247  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
248  * </ul>
249  *
250  * @see SWT#BORDER
251  * @see SWT#CLOSE
252  * @see SWT#MIN
253  * @see SWT#MAX
254  * @see SWT#RESIZE
255  * @see SWT#TITLE
256  * @see SWT#NO_TRIM
257  * @see SWT#SHELL_TRIM
258  * @see SWT#DIALOG_TRIM
259  * @see SWT#MODELESS
260  * @see SWT#PRIMARY_MODAL
261  * @see SWT#APPLICATION_MODAL
262  * @see SWT#SYSTEM_MODAL
263  */

264 public Shell (Display display, int style) {
265     this (display, null, style, 0, false);
266 }
267
268 Shell (Display display, Shell parent, int style, int handle, boolean embedded) {
269     super ();
270     checkSubclass ();
271     if (display == null) display = Display.getCurrent ();
272     if (display == null) display = Display.getDefault ();
273     if (!display.isValidThread ()) {
274         error (SWT.ERROR_THREAD_INVALID_ACCESS);
275     }
276     if (parent != null && parent.isDisposed ()) {
277         error (SWT.ERROR_INVALID_ARGUMENT);
278     }
279     this.style = checkStyle (style);
280     this.parent = parent;
281     this.display = display;
282     this.handle = handle;
283     if (handle != 0 && !embedded) {
284         state |= FOREIGN_HANDLE;
285     }
286     createWidget ();
287 }
288
289 /**
290  * Constructs a new instance of this class given only its
291  * parent. It is created with style <code>SWT.DIALOG_TRIM</code>.
292  * <p>
293  * Note: Currently, null can be passed in for the parent.
294  * This has the effect of creating the shell on the currently active
295  * display if there is one. If there is no current display, the
296  * shell is created on a "default" display. <b>Passing in null as
297  * the parent is not considered to be good coding style,
298  * and may not be supported in a future release of SWT.</b>
299  * </p>
300  *
301  * @param parent a shell which will be the parent of the new instance
302  *
303  * @exception IllegalArgumentException <ul>
304  * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
305  * </ul>
306  * @exception SWTException <ul>
307  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
308  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
309  * </ul>
310  */

311 public Shell (Shell parent) {
312     this (parent, OS.IsWinCE ? SWT.NONE : SWT.DIALOG_TRIM);
313 }
314
315 /**
316  * Constructs a new instance of this class given its parent
317  * and a style value describing its behavior and appearance.
318  * <p>
319  * The style value is either one of the style constants defined in
320  * class <code>SWT</code> which is applicable to instances of this
321  * class, or must be built by <em>bitwise OR</em>'ing together
322  * (that is, using the <code>int</code> "|" operator) two or more
323  * of those <code>SWT</code> style constants. The class description
324  * lists the style constants that are applicable to the class.
325  * Style bits are also inherited from superclasses.
326  * </p><p>
327  * Note: Currently, null can be passed in for the parent.
328  * This has the effect of creating the shell on the currently active
329  * display if there is one. If there is no current display, the
330  * shell is created on a "default" display. <b>Passing in null as
331  * the parent is not considered to be good coding style,
332  * and may not be supported in a future release of SWT.</b>
333  * </p>
334  *
335  * @param parent a shell which will be the parent of the new instance
336  * @param style the style of control to construct
337  *
338  * @exception IllegalArgumentException <ul>
339  * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
340  * </ul>
341  * @exception SWTException <ul>
342  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
343  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
344  * </ul>
345  *
346  * @see SWT#BORDER
347  * @see SWT#CLOSE
348  * @see SWT#MIN
349  * @see SWT#MAX
350  * @see SWT#RESIZE
351  * @see SWT#TITLE
352  * @see SWT#NO_TRIM
353  * @see SWT#SHELL_TRIM
354  * @see SWT#DIALOG_TRIM
355  * @see SWT#ON_TOP
356  * @see SWT#TOOL
357  * @see SWT#MODELESS
358  * @see SWT#PRIMARY_MODAL
359  * @see SWT#APPLICATION_MODAL
360  * @see SWT#SYSTEM_MODAL
361  */

362 public Shell (Shell parent, int style) {
363     this (parent != null ? parent.display : null, parent, style, 0, false);
364 }
365
366 /**
367  * Invokes platform specific functionality to allocate a new shell.
368  * <p>
369  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
370  * API for <code>Shell</code>. It is marked public only so that it
371  * can be shared within the packages provided by SWT. It is not
372  * available on all platforms, and should never be called from
373  * application code.
374  * </p>
375  *
376  * @param display the display for the shell
377  * @param handle the handle for the shell
378  * @return a new shell object containing the specified display and handle
379  */

380 public static Shell win32_new (Display display, int handle) {
381     return new Shell (display, null, SWT.NO_TRIM, handle, true);
382 }
383
384 public static Shell internal_new (Display display, int handle) {
385     return new Shell (display, null, SWT.NO_TRIM, handle, false);
386 }
387
388 static int checkStyle (int style) {
389     style = Decorations.checkStyle (style);
390     int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
391     int bits = style & ~mask;
392     if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
393     if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
394     if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL;
395     return bits;
396 }
397
398 /**
399  * Adds the listener to the collection of listeners who will
400  * be notified when operations are performed on the receiver,
401  * by sending the listener one of the messages defined in the
402  * <code>ShellListener</code> interface.
403  *
404  * @param listener the listener which should be notified
405  *
406  * @exception IllegalArgumentException <ul>
407  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
408  * </ul>
409  * @exception SWTException <ul>
410  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
411  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
412  * </ul>
413  *
414  * @see ShellListener
415  * @see #removeShellListener
416  */

417 public void addShellListener (ShellListener listener) {
418     checkWidget ();
419     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
420     TypedListener typedListener = new TypedListener (listener);
421     addListener (SWT.Close,typedListener);
422     addListener (SWT.Iconify,typedListener);
423     addListener (SWT.Deiconify,typedListener);
424     addListener (SWT.Activate, typedListener);
425     addListener (SWT.Deactivate, typedListener);
426 }
427
428 int balloonTipHandle () {
429     if (balloonTipHandle == 0) createBalloonTipHandle ();
430     return balloonTipHandle;
431 }
432
433 int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
434     if (handle == 0) return 0;
435     if (hwnd == toolTipHandle || hwnd == balloonTipHandle) {
436         return OS.CallWindowProc (ToolTipProc, hwnd, msg, wParam, lParam);
437     }
438     if (hwndMDIClient != 0) {
439         return OS.DefFrameProc (hwnd, hwndMDIClient, msg, wParam, lParam);
440     }
441     if (windowProc != 0) {
442         return OS.CallWindowProc (windowProc, hwnd, msg, wParam, lParam);
443     }
444     if ((style & SWT.TOOL) != 0) {
445         int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
446         if ((style & trim) == 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam);
447     }
448     if (parent != null) {
449         switch (msg) {
450             case OS.WM_KILLFOCUS:
451             case OS.WM_SETFOCUS:
452                 return OS.DefWindowProc (hwnd, msg, wParam, lParam);
453         }
454         return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam);
455     }
456     return OS.DefWindowProc (hwnd, msg, wParam, lParam);
457 }
458
459 /**
460  * Requests that the window manager close the receiver in
461  * the same way it would be closed when the user clicks on
462  * the "close box" or performs some other platform specific
463  * key or mouse combination that indicates the window
464  * should be removed.
465  *
466  * @exception SWTException <ul>
467  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
468  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
469  * </ul>
470  *
471  * @see SWT#Close
472  * @see #dispose
473  */

474 public void close () {
475     checkWidget ();
476     closeWidget ();
477 }
478
479 void createBalloonTipHandle () {
480     balloonTipHandle = OS.CreateWindowEx (
481         0,
482         new TCHAR (0, OS.TOOLTIPS_CLASS, true),
483         null,
484         OS.TTS_ALWAYSTIP | OS.TTS_BALLOON,
485         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
486         handle,
487         0,
488         OS.GetModuleHandle (null),
489         null);
490     if (balloonTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
491     if (ToolTipProc == 0) {
492         ToolTipProc = OS.GetWindowLong (balloonTipHandle, OS.GWL_WNDPROC);
493     }
494     /*
495     * Feature in Windows. Despite the fact that the
496     * tool tip text contains \r\n, the tooltip will
497     * not honour the new line unless TTM_SETMAXTIPWIDTH
498     * is set. The fix is to set TTM_SETMAXTIPWIDTH to
499     * a large value.
500     */

501     OS.SendMessage (balloonTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
502     display.addControl (balloonTipHandle, this);
503     OS.SetWindowLong (balloonTipHandle, OS.GWL_WNDPROC, display.windowProc);
504 }
505
506 void createHandle () {
507     boolean embedded = handle != 0 && (state & FOREIGN_HANDLE) == 0;
508     
509     /*
510     * On Windows 98 and NT, setting a window to be the
511     * top most window using HWND_TOPMOST can result in a
512     * parent dialog shell being moved behind its parent
513     * if the dialog has a sibling that is currently on top
514     * This only occurs using SetWindowPos (), not when the
515     * handle is created.
516     */

517     /*
518     * The following code is intentionally commented.
519     */

520 // if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = true;
521
if (handle == 0 || embedded) {
522         super.createHandle ();
523     } else {
524         state |= CANVAS;
525         if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
526             state |= THEME_BACKGROUND;
527         }
528         windowProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
529     }
530     
531     /*
532     * The following code is intentionally commented.
533     */

534 // if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = false;
535

536     if (!embedded) {
537         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
538         bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION);
539         if (!OS.IsWinCE) bits |= OS.WS_POPUP;
540         if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
541         if ((style & SWT.NO_TRIM) == 0) {
542             if ((style & (SWT.BORDER | SWT.RESIZE)) == 0) bits |= OS.WS_BORDER;
543         }
544         /*
545         * Bug in Windows. When the WS_CAPTION bits are cleared using
546         * SetWindowLong(), Windows does not resize the client area of
547         * the window to get rid of the caption until the first resize.
548         * The fix is to use SetWindowPos() with SWP_DRAWFRAME to force
549         * the frame to be redrawn and resized.
550         */

551         OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
552         int flags = OS.SWP_DRAWFRAME | OS.SWP_NOMOVE | OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
553         SetWindowPos (handle, 0, 0, 0, 0, 0, flags);
554         if (OS.IsWinCE) _setMaximized (true);
555         if (OS.IsPPC) {
556             psai = new SHACTIVATEINFO ();
557             psai.cbSize = SHACTIVATEINFO.sizeof;
558         }
559     }
560     if (OS.IsDBLocale) {
561         hIMC = OS.ImmCreateContext ();
562         if (hIMC != 0) OS.ImmAssociateContext (handle, hIMC);
563     }
564 }
565
566 void createToolTip (ToolTip toolTip) {
567     int id = 0;
568     if (toolTips == null) toolTips = new ToolTip [4];
569     while (id < toolTips.length && toolTips [id] != null) id++;
570     if (id == toolTips.length) {
571         ToolTip [] newToolTips = new ToolTip [toolTips.length + 4];
572         System.arraycopy (toolTips, 0, newToolTips, 0, toolTips.length);
573         toolTips = newToolTips;
574     }
575     toolTips [id] = toolTip;
576     toolTip.id = id + Display.ID_START;
577     if (OS.IsWinCE) return;
578     TOOLINFO lpti = new TOOLINFO ();
579     lpti.cbSize = TOOLINFO.sizeof;
580     lpti.hwnd = handle;
581     lpti.uId = toolTip.id;
582     lpti.uFlags = OS.TTF_TRACK;
583     lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
584     OS.SendMessage (toolTip.hwndToolTip (), OS.TTM_ADDTOOL, 0, lpti);
585 }
586
587 void createToolTipHandle () {
588     toolTipHandle = OS.CreateWindowEx (
589         0,
590         new TCHAR (0, OS.TOOLTIPS_CLASS, true),
591         null,
592         OS.TTS_ALWAYSTIP,
593         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
594         handle,
595         0,
596         OS.GetModuleHandle (null),
597         null);
598     if (toolTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
599     if (ToolTipProc == 0) {
600         ToolTipProc = OS.GetWindowLong (toolTipHandle, OS.GWL_WNDPROC);
601     }
602     /*
603     * Feature in Windows. Despite the fact that the
604     * tool tip text contains \r\n, the tooltip will
605     * not honour the new line unless TTM_SETMAXTIPWIDTH
606     * is set. The fix is to set TTM_SETMAXTIPWIDTH to
607     * a large value.
608     */

609     OS.SendMessage (toolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
610     display.addControl (toolTipHandle, this);
611     OS.SetWindowLong (toolTipHandle, OS.GWL_WNDPROC, display.windowProc);
612 }
613
614 void deregister () {
615     super.deregister ();
616     if (toolTipHandle != 0) display.removeControl (toolTipHandle);
617     if (balloonTipHandle != 0) display.removeControl (balloonTipHandle);
618 }
619
620 void destroyToolTip (ToolTip toolTip) {
621     if (toolTips == null) return;
622     toolTips [toolTip.id - Display.ID_START] = null;
623     if (OS.IsWinCE) return;
624     if (balloonTipHandle != 0) {
625         TOOLINFO lpti = new TOOLINFO ();
626         lpti.cbSize = TOOLINFO.sizeof;
627         lpti.uId = toolTip.id;
628         lpti.hwnd = handle;
629         OS.SendMessage (balloonTipHandle, OS.TTM_DELTOOL, 0, lpti);
630     }
631     toolTip.id = -1;
632 }
633
634 void destroyWidget () {
635     fixActiveShell ();
636     super.destroyWidget ();
637 }
638
639 public void dispose () {
640     /*
641     * This code is intentionally commented. On some
642     * platforms, the owner window is repainted right
643     * away when a dialog window exits. This behavior
644     * is currently unspecified.
645     */

646 // /*
647
// * Note: It is valid to attempt to dispose a widget
648
// * more than once. If this happens, fail silently.
649
// */
650
// if (!isValidWidget ()) return;
651
// if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
652
// Display oldDisplay = display;
653
super.dispose ();
654     // widget is disposed at this point
655
// if (oldDisplay != null) oldDisplay.update ();
656
}
657
658 void enableWidget (boolean enabled) {
659     if (enabled) {
660         state &= ~DISABLED;
661     } else {
662         state |= DISABLED;
663     }
664     if (Display.TrimEnabled) {
665         if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled);
666     } else {
667         OS.EnableWindow (handle, enabled);
668     }
669 }
670
671 int findBrush (int value, int lbStyle) {
672     if (lbStyle == OS.BS_SOLID) {
673         for (int i=0; i<SYSTEM_COLORS.length; i++) {
674             if (value == OS.GetSysColor (SYSTEM_COLORS [i])) {
675                 return OS.GetSysColorBrush (SYSTEM_COLORS [i]);
676             }
677         }
678     }
679     if (brushes == null) brushes = new int [BRUSHES_SIZE];
680     LOGBRUSH logBrush = new LOGBRUSH ();
681     for (int i=0; i<brushes.length; i++) {
682         int hBrush = brushes [i];
683         if (hBrush == 0) break;
684         OS.GetObject (hBrush, LOGBRUSH.sizeof, logBrush);
685         switch (logBrush.lbStyle) {
686             case OS.BS_SOLID:
687                 if (lbStyle == OS.BS_SOLID) {
688                     if (logBrush.lbColor == value) return hBrush;
689                 }
690                 break;
691             case OS.BS_PATTERN:
692                 if (lbStyle == OS.BS_PATTERN) {
693                     if (logBrush.lbHatch == value) return hBrush;
694                 }
695                 break;
696         }
697     }
698     int length = brushes.length;
699     int hBrush = brushes [--length];
700     if (hBrush != 0) OS.DeleteObject (hBrush);
701     System.arraycopy (brushes, 0, brushes, 1, length);
702     switch (lbStyle) {
703         case OS.BS_SOLID:
704             hBrush = OS.CreateSolidBrush (value);
705             break;
706         case OS.BS_PATTERN:
707             hBrush = OS.CreatePatternBrush (value);
708             break;
709     }
710     return brushes [0] = hBrush;
711 }
712
713 Control findBackgroundControl () {
714     return background != -1 || backgroundImage != null ? this : null;
715 }
716
717 Cursor findCursor () {
718     return cursor;
719 }
720
721 Control findThemeControl () {
722     return null;
723 }
724
725 ToolTip findToolTip (int id) {
726     if (toolTips == null) return null;
727     id = id - Display.ID_START;
728     return 0 <= id && id < toolTips.length ? toolTips [id] : null;
729 }
730
731 void fixActiveShell () {
732     /*
733     * Feature in Windows. When the active shell is disposed
734     * or hidden, Windows normally makes the parent shell active
735     * and assigns focus. This does not happen when the parent
736     * shell is disabled. Instead, Windows assigns focus to the
737     * next shell on the desktop (possibly a shell in another
738     * application). The fix is to activate the disabled parent
739     * shell before disposing or hiding the active shell.
740     */

741     int hwndParent = OS.GetParent (handle);
742     if (hwndParent != 0 && handle == OS.GetActiveWindow ()) {
743         if (!OS.IsWindowEnabled (hwndParent) && OS.IsWindowVisible (hwndParent)) {
744             OS.SetActiveWindow (hwndParent);
745         }
746     }
747 }
748
749 void fixShell (Shell newShell, Control control) {
750     if (this == newShell) return;
751     if (control == lastActive) setActiveControl (null);
752     String JavaDoc toolTipText = control.toolTipText;
753     if (toolTipText != null) {
754         control.setToolTipText (this, null);
755         control.setToolTipText (newShell, toolTipText);
756     }
757 }
758
759 void fixToolTip () {
760     /*
761     * Bug in Windows. On XP, when a tooltip is
762     * hidden due to a time out or mouse press,
763     * the tooltip remains active although no
764     * longer visible and won't show again until
765     * another tooltip becomes active. If there
766     * is only one tooltip in the window, it will
767     * never show again. The fix is to remove the
768     * current tooltip and add it again every time
769     * the mouse leaves the control.
770     */

771     if (OS.COMCTL32_MAJOR >= 6) {
772         if (toolTipHandle == 0) return;
773         TOOLINFO lpti = new TOOLINFO ();
774         lpti.cbSize = TOOLINFO.sizeof;
775         if (OS.SendMessage (toolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
776             if ((lpti.uFlags & OS.TTF_IDISHWND) != 0) {
777                 OS.SendMessage (toolTipHandle, OS.TTM_DELTOOL, 0, lpti);
778                 OS.SendMessage (toolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
779             }
780         }
781     }
782 }
783
784 /**
785  * If the receiver is visible, moves it to the top of the
786  * drawing order for the display on which it was created
787  * (so that all other shells on that display, which are not
788  * the receiver's children will be drawn behind it) and forces
789  * the window manager to make the shell active.
790  *
791  * @exception SWTException <ul>
792  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
793  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
794  * </ul>
795  *
796  * @since 2.0
797  * @see Control#moveAbove
798  * @see Control#setFocus
799  * @see Control#setVisible
800  * @see Display#getActiveShell
801  * @see Decorations#setDefaultButton(Button)
802  * @see Shell#open
803  * @see Shell#setActive
804  */

805 public void forceActive () {
806     checkWidget ();
807     if(!isVisible()) return;
808     OS.SetForegroundWindow (handle);
809 }
810
811 void forceResize () {
812     /* Do nothing */
813 }
814
815 public Rectangle getBounds () {
816     checkWidget ();
817     if (!OS.IsWinCE) {
818         if (OS.IsIconic (handle)) return super.getBounds ();
819     }
820     RECT rect = new RECT ();
821     OS.GetWindowRect (handle, rect);
822     int width = rect.right - rect.left;
823     int height = rect.bottom - rect.top;
824     return new Rectangle (rect.left, rect.top, width, height);
825 }
826
827 ToolTip getCurrentToolTip () {
828     if (toolTipHandle != 0) {
829         ToolTip tip = getCurrentToolTip (toolTipHandle);
830         if (tip != null) return tip;
831     }
832     if (balloonTipHandle != 0) {
833         ToolTip tip = getCurrentToolTip (balloonTipHandle);
834         if (tip != null) return tip;
835     }
836     return null;
837 }
838
839 ToolTip getCurrentToolTip (int hwndToolTip) {
840     if (hwndToolTip == 0) return null;
841     if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
842         TOOLINFO lpti = new TOOLINFO ();
843         lpti.cbSize = TOOLINFO.sizeof;
844         if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
845             if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) return findToolTip (lpti.uId);
846         }
847     }
848     return null;
849 }
850
851 public boolean getEnabled () {
852     checkWidget ();
853     return (state & DISABLED) == 0;
854 }
855
856 /**
857  * Returns the receiver's input method editor mode. This
858  * will be the result of bitwise OR'ing together one or
859  * more of the following constants defined in class
860  * <code>SWT</code>:
861  * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
862  * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
863  *
864  * @return the IME mode
865  *
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>
869  * </ul>
870  *
871  * @see SWT
872  */

873 public int getImeInputMode () {
874     checkWidget ();
875     if (!OS.IsDBLocale) return 0;
876     int hIMC = OS.ImmGetContext (handle);
877     int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
878     boolean open = OS.ImmGetOpenStatus (hIMC);
879     if (open) open = OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence);
880     OS.ImmReleaseContext (handle, hIMC);
881     if (!open) return SWT.NONE;
882     int result = 0;
883     if ((lpfdwConversion [0] & OS.IME_CMODE_ROMAN) != 0) result |= SWT.ROMAN;
884     if ((lpfdwConversion [0] & OS.IME_CMODE_FULLSHAPE) != 0) result |= SWT.DBCS;
885     if ((lpfdwConversion [0] & OS.IME_CMODE_KATAKANA) != 0) return result | SWT.PHONETIC;
886     if ((lpfdwConversion [0] & OS.IME_CMODE_NATIVE) != 0) return result | SWT.NATIVE;
887     return result | SWT.ALPHA;
888 }
889
890 public Point getLocation () {
891     checkWidget ();
892     if (!OS.IsWinCE) {
893         if (OS.IsIconic (handle)) {
894             return super.getLocation ();
895         }
896     }
897     RECT rect = new RECT ();
898     OS.GetWindowRect (handle, rect);
899     return new Point (rect.left, rect.top);
900 }
901
902 /**
903  * Returns a point describing the minimum receiver's size. The
904  * x coordinate of the result is the minimum width of the receiver.
905  * The y coordinate of the result is the minimum height of the
906  * receiver.
907  *
908  * @return the receiver's size
909  *
910  * @exception SWTException <ul>
911  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
912  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
913  * </ul>
914  *
915  * @since 3.1
916  */

917 public Point getMinimumSize () {
918     checkWidget ();
919     int width = Math.max (0, minWidth);
920     int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
921     if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
922         width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
923     }
924     int height = Math.max (0, minHeight);
925     if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
926         if ((style & SWT.RESIZE) != 0) {
927             height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
928         } else {
929             RECT rect = new RECT ();
930             int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
931             int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
932             OS.AdjustWindowRectEx (rect, bits1, false, bits2);
933             height = Math.max (height, rect.bottom - rect.top);
934         }
935     }
936     return new Point (width, height);
937 }
938
939 /**
940  * Returns the region that defines the shape of the shell,
941  * or null if the shell has the default shape.
942  *
943  * @return the region that defines the shape of the shell (or null)
944  *
945  * @exception SWTException <ul>
946  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
947  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
948  * </ul>
949  *
950  * @since 3.0
951  *
952  */

953 public Region getRegion () {
954     checkWidget ();
955     return region;
956 }
957
958 public Shell getShell () {
959     checkWidget ();
960     return this;
961 }
962
963 public Point getSize () {
964     checkWidget ();
965     if (!OS.IsWinCE) {
966         if (OS.IsIconic (handle)) return super.getSize ();
967     }
968     RECT rect = new RECT ();
969     OS.GetWindowRect (handle, rect);
970     int width = rect.right - rect.left;
971     int height = rect.bottom - rect.top;
972     return new Point (width, height);
973 }
974
975 /**
976  * Returns an array containing all shells which are
977  * descendants of the receiver.
978  * <p>
979  * @return the dialog shells
980  *
981  * @exception SWTException <ul>
982  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
983  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
984  * </ul>
985  */

986 public Shell [] getShells () {
987     checkWidget ();
988     int count = 0;
989     Shell [] shells = display.getShells ();
990     for (int i=0; i<shells.length; i++) {
991         Control shell = shells [i];
992         do {
993             shell = shell.parent;
994         } while (shell != null && shell != this);
995         if (shell == this) count++;
996     }
997     int index = 0;
998     Shell [] result = new Shell [count];
999     for (int i=0; i<shells.length; i++) {
1000        Control shell = shells [i];
1001        do {
1002            shell = shell.parent;
1003        } while (shell != null && shell != this);
1004        if (shell == this) {
1005            result [index++] = shells [i];
1006        }
1007    }
1008    return result;
1009}
1010
1011Composite findDeferredControl () {
1012    return layoutCount > 0 ? this : null;
1013}
1014
1015public boolean isEnabled () {
1016    checkWidget ();
1017    return getEnabled ();
1018}
1019
1020public boolean isVisible () {
1021    checkWidget ();
1022    return getVisible ();
1023}
1024
1025int hwndMDIClient () {
1026    if (hwndMDIClient == 0) {
1027        int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
1028        hwndMDIClient = OS.CreateWindowEx (
1029            0,
1030            new TCHAR (0, "MDICLIENT", true),
1031            null,
1032            widgetStyle,
1033            0, 0, 0, 0,
1034            handle,
1035            0,
1036            OS.GetModuleHandle (null),
1037            new CREATESTRUCT ());
1038// OS.ShowWindow (hwndMDIClient, OS.SW_SHOW);
1039
}
1040    return hwndMDIClient;
1041}
1042
1043/**
1044 * Moves the receiver to the top of the drawing order for
1045 * the display on which it was created (so that all other
1046 * shells on that display, which are not the receiver's
1047 * children will be drawn behind it), marks it visible,
1048 * sets the focus and asks the window manager to make the
1049 * shell active.
1050 *
1051 * @exception SWTException <ul>
1052 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1053 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1054 * </ul>
1055 *
1056 * @see Control#moveAbove
1057 * @see Control#setFocus
1058 * @see Control#setVisible
1059 * @see Display#getActiveShell
1060 * @see Decorations#setDefaultButton(Button)
1061 * @see Shell#setActive
1062 * @see Shell#forceActive
1063 */

1064public void open () {
1065    checkWidget ();
1066    STARTUPINFO lpStartUpInfo = Display.lpStartupInfo;
1067    if (lpStartUpInfo == null || (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) == 0) {
1068        bringToTop ();
1069        if (isDisposed ()) return;
1070    }
1071    /*
1072    * Feature on WinCE PPC. A new application becomes
1073    * the foreground application only if it has at least
1074    * one visible window before the event loop is started.
1075    * The workaround is to explicitly force the shell to
1076    * be the foreground window.
1077    */

1078    if (OS.IsWinCE) OS.SetForegroundWindow (handle);
1079    OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
1080    setVisible (true);
1081    if (isDisposed ()) return;
1082    /*
1083    * Bug in Windows XP. Despite the fact that an icon has been
1084    * set for a window, the task bar displays the wrong icon the
1085    * first time the window is made visible with ShowWindow() after
1086    * a call to BringToTop(), when a long time elapses between the
1087    * ShowWindow() and the time the event queue is read. The icon
1088    * in the window trimming is correct but the one in the task
1089    * bar does not get updated. The fix is to call PeekMessage()
1090    * with the flag PM_NOREMOVE and PM_QS_SENDMESSAGE to respond
1091    * to a cross thread WM_GETICON.
1092    *
1093    * NOTE: This allows other cross thread messages to be delivered,
1094    * most notably WM_ACTIVATE.
1095    */

1096    MSG msg = new MSG ();
1097    int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
1098    OS.PeekMessage (msg, 0, 0, 0, flags);
1099    if (!restoreFocus () && !traverseGroup (true)) setFocus ();
1100}
1101
1102void register () {
1103    super.register ();
1104    if (toolTipHandle != 0) display.addControl (toolTipHandle, this);
1105    if (balloonTipHandle != 0) display.addControl (balloonTipHandle, this);
1106}
1107
1108void releaseBrushes () {
1109    if (brushes != null) {
1110        for (int i=0; i<brushes.length; i++) {
1111            if (brushes [i] != 0) OS.DeleteObject (brushes [i]);
1112        }
1113    }
1114    brushes = null;
1115}
1116
1117void releaseChildren (boolean destroy) {
1118    Shell [] shells = getShells ();
1119    for (int i=0; i<shells.length; i++) {
1120        Shell shell = shells [i];
1121        if (shell != null && !shell.isDisposed ()) {
1122            shell.release (false);
1123        }
1124    }
1125    if (toolTips != null) {
1126        for (int i=0; i<toolTips.length; i++) {
1127            ToolTip toolTip = toolTips [i];
1128            if (toolTip != null && !toolTip.isDisposed ()) {
1129                toolTip.release (false);
1130            }
1131        }
1132    }
1133    toolTips = null;
1134    super.releaseChildren (destroy);
1135}
1136
1137void releaseHandle () {
1138    super.releaseHandle ();
1139    hwndMDIClient = 0;
1140}
1141
1142void releaseParent () {
1143    /* Do nothing */
1144}
1145
1146void releaseWidget () {
1147    super.releaseWidget ();
1148    releaseBrushes ();
1149    activeMenu = null;
1150    display.clearModal (this);
1151    if (lpstrTip != 0) {
1152        int hHeap = OS.GetProcessHeap ();
1153        OS.HeapFree (hHeap, 0, lpstrTip);
1154    }
1155    lpstrTip = 0;
1156    toolTipHandle = balloonTipHandle = 0;
1157    if (OS.IsDBLocale) {
1158        if (hIMC != 0) OS.ImmDestroyContext (hIMC);
1159    }
1160    lastActive = null;
1161    region = null;
1162    toolTitle = balloonTitle = null;
1163    lockToolTipControl = null;
1164}
1165
1166void removeMenu (Menu menu) {
1167    super.removeMenu (menu);
1168    if (menu == activeMenu) activeMenu = null;
1169}
1170
1171/**
1172 * Removes the listener from the collection of listeners who will
1173 * be notified when operations are performed on the receiver.
1174 *
1175 * @param listener the listener which should no longer be notified
1176 *
1177 * @exception IllegalArgumentException <ul>
1178 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1179 * </ul>
1180 * @exception SWTException <ul>
1181 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1182 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1183 * </ul>
1184 *
1185 * @see ShellListener
1186 * @see #addShellListener
1187 */

1188public void removeShellListener (ShellListener listener) {
1189    checkWidget ();
1190    if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1191    if (eventTable == null) return;
1192    eventTable.unhook (SWT.Close, listener);
1193    eventTable.unhook (SWT.Iconify,listener);
1194    eventTable.unhook (SWT.Deiconify,listener);
1195    eventTable.unhook (SWT.Activate, listener);
1196    eventTable.unhook (SWT.Deactivate, listener);
1197}
1198
1199LRESULT selectPalette (int hPalette) {
1200    int hDC = OS.GetDC (handle);
1201    int hOld = OS.SelectPalette (hDC, hPalette, false);
1202    int result = OS.RealizePalette (hDC);
1203    if (result > 0) {
1204        OS.InvalidateRect (handle, null, true);
1205    } else {
1206        OS.SelectPalette (hDC, hOld, true);
1207        OS.RealizePalette (hDC);
1208    }
1209    OS.ReleaseDC (handle, hDC);
1210    return (result > 0) ? LRESULT.ONE : LRESULT.ZERO;
1211}
1212
1213/**
1214 * If the receiver is visible, moves it to the top of the
1215 * drawing order for the display on which it was created
1216 * (so that all other shells on that display, which are not
1217 * the receiver's children will be drawn behind it) and asks
1218 * the window manager to make the shell active
1219 *
1220 * @exception SWTException <ul>
1221 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1222 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1223 * </ul>
1224 *
1225 * @since 2.0
1226 * @see Control#moveAbove
1227 * @see Control#setFocus
1228 * @see Control#setVisible
1229 * @see Display#getActiveShell
1230 * @see Decorations#setDefaultButton(Button)
1231 * @see Shell#open
1232 * @see Shell#setActive
1233 */

1234public void setActive () {
1235    checkWidget ();
1236    if (!isVisible ()) return;
1237    bringToTop ();
1238    // widget could be disposed at this point
1239
}
1240
1241void setActiveControl (Control control) {
1242    if (control != null && control.isDisposed ()) control = null;
1243    if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
1244    if (lastActive == control) return;
1245    
1246    /*
1247    * Compute the list of controls to be activated and
1248    * deactivated by finding the first common parent
1249    * control.
1250    */

1251    Control [] activate = (control == null) ? new Control [0] : control.getPath ();
1252    Control [] deactivate = (lastActive == null) ? new Control [0] : lastActive.getPath ();
1253    lastActive = control;
1254    int index = 0, length = Math.min (activate.length, deactivate.length);
1255    while (index < length) {
1256        if (activate [index] != deactivate [index]) break;
1257        index++;
1258    }
1259    
1260    /*
1261    * It is possible (but unlikely), that application
1262    * code could have destroyed some of the widgets. If
1263    * this happens, keep processing those widgets that
1264    * are not disposed.
1265    */

1266    for (int i=deactivate.length-1; i>=index; --i) {
1267        if (!deactivate [i].isDisposed ()) {
1268            deactivate [i].sendEvent (SWT.Deactivate);
1269        }
1270    }
1271    for (int i=activate.length-1; i>=index; --i) {
1272        if (!activate [i].isDisposed ()) {
1273            activate [i].sendEvent (SWT.Activate);
1274        }
1275    }
1276}
1277
1278void setBounds (int x, int y, int width, int height, int flags, boolean defer) {
1279    super.setBounds (x, y, width, height, flags, false);
1280}
1281
1282public void setEnabled (boolean enabled) {
1283    checkWidget ();
1284    if (((state & DISABLED) == 0) == enabled) return;
1285    super.setEnabled (enabled);
1286    if (enabled && handle == OS.GetActiveWindow ()) {
1287        if (!restoreFocus ()) traverseGroup (true);
1288    }
1289}
1290
1291/**
1292 * Sets the input method editor mode to the argument which
1293 * should be the result of bitwise OR'ing together one or more
1294 * of the following constants defined in class <code>SWT</code>:
1295 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
1296 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
1297 *
1298 * @param mode the new IME mode
1299 *
1300 * @exception SWTException <ul>
1301 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1302 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1303 * </ul>
1304 *
1305 * @see SWT
1306 */

1307public void setImeInputMode (int mode) {
1308    checkWidget ();
1309    if (!OS.IsDBLocale) return;
1310    boolean imeOn = mode != SWT.NONE && mode != SWT.ROMAN;
1311    int hIMC = OS.ImmGetContext (handle);
1312    OS.ImmSetOpenStatus (hIMC, imeOn);
1313    if (imeOn) {
1314        int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
1315        if (OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence)) {
1316            int newBits = 0;
1317            int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA;
1318            if ((mode & SWT.PHONETIC) != 0) {
1319                newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE;
1320                oldBits = 0;
1321            } else {
1322                if ((mode & SWT.NATIVE) != 0) {
1323                    newBits = OS.IME_CMODE_NATIVE;
1324                    oldBits = OS.IME_CMODE_KATAKANA;
1325                }
1326            }
1327            if ((mode & SWT.DBCS) != 0) {
1328                newBits |= OS.IME_CMODE_FULLSHAPE;
1329            } else {
1330                oldBits |= OS.IME_CMODE_FULLSHAPE;
1331            }
1332            if ((mode & SWT.ROMAN) != 0) {
1333                newBits |= OS.IME_CMODE_ROMAN;
1334            } else {
1335                oldBits |= OS.IME_CMODE_ROMAN;
1336            }
1337            lpfdwConversion [0] |= newBits; lpfdwConversion [0] &= ~oldBits;
1338            OS.ImmSetConversionStatus (hIMC, lpfdwConversion [0], lpfdwSentence [0]);
1339        }
1340    }
1341    OS.ImmReleaseContext (handle, hIMC);
1342}
1343
1344/**
1345 * Sets the receiver's minimum size to the size specified by the arguments.
1346 * If the new minimum size is larger than the current size of the receiver,
1347 * the receiver is resized to the new minimum size.
1348 *
1349 * @param width the new minimum width for the receiver
1350 * @param height the new minimum height for the receiver
1351 *
1352 * @exception SWTException <ul>
1353 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1354 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1355 * </ul>
1356 *
1357 * @since 3.1
1358 */

1359public void setMinimumSize (int width, int height) {
1360    checkWidget ();
1361    int widthLimit = 0, heightLimit = 0;
1362    int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1363    if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
1364        widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK);
1365        if ((style & SWT.RESIZE) != 0) {
1366            heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK);
1367        } else {
1368            RECT rect = new RECT ();
1369            int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
1370            int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1371            OS.AdjustWindowRectEx (rect, bits1, false, bits2);
1372            heightLimit = rect.bottom - rect.top;
1373        }
1374    }
1375    minWidth = Math.max (widthLimit, width);
1376    minHeight = Math.max (heightLimit, height);
1377    Point size = getSize ();
1378    int newWidth = Math.max (size.x, minWidth);
1379    int newHeight = Math.max (size.y, minHeight);
1380    if (minWidth <= widthLimit) minWidth = SWT.DEFAULT;
1381    if (minHeight <= heightLimit) minHeight = SWT.DEFAULT;
1382    if (newWidth != size.x || newHeight != size.y) setSize (newWidth, newHeight);
1383}
1384
1385/**
1386 * Sets the receiver's minimum size to the size specified by the argument.
1387 * If the new minimum size is larger than the current size of the receiver,
1388 * the receiver is resized to the new minimum size.
1389 *
1390 * @param size the new minimum size for the receiver
1391 *
1392 * @exception IllegalArgumentException <ul>
1393 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
1394 * </ul>
1395 * @exception SWTException <ul>
1396 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1397 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1398 * </ul>
1399 *
1400 * @since 3.1
1401 */

1402public void setMinimumSize (Point size) {
1403    checkWidget ();
1404    if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
1405    setMinimumSize (size.x, size.y);
1406}
1407
1408void setItemEnabled (int cmd, boolean enabled) {
1409    int hMenu = OS.GetSystemMenu (handle, false);
1410    if (hMenu == 0) return;
1411    int flags = OS.MF_ENABLED;
1412    if (!enabled) flags = OS.MF_DISABLED | OS.MF_GRAYED;
1413    OS.EnableMenuItem (hMenu, cmd, OS.MF_BYCOMMAND | flags);
1414}
1415
1416void setParent () {
1417    /* Do nothing. Not necessary for Shells */
1418}
1419
1420/**
1421 * Sets the shape of the shell to the region specified
1422 * by the argument. When the argument is null, the
1423 * default shape of the shell is restored. The shell
1424 * must be created with the style SWT.NO_TRIM in order
1425 * to specify a region.
1426 *
1427 * @param region the region that defines the shape of the shell (or null)
1428 *
1429 * @exception IllegalArgumentException <ul>
1430 * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
1431 * </ul>
1432 * @exception SWTException <ul>
1433 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1434 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1435 * </ul>
1436 *
1437 * @since 3.0
1438 *
1439 */

1440public void setRegion (Region region) {
1441    checkWidget ();
1442    if ((style & SWT.NO_TRIM) == 0) return;
1443    if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
1444    int hRegion = 0;
1445    if (region != null) {
1446        hRegion = OS.CreateRectRgn (0, 0, 0, 0);
1447        OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR);
1448    }
1449    OS.SetWindowRgn (handle, hRegion, true);
1450    this.region = region;
1451}
1452
1453void setToolTipText (int hwnd, String JavaDoc text) {
1454    if (OS.IsWinCE) return;
1455    TOOLINFO lpti = new TOOLINFO ();
1456    lpti.cbSize = TOOLINFO.sizeof;
1457    lpti.hwnd = handle;
1458    lpti.uId = hwnd;
1459    int hwndToolTip = toolTipHandle ();
1460    if (text == null) {
1461        OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, lpti);
1462    } else {
1463        if (OS.SendMessage (hwndToolTip, OS.TTM_GETTOOLINFO, 0, lpti) != 0) {
1464            OS.SendMessage (hwndToolTip, OS.TTM_UPDATE, 0, 0);
1465        } else {
1466            lpti.uFlags = OS.TTF_IDISHWND | OS.TTF_SUBCLASS;
1467            lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
1468            OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, lpti);
1469        }
1470    }
1471}
1472
1473void setToolTipText (NMTTDISPINFO lpnmtdi, byte [] buffer) {
1474    /*
1475    * Ensure that the current position of the mouse
1476    * is inside the client area of the shell. This
1477    * prevents tool tips from popping up over the
1478    * shell trimmings.
1479    */

1480    if (!hasCursor ()) return;
1481    int hHeap = OS.GetProcessHeap ();
1482    if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip);
1483    int byteCount = buffer.length;
1484    lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
1485    OS.MoveMemory (lpstrTip, buffer, byteCount);
1486    lpnmtdi.lpszText = lpstrTip;
1487}
1488
1489void setToolTipText (NMTTDISPINFO lpnmtdi, char [] buffer) {
1490    /*
1491    * Ensure that the current position of the mouse
1492    * is inside the client area of the shell. This
1493    * prevents tool tips from popping up over the
1494    * shell trimmings.
1495    */

1496    if (!hasCursor ()) return;
1497    int hHeap = OS.GetProcessHeap ();
1498    if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip);
1499    int byteCount = buffer.length * 2;
1500    lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
1501    OS.MoveMemory (lpstrTip, buffer, byteCount);
1502    lpnmtdi.lpszText = lpstrTip;
1503}
1504
1505void setToolTipTitle (int hwndToolTip, String JavaDoc text, int icon) {
1506    /*
1507    * Bug in Windows. For some reason, when TTM_SETTITLE
1508    * is used to set the title of a tool tip, Windows leaks
1509    * GDI objects. This happens even when TTM_SETTITLE is
1510    * called with TTI_NONE and NULL. The documentation
1511    * states that Windows copies the icon and that the
1512    * programmer must free the copy but does not provide
1513    * API to get the icon. For example, when TTM_SETTITLE
1514    * is called with ICON_ERROR, when TTM_GETTITLE is used
1515    * to query the title and the icon, the uTitleBitmap
1516    * field in the TTGETTITLE struct is zero. The fix
1517    * is to remember these values, only set them when then
1518    * change and leak less.
1519    *
1520    * NOTE: This only happens on Vista.
1521    */

1522    if (hwndToolTip != toolTipHandle && hwndToolTip != balloonTipHandle) {
1523        return;
1524    }
1525    if (hwndToolTip == toolTipHandle) {
1526        if (text == toolTitle || (toolTitle != null && toolTitle.equals (text))) {
1527            if (icon == toolIcon) return;
1528        }
1529        toolTitle = text;
1530        toolIcon = icon;
1531    } else {
1532        if (hwndToolTip == balloonTipHandle) {
1533            if (text == balloonTitle || (balloonTitle != null && balloonTitle.equals (text))) {
1534                if (icon == toolIcon) return;
1535            }
1536            balloonTitle = text;
1537            balloonIcon = icon;
1538        }
1539    }
1540    if (text != null) {
1541        TCHAR pszTitle = new TCHAR (getCodePage (), text, true);
1542        OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, pszTitle);
1543    } else {
1544        OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0);
1545    }
1546}
1547
1548public void setVisible (boolean visible) {
1549    checkWidget ();
1550    if (drawCount != 0) {
1551        if (((state & HIDDEN) == 0) == visible) return;
1552    } else {
1553        if (visible == OS.IsWindowVisible (handle)) return;
1554    }
1555    
1556    /*
1557    * Feature in Windows. When ShowWindow() is called used to hide
1558    * a window, Windows attempts to give focus to the parent. If the
1559    * parent is disabled by EnableWindow(), focus is assigned to
1560    * another windows on the desktop. This means that if you hide
1561    * a modal window before the parent is enabled, the parent will
1562    * not come to the front. The fix is to change the modal state
1563    * before hiding or showing a window so that this does not occur.
1564    */

1565    int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
1566    if ((style & mask) != 0) {
1567        if (visible) {
1568            display.setModalShell (this);
1569            Control control = display._getFocusControl ();
1570            if (control != null && !control.isActive ()) {
1571                bringToTop ();
1572                if (isDisposed ()) return;
1573            }
1574            int hwndShell = OS.GetActiveWindow ();
1575            if (hwndShell == 0) {
1576                if (parent != null) hwndShell = parent.handle;
1577            }
1578            if (hwndShell != 0) {
1579                OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
1580            }
1581            OS.ReleaseCapture ();
1582        } else {
1583            display.clearModal (this);
1584        }
1585    } else {
1586        updateModal ();
1587    }
1588    
1589    /*
1590    * Bug in Windows. Calling ShowOwnedPopups() to hide the
1591    * child windows of a hidden window causes the application
1592    * to be deactivated. The fix is to call ShowOwnedPopups()
1593    * to hide children before hiding the parent.
1594    */

1595    if (showWithParent && !visible) {
1596        if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, false);
1597    }
1598    if (!visible) fixActiveShell ();
1599    super.setVisible (visible);
1600    if (isDisposed ()) return;
1601    if (showWithParent == visible) return;
1602    showWithParent = visible;
1603    if (visible) {
1604        if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true);
1605    }
1606}
1607
1608void subclass () {
1609    super.subclass ();
1610    if (ToolTipProc != 0) {
1611        int newProc = display.windowProc;
1612        if (toolTipHandle != 0) {
1613            OS.SetWindowLong (toolTipHandle, OS.GWL_WNDPROC, newProc);
1614        }
1615        if (balloonTipHandle != 0) {
1616            OS.SetWindowLong (balloonTipHandle, OS.GWL_WNDPROC, newProc);
1617        }
1618    }
1619}
1620
1621int toolTipHandle () {
1622    if (toolTipHandle == 0) createToolTipHandle ();
1623    return toolTipHandle;
1624}
1625
1626boolean translateAccelerator (MSG msg) {
1627    if (!isEnabled () || !isActive ()) return false;
1628    if (menuBar != null && !menuBar.isEnabled ()) return false;
1629    return translateMDIAccelerator (msg) || translateMenuAccelerator (msg);
1630}
1631
1632boolean traverseEscape () {
1633    if (parent == null) return false;
1634    if (!isVisible () || !isEnabled ()) return false;
1635    close ();
1636    return true;
1637}
1638
1639void unsubclass () {
1640    super.unsubclass ();
1641    if (ToolTipProc != 0) {
1642        if (toolTipHandle != 0) {
1643            OS.SetWindowLong (toolTipHandle, OS.GWL_WNDPROC, ToolTipProc);
1644        }
1645        if (toolTipHandle != 0) {
1646            OS.SetWindowLong (toolTipHandle, OS.GWL_WNDPROC, ToolTipProc);
1647        }
1648    }
1649}
1650
1651void updateModal () {
1652    if (Display.TrimEnabled) {
1653        setItemEnabled (OS.SC_CLOSE, isActive ());
1654    } else {
1655        OS.EnableWindow (handle, isActive ());
1656    }
1657}
1658
1659CREATESTRUCT widgetCreateStruct () {
1660    return null;
1661}
1662
1663int widgetParent () {
1664    if (handle != 0) return handle;
1665    return parent != null ? parent.handle : 0;
1666}
1667
1668int widgetExtStyle () {
1669    int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD;
1670    if ((style & SWT.TOOL) != 0) bits |= OS.WS_EX_TOOLWINDOW;
1671    
1672    /*
1673    * Feature in Windows. When a window that does not have a parent
1674    * is created, it is automatically added to the Windows Task Bar,
1675    * even when it has no title. The fix is to use WS_EX_TOOLWINDOW
1676    * which does not cause the window to appear in the Task Bar.
1677    */

1678    if (!OS.IsWinCE) {
1679        if (parent == null) {
1680            if ((style & SWT.ON_TOP) != 0) {
1681                int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1682                if ((style & SWT.NO_TRIM) != 0 || (style & trim) == 0) {
1683                    bits |= OS.WS_EX_TOOLWINDOW;
1684                }
1685            }
1686        }
1687    }
1688    
1689    /*
1690    * Bug in Windows 98 and NT. Creating a window with the
1691    * WS_EX_TOPMOST extended style can result in a dialog shell
1692    * being moved behind its parent. The exact case where this
1693    * happens is a shell with two dialog shell children where
1694    * each dialog child has another hidden dialog child with
1695    * the WS_EX_TOPMOST extended style. Clicking on either of
1696    * the visible dialogs causes them to become active but move
1697    * to the back, behind the parent shell. The fix is to
1698    * disallow the WS_EX_TOPMOST extended style on Windows 98
1699    * and NT.
1700    */

1701    if (parent != null) {
1702        if (OS.IsWin95) return bits;
1703        if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
1704            return bits;
1705        }
1706    }
1707    if ((style & SWT.ON_TOP) != 0) bits |= OS.WS_EX_TOPMOST;
1708    return bits;
1709}
1710
1711TCHAR windowClass () {
1712    if (OS.IsSP) return DialogClass;
1713    if ((style & SWT.TOOL) != 0) {
1714        int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
1715        if ((style & trim) == 0) return display.windowShadowClass;
1716    }
1717    return parent != null ? DialogClass : super.windowClass ();
1718}
1719
1720int windowProc () {
1721    if (windowProc != 0) return windowProc;
1722    if (OS.IsSP) return DialogProc;
1723    if ((style & SWT.TOOL) != 0) {
1724        int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
1725        if ((style & trim) == 0) super.windowProc ();
1726    }
1727    return parent != null ? DialogProc : super.windowProc ();
1728}
1729
1730int windowProc (int hwnd, int msg, int wParam, int lParam) {
1731    if (handle == 0) return 0;
1732    if (hwnd == toolTipHandle || hwnd == balloonTipHandle) {
1733        switch (msg) {
1734            case OS.WM_TIMER: {
1735                if (wParam != ToolTip.TIMER_ID) break;
1736                ToolTip tip = getCurrentToolTip (hwnd);
1737                if (tip != null && tip.autoHide) {
1738                    tip.setVisible (false);
1739                }
1740                break;
1741            }
1742            case OS.WM_LBUTTONDOWN: {
1743                ToolTip tip = getCurrentToolTip (hwnd);
1744                if (tip != null) {
1745                    tip.setVisible (false);
1746                    tip.postEvent (SWT.Selection);
1747                }
1748                break;
1749            }
1750        }
1751        return callWindowProc (hwnd, msg, wParam, lParam);
1752    }
1753    return super.windowProc (hwnd, msg, wParam, lParam);
1754}
1755
1756int widgetStyle () {
1757    int bits = super.widgetStyle ();
1758    if (handle != 0) return bits | OS.WS_CHILD;
1759    bits &= ~OS.WS_CHILD;
1760    /*
1761    * Feature in WinCE. Calling CreateWindowEx () with WS_OVERLAPPED
1762    * and a parent window causes the new window to become a WS_CHILD of
1763    * the parent instead of a dialog child. The fix is to use WS_POPUP
1764    * for a window with a parent.
1765    *
1766    * Feature in WinCE PPC. A window without a parent with WS_POPUP
1767    * always shows on top of the Pocket PC 'Today Screen'. The fix
1768    * is to not set WS_POPUP for a window without a parent on WinCE
1769    * devices.
1770    *
1771    * NOTE: WS_POPUP causes CreateWindowEx () to ignore CW_USEDEFAULT
1772    * and causes the default window location and size to be zero.
1773    */

1774    if (OS.IsWinCE) {
1775        if (OS.IsSP) return bits | OS.WS_POPUP;
1776        return parent == null ? bits : bits | OS.WS_POPUP;
1777    }
1778    
1779    /*
1780    * Use WS_OVERLAPPED for all windows, either dialog or top level
1781    * so that CreateWindowEx () will respect CW_USEDEFAULT and set
1782    * the default window location and size.
1783    *
1784    * NOTE: When a WS_OVERLAPPED window is created, Windows gives
1785    * the new window WS_CAPTION style bits. These two constants are
1786    * as follows:
1787    *
1788    * WS_OVERLAPPED = 0
1789    * WS_CAPTION = WS_BORDER | WS_DLGFRAME
1790    *
1791    */

1792    return bits | OS.WS_OVERLAPPED | OS.WS_CAPTION;
1793}
1794
1795LRESULT WM_ACTIVATE (int wParam, int lParam) {
1796    if (OS.IsPPC) {
1797        /*
1798        * Note: this does not work when we get WM_ACTIVATE prior
1799        * to adding a listener.
1800        */

1801        if (hooks (SWT.HardKeyDown) || hooks (SWT.HardKeyUp)) {
1802            int fActive = wParam & 0xFFFF;
1803            int hwnd = fActive != 0 ? handle : 0;
1804            for (int bVk=OS.VK_APP1; bVk<=OS.VK_APP6; bVk++) {
1805                OS.SHSetAppKeyWndAssoc ((byte) bVk, hwnd);
1806            }
1807        }
1808        /* Restore SIP state when window is activated */
1809        if ((wParam & 0xFFFF) != 0) {
1810            OS.SHSipPreference (handle, psai.fSipUp == 0 ? OS.SIP_DOWN : OS.SIP_UP);
1811        }
1812    }
1813
1814    /*
1815    * Bug in Windows XP. When a Shell is deactivated, the
1816    * IME composition window does not go away. This causes
1817    * repaint issues. The fix is to close the IME to cause
1818    * the composition string to be committed.
1819    *
1820    * Note. The IME needs to be reopened in order to preserve
1821    * the input method status.
1822    */

1823    if (OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
1824        if ((wParam & 0xFFFF) == 0 && OS.IsDBLocale && hIMC != 0) {
1825            if (OS.ImmGetOpenStatus(hIMC)) {
1826                OS.ImmSetOpenStatus (hIMC, false);
1827                OS.ImmSetOpenStatus (hIMC, true);
1828            }
1829        }
1830    }
1831    
1832    /* Process WM_ACTIVATE */
1833    LRESULT result = super.WM_ACTIVATE (wParam, lParam);
1834    if ((wParam & 0xFFFF) == 0) {
1835        if (lParam == 0 || (lParam != toolTipHandle && lParam != balloonTipHandle)) {
1836            ToolTip tip = getCurrentToolTip ();
1837            if (tip != null) tip.setVisible (false);
1838        }
1839    }
1840    return parent != null ? LRESULT.ZERO : result;
1841}
1842
1843LRESULT WM_COMMAND (int wParam, int lParam) {
1844    if (OS.IsPPC) {
1845        /*
1846        * Note in WinCE PPC: Close the Shell when the "Done Button" has
1847        * been pressed. lParam is either 0 (PocketPC 2002) or the handle
1848        * to the Shell (PocketPC).
1849        */

1850        int loWord = wParam & 0xFFFF;
1851        if (loWord == OS.IDOK && (lParam == 0 || lParam == handle)) {
1852            OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
1853            return LRESULT.ZERO;
1854        }
1855    }
1856    /*
1857    * Feature in Windows. On PPC, the menu is not actually an HMENU.
1858    * By observation, it is a tool bar that is configured to look like
1859    * a menu. Therefore, when the PPC menu sends WM_COMMAND messages,
1860    * lParam is not zero because the WM_COMMAND was not sent from a menu.
1861    * Sub menu item events originate from the menu bar. Top menu items
1862    * events originate from a tool bar. The fix is to detect the source
1863    * of the WM_COMMAND and set lParam to zero to pretend that the message
1864    * came from a real Windows menu, not a tool bar.
1865    */

1866    if (OS.IsPPC || OS.IsSP) {
1867        if (menuBar != null) {
1868            int hwndCB = menuBar.hwndCB;
1869            if (lParam != 0 && hwndCB != 0) {
1870                if (lParam == hwndCB) {
1871                    return super.WM_COMMAND (wParam, 0);
1872                } else {
1873                    int hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD);
1874                    if (lParam == hwndChild) return super.WM_COMMAND (wParam, 0);
1875                }
1876            }
1877        }
1878    }
1879    return super.WM_COMMAND (wParam, lParam);
1880}
1881
1882LRESULT WM_DESTROY (int wParam, int lParam) {
1883    LRESULT result = super.WM_DESTROY (wParam, lParam);
1884    /*
1885    * When the shell is a WS_CHILD window of a non-SWT
1886    * window, the destroy code does not get called because
1887    * the non-SWT window does not call dispose (). Instead,
1888    * the destroy code is called here in WM_DESTROY.
1889    */

1890    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1891    if ((bits & OS.WS_CHILD) != 0) {
1892        releaseParent ();
1893        release (false);
1894    }
1895    return result;
1896}
1897
1898LRESULT WM_ERASEBKGND (int wParam, int lParam) {
1899    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
1900    if (result != null) return result;
1901    /*
1902    * Feature in Windows. When a shell is resized by dragging
1903    * the resize handles, Windows temporarily fills in black
1904    * rectangles where the new contents of the shell should
1905    * draw. The fix is to always draw the background of shells.
1906    *
1907    * NOTE: This only happens on Vista.
1908    */

1909    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
1910        drawBackground (wParam);
1911        return LRESULT.ONE;
1912    }
1913    return result;
1914}
1915
1916LRESULT WM_ENTERIDLE (int wParam, int lParam) {
1917    LRESULT result = super.WM_ENTERIDLE (wParam, lParam);
1918    if (result != null) return result;
1919    if (OS.IsWinCE && display.runMessages) {
1920        if (display.runAsyncMessages (true)) display.wakeThread ();
1921    }
1922    return result;
1923}
1924
1925LRESULT WM_GETMINMAXINFO (int wParam, int lParam) {
1926    LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam);
1927    if (result != null) return result;
1928    if (minWidth != SWT.DEFAULT || minHeight != SWT.DEFAULT) {
1929        MINMAXINFO info = new MINMAXINFO ();
1930        OS.MoveMemory (info, lParam, MINMAXINFO.sizeof);
1931        if (minWidth != SWT.DEFAULT) info.ptMinTrackSize_x = minWidth;
1932        if (minHeight != SWT.DEFAULT) info.ptMinTrackSize_y = minHeight;
1933        OS.MoveMemory (lParam, info, MINMAXINFO.sizeof);
1934        return LRESULT.ZERO;
1935    }
1936    return result;
1937}
1938
1939LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) {
1940    LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam);
1941    if (result != null) return result;
1942    
1943    /*
1944    * Check for WM_MOUSEACTIVATE when an MDI shell is active
1945    * and stop the normal shell activation but allow the mouse
1946    * down to be delivered.
1947    */

1948    int hittest = (short) (lParam & 0xFFFF);
1949    switch (hittest) {
1950        case OS.HTERROR:
1951        case OS.HTTRANSPARENT:
1952        case OS.HTNOWHERE:
1953            break;
1954        default: {
1955            Control control = display._getFocusControl ();
1956            if (control != null) {
1957                Decorations decorations = control.menuShell ();
1958                if (decorations.getShell () == this && decorations != this) {
1959                    display.ignoreRestoreFocus = true;
1960                    display.lastHittest = hittest;
1961                    display.lastHittestControl = null;
1962                    if (hittest == OS.HTMENU || hittest == OS.HTSYSMENU) {
1963                        display.lastHittestControl = control;
1964                        return null;
1965                    }
1966                    if (OS.IsWin95 && hittest == OS.HTCAPTION) {
1967                        display.lastHittestControl = control;
1968                    }
1969                    return new LRESULT (OS.MA_NOACTIVATE);
1970                }
1971            }
1972        }
1973    }
1974    if (hittest == OS.HTMENU) return null;
1975    
1976    /*
1977    * Get the current location of the cursor,
1978    * not the location of the cursor when the
1979    * WM_MOUSEACTIVATE was generated. This is
1980    * strictly incorrect but is necessary in
1981    * order to support Activate and Deactivate
1982    * events for embedded widgets that have
1983    * their own event loop. In that case, the
1984    * cursor location reported by GetMessagePos()
1985    * is the one for our event loop, not the
1986    * embedded widget's event loop.
1987    */

1988    POINT pt = new POINT ();
1989    if (!OS.GetCursorPos (pt)) {
1990        int pos = OS.GetMessagePos ();
1991        pt.x = (short) (pos & 0xFFFF);
1992        pt.y = (short) (pos >> 16);
1993    }
1994    int hwnd = OS.WindowFromPoint (pt);
1995    if (hwnd == 0) return null;
1996    Control control = display.findControl (hwnd);
1997    
1998    /*
1999    * When a shell is created with SWT.ON_TOP and SWT.NO_FOCUS,
2000    * do not activate the shell when the user clicks on the
2001    * the client area or on the border or a control within the
2002    * shell that does not take focus.
2003    */

2004    if (control != null && (control.state & CANVAS) != 0) {
2005        if ((control.style & SWT.NO_FOCUS) != 0) {
2006            int bits = SWT.ON_TOP | SWT.NO_FOCUS;
2007            if ((style & bits) == bits) {
2008                if (hittest == OS.HTBORDER || hittest == OS.HTCLIENT) {
2009                    return new LRESULT (OS.MA_NOACTIVATE);
2010                }
2011            }
2012        }
2013    }
2014    
2015    setActiveControl (control);
2016    return null;
2017}
2018
2019LRESULT WM_MOVE (int wParam, int lParam) {
2020    LRESULT result = super.WM_MOVE (wParam, lParam);
2021    if (result != null) return result;
2022    ToolTip tip = getCurrentToolTip ();
2023    if (tip != null) tip.setVisible (false);
2024    return result;
2025}
2026
2027LRESULT WM_NCACTIVATE (int wParam, int lParam) {
2028    Display display = this.display;
2029    LRESULT result = super.WM_NCACTIVATE (wParam, lParam);
2030    if (display.isXMouseActive ()) {
2031        if (lockToolTipControl != null) {
2032            if (OS.GetAsyncKeyState (OS.VK_LBUTTON) < 0) return result;
2033            if (OS.GetAsyncKeyState (OS.VK_MBUTTON) < 0) return result;
2034            if (OS.GetAsyncKeyState (OS.VK_RBUTTON) < 0) return result;
2035            if (OS.GetAsyncKeyState (OS.VK_XBUTTON1) < 0) return result;
2036            if (OS.GetAsyncKeyState (OS.VK_XBUTTON2) < 0) return result;
2037            return LRESULT.ZERO;
2038        }
2039    }
2040    return result;
2041}
2042
2043LRESULT WM_NCHITTEST (int wParam, int lParam) {
2044    if (!OS.IsWindowEnabled (handle)) return null;
2045    if (!isEnabled () || !isActive ()) {
2046        if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE);
2047        int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
2048        if (hittest == OS.HTCLIENT || hittest == OS.HTMENU) hittest = OS.HTBORDER;
2049        return new LRESULT (hittest);
2050    }
2051    if (menuBar != null && !menuBar.getEnabled ()) {
2052        int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
2053        if (hittest == OS.HTMENU) hittest = OS.HTBORDER;
2054        return new LRESULT (hittest);
2055    }
2056    return null;
2057}
2058
2059LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) {
2060    LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam);
2061    if (result != null) return result;
2062    /*
2063    * When the normal activation was interrupted in WM_MOUSEACTIVATE
2064    * because the active shell was an MDI shell, set the active window
2065    * to the top level shell but lock the active window and stop focus
2066    * changes. This allows the user to interact the top level shell
2067    * in the normal manner.
2068    */

2069    if (!display.ignoreRestoreFocus) return result;
2070    Display display = this.display;
2071    int hwndActive = 0;
2072    boolean fixActive = OS.IsWin95 && display.lastHittest == OS.HTCAPTION;
2073    if (fixActive) hwndActive = OS.SetActiveWindow (handle);
2074    display.lockActiveWindow = true;
2075    int code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
2076    display.lockActiveWindow = false;
2077    if (fixActive) OS.SetActiveWindow (hwndActive);
2078    Control focusControl = display.lastHittestControl;
2079    if (focusControl != null && !focusControl.isDisposed ()) {
2080        focusControl.setFocus ();
2081    }
2082    display.lastHittestControl = null;
2083    display.ignoreRestoreFocus = false;
2084    return new LRESULT (code);
2085}
2086
2087LRESULT WM_PALETTECHANGED (int wParam, int lParam) {
2088    if (wParam != handle) {
2089        int hPalette = display.hPalette;
2090        if (hPalette != 0) return selectPalette (hPalette);
2091    }
2092    return super.WM_PALETTECHANGED (wParam, lParam);
2093}
2094
2095LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) {
2096    int hPalette = display.hPalette;
2097    if (hPalette != 0) return selectPalette (hPalette);
2098    return super.WM_QUERYNEWPALETTE (wParam, lParam);
2099}
2100
2101LRESULT WM_SETCURSOR (int wParam, int lParam) {
2102    /*
2103    * Feature in Windows. When the shell is disabled
2104    * by a Windows standard dialog (like a MessageBox
2105    * or FileDialog), clicking in the shell does not
2106    * bring the shell or the dialog to the front. The
2107    * fix is to detect this case and bring the shell
2108    * forward.
2109    */

2110    int msg = (short) (lParam >> 16);
2111    if (msg == OS.WM_LBUTTONDOWN) {
2112        if (!Display.TrimEnabled) {
2113            Shell modalShell = display.getModalShell ();
2114            if (modalShell != null && !isActive ()) {
2115                int hwndModal = modalShell.handle;
2116                if (OS.IsWindowEnabled (hwndModal)) {
2117                    OS.SetActiveWindow (hwndModal);
2118                }
2119            }
2120        }
2121        if (!OS.IsWindowEnabled (handle)) {
2122            if (!OS.IsWinCE) {
2123                int hwndPopup = OS.GetLastActivePopup (handle);
2124                if (hwndPopup != 0 && hwndPopup != handle) {
2125                    if (display.getControl (hwndPopup) == null) {
2126                        if (OS.IsWindowEnabled (hwndPopup)) {
2127                            OS.SetActiveWindow (hwndPopup);
2128                        }
2129                    }
2130                }
2131            }
2132        }
2133    }
2134    /*
2135    * When the shell that contains a cursor is disabled,
2136    * WM_SETCURSOR is called with HTERROR. Normally,
2137    * when a control is disabled, the parent will get
2138    * mouse and cursor events. In the case of a disabled
2139    * shell, there is no enabled parent. In order to
2140    * show the cursor when a shell is disabled, it is
2141    * necessary to override WM_SETCURSOR when called
2142    * with HTERROR to set the cursor but only when the
2143    * mouse is in the client area of the shell.
2144    */

2145    int hitTest = (short) (lParam & 0xFFFF);
2146    if (hitTest == OS.HTERROR) {
2147        if (!getEnabled ()) {
2148            Control control = display.getControl (wParam);
2149            if (control == this && cursor != null) {
2150                POINT pt = new POINT ();
2151                int pos = OS.GetMessagePos ();
2152                pt.x = (short) (pos & 0xFFFF);
2153                pt.y = (short) (pos >> 16);
2154                OS.ScreenToClient (handle, pt);
2155                RECT rect = new RECT ();
2156                OS.GetClientRect (handle, rect);
2157                if (OS.PtInRect (rect, pt)) {
2158                    OS.SetCursor (cursor.handle);
2159                    switch (msg) {
2160                        case OS.WM_LBUTTONDOWN:
2161                        case OS.WM_RBUTTONDOWN:
2162                        case OS.WM_MBUTTONDOWN:
2163                        case OS.WM_XBUTTONDOWN:
2164                            OS.MessageBeep (OS.MB_OK);
2165                    }
2166                    return LRESULT.ONE;
2167                }
2168            }
2169        }
2170    }
2171    return super.WM_SETCURSOR (wParam, lParam);
2172}
2173
2174LRESULT WM_SETTINGCHANGE (int wParam, int lParam) {
2175    LRESULT result = super.WM_SETTINGCHANGE (wParam, lParam);
2176    if (result != null) return result;
2177    if (OS.IsPPC) {
2178        if (wParam == OS.SPI_SETSIPINFO) {
2179            /*
2180            * The SIP is in a new state. Cache its new value.
2181            * Resize the Shell if it has the style SWT.RESIZE.
2182            * Note that SHHandleWMSettingChange resizes the
2183            * Shell and also updates the cached state.
2184            */

2185            if ((style & SWT.RESIZE) != 0) {
2186                OS.SHHandleWMSettingChange (handle, wParam, lParam, psai);
2187                return LRESULT.ZERO;
2188            } else {
2189                SIPINFO pSipInfo = new SIPINFO ();
2190                pSipInfo.cbSize = SIPINFO.sizeof;
2191                OS.SipGetInfo (pSipInfo);
2192                psai.fSipUp = pSipInfo.fdwFlags & OS.SIPF_ON;
2193            }
2194        }
2195    }
2196    return result;
2197}
2198
2199LRESULT WM_SHOWWINDOW (int wParam, int lParam) {
2200    LRESULT result = super.WM_SHOWWINDOW (wParam, lParam);
2201    if (result != null) return result;
2202    /*
2203    * Bug in Windows. If the shell is hidden while the parent
2204    * is iconic, Windows shows the shell when the parent is
2205    * deiconified. This does not happen if the shell is hidden
2206    * while the parent is not an icon. The fix is to track
2207    * visible state for the shell and refuse to show the shell
2208    * when the parent is shown.
2209    */

2210    if (lParam == OS.SW_PARENTOPENING) {
2211        Control control = this;
2212        while (control != null) {
2213            Shell shell = control.getShell ();
2214            if (!shell.showWithParent) return LRESULT.ZERO;
2215            control = control.parent;
2216        }
2217    }
2218    return result;
2219}
2220
2221LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
2222    LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
2223    if (result != null) return result;
2224    /*
2225    * Feature in Windows. When the last visible window in
2226    * a process minimized, Windows swaps out the memory for
2227    * the process. The assumption is that the user can no
2228    * longer interact with the window, so the memory can be
2229    * released to other applications. However, for programs
2230    * that use a lot of memory, swapping the memory back in
2231    * can take a long time, sometimes minutes. The fix is
2232    * to intercept WM_SYSCOMMAND looking for SC_MINIMIZE
2233    * and use ShowWindow() with SW_SHOWMINIMIZED to minimize
2234    * the window, rather than running the default window proc.
2235    *
2236    * NOTE: The default window proc activates the next
2237    * top-level window in the Z-order while ShowWindow()
2238    * with SW_SHOWMINIMIZED does not. There is no fix for
2239    * this at this time.
2240    */

2241    if (OS.IsWinNT) {
2242        int cmd = wParam & 0xFFF0;
2243        switch (cmd) {
2244            case OS.SC_MINIMIZE:
2245                long memory = Runtime.getRuntime ().totalMemory ();
2246                if (memory >= 32 * 1024 * 1024) {
2247                    OS.ShowWindow (handle, OS.SW_SHOWMINIMIZED);
2248                    return LRESULT.ZERO;
2249                }
2250        }
2251    }
2252    return result;
2253}
2254
2255LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
2256    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam);
2257    if (result != null) return result;
2258    WINDOWPOS lpwp = new WINDOWPOS ();
2259    OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
2260    if ((lpwp.flags & OS.SWP_NOSIZE) == 0) {
2261        lpwp.cx = Math.max (lpwp.cx, minWidth);
2262        int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
2263        if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
2264            lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
2265        }
2266        lpwp.cy = Math.max (lpwp.cy, minHeight);
2267        if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
2268            if ((style & SWT.RESIZE) != 0) {
2269                lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
2270            } else {
2271                RECT rect = new RECT ();
2272                int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
2273                int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
2274                OS.AdjustWindowRectEx (rect, bits1, false, bits2);
2275                lpwp.cy = Math.max (lpwp.cy, rect.bottom - rect.top);
2276            }
2277        }
2278        OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
2279    }
2280    return result;
2281}
2282}
2283
Popular Tags