root/dwt/widgets/Control.d

Revision 263:27244095ce14, 161.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.Control;
14
15 import dwt.DWT;
16 import dwt.DWTException;
17 import dwt.accessibility.Accessible;
18 import dwt.events.ControlListener;
19 import dwt.events.DragDetectListener;
20 import dwt.events.FocusListener;
21 import dwt.events.HelpListener;
22 import dwt.events.KeyListener;
23 import dwt.events.MenuDetectListener;
24 import dwt.events.MouseEvent;
25 import dwt.events.MouseListener;
26 import dwt.events.MouseMoveListener;
27 import dwt.events.MouseTrackListener;
28 import dwt.events.MouseWheelListener;
29 import dwt.events.PaintListener;
30 import dwt.events.TraverseListener;
31 import dwt.graphics.Color;
32 import dwt.graphics.Cursor;
33 import dwt.graphics.Drawable;
34 import dwt.graphics.Font;
35 import dwt.graphics.GC;
36 import dwt.graphics.GCData;
37 import dwt.graphics.Image;
38 import dwt.graphics.Point;
39 import dwt.graphics.Rectangle;
40 import dwt.graphics.Region;
41 import dwt.internal.win32.OS;
42 import dwt.widgets.Widget;
43 import dwt.widgets.Composite;
44 import dwt.widgets.Dialog;
45 import dwt.widgets.Event;
46 import dwt.widgets.Shell;
47 import dwt.widgets.Menu;
48 import dwt.widgets.MenuItem;
49 import dwt.widgets.Decorations;
50 import dwt.widgets.TypedListener;
51 import dwt.widgets.Listener;
52 import dwt.widgets.Display;
53 import dwt.widgets.Monitor;
54
55 import dwt.dwthelper.utils;
56 import dwt.dwthelper.System;
57
58 import tango.util.log.Trace;
59 static import tango.sys.Common;
60 void trc( int line ){
61     Trace.formatln( "Control {}", line );
62 }
63
64 /**
65  * Control is the abstract superclass of all windowed user interface classes.
66  * <p>
67  * <dl>
68  * <dt><b>Styles:</b>
69  * <dd>BORDER</dd>
70  * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
71  * <dt><b>Events:</b>
72  * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
73  *     MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize, Traverse</dd>
74  * </dl>
75  * </p><p>
76  * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
77  * </p><p>
78  * IMPORTANT: This class is intended to be subclassed <em>only</em>
79  * within the DWT implementation.
80  * </p>
81  *
82  * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a>
83  * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample</a>
84  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
85  */
86
87 public abstract class Control : Widget, Drawable {
88
89     alias Widget.dragDetect dragDetect;
90     alias Widget.callWindowProc callWindowProc;
91
92     /**
93      * the handle to the OS resource
94      * (Warning: This field is platform dependent)
95      * <p>
96      * <b>IMPORTANT:</b> This field is <em>not</em> part of the DWT
97      * public API. It is marked public only so that it can be shared
98      * within the packages provided by DWT. It is not available on all
99      * platforms and should never be accessed from application code.
100      * </p>
101      */
102     public HANDLE handle;
103     Composite parent;
104     Cursor cursor;
105     Menu menu;
106     String toolTipText_;
107     Object layoutData;
108     Accessible accessible;
109     Image backgroundImage;
110     Region region;
111     Font font;
112     int drawCount, foreground, background;
113
114 /**
115  * Prevents uninitialized instances from being created outside the package.
116  */
117 this () {
118 }
119
120 /**
121  * Constructs a new instance of this class given its parent
122  * and a style value describing its behavior and appearance.
123  * <p>
124  * The style value is either one of the style constants defined in
125  * class <code>DWT</code> which is applicable to instances of this
126  * class, or must be built by <em>bitwise OR</em>'ing together
127  * (that is, using the <code>int</code> "|" operator) two or more
128  * of those <code>DWT</code> style constants. The class description
129  * lists the style constants that are applicable to the class.
130  * Style bits are also inherited from superclasses.
131  * </p>
132  *
133  * @param parent a composite control which will be the parent of the new instance (cannot be null)
134  * @param style the style of control to construct
135  *
136  * @exception IllegalArgumentException <ul>
137  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
138  * </ul>
139  * @exception DWTException <ul>
140  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
141  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
142  * </ul>
143  *
144  * @see DWT#BORDER
145  * @see Widget#checkSubclass
146  * @see Widget#getStyle
147  */
148 public this (Composite parent, int style) {
149     super (parent, style);
150     this.parent = parent;
151     createWidget ();
152 }
153
154 /**
155  * Adds the listener to the collection of listeners who will
156  * be notified when the control is moved or resized, by sending
157  * it one of the messages defined in the <code>ControlListener</code>
158  * interface.
159  *
160  * @param listener the listener which should be notified
161  *
162  * @exception IllegalArgumentException <ul>
163  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
164  * </ul>
165  * @exception DWTException <ul>
166  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
167  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
168  * </ul>
169  *
170  * @see ControlListener
171  * @see #removeControlListener
172  */
173 public void addControlListener(ControlListener listener) {
174     checkWidget ();
175     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
176     TypedListener typedListener = new TypedListener (listener);
177     addListener (DWT.Resize,typedListener);
178     addListener (DWT.Move,typedListener);
179 }
180
181 /**
182  * Adds the listener to the collection of listeners who will
183  * be notified when a drag gesture occurs, by sending it
184  * one of the messages defined in the <code>DragDetectListener</code>
185  * interface.
186  *
187  * @param listener the listener which should be notified
188  *
189  * @exception IllegalArgumentException <ul>
190  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
191  * </ul>
192  * @exception DWTException <ul>
193  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
194  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
195  * </ul>
196  *
197  * @see DragDetectListener
198  * @see #removeDragDetectListener
199  *
200  * @since 3.3
201  */
202 public void addDragDetectListener (DragDetectListener listener) {
203     checkWidget ();
204     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
205     TypedListener typedListener = new TypedListener (listener);
206     addListener (DWT.DragDetect,typedListener);
207 }
208
209 /**
210  * Adds the listener to the collection of listeners who will
211  * be notified when the control gains or loses focus, by sending
212  * it one of the messages defined in the <code>FocusListener</code>
213  * interface.
214  *
215  * @param listener the listener which should be notified
216  *
217  * @exception IllegalArgumentException <ul>
218  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
219  * </ul>
220  * @exception DWTException <ul>
221  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
222  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
223  * </ul>
224  *
225  * @see FocusListener
226  * @see #removeFocusListener
227  */
228 public void addFocusListener (FocusListener listener) {
229     checkWidget ();
230     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
231     TypedListener typedListener = new TypedListener (listener);
232     addListener (DWT.FocusIn,typedListener);
233     addListener (DWT.FocusOut,typedListener);
234 }
235
236 /**
237  * Adds the listener to the collection of listeners who will
238  * be notified when help events are generated for the control,
239  * by sending it one of the messages defined in the
240  * <code>HelpListener</code> interface.
241  *
242  * @param listener the listener which should be notified
243  *
244  * @exception IllegalArgumentException <ul>
245  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
246  * </ul>
247  * @exception DWTException <ul>
248  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
249  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
250  * </ul>
251  *
252  * @see HelpListener
253  * @see #removeHelpListener
254  */
255 public void addHelpListener (HelpListener listener) {
256     checkWidget ();
257     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
258     TypedListener typedListener = new TypedListener (listener);
259     addListener (DWT.Help, typedListener);
260 }
261
262 /**
263  * Adds the listener to the collection of listeners who will
264  * be notified when keys are pressed and released on the system keyboard, by sending
265  * it one of the messages defined in the <code>KeyListener</code>
266  * interface.
267  * <p>
268  * When a key listener is added to a control, the control
269  * will take part in widget traversal.  By default, all
270  * traversal keys (such as the tab key and so on) are
271  * delivered to the control.  In order for a control to take
272  * part in traversal, it should listen for traversal events.
273  * Otherwise, the user can traverse into a control but not
274  * out.  Note that native controls such as table and tree
275  * implement key traversal in the operating system.  It is
276  * not necessary to add traversal listeners for these controls,
277  * unless you want to override the default traversal.
278  * </p>
279  * @param listener the listener which should be notified
280  *
281  * @exception IllegalArgumentException <ul>
282  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
283  * </ul>
284  * @exception DWTException <ul>
285  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
286  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
287  * </ul>
288  *
289  * @see KeyListener
290  * @see #removeKeyListener
291  */
292 public void addKeyListener (KeyListener listener) {
293     checkWidget ();
294     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
295     TypedListener typedListener = new TypedListener (listener);
296     addListener (DWT.KeyUp,typedListener);
297     addListener (DWT.KeyDown,typedListener);
298 }
299
300 /**
301  * Adds the listener to the collection of listeners who will
302  * be notified when the platform-specific context menu trigger
303  * has occurred, by sending it one of the messages defined in
304  * the <code>MenuDetectListener</code> interface.
305  *
306  * @param listener the listener which should be notified
307  *
308  * @exception IllegalArgumentException <ul>
309  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
310  * </ul>
311  * @exception DWTException <ul>
312  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
313  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
314  * </ul>
315  *
316  * @see MenuDetectListener
317  * @see #removeMenuDetectListener
318  *
319  * @since 3.3
320  */
321 public void addMenuDetectListener (MenuDetectListener listener) {
322     checkWidget ();
323     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
324     TypedListener typedListener = new TypedListener (listener);
325     addListener (DWT.MenuDetect, typedListener);
326 }
327
328 /**
329  * Adds the listener to the collection of listeners who will
330  * be notified when mouse buttons are pressed and released, by sending
331  * it one of the messages defined in the <code>MouseListener</code>
332  * interface.
333  *
334  * @param listener the listener which should be notified
335  *
336  * @exception IllegalArgumentException <ul>
337  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
338  * </ul>
339  * @exception DWTException <ul>
340  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
341  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
342  * </ul>
343  *
344  * @see MouseListener
345  * @see #removeMouseListener
346  */
347 public void addMouseListener (MouseListener listener) {
348     checkWidget ();
349     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
350     TypedListener typedListener = new TypedListener (listener);
351     addListener (DWT.MouseDown,typedListener);
352     addListener (DWT.MouseUp,typedListener);
353     addListener (DWT.MouseDoubleClick,typedListener);
354 }
355
356 /**
357  * Adds the listener to the collection of listeners who will
358  * be notified when the mouse passes or hovers over controls, by sending
359  * it one of the messages defined in the <code>MouseTrackListener</code>
360  * interface.
361  *
362  * @param listener the listener which should be notified
363  *
364  * @exception IllegalArgumentException <ul>
365  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
366  * </ul>
367  * @exception DWTException <ul>
368  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
369  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
370  * </ul>
371  *
372  * @see MouseTrackListener
373  * @see #removeMouseTrackListener
374  */
375 public void addMouseTrackListener (MouseTrackListener listener) {
376     checkWidget ();
377     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
378     TypedListener typedListener = new TypedListener (listener);
379     addListener (DWT.MouseEnter,typedListener);
380     addListener (DWT.MouseExit,typedListener);
381     addListener (DWT.MouseHover,typedListener);
382 }
383
384 /**
385  * Adds the listener to the collection of listeners who will
386  * be notified when the mouse moves, by sending it one of the
387  * messages defined in the <code>MouseMoveListener</code>
388  * interface.
389  *
390  * @param listener the listener which should be notified
391  *
392  * @exception IllegalArgumentException <ul>
393  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
394  * </ul>
395  * @exception DWTException <ul>
396  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
397  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
398  * </ul>
399  *
400  * @see MouseMoveListener
401  * @see #removeMouseMoveListener
402  */
403 public void addMouseMoveListener (MouseMoveListener listener) {
404     checkWidget ();
405     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
406     TypedListener typedListener = new TypedListener (listener);
407     addListener (DWT.MouseMove,typedListener);
408 }
409
410 /**
411  * Adds the listener to the collection of listeners who will
412  * be notified when the mouse wheel is scrolled, by sending
413  * it one of the messages defined in the
414  * <code>MouseWheelListener</code> interface.
415  *
416  * @param listener the listener which should be notified
417  *
418  * @exception IllegalArgumentException <ul>
419  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
420  * </ul>
421  * @exception DWTException <ul>
422  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
423  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
424  * </ul>
425  *
426  * @see MouseWheelListener
427  * @see #removeMouseWheelListener
428  *
429  * @since 3.3
430  */
431 public void addMouseWheelListener (MouseWheelListener listener) {
432     checkWidget ();
433     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
434     TypedListener typedListener = new TypedListener (listener);
435     addListener (DWT.MouseWheel, typedListener);
436 }
437
438 /**
439  * Adds the listener to the collection of listeners who will
440  * be notified when the receiver needs to be painted, by sending it
441  * one of the messages defined in the <code>PaintListener</code>
442  * interface.
443  *
444  * @param listener the listener which should be notified
445  *
446  * @exception IllegalArgumentException <ul>
447  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
448  * </ul>
449  * @exception DWTException <ul>
450  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
451  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
452  * </ul>
453  *
454  * @see PaintListener
455  * @see #removePaintListener
456  */
457 public void addPaintListener (PaintListener listener) {
458     checkWidget ();
459     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
460     TypedListener typedListener = new TypedListener (listener);
461     addListener (DWT.Paint,typedListener);
462 }
463
464 /**
465  * Adds the listener to the collection of listeners who will
466  * be notified when traversal events occur, by sending it
467  * one of the messages defined in the <code>TraverseListener</code>
468  * interface.
469  *
470  * @param listener the listener which should be notified
471  *
472  * @exception IllegalArgumentException <ul>
473  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
474  * </ul>
475  * @exception DWTException <ul>
476  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
477  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
478  * </ul>
479  *
480  * @see TraverseListener
481  * @see #removeTraverseListener
482  */
483 public void addTraverseListener (TraverseListener listener) {
484     checkWidget ();
485     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
486     TypedListener typedListener = new TypedListener (listener);
487     addListener (DWT.Traverse,typedListener);
488 }
489
490 HANDLE borderHandle () {
491     return handle;
492 }
493
494 void checkBackground () {
495     Shell shell = getShell ();
496     if (this is shell) return;
497     state &= ~PARENT_BACKGROUND;
498     Composite composite = parent;
499     do {
500         auto mode = composite.backgroundMode;
501         if (mode !is 0) {
502             if (mode is DWT.INHERIT_DEFAULT) {
503                 Control control = this;
504                 do {
505                     if ((control.state & THEME_BACKGROUND) is 0) {
506                         return;
507                     }
508                     control = control.parent;
509                 } while (control !is composite);
510             }
511             state |= PARENT_BACKGROUND;
512             return;
513         }
514         if (composite is shell) break;
515         composite = composite.parent;
516     } while (true);
517 }
518
519 void checkBorder () {
520     if (getBorderWidth () is 0) style &= ~DWT.BORDER;
521 }
522
523 void checkBuffered () {
524     style &= ~DWT.DOUBLE_BUFFERED;
525 }
526
527 void checkComposited () {
528     /* Do nothing */
529 }
530
531 bool checkHandle (HWND hwnd) {
532     return hwnd is handle;
533 }
534
535 void checkMirrored () {
536     if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
537         int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
538         if ((bits & OS.WS_EX_LAYOUTRTL) !is 0) style |= DWT.MIRRORED;
539     }
540 }
541
542 /**
543  * Returns the preferred size of the receiver.
544  * <p>
545  * The <em>preferred size</em> of a control is the size that it would
546  * best be displayed at. The width hint and height hint arguments
547  * allow the caller to ask a control questions such as "Given a particular
548  * width, how high does the control need to be to show all of the contents?"
549  * To indicate that the caller does not wish to constrain a particular
550  * dimension, the constant <code>DWT.DEFAULT</code> is passed for the hint.
551  * </p>
552  *
553  * @param wHint the width hint (can be <code>DWT.DEFAULT</code>)
554  * @param hHint the height hint (can be <code>DWT.DEFAULT</code>)
555  * @return the preferred size of the control
556  *
557  * @exception DWTException <ul>
558  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
559  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
560  * </ul>
561  *
562  * @see Layout
563  * @see #getBorderWidth
564  * @see #getBounds
565  * @see #getSize
566  * @see #pack(bool)
567  * @see "computeTrim, getClientArea for controls that implement them"
568  */
569 public Point computeSize (int wHint, int hHint) {
570     return computeSize (wHint, hHint, true);
571 }
572
573 /**
574  * Returns the preferred size of the receiver.
575  * <p>
576  * The <em>preferred size</em> of a control is the size that it would
577  * best be displayed at. The width hint and height hint arguments
578  * allow the caller to ask a control questions such as "Given a particular
579  * width, how high does the control need to be to show all of the contents?"
580  * To indicate that the caller does not wish to constrain a particular
581  * dimension, the constant <code>DWT.DEFAULT</code> is passed for the hint.
582  * </p><p>
583  * If the changed flag is <code>true</code>, it indicates that the receiver's
584  * <em>contents</em> have changed, therefore any caches that a layout manager
585  * containing the control may have been keeping need to be flushed. When the
586  * control is resized, the changed flag will be <code>false</code>, so layout
587  * manager caches can be retained.
588  * </p>
589  *
590  * @param wHint the width hint (can be <code>DWT.DEFAULT</code>)
591  * @param hHint the height hint (can be <code>DWT.DEFAULT</code>)
592  * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
593  * @return the preferred size of the control.
594  *
595  * @exception DWTException <ul>
596  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
597  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
598  * </ul>
599  *
600  * @see Layout
601  * @see #getBorderWidth
602  * @see #getBounds
603  * @see #getSize
604  * @see #pack(bool)
605  * @see "computeTrim, getClientArea for controls that implement them"
606  */
607 public Point computeSize (int wHint, int hHint, bool changed) {
608     checkWidget ();
609     int width = DEFAULT_WIDTH;
610     int height = DEFAULT_HEIGHT;
611     if (wHint !is DWT.DEFAULT) width = wHint;
612     if (hHint !is DWT.DEFAULT) height = hHint;
613     int border = getBorderWidth ();
614     width += border * 2;
615     height += border * 2;
616     return new Point (width, height);
617 }
618
619 Control computeTabGroup () {
620     if (isTabGroup ()) return this;
621     return parent.computeTabGroup ();
622 }
623
624 Control computeTabRoot () {
625     Control [] tabList = parent._getTabList ();
626     if (tabList !is null) {
627         int index = 0;
628         while (index < tabList.length) {
629             if (tabList [index] is this) break;
630             index++;
631         }
632         if (index is tabList.length) {
633             if (isTabGroup ()) return this;
634         }
635     }
636     return parent.computeTabRoot ();
637 }
638
639 Control [] computeTabList () {
640     if (isTabGroup ()) {
641         if (getVisible () && getEnabled ()) {
642             return [this];
643         }
644     }
645     return new Control [0];
646 }
647
648 void createHandle () {
649     auto hwndParent = widgetParent ();
650     handle = OS.CreateWindowEx (
651         widgetExtStyle (),
652         StrToTCHARz( windowClass () ),
653         null,
654         widgetStyle (),
655         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
656         hwndParent,
657         null,
658         OS.GetModuleHandle (null),
659         widgetCreateStruct ());
660     if (handle is null) error (DWT.ERROR_NO_HANDLES);
661     int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
662     if ((bits & OS.WS_CHILD) !is 0) {
663         OS.SetWindowLongPtr (handle, OS.GWLP_ID, cast(LONG_PTR)handle);
664     }
665     if (OS.IsDBLocale && hwndParent !is null) {
666         auto hIMC = OS.ImmGetContext (hwndParent);
667         OS.ImmAssociateContext (handle, hIMC);
668         OS.ImmReleaseContext (hwndParent, hIMC);
669     }
670 }
671
672 void createWidget () {
673     state |= DRAG_DETECT;
674     foreground = background = -1;
675     checkOrientation (parent);
676     createHandle ();
677     checkBackground ();
678     checkBuffered ();
679     checkComposited ();
680     register ();
681     subclass ();
682     setDefaultFont ();
683     checkMirrored ();
684     checkBorder ();
685     if ((state & PARENT_BACKGROUND) !is 0) {
686         setBackground ();
687     }
688 }
689
690 int defaultBackground () {
691     static if (OS.IsWinCE) return OS.GetSysColor (OS.COLOR_WINDOW);
692     return OS.GetSysColor (OS.COLOR_BTNFACE);
693 }
694
695 HFONT defaultFont () {
696     return display.getSystemFont ().handle;
697 }
698
699 int defaultForeground () {
700     return OS.GetSysColor (OS.COLOR_WINDOWTEXT);
701 }
702
703 void deregister () {
704     display.removeControl (handle);
705 }
706
707 override void destroyWidget () {
708     auto hwnd = topHandle ();
709     releaseHandle ();
710     if (hwnd !is null) {
711         OS.DestroyWindow (hwnd);
712     }
713 }
714
715 /**
716  * Detects a drag and drop gesture.  This method is used
717  * to detect a drag gesture when called from within a mouse
718  * down listener.
719  *
720  * <p>By default, a drag is detected when the gesture
721  * occurs anywhere within the client area of a control.
722  * Some controls, such as tables and trees, override this
723  * behavior.  In addition to the operating system specific
724  * drag gesture, they require the mouse to be inside an
725  * item.  Custom widget writers can use <code>setDragDetect</code>
726  * to disable the default detection, listen for mouse down,
727  * and then call <code>dragDetect()</code> from within the
728  * listener to conditionally detect a drag.
729  * </p>
730  *
731  * @param event the mouse down event
732  *
733  * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
734  *
735  * @exception IllegalArgumentException <ul>
736  *   <li>ERROR_NULL_ARGUMENT when the event is null</li>
737  * </ul>
738  * @exception DWTException <ul>
739  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
740  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
741  * </ul>
742  *
743  * @see DragDetectListener
744  * @see #addDragDetectListener