root/dwt/widgets/Shell.d

Revision 263:27244095ce14, 86.0 kB (checked in by Frank Benoit <benoit@tionex.de>, 4 months ago)

Fix struct sizes, based on a comparison to the values seen by C apps.

Line 
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module dwt.widgets.Shell;
14
15 import dwt.DWT;
16 import dwt.DWTException;
17 import dwt.events.ShellListener;
18 import dwt.graphics.Cursor;
19 import dwt.graphics.GC;
20 import dwt.graphics.Point;
21 import dwt.graphics.Rectangle;
22 import dwt.graphics.Region;
23 import dwt.internal.win32.OS;
24
25 import dwt.widgets.Composite;
26 import dwt.widgets.Decorations;
27 import dwt.widgets.Control;
28 import dwt.widgets.Menu;
29 import dwt.widgets.ToolTip;
30 import dwt.widgets.Display;
31 import dwt.widgets.TypedListener;
32 import dwt.widgets.Event;
33
34 import dwt.dwthelper.utils;
35
36 import tango.util.log.Trace;
37 void trc( int line ){
38     Trace.formatln( "Shell {}", line );
39 }
40
41 /**
42  * Instances of this class represent the "windows"
43  * which the desktop or "window manager" is managing.
44  * Instances that do not have a parent (that is, they
45  * are built using the constructor, which takes a
46  * <code>Display</code> as the argument) are described
47  * as <em>top level</em> shells. Instances that do have
48  * a parent are described as <em>secondary</em> or
49  * <em>dialog</em> shells.
50  * <p>
51  * Instances are always displayed in one of the maximized,
52  * minimized or normal states:
53  * <ul>
54  * <li>
55  * When an instance is marked as <em>maximized</em>, the
56  * window manager will typically resize it to fill the
57  * entire visible area of the display, and the instance
58  * is usually put in a state where it can not be resized
59  * (even if it has style <code>RESIZE</code>) until it is
60  * no longer maximized.
61  * </li><li>
62  * When an instance is in the <em>normal</em> state (neither
63  * maximized or minimized), its appearance is controlled by
64  * the style constants which were specified when it was created
65  * and the restrictions of the window manager (see below).
66  * </li><li>
67  * When an instance has been marked as <em>minimized</em>,
68  * its contents (client area) will usually not be visible,
69  * and depending on the window manager, it may be
70  * "iconified" (that is, replaced on the desktop by a small
71  * simplified representation of itself), relocated to a
72  * distinguished area of the screen, or hidden. Combinations
73  * of these changes are also possible.
74  * </li>
75  * </ul>
76  * </p><p>
77  * The <em>modality</em> of an instance may be specified using
78  * style bits. The modality style bits are used to determine
79  * whether input is blocked for other shells on the display.
80  * The <code>PRIMARY_MODAL</code> style allows an instance to block
81  * input to its parent. The <code>APPLICATION_MODAL</code> style
82  * allows an instance to block input to every other shell in the
83  * display. The <code>SYSTEM_MODAL</code> style allows an instance
84  * to block input to all shells, including shells belonging to
85  * different applications.
86  * </p><p>
87  * Note: The styles supported by this class are treated
88  * as <em>HINT</em>s, since the window manager for the
89  * desktop on which the instance is visible has ultimate
90  * control over the appearance and behavior of decorations
91  * and modality. For example, some window managers only
92  * support resizable windows and will always assume the
93  * RESIZE style, even if it is not set. In addition, if a
94  * modality style is not supported, it is "upgraded" to a
95  * more restrictive modality style that is supported. For
96  * example, if <code>PRIMARY_MODAL</code> is not supported,
97  * it would be upgraded to <code>APPLICATION_MODAL</code>.
98  * A modality style may also be "downgraded" to a less
99  * restrictive style. For example, most operating systems
100  * no longer support <code>SYSTEM_MODAL</code> because
101  * it can freeze up the desktop, so this is typically
102  * downgraded to <code>APPLICATION_MODAL</code>.
103  * <dl>
104  * <dt><b>Styles:</b></dt>
105  * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd>
106  * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
107  * <dt><b>Events:</b></dt>
108  * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
109  * </dl>
110  * Class <code>DWT</code> provides two "convenience constants"
111  * for the most commonly required style combinations:
112  * <dl>
113  * <dt><code>SHELL_TRIM</code></dt>
114  * <dd>
115  * the result of combining the constants which are required
116  * to produce a typical application top level shell: (that
117  * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
118  * </dd>
119  * <dt><code>DIALOG_TRIM</code></dt>
120  * <dd>
121  * the result of combining the constants which are required
122  * to produce a typical application dialog shell: (that
123  * is, <code>TITLE | CLOSE | BORDER</code>)
124  * </dd>
125  * </dl>
126  * </p>
127  * <p>
128  * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
129  * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
130  * </p><p>
131  * IMPORTANT: This class is not intended to be subclassed.
132  * </p>
133  *
134  * @see Decorations
135  * @see DWT
136  * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell snippets</a>
137  * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample</a>
138  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
139  */
140 public class Shell : Decorations {
141
142     alias Decorations.setBounds setBounds;
143     alias Decorations.setParent setParent;
144     alias Decorations.setToolTipText setToolTipText;
145
146     Menu activeMenu;
147     ToolTip [] toolTips;
148     HIMC hIMC;
149     HWND hwndMDIClient_;
150     TCHAR* lpstrTip;
151     HANDLE toolTipHandle_;
152     HANDLE balloonTipHandle_;
153     int minWidth = DWT.DEFAULT, minHeight = DWT.DEFAULT;
154     HBRUSH [] brushes;
155     bool showWithParent, fullScreen, wasMaximized;
156     String toolTitle, balloonTitle;
157     HICON toolIcon;
158     HICON balloonIcon;
159     WNDPROC windowProc_;
160     Control lastActive;
161     static if( OS.IsWinCE ){
162         SHACTIVATEINFO psai;
163     }
164     static /+const+/ WNDPROC ToolTipProc;
165     static /+const+/ WNDPROC DialogProc;
166     static if( OS.IsWinCE ){
167         static const TCHAR[] DialogClass = "Dialog\0"w;
168     }
169     else{
170         static const TCHAR[] DialogClass = "#32770\0"w;
171     }
172     const static int [] SYSTEM_COLORS = [
173         OS.COLOR_BTNFACE,
174         OS.COLOR_WINDOW,
175         OS.COLOR_BTNTEXT,
176         OS.COLOR_WINDOWTEXT,
177         OS.COLOR_HIGHLIGHT,
178         OS.COLOR_SCROLLBAR,
179     ];
180     final static int BRUSHES_SIZE = 32;
181
182     private static bool static_this_completed = false;
183     private static void static_this() {
184         if( static_this_completed ){
185             return;
186         }
187         synchronized {
188             if( static_this_completed ){
189                 return;
190             }
191             WNDCLASS lpWndClass;
192             OS.GetClassInfo (null, DialogClass.ptr, &lpWndClass);
193             DialogProc = lpWndClass.lpfnWndProc;
194             static_this_completed = true;
195         }
196     }
197
198 /**
199  * Constructs a new instance of this class. This is equivalent
200  * to calling <code>Shell((Display) null)</code>.
201  *
202  * @exception DWTException <ul>
203  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
204  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
205  * </ul>
206  */
207 public this () {
208     this (cast(Display) null);
209 }
210
211 /**
212  * Constructs a new instance of this class given only the style
213  * value describing its behavior and appearance. This is equivalent
214  * to calling <code>Shell((Display) null, style)</code>.
215  * <p>
216  * The style value is either one of the style constants defined in
217  * class <code>DWT</code> which is applicable to instances of this
218  * class, or must be built by <em>bitwise OR</em>'ing together
219  * (that is, using the <code>int</code> "|" operator) two or more
220  * of those <code>DWT</code> style constants. The class description
221  * lists the style constants that are applicable to the class.
222  * Style bits are also inherited from superclasses.
223  * </p>
224  *
225  * @param style the style of control to construct
226  *
227  * @exception DWTException <ul>
228  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
229  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
230  * </ul>
231  *
232  * @see DWT#BORDER
233  * @see DWT#CLOSE
234  * @see DWT#MIN
235  * @see DWT#MAX
236  * @see DWT#RESIZE
237  * @see DWT#TITLE
238  * @see DWT#NO_TRIM
239  * @see DWT#SHELL_TRIM
240  * @see DWT#DIALOG_TRIM
241  * @see DWT#MODELESS
242  * @see DWT#PRIMARY_MODAL
243  * @see DWT#APPLICATION_MODAL
244  * @see DWT#SYSTEM_MODAL
245  */
246 public this (int style) {
247     this (cast(Display) null, style);
248 }
249
250 /**
251  * Constructs a new instance of this class given only the display
252  * to create it on. It is created with style <code>DWT.SHELL_TRIM</code>.
253  * <p>
254  * Note: Currently, null can be passed in for the display argument.
255  * This has the effect of creating the shell on the currently active
256  * display if there is one. If there is no current display, the
257  * shell is created on a "default" display. <b>Passing in null as
258  * the display argument is not considered to be good coding style,
259  * and may not be supported in a future release of DWT.</b>
260  * </p>
261  *
262  * @param display the display to create the shell on
263  *
264  * @exception DWTException <ul>
265  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
266  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
267  * </ul>
268  */
269 public this (Display display) {
270     this (display, OS.IsWinCE ? DWT.NONE : DWT.SHELL_TRIM);
271 }
272
273 /**
274  * Constructs a new instance of this class given the display
275  * to create it on and a style value describing its behavior
276  * and appearance.
277  * <p>
278  * The style value is either one of the style constants defined in
279  * class <code>DWT</code> which is applicable to instances of this
280  * class, or must be built by <em>bitwise OR</em>'ing together
281  * (that is, using the <code>int</code> "|" operator) two or more
282  * of those <code>DWT</code> style constants. The class description
283  * lists the style constants that are applicable to the class.
284  * Style bits are also inherited from superclasses.
285  * </p><p>
286  * Note: Currently, null can be passed in for the display argument.
287  * This has the effect of creating the shell on the currently active
288  * display if there is one. If there is no current display, the
289  * shell is created on a "default" display. <b>Passing in null as
290  * the display argument is not considered to be good coding style,
291  * and may not be supported in a future release of DWT.</b>
292  * </p>
293  *
294  * @param display the display to create the shell on
295  * @param style the style of control to construct
296  *
297  * @exception DWTException <ul>
298  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
299  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
300  * </ul>
301  *
302  * @see DWT#BORDER
303  * @see DWT#CLOSE
304  * @see DWT#MIN
305  * @see DWT#MAX
306  * @see DWT#RESIZE
307  * @see DWT#TITLE
308  * @see DWT#NO_TRIM
309  * @see DWT#SHELL_TRIM
310  * @see DWT#DIALOG_TRIM
311  * @see DWT#MODELESS
312  * @see DWT#PRIMARY_MODAL
313  * @see DWT#APPLICATION_MODAL
314  * @see DWT#SYSTEM_MODAL
315  */
316 public this (Display display, int style) {
317     this (display, null, style, null, false);
318 }
319
320 this (Display display, Shell parent, int style, HWND handle, bool embedded) {
321     static_this();
322     super ();
323     checkSubclass ();
324     if (display is null) display = Display.getCurrent ();
325     if (display is null) display = Display.getDefault ();
326     if (!display.isValidThread ()) {
327         error (DWT.ERROR_THREAD_INVALID_ACCESS);
328     }
329     if (parent !is null && parent.isDisposed ()) {
330         error (DWT.ERROR_INVALID_ARGUMENT);
331     }
332     this.style = checkStyle (style);
333     this.parent = parent;
334     this.display = display;
335     this.handle = handle;
336     if (handle !is null && !embedded) {
337         state |= FOREIGN_HANDLE;
338     }
339     createWidget ();
340 }
341
342 /**
343  * Constructs a new instance of this class given only its
344  * parent. It is created with style <code>DWT.DIALOG_TRIM</code>.
345  * <p>
346  * Note: Currently, null can be passed in for the parent.
347  * This has the effect of creating the shell on the currently active
348  * display if there is one. If there is no current display, the
349  * shell is created on a "default" display. <b>Passing in null as
350  * the parent is not considered to be good coding style,
351  * and may not be supported in a future release of DWT.</b>
352  * </p>
353  *
354  * @param parent a shell which will be the parent of the new instance
355  *
356  * @exception IllegalArgumentException <ul>
357  *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
358  * </ul>
359  * @exception DWTException <ul>
360  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
361  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
362  * </ul>
363  */
364 public this (Shell parent) {
365     this (parent, OS.IsWinCE ? DWT.NONE : DWT.DIALOG_TRIM);
366 }
367
368 /**
369  * Constructs a new instance of this class given its parent
370  * and a style value describing its behavior and appearance.
371  * <p>
372  * The style value is either one of the style constants defined in
373  * class <code>DWT</code> which is applicable to instances of this
374  * class, or must be built by <em>bitwise OR</em>'ing together
375  * (that is, using the <code>int</code> "|" operator) two or more
376  * of those <code>DWT</code> style constants. The class description
377  * lists the style constants that are applicable to the class.
378  * Style bits are also inherited from superclasses.
379  * </p><p>
380  * Note: Currently, null can be passed in for the parent.
381  * This has the effect of creating the shell on the currently active
382  * display if there is one. If there is no current display, the
383  * shell is created on a "default" display. <b>Passing in null as
384  * the parent is not considered to be good coding style,
385  * and may not be supported in a future release of DWT.</b>
386  * </p>
387  *
388  * @param parent a shell which will be the parent of the new instance
389  * @param style the style of control to construct
390  *
391  * @exception IllegalArgumentException <ul>
392  *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
393  * </ul>
394  * @exception DWTException <ul>
395  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
396  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
397  * </ul>
398  *
399  * @see DWT#BORDER
400  * @see DWT#CLOSE
401  * @see DWT#MIN
402  * @see DWT#MAX
403  * @see DWT#RESIZE
404  * @see DWT#TITLE
405  * @see DWT#NO_TRIM
406  * @see DWT#SHELL_TRIM
407  * @see DWT#DIALOG_TRIM
408  * @see DWT#ON_TOP
409  * @see DWT#TOOL
410  * @see DWT#MODELESS
411  * @see DWT#PRIMARY_MODAL
412  * @see DWT#APPLICATION_MODAL
413  * @see DWT#SYSTEM_MODAL
414  */
415 public this (Shell parent, int style) {
416     this (parent !is null ? parent.display : null, parent, style, null, false);
417 }
418
419 /**
420  * Invokes platform specific functionality to allocate a new shell
421  * that is embedded.
422  * <p>
423  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
424  * API for <code>Shell</code>. It is marked public only so that it
425  * can be shared within the packages provided by DWT. It is not
426  * available on all platforms, and should never be called from
427  * application code.
428  * </p>
429  *
430  * @param display the display for the shell
431  * @param handle the handle for the shell
432  * @return a new shell object containing the specified display and handle
433  */
434 public static Shell win32_new (Display display, HWND handle) {
435     return new Shell (display, null, DWT.NO_TRIM, handle, true);
436 }
437
438 /**
439  * Invokes platform specific functionality to allocate a new shell
440  * that is not embedded.
441  * <p>
442  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
443  * API for <code>Shell</code>. It is marked public only so that it
444  * can be shared within the packages provided by DWT. It is not
445  * available on all platforms, and should never be called from
446  * application code.
447  * </p>
448  *
449  * @param display the display for the shell
450  * @param handle the handle for the shell
451  * @return a new shell object containing the specified display and handle
452  *
453  * @since 3.3
454  */
455 public static Shell internal_new (Display display, HWND handle) {
456     return new Shell (display, null, DWT.NO_TRIM, handle, false);
457 }
458
459 static int checkStyle (int style) {
460     style = Decorations.checkStyle (style);
461     style &= ~DWT.TRANSPARENT;
462     int mask = DWT.SYSTEM_MODAL | DWT.APPLICATION_MODAL | DWT.PRIMARY_MODAL;
463     int bits = style & ~mask;
464     if ((style & DWT.SYSTEM_MODAL) !is 0) return bits | DWT.SYSTEM_MODAL;
465     if ((style & DWT.APPLICATION_MODAL) !is 0) return bits | DWT.APPLICATION_MODAL;
466     if ((style & DWT.PRIMARY_MODAL) !is 0) return bits | DWT.PRIMARY_MODAL;
467     return bits;
468 }
469
470 /**
471  * Adds the listener to the collection of listeners who will
472  * be notified when operations are performed on the receiver,
473  * by sending the listener one of the messages defined in the
474  * <code>ShellListener</code> interface.
475  *
476  * @param listener the listener which should be notified
477  *
478  * @exception IllegalArgumentException <ul>
479  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
480  * </ul>
481  * @exception DWTException <ul>
482  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
483  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
484  * </ul>
485  *
486  * @see ShellListener
487  * @see #removeShellListener
488  */
489 public void addShellListener (ShellListener listener) {
490     checkWidget ();
491     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
492     TypedListener typedListener = new TypedListener (listener);
493     addListener (DWT.Close,typedListener);
494     addListener (DWT.Iconify,typedListener);
495     addListener (DWT.Deiconify,typedListener);
496     addListener (DWT.Activate, typedListener);
497     addListener (DWT.Deactivate, typedListener);
498 }
499
500 HANDLE balloonTipHandle () {
501     if (balloonTipHandle_ is null) createBalloonTipHandle ();
502     return balloonTipHandle_;
503 }
504
505 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
506     if (handle is null) return 0;
507     if (hwnd is toolTipHandle_ || hwnd is balloonTipHandle_) {
508         return OS.CallWindowProc (ToolTipProc, hwnd, msg, wParam, lParam);
509     }
510     if (hwndMDIClient_ !is null) {
511         return OS.DefFrameProc (hwnd, hwndMDIClient_, msg, wParam, lParam);
512     }
513     if (windowProc_ !is null) {
514         return OS.CallWindowProc (windowProc_, hwnd, msg, wParam, lParam);
515     }
516     if ((style & DWT.TOOL) !is 0) {
517         int trim = DWT.TITLE | DWT.CLOSE | DWT.MIN | DWT.MAX | DWT.BORDER | DWT.RESIZE;
518         if ((style & trim) is 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam);
519     }
520     if (parent !is null) {
521         switch (msg) {
522             case OS.WM_KILLFOCUS:
523             case OS.WM_SETFOCUS:
524                 return OS.DefWindowProc (hwnd, msg, wParam, lParam);
525             default:
526         }
527         return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam);
528     }
529     return OS.DefWindowProc (hwnd, msg, wParam, lParam);
530 }
531
532 /**
533  * Requests that the window manager close the receiver in
534  * the same way it would be closed when the user clicks on
535  * the "close box" or performs some other platform specific
536  * key or mouse combination that indicates the window
537  * should be removed.
538  *
539  * @exception DWTException <ul>
540  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
541  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
542  * </ul>
543  *
544  * @see DWT#Close
545  * @see #dispose
546  */
547 public void close () {
548     checkWidget ();
549     closeWidget ();
550 }
551
552 void createBalloonTipHandle () {
553     balloonTipHandle_ = OS.CreateWindowEx (
554         0,
555         OS.TOOLTIPS_CLASS.ptr,
556         null,
557         OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON,
558         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
559         handle,
560         null,
561         OS.GetModuleHandle (null),
562         null);
563     if (balloonTipHandle_ is null) error (DWT.ERROR_NO_HANDLES);
564     if (ToolTipProc is null) {
565         ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC);
566     }
567     /*
568     * Feature in Windows.  Despite the fact that the
569     * tool tip text contains \r\n, the tooltip will
570     * not honour the new line unless TTM_SETMAXTIPWIDTH
571     * is set.  The fix is to set TTM_SETMAXTIPWIDTH to
572     * a large value.
573     */
574     OS.SendMessage (balloonTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
575     display.addControl (balloonTipHandle_, this);
576     OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, display.windowProc);
577 }
578
579 override void createHandle () {
580     bool embedded = handle !is null && (state & FOREIGN_HANDLE) is 0;
581
582     /*
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
588     * handle is created.
589     */
590     /*
591     * The following code is intentionally commented.
592     */
593 //  if ((style & DWT.ON_TOP) !is 0) display.lockActiveWindow = true;
594     if (handle is null || embedded) {
595         super.createHandle ();
596     } else {
597         state |= CANVAS;
598         if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
599             state |= THEME_BACKGROUND;
600         }
601         windowProc_ = cast(WNDPROC) OS.GetWindowLong (handle, OS.GWL_WNDPROC);
602     }
603
604     /*
605     * The following code is intentionally commented.
606     */
607 //  if ((style & DWT.ON_TOP) !is 0)  display.lockActiveWindow = false;
608
609     if (!embedded) {
610         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
611         bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION);
612         static if (!OS.IsWinCE) bits |= OS.WS_POPUP;
613         if ((style & DWT.TITLE) !is 0) bits |= OS.WS_CAPTION;
614         if ((style & DWT.NO_TRIM) is 0) {
615             if ((style & (DWT.BORDER | DWT.RESIZE)) is 0) bits |= OS.WS_BORDER;
616         }
617         /*
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.
623         */
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         SetWindowPos (handle, null, 0, 0, 0, 0, flags);
627         static if (OS.IsWinCE) _setMaximized (true);
628         static if (OS.IsPPC) {
629             psai = new SHACTIVATEINFO ();
630             psai.cbSize = SHACTIVATEINFO.sizeof;
631         }
632     }
633     if (OS.IsDBLocale) {
634         hIMC = OS.ImmCreateContext ();
635         if (hIMC !is null) OS.ImmAssociateContext (handle, hIMC);
636     }
637 }
638
639 void createToolTip (ToolTip toolTip) {
640     int id = 0;
641     if (toolTips is null) toolTips = new ToolTip [4];
642     while (id < toolTips.length && toolTips [id] !is null) id++;
643     if (id is toolTips.length) {
644         ToolTip [] newToolTips = new ToolTip [toolTips.length + 4];
645         System.arraycopy (toolTips, 0, newToolTips, 0, toolTips.length);
646         toolTips = newToolTips;
647     }
648     toolTips [id] = toolTip;
649     toolTip.id = id + Display.ID_START;
650     static if (OS.IsWinCE) return;
651     TOOLINFO lpti;
652     lpti.cbSize = OS.TOOLINFO_sizeof;
653     lpti.hwnd = handle;
654     lpti.uId = toolTip.id;
655     lpti.uFlags = OS.TTF_TRACK;
656     lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
657     OS.SendMessage (toolTip.hwndToolTip (), OS.TTM_ADDTOOL, 0, &lpti);
658 }
659
660 void createToolTipHandle () {
661     toolTipHandle_ = OS.CreateWindowEx (
662         0,
663         OS.TOOLTIPS_CLASS.ptr,
664         null,
665         OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX,
666         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
667         handle,
668         null,
669         OS.GetModuleHandle (null),
670         null);
671     if (toolTipHandle_ is null) error (DWT.ERROR_NO_HANDLES);
672     if (ToolTipProc is null) {
673         ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC);
674     }
675     /*
676     * Feature in Windows.  Despite the fact that the
677     * tool tip text contains \r\n, the tooltip will
678     * not honour the new line unless TTM_SETMAXTIPWIDTH
679     * is set.  The fix is to set TTM_SETMAXTIPWIDTH to
680     * a large value.
681     */
682     OS.SendMessage (toolTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
683     display.addControl (toolTipHandle_, this);
684     OS.SetWindowLongPtr (toolTipHandle_, OS.