diff dwt/widgets/Composite.d @ 31:92c102dd64a3

Added all widgets modules as dummy. Most modules of accessible are equal to the linux version, except Accessible.
author Frank Benoit <benoit@tionex.de>
date Mon, 28 Jan 2008 04:47:28 +0100
parents
children 39a9959ef14d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/widgets/Composite.d	Mon Jan 28 04:47:28 2008 +0100
@@ -0,0 +1,1609 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module dwt.widgets.Composite;
+
+import dwt.widgets.Scrollable;
+import dwt.widgets.Control;
+
+class Composite : Scrollable {
+public Control [] getChildren () ;
+}
+/++
+import dwt.DWT;
+import dwt.DWTException;
+import dwt.graphics.Font;
+import dwt.graphics.GC;
+import dwt.graphics.GCData;
+import dwt.graphics.Image;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.internal.Callback;
+import dwt.internal.win32.LRESULT;
+import dwt.internal.win32.MSG;
+import dwt.internal.win32.NMHDR;
+import dwt.internal.win32.NMTTDISPINFO;
+import dwt.internal.win32.NMTTDISPINFOA;
+import dwt.internal.win32.NMTTDISPINFOW;
+import dwt.internal.win32.OS;
+import dwt.internal.win32.PAINTSTRUCT;
+import dwt.internal.win32.POINT;
+import dwt.internal.win32.RECT;
+import dwt.internal.win32.WINDOWPOS;
+
+/**
+ * Instances of this class are controls which are capable
+ * of containing other controls.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
+ * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
+ * They can be used with <code>Composite</code> if you are drawing your own, but their
+ * behavior is undefined if they are used with subclasses of <code>Composite</code> other
+ * than <code>Canvas</code>.
+ * </p><p>
+ * Note: The <code>CENTER</code> style, although undefined for composites, has the
+ * same value as <code>EMBEDDED</code> (which is used to embed widgets from other
+ * widget toolkits into DWT).  On some operating systems (GTK, Motif), this may cause
+ * the children of this composite to be obscured.  The <code>EMBEDDED</code> style
+ * is for use by other widget toolkits and should normally never be used.
+ * </p><p>
+ * This class may be subclassed by custom control implementors
+ * who are building controls that are constructed from aggregates
+ * of other controls.
+ * </p>
+ *
+ * @see Canvas
+ */
+
+public class Composite extends Scrollable {
+    Layout layout;
+    int font;
+    WINDOWPOS [] lpwp;
+    Control [] tabList;
+    int layoutCount, backgroundMode;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Composite () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>DWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see DWT#NO_BACKGROUND
+ * @see DWT#NO_FOCUS
+ * @see DWT#NO_MERGE_PAINTS
+ * @see DWT#NO_REDRAW_RESIZE
+ * @see DWT#NO_RADIO_GROUP
+ * @see Widget#getStyle
+ */
+public Composite (Composite parent, int style) {
+    super (parent, style);
+}
+
+Control [] _getChildren () {
+    int count = 0;
+    int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    if (hwndChild is 0) return new Control [0];
+    while (hwndChild !is 0) {
+        count++;
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    Control [] children = new Control [count];
+    int index = 0;
+    hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    while (hwndChild !is 0) {
+        Control control = display.getControl (hwndChild);
+        if (control !is null && control !is this) {
+            children [index++] = control;
+        }
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    if (count is index) return children;
+    Control [] newChildren = new Control [index];
+    System.arraycopy (children, 0, newChildren, 0, index);
+    return newChildren;
+}
+
+Control [] _getTabList () {
+    if (tabList is null) return tabList;
+    int count = 0;
+    for (int i=0; i<tabList.length; i++) {
+        if (!tabList [i].isDisposed ()) count++;
+    }
+    if (count is tabList.length) return tabList;
+    Control [] newList = new Control [count];
+    int index = 0;
+    for (int i=0; i<tabList.length; i++) {
+        if (!tabList [i].isDisposed ()) {
+            newList [index++] = tabList [i];
+        }
+    }
+    tabList = newList;
+    return tabList;
+}
+
+/**
+ * Clears any data that has been cached by a Layout for all widgets that
+ * are in the parent hierarchy of the changed control up to and including the
+ * receiver.  If an ancestor does not have a layout, it is skipped.
+ *
+ * @param changed an array of controls that changed state and require a recalculation of size
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void changed (Control[] changed) {
+    checkWidget ();
+    if (changed is null) error (DWT.ERROR_INVALID_ARGUMENT);
+    for (int i=0; i<changed.length; i++) {
+        Control control = changed [i];
+        if (control is null) error (DWT.ERROR_INVALID_ARGUMENT);
+        if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+        bool ancestor = false;
+        Composite composite = control.parent;
+        while (composite !is null) {
+            ancestor = composite is this;
+            if (ancestor) break;
+            composite = composite.parent;
+        }
+        if (!ancestor) error (DWT.ERROR_INVALID_PARENT);
+    }
+    for (int i=0; i<changed.length; i++) {
+        Control child = changed [i];
+        Composite composite = child.parent;
+        while (child !is this) {
+            if (composite.layout is null || !composite.layout.flushCache (child)) {
+                composite.state |= LAYOUT_CHANGED;
+            }
+            child = composite;
+            composite = child.parent;
+        }
+    }
+}
+
+void checkBuffered () {
+    if (OS.IsWinCE || (state & CANVAS) is 0) {
+        super.checkBuffered ();
+    }
+}
+
+protected void checkSubclass () {
+    /* Do nothing - Subclassing is allowed */
+}
+
+Control [] computeTabList () {
+    Control result [] = super.computeTabList ();
+    if (result.length is 0) return result;
+    Control [] list = tabList !is null ? _getTabList () : _getChildren ();
+    for (int i=0; i<list.length; i++) {
+        Control child = list [i];
+        Control [] childList = child.computeTabList ();
+        if (childList.length !is 0) {
+            Control [] newResult = new Control [result.length + childList.length];
+            System.arraycopy (result, 0, newResult, 0, result.length);
+            System.arraycopy (childList, 0, newResult, result.length, childList.length);
+            result = newResult;
+        }
+    }
+    return result;
+}
+
+public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    Point size;
+    if (layout !is null) {
+        if (wHint is DWT.DEFAULT || hHint is DWT.DEFAULT) {
+            changed |= (state & LAYOUT_CHANGED) !is 0;
+            state &= ~LAYOUT_CHANGED;
+            size = layout.computeSize (this, wHint, hHint, changed);
+        } else {
+            size = new Point (wHint, hHint);
+        }
+    } else {
+        size = minimumSize (wHint, hHint, changed);
+    }
+    if (size.x is 0) size.x = DEFAULT_WIDTH;
+    if (size.y is 0) size.y = DEFAULT_HEIGHT;
+    if (wHint !is DWT.DEFAULT) size.x = wHint;
+    if (hHint !is DWT.DEFAULT) size.y = hHint;
+    Rectangle trim = computeTrim (0, 0, size.x, size.y);
+    return new Point (trim.width, trim.height);
+}
+
+void createHandle () {
+    super.createHandle ();
+    state |= CANVAS;
+    if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
+        state |= THEME_BACKGROUND;
+    }
+}
+
+Composite findDeferredControl () {
+    return layoutCount > 0 ? this : parent.findDeferredControl ();
+}
+
+Menu [] findMenus (Control control) {
+    if (control is this) return new Menu [0];
+    Menu result [] = super.findMenus (control);
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        Menu [] menuList = child.findMenus (control);
+        if (menuList.length !is 0) {
+            Menu [] newResult = new Menu [result.length + menuList.length];
+            System.arraycopy (result, 0, newResult, 0, result.length);
+            System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
+            result = newResult;
+        }
+    }
+    return result;
+}
+
+void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
+    super.fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        children [i].fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+    }
+}
+
+void fixTabList (Control control) {
+    if (tabList is null) return;
+    int count = 0;
+    for (int i=0; i<tabList.length; i++) {
+        if (tabList [i] is control) count++;
+    }
+    if (count is 0) return;
+    Control [] newList = null;
+    int length = tabList.length - count;
+    if (length !is 0) {
+        newList = new Control [length];
+        int index = 0;
+        for (int i=0; i<tabList.length; i++) {
+            if (tabList [i] !is control) {
+                newList [index++] = tabList [i];
+            }
+        }
+    }
+    tabList = newList;
+}
+
+/**
+ * Returns the receiver's background drawing mode. This
+ * will be one of the following constants defined in class
+ * <code>DWT</code>:
+ * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
+ * <code>INHERTIT_FORCE</code>.
+ *
+ * @return the background mode
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see DWT
+ *
+ * @since 3.2
+ */
+public int getBackgroundMode () {
+    checkWidget ();
+    return backgroundMode;
+}
+
+/**
+ * Returns a (possibly empty) array containing the receiver's children.
+ * Children are returned in the order that they are drawn.  The topmost
+ * control appears at the beginning of the array.  Subsequent controls
+ * draw beneath this control and appear later in the array.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of children, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return an array of children
+ *
+ * @see Control#moveAbove
+ * @see Control#moveBelow
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public Control [] getChildren () {
+    checkWidget ();
+    return _getChildren ();
+}
+
+int getChildrenCount () {
+    /*
+    * NOTE: The current implementation will count
+    * non-registered children.
+    */
+    int count = 0;
+    int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    while (hwndChild !is 0) {
+        count++;
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    return count;
+}
+
+/**
+ * Returns layout which is associated with the receiver, or
+ * null if one has not been set.
+ *
+ * @return the receiver's layout or null
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public Layout getLayout () {
+    checkWidget ();
+    return layout;
+}
+
+/**
+ * Gets the (possibly empty) tabbing order for the control.
+ *
+ * @return tabList the ordered list of controls representing the tab order
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #setTabList
+ */
+public Control [] getTabList () {
+    checkWidget ();
+    Control [] tabList = _getTabList ();
+    if (tabList is null) {
+        int count = 0;
+        Control [] list =_getChildren ();
+        for (int i=0; i<list.length; i++) {
+            if (list [i].isTabGroup ()) count++;
+        }
+        tabList = new Control [count];
+        int index = 0;
+        for (int i=0; i<list.length; i++) {
+            if (list [i].isTabGroup ()) {
+                tabList [index++] = list [i];
+            }
+        }
+    }
+    return tabList;
+}
+
+bool hooksKeys () {
+    return hooks (DWT.KeyDown) || hooks (DWT.KeyUp);
+}
+
+/**
+ * Returns <code>true</code> if the receiver has deferred
+ * the performing of layout, and <code>false</code> otherwise.
+ *
+ * @return the receiver's deferred layout state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #setLayoutDeferred(bool)
+ * @see #isLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public bool getLayoutDeferred () {
+    checkWidget ();
+    return layoutCount > 0 ;
+}
+
+/**
+ * Returns <code>true</code> if the receiver or any ancestor
+ * up to and including the receiver's nearest ancestor shell
+ * has deferred the performing of layouts.  Otherwise, <code>false</code>
+ * is returned.
+ *
+ * @return the receiver's deferred layout state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #setLayoutDeferred(bool)
+ * @see #getLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public bool isLayoutDeferred () {
+    checkWidget ();
+    return findDeferredControl () !is null;
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the receiver does not have a layout, do nothing.
+ * <p>
+ * This is equivalent to calling <code>layout(true)</code>.
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void layout () {
+    checkWidget ();
+    layout (true);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the argument is <code>true</code> the layout must not rely
+ * on any information it has cached about the immediate children. If it
+ * is <code>false</code> the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the receiver does not have a layout, do nothing.
+ * <p>
+ * If a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child.  The layout
+ * will cascade down through all child widgets in the receiver's widget
+ * tree until a child is encountered that does not resize.  Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as <code>layout(false)</code>).
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void layout (bool changed) {
+    checkWidget ();
+    if (layout is null) return;
+    layout (changed, false);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the changed argument is <code>true</code> the layout must not rely
+ * on any information it has cached about its children. If it
+ * is <code>false</code> the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the all argument is <code>true</code> the layout will cascade down
+ * through all child widgets in the receiver's widget tree, regardless of
+ * whether the child has changed size.  The changed argument is applied to
+ * all layouts.  If the all argument is <code>false</code>, the layout will
+ * <em>not</em> cascade down through all child widgets in the receiver's widget
+ * tree.  However, if a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child.  Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as <code>layout(false)</code>).
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
+ * @param all <code>true</code> if all children in the receiver's widget tree should be laid out, and <code>false</code> otherwise
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void layout (bool changed, bool all) {
+    checkWidget ();
+    if (layout is null && !all) return;
+    markLayout (changed, all);
+    updateLayout (true, all);
+}
+
+/**
+ * Forces a lay out (that is, sets the size and location) of all widgets that
+ * are in the parent hierarchy of the changed control up to and including the
+ * receiver.  The layouts in the hierarchy must not rely on any information
+ * cached about the changed control or any of its ancestors.  The layout may
+ * (potentially) optimize the work it is doing by assuming that none of the
+ * peers of the changed control have changed state since the last layout.
+ * If an ancestor does not have a layout, skip it.
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed a control that has had a state change which requires a recalculation of its size
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void layout (Control [] changed) {
+    checkWidget ();
+    if (changed is null) error (DWT.ERROR_INVALID_ARGUMENT);
+    for (int i=0; i<changed.length; i++) {
+        Control control = changed [i];
+        if (control is null) error (DWT.ERROR_INVALID_ARGUMENT);
+        if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+        bool ancestor = false;
+        Composite composite = control.parent;
+        while (composite !is null) {
+            ancestor = composite is this;
+            if (ancestor) break;
+            composite = composite.parent;
+        }
+        if (!ancestor) error (DWT.ERROR_INVALID_PARENT);
+    }
+    int updateCount = 0;
+    Composite [] update = new Composite [16];
+    for (int i=0; i<changed.length; i++) {
+        Control child = changed [i];
+        Composite composite = child.parent;
+        while (child !is this) {
+            if (composite.layout !is null) {
+                composite.state |= LAYOUT_NEEDED;
+                if (!composite.layout.flushCache (child)) {
+                    composite.state |= LAYOUT_CHANGED;
+                }
+            }
+            if (updateCount is update.length) {
+                Composite [] newUpdate = new Composite [update.length + 16];
+                System.arraycopy (update, 0, newUpdate, 0, update.length);
+                update = newUpdate;
+            }
+            child = update [updateCount++] = composite;
+            composite = child.parent;
+        }
+    }
+    for (int i=updateCount-1; i>=0; i--) {
+        update [i].updateLayout (true, false);
+    }
+}
+
+void markLayout (bool changed, bool all) {
+    if (layout !is null) {
+        state |= LAYOUT_NEEDED;
+        if (changed) state |= LAYOUT_CHANGED;
+    }
+    if (all) {
+        Control [] children = _getChildren ();
+        for (int i=0; i<children.length; i++) {
+            children [i].markLayout (changed, all);
+        }
+    }
+}
+
+Point minimumSize (int wHint, int hHint, bool changed) {
+    Control [] children = _getChildren ();
+    int width = 0, height = 0;
+    for (int i=0; i<children.length; i++) {
+        Rectangle rect = children [i].getBounds ();
+        width = Math.max (width, rect.x + rect.width);
+        height = Math.max (height, rect.y + rect.height);
+    }
+    return new Point (width, height);
+}
+
+bool redrawChildren () {
+    if (!super.redrawChildren ()) return false;
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        children [i].redrawChildren ();
+    }
+    return true;
+}
+
+void releaseChildren (bool destroy) {
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child !is null && !child.isDisposed ()) {
+            child.release (false);
+        }
+    }
+    super.releaseChildren (destroy);
+}
+
+void releaseWidget () {
+    super.releaseWidget ();
+    if ((state & CANVAS) !is 0 && (style & DWT.EMBEDDED) !is 0) {
+        int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+        if (hwndChild !is 0) {
+            int threadId = OS.GetWindowThreadProcessId (hwndChild, null);
+            if (threadId !is OS.GetCurrentThreadId ()) {
+                OS.ShowWindow (hwndChild, OS.SW_HIDE);
+                OS.SetParent (hwndChild, 0);
+            }
+        }
+    }
+    layout = null;
+    tabList = null;
+    lpwp = null;
+}
+
+void removeControl (Control control) {
+    fixTabList (control);
+    resizeChildren ();
+}
+
+void resizeChildren () {
+    if (lpwp is null) return;
+    do {
+        WINDOWPOS [] currentLpwp = lpwp;
+        lpwp = null;
+        if (!resizeChildren (true, currentLpwp)) {
+            resizeChildren (false, currentLpwp);
+        }
+    } while (lpwp !is null);
+}
+
+bool resizeChildren (bool defer, WINDOWPOS [] pwp) {
+    if (pwp is null) return true;
+    int hdwp = 0;
+    if (defer) {
+        hdwp = OS.BeginDeferWindowPos (pwp.length);
+        if (hdwp is 0) return false;
+    }
+    for (int i=0; i<pwp.length; i++) {
+        WINDOWPOS wp = pwp [i];
+        if (wp !is null) {
+            /*
+            * This code is intentionally commented.  All widgets that
+            * are created by DWT have WS_CLIPSIBLINGS to ensure that
+            * application code does not draw outside of the control.
+            */
+//          int count = parent.getChildrenCount ();
+//          if (count > 1) {
+//              int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//              if ((bits & OS.WS_CLIPSIBLINGS) is 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//          }
+            if (defer) {
+                hdwp = DeferWindowPos (hdwp, wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+                if (hdwp is 0) return false;
+            } else {
+                SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+            }
+        }
+    }
+    if (defer) return OS.EndDeferWindowPos (hdwp);
+    return true;
+}
+
+void resizeEmbeddedHandle(int embeddedHandle, int width, int height) {
+    if (embeddedHandle is 0) return;
+    int [] processID = new int [1];
+    int threadId = OS.GetWindowThreadProcessId (embeddedHandle, processID);
+    if (threadId !is OS.GetCurrentThreadId ()) {
+        if (processID [0] is OS.GetCurrentProcessId ()) {
+            if (display.msgHook is 0) {
+                if (!OS.IsWinCE) {
+                    display.getMsgCallback = new Callback (display, "getMsgProc", 3);
+                    display.getMsgProc = display.getMsgCallback.getAddress ();
+                    if (display.getMsgProc is 0) error (DWT.ERROR_NO_MORE_CALLBACKS);
+                    display.msgHook = OS.SetWindowsHookEx (OS.WH_GETMESSAGE, display.getMsgProc, OS.GetLibraryHandle(), threadId);
+                    OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
+                }
+            }
+        }
+        int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE | OS.SWP_ASYNCWINDOWPOS;
+        OS.SetWindowPos (embeddedHandle, 0, 0, 0, width, height, flags);
+    }
+}
+
+void sendResize () {
+    setResizeChildren (false);
+    sendEvent (DWT.Resize);
+    if (isDisposed ()) return;
+    if (layout !is null) {
+        markLayout (false, false);
+        updateLayout (false, false);
+    }
+    setResizeChildren (true);
+}
+
+/**
+ * Sets the background drawing mode to the argument which should
+ * be one of the following constants defined in class <code>DWT</code>:
+ * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
+ * <code>INHERIT_FORCE</code>.
+ *
+ * @param mode the new background mode
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see DWT
+ *
+ * @since 3.2
+ */
+public void setBackgroundMode (int mode) {
+    checkWidget ();
+    backgroundMode = mode;
+    Control [] children = _getChildren ();
+    for (int i = 0; i < children.length; i++) {
+        children [i].updateBackgroundMode ();
+    }
+}
+
+bool setFixedFocus () {
+    checkWidget ();
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setRadioFocus ()) return true;
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setFixedFocus ()) return true;
+    }
+    return super.setFixedFocus ();
+}
+
+public bool setFocus () {
+    checkWidget ();
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setRadioFocus ()) return true;
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setFocus ()) return true;
+    }
+    return super.setFocus ();
+}
+
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void setLayout (Layout layout) {
+    checkWidget ();
+    this.layout = layout;
+}
+
+/**
+ * If the argument is <code>true</code>, causes subsequent layout
+ * operations in the receiver or any of its children to be ignored.
+ * No layout of any kind can occur in the receiver or any of its
+ * children until the flag is set to false.
+ * Layout operations that occurred while the flag was
+ * <code>true</code> are remembered and when the flag is set to
+ * <code>false</code>, the layout operations are performed in an
+ * optimized manner.  Nested calls to this method are stacked.
+ *
+ * @param defer the new defer state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #layout(bool)
+ * @see #layout(Control[])
+ *
+ * @since 3.1
+ */
+public void setLayoutDeferred (bool defer) {
+    if (!defer) {
+        if (--layoutCount is 0) {
+            if ((state & LAYOUT_CHILD) !is 0 || (state & LAYOUT_NEEDED) !is 0) {
+                updateLayout (true, true);
+            }
+        }
+    } else {
+        layoutCount++;
+    }
+}
+/**
+ * Sets the tabbing order for the specified controls to
+ * match the order that they occur in the argument list.
+ *
+ * @param tabList the ordered list of controls representing the tab order or null
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void setTabList (Control [] tabList) {
+    checkWidget ();
+    if (tabList !is null) {
+        for (int i=0; i<tabList.length; i++) {
+            Control control = tabList [i];
+            if (control is null) error (DWT.ERROR_INVALID_ARGUMENT);
+            if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+            if (control.parent !is this) error (DWT.ERROR_INVALID_PARENT);
+        }
+        Control [] newList = new Control [tabList.length];
+        System.arraycopy (tabList, 0, newList, 0, tabList.length);
+        tabList = newList;
+    }
+    this.tabList = tabList;
+}
+
+void setResizeChildren (bool resize) {
+    if (resize) {
+        resizeChildren ();
+    } else {
+        int count = getChildrenCount ();
+        if (count > 1 && lpwp is null) {
+            lpwp = new WINDOWPOS [count];
+        }
+    }
+}
+
+bool setTabGroupFocus () {
+    if (isTabItem ()) return setTabItemFocus ();
+    bool takeFocus = (style & DWT.NO_FOCUS) is 0;
+    if ((state & CANVAS) !is 0) {
+        takeFocus = hooksKeys ();
+        if ((style & DWT.EMBEDDED) !is 0) takeFocus = true;
+    }
+    if (takeFocus && setTabItemFocus ()) return true;
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.isTabItem () && child.setRadioFocus ()) return true;
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.isTabItem () && child.setTabItemFocus ()) return true;
+    }
+    return false;
+}
+
+String toolTipText (NMTTDISPINFO hdr) {
+    Shell shell = getShell ();
+    if ((hdr.uFlags & OS.TTF_IDISHWND) is 0) {
+        String string = null;
+        ToolTip toolTip = shell.findToolTip (hdr.idFrom);
+        if (toolTip !is null) {
+            string = toolTip.message;
+            if (string is null || string.length () is 0) string = " ";
+        }
+        return string;
+    }
+    shell.setToolTipTitle (hdr.hwndFrom, null, 0);
+    OS.SendMessage (hdr.hwndFrom, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+    Control control = display.getControl (hdr.idFrom);
+    return control !is null ? control.toolTipText : null;
+}
+
+bool translateMnemonic (Event event, Control control) {
+    if (super.translateMnemonic (event, control)) return true;
+    if (control !is null) {
+        Control [] children = _getChildren ();
+        for (int i=0; i<children.length; i++) {
+            Control child = children [i];
+            if (child.translateMnemonic (event, control)) return true;
+        }
+    }
+    return false;
+}
+
+bool translateTraversal (MSG msg) {
+    if ((state & CANVAS) !is 0 ) {
+        if ((style & DWT.EMBEDDED) !is 0) return false;
+        switch (msg.wParam) {
+            case OS.VK_UP:
+            case OS.VK_LEFT:
+            case OS.VK_DOWN:
+            case OS.VK_RIGHT:
+            case OS.VK_PRIOR:
+            case OS.VK_NEXT:
+                OS.SendMessage (msg.hwnd, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+                break;
+        }
+    }
+    return super.translateTraversal (msg);
+}
+
+void updateBackgroundColor () {
+    super.updateBackgroundColor ();
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        if ((children [i].state & PARENT_BACKGROUND) !is 0) {
+            children [i].updateBackgroundColor ();
+        }
+    }
+}
+
+void updateBackgroundImage () {
+    super.updateBackgroundImage ();
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        if ((children [i].state & PARENT_BACKGROUND) !is 0) {
+            children [i].updateBackgroundImage ();
+        }
+    }
+}
+
+void updateBackgroundMode () {
+    super.updateBackgroundMode ();
+    Control [] children = _getChildren ();
+    for (int i = 0; i < children.length; i++) {
+        children [i].updateBackgroundMode ();
+    }
+}
+
+void updateFont (Font oldFont, Font newFont) {
+    super.updateFont (oldFont, newFont);
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control control = children [i];
+        if (!control.isDisposed ()) {
+            control.updateFont (oldFont, newFont);
+        }
+    }
+}
+
+void updateLayout (bool resize, bool all) {
+    Composite parent = findDeferredControl ();
+    if (parent !is null) {
+        parent.state |= LAYOUT_CHILD;
+        return;
+    }
+    if ((state & LAYOUT_NEEDED) !is 0) {
+        bool changed = (state & LAYOUT_CHANGED) !is 0;
+        state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
+        if (resize) setResizeChildren (false);
+        layout.layout (this, changed);
+        if (resize) setResizeChildren (true);
+    }
+    if (all) {
+        state &= ~LAYOUT_CHILD;
+        Control [] children = _getChildren ();
+        for (int i=0; i<children.length; i++) {
+            children [i].updateLayout (resize, all);
+        }
+    }
+}
+
+int widgetStyle () {
+    /* Force clipping of children by setting WS_CLIPCHILDREN */
+    return super.widgetStyle () | OS.WS_CLIPCHILDREN;
+}
+
+LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) {
+        /* Return zero to indicate that the background was not erased */
+        if ((style & DWT.NO_BACKGROUND) !is 0) return LRESULT.ZERO;
+    }
+    return result;
+}
+
+LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) {
+        int flags = 0;
+        if (hooksKeys ()) {
+            flags |= OS.DLGC_WANTALLKEYS | OS.DLGC_WANTARROWS | OS.DLGC_WANTTAB;
+        }
+        if ((style & DWT.NO_FOCUS) !is 0) flags |= OS.DLGC_STATIC;
+        if (OS.GetWindow (handle, OS.GW_CHILD) !is 0) flags |= OS.DLGC_STATIC;
+        if (flags !is 0) return new LRESULT (flags);
+    }
+    return result;
+}
+
+LRESULT WM_GETFONT (int wParam, int lParam) {
+    LRESULT result = super.WM_GETFONT (wParam, lParam);
+    if (result !is null) return result;
+    int code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
+    if (code !is 0) return new LRESULT (code);
+    if (font is 0) font = defaultFont ();
+    return new LRESULT (font);
+}
+
+LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+
+    /* Set focus for a canvas with no children */
+    if ((state & CANVAS) !is 0) {
+        if ((style & DWT.NO_FOCUS) is 0 && hooksKeys ()) {
+            if (OS.GetWindow (handle, OS.GW_CHILD) is 0) setFocus ();
+        }
+    }
+    return result;
+}
+
+LRESULT WM_NCPAINT (int wParam, int lParam) {
+    LRESULT result = super.WM_NCPAINT (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) {
+        result = wmNCPaint (handle, wParam, lParam);
+    }
+    return result;
+}
+
+LRESULT WM_PARENTNOTIFY (int wParam, int lParam) {
+    if ((state & CANVAS) !is 0 && (style & DWT.EMBEDDED) !is 0) {
+        if ((wParam & 0xFFFF) is OS.WM_CREATE) {
+            RECT rect = new RECT ();
+            OS.GetClientRect (handle, rect);
+            resizeEmbeddedHandle (lParam, rect.right - rect.left, rect.bottom - rect.top);
+        }
+    }
+    return super.WM_PARENTNOTIFY (wParam, lParam);
+}
+
+LRESULT WM_PAINT (int wParam, int lParam) {
+    if ((state & CANVAS) is 0 || (state & FOREIGN_HANDLE) !is 0) {
+        return super.WM_PAINT (wParam, lParam);
+    }
+
+    /* Set the clipping bits */
+    int oldBits = 0, newBits = 0;
+    if (!OS.IsWinCE) {
+        oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        newBits = oldBits | OS.WS_CLIPSIBLINGS | OS.WS_CLIPCHILDREN;
+        if (newBits !is oldBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+    }
+
+    /* Paint the control and the background */
+    PAINTSTRUCT ps = new PAINTSTRUCT ();
+    if (hooks (DWT.Paint)) {
+
+        /* Use the buffered paint when possible */
+        bool bufferedPaint = false;
+        if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                if ((style & (DWT.NO_MERGE_PAINTS | DWT.RIGHT_TO_LEFT)) is 0) {
+                    bufferedPaint = true;
+                }
+            }
+        }
+        if (bufferedPaint) {
+            int hDC = OS.BeginPaint (handle, ps);
+            int width = ps.right - ps.left;
+            int height = ps.bottom - ps.top;
+            if (width !is 0 && height !is 0) {
+                int [] phdc = new int [1];
+                int flags = OS.BPBF_COMPATIBLEBITMAP;
+                RECT prcTarget = new RECT ();
+                OS.SetRect (prcTarget, ps.left, ps.top, ps.right, ps.bottom);
+                int hBufferedPaint = OS.BeginBufferedPaint (hDC, prcTarget, flags, null, phdc);
+                GCData data = new GCData ();
+                if ((OS.GetLayout (hDC) & OS.LAYOUT_RTL) !is 0) {
+                    data.style = DWT.RIGHT_TO_LEFT | DWT.MIRRORED;
+                } else {
+                    data.style = DWT.LEFT_TO_RIGHT;
+                }
+                data.device = display;
+                data.foreground = getForegroundPixel ();
+                Control control = findBackgroundControl ();
+                if (control is null) control = this;
+                data.background = control.getBackgroundPixel ();
+                data.hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                if ((style & DWT.NO_BACKGROUND) !is 0) {
+                    /* This code is intentionally commented because it may be slow to copy bits from the screen */
+                    //paintGC.copyArea (image, ps.left, ps.top);
+                } else {
+                    RECT rect = new RECT ();
+                    OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                    drawBackground (phdc [0], rect);
+                }
+                GC gc = GC.win32_new (phdc [0], data);
+                Event event = new Event ();
+                event.gc = gc;
+                event.x = ps.left;
+                event.y = ps.top;
+                event.width = width;
+                event.height = height;
+                sendEvent (DWT.Paint, event);
+                gc.dispose ();
+                OS.EndBufferedPaint (hBufferedPaint, true);
+            }
+            OS.EndPaint (handle, ps);
+        } else {
+
+            /* Create the paint GC */
+            GCData data = new GCData ();
+            data.ps = ps;
+            data.hwnd = handle;
+            GC gc = GC.win32_new (this, data);
+
+            /* Get the system region for the paint HDC */
+            int sysRgn = 0;
+            if ((style & (DWT.NO_MERGE_PAINTS | DWT.DOUBLE_BUFFERED)) !is 0) {
+                sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
+                if (OS.GetRandomRgn (gc.handle, sysRgn, OS.SYSRGN) is 1) {
+                    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+                        if ((OS.GetLayout (gc.handle) & OS.LAYOUT_RTL) !is 0) {
+                            int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                            int [] lpRgnData = new int [nBytes / 4];
+                            OS.GetRegionData (sysRgn, nBytes, lpRgnData);
+                            int newSysRgn = OS.ExtCreateRegion (new float [] {-1, 0, 0, 1, 0, 0}, nBytes, lpRgnData);
+                            OS.DeleteObject (sysRgn);
+                            sysRgn = newSysRgn;
+                        }
+                    }
+                    if (OS.IsWinNT) {
+                        POINT pt = new POINT();
+                        OS.MapWindowPoints (0, handle, pt, 1);
+                        OS.OffsetRgn (sysRgn, pt.x, pt.y);
+                    }
+                }
+            }
+
+            /* Send the paint event */
+            int width = ps.right - ps.left;
+            int height = ps.bottom - ps.top;
+            if (width !is 0 && height !is 0) {
+                GC paintGC = null;
+                Image image = null;
+                if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+                    image = new Image (display, width, height);
+                    paintGC = gc;
+                    gc = new GC (image, paintGC.getStyle() & DWT.RIGHT_TO_LEFT);
+                    GCData gcData = gc.getGCData ();
+                    gcData.uiState = data.uiState;
+                    gc.setForeground (getForeground ());
+                    gc.setBackground (getBackground ());
+                    gc.setFont (getFont ());
+                    OS.OffsetRgn (sysRgn, -ps.left, -ps.top);
+                    OS.SelectClipRgn (gc.handle, sysRgn);
+                    OS.OffsetRgn (sysRgn, ps.left, ps.top);
+                    OS.SetMetaRgn (gc.handle);
+                    OS.SetWindowOrgEx (gc.handle, ps.left, ps.top, null);
+                    OS.SetBrushOrgEx (gc.handle, ps.left, ps.top, null);
+                    if ((style & DWT.NO_BACKGROUND) !is 0) {
+                        /* This code is intentionally commented because it may be slow to copy bits from the screen */
+                        //paintGC.copyArea (image, ps.left, ps.top);
+                    } else {
+                        RECT rect = new RECT ();
+                        OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                        drawBackground (gc.handle, rect);
+                    }
+                }
+                Event event = new Event ();
+                event.gc = gc;
+                RECT rect = null;
+                if ((style & DWT.NO_MERGE_PAINTS) !is 0 && OS.GetRgnBox (sysRgn, rect = new RECT ()) is OS.COMPLEXREGION) {
+                    int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                    int [] lpRgnData = new int [nBytes / 4];
+                    OS.GetRegionData (sysRgn, nBytes, lpRgnData);
+                    int count = lpRgnData [2];
+                    for (int i=0; i<count; i++) {
+                        int offset = 8 + (i << 2);
+                        OS.SetRect (rect, lpRgnData [offset], lpRgnData [offset + 1], lpRgnData [offset + 2], lpRgnData [offset + 3]);
+                        if ((style & (DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND)) is 0) {
+                            drawBackground (gc.handle, rect);
+                        }
+                        event.x = rect.left;
+                        event.y = rect.top;
+                        event.width = rect.right - rect.left;
+                        event.height = rect.bottom - rect.top;
+                        event.count = count - 1 - i;
+                        sendEvent (DWT.Paint, event);
+                    }
+                } else {
+                    if ((style & (DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND)) is 0) {
+                        if (rect is null) rect = new RECT ();
+                        OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                        drawBackground (gc.handle, rect);
+                    }
+                    event.x = ps.left;
+                    event.y = ps.top;
+                    event.width = width;
+                    event.height = height;
+                    sendEvent (DWT.Paint, event);
+                }
+                // widget could be disposed at this point
+                event.gc = null;
+                if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+                    gc.dispose();
+                    if (!isDisposed ()) paintGC.drawImage (image, ps.left, ps.top);
+                    image.dispose ();
+                    gc = paintGC;
+                }
+            }
+            if (sysRgn !is 0) OS.DeleteObject (sysRgn);
+
+            /* Dispose the paint GC */
+            gc.dispose ();
+        }
+    } else {
+        int hDC = OS.BeginPaint (handle, ps);
+        if ((style & DWT.NO_BACKGROUND) is 0) {
+            RECT rect = new RECT ();
+            OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+            drawBackground (hDC, rect);
+        }
+        OS.EndPaint (handle, ps);
+    }
+
+    /* Restore the clipping bits */
+    if (!OS.IsWinCE && !isDisposed ()) {
+        if (newBits !is oldBits) {
+            /*
+            * It is possible (but unlikely), that application
+            * code could have disposed the widget in the paint
+            * event.  If this happens, don't attempt to restore
+            * the style.
+            */
+            if (!isDisposed ()) {
+                OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
+            }
+        }
+    }
+    return LRESULT.ZERO;
+}
+
+LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+    LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) {
+        forceResize ();
+        int nSavedDC = OS.SaveDC (wParam);
+        RECT rect = new RECT ();
+        OS.GetClientRect (handle, rect);
+        if ((style & DWT.NO_BACKGROUND) is 0) {
+            drawBackground (wParam, rect);
+        }
+        if (hooks (DWT.Paint) || filters (DWT.Paint)) {
+            GCData data = new GCData ();
+            data.device = display;
+            data.foreground = getForegroundPixel ();
+            Control control = findBackgroundControl ();
+            if (control is null) control = this;
+            data.background = control.getBackgroundPixel ();
+            data.hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+            data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+            GC gc = GC.win32_new (wParam, data);
+            Event event = new Event ();
+            event.gc = gc;
+            event.x = rect.left;
+            event.y = rect.top;
+            event.width = rect.right - rect.left;
+            event.height = rect.bottom - rect.top;
+            sendEvent (DWT.Paint, event);
+            event.gc = null;
+            gc.dispose ();
+        }
+        OS.RestoreDC (wParam, nSavedDC);
+    }
+    return result;
+}
+
+LRESULT WM_SETFONT (int wParam, int lParam) {
+    if (lParam !is 0) OS.InvalidateRect (handle, null, true);
+    return super.WM_SETFONT (font = wParam, lParam);
+}
+
+LRESULT WM_SIZE (int wParam, int lParam) {
+
+    /* Begin deferred window positioning */
+    setResizeChildren (false);
+
+    /* Resize and Layout */
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in the resize
+    * event.  If this happens, end the processing of the
+    * Windows message by returning the result of the
+    * WM_SIZE message.
+    */
+    if (isDisposed ()) return result;
+    if (layout !is null) {
+        markLayout (false, false);
+        updateLayout (false, false);
+    }
+
+    /* End deferred window positioning */
+    setResizeChildren (true);
+
+    /* Damage the widget to cause a repaint */
+    if (OS.IsWindowVisible (handle)) {
+        if ((state & CANVAS) !is 0) {
+            if ((style & DWT.NO_REDRAW_RESIZE) is 0) {
+                if (hooks (DWT.Paint)) {
+                    OS.InvalidateRect (handle, null, true);
+                }
+            }
+        }
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            if (findThemeControl () !is null) redrawChildren ();
+        }
+    }
+
+    /* Resize the embedded window */
+    if ((state & CANVAS) !is 0 && (style & DWT.EMBEDDED) !is 0) {
+        resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), lParam & 0xFFFF, lParam >> 16);
+    }
+    return result;
+}
+
+LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+    if (result !is null) return result;
+    int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    while (hwndChild !is 0) {
+        OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0);
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    return result;
+}
+
+LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * Check to see if the command is a system command or
+    * a user menu item that was added to the system menu.
+    */
+    if ((wParam & 0xF000) is 0) return result;
+
+    /*
+    * Bug in Windows.  When a vertical or horizontal scroll bar is
+    * hidden or shown while the opposite scroll bar is being scrolled
+    * by the user (with WM_HSCROLL code SB_LINEDOWN), the scroll bar
+    * does not redraw properly.  The fix is to detect this case and
+    * redraw the non-client area.
+    */
+    if (!OS.IsWinCE) {
+        int cmd = wParam & 0xFFF0;
+        switch (cmd) {
+            case OS.SC_HSCROLL:
+            case OS.SC_VSCROLL:
+                bool showHBar = horizontalBar !is null && horizontalBar.getVisible ();
+                bool showVBar = verticalBar !is null && verticalBar.getVisible ();
+                int code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam);
+                if ((showHBar !is (horizontalBar !is null && horizontalBar.getVisible ())) ||
+                    (showVBar !is (verticalBar !is null && verticalBar.getVisible ()))) {
+                        int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW;
+                        OS.RedrawWindow (handle, null, 0, flags);
+                    }
+                if (code is 0) return LRESULT.ZERO;
+                return new LRESULT (code);
+        }
+    }
+    /* Return the result */
+    return result;
+}
+
+LRESULT WM_UPDATEUISTATE (int wParam, int lParam) {
+    LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) OS.InvalidateRect (handle, null, false);
+    return result;
+}
+
+LRESULT wmNCPaint (int hwnd, int wParam, int lParam) {
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+        if ((bits1 & OS.WS_EX_CLIENTEDGE) !is 0) {
+            int code = 0;
+            int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+            if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) {
+                code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam);
+            }
+            int hDC = OS.GetWindowDC (hwnd);
+            RECT rect = new RECT ();
+            OS.GetWindowRect (hwnd, rect);
+            rect.right -= rect.left;
+            rect.bottom -= rect.top;
+            rect.left = rect.top = 0;
+            int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
+            OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border);
+            OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null);
+            OS.ReleaseDC (hwnd, hDC);
+            return new LRESULT (code);
+        }
+    }
+    return null;
+}
+
+LRESULT wmNotify (NMHDR hdr, int wParam, int lParam) {
+    if (!OS.IsWinCE) {
+        switch (hdr.code) {
+            /*
+            * Feature in Windows.  When the tool tip control is
+            * created, the parent of the tool tip is the shell.
+            * If SetParent () is used to reparent the tool bar
+            * into a new shell, the tool tip is not reparented
+            * and pops up underneath the new shell.  The fix is
+            * to make sure the tool tip is a topmost window.
+            */
+            case OS.TTN_SHOW:
+            case OS.TTN_POP: {
+                /*
+                * Bug in Windows 98 and NT.  Setting the tool tip to be the
+                * top most window using HWND_TOPMOST can result in a parent
+                * dialog shell being moved behind its parent if the dialog
+                * has a sibling that is currently on top.  The fix is to
+                * lock the z-order of the active window.
+                *
+                * Feature in Windows.  Using SetWindowPos() with HWND_NOTOPMOST
+                * to clear the topmost state of a window whose parent is already
+                * topmost clears the topmost state of the parent.  The fix is to
+                * check if the parent is already on top and neither set or clear
+                * the topmost status of the tool tip.
+                */
+                int hwndParent = hdr.hwndFrom;
+                do {
+                    hwndParent = OS.GetParent (hwndParent);
+                    if (hwndParent is 0) break;
+                    int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                    if ((bits & OS.WS_EX_TOPMOST) !is 0) break;
+                } while (true);
+                if (hwndParent !is 0) break;
+                display.lockActiveWindow = true;
+                int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOSIZE;
+                int hwndInsertAfter = hdr.code is OS.TTN_SHOW ? OS.HWND_TOPMOST : OS.HWND_NOTOPMOST;
+                SetWindowPos (hdr.hwndFrom, hwndInsertAfter, 0, 0, 0, 0, flags);
+                display.lockActiveWindow = false;
+                break;
+            }
+            /*
+            * Bug in Windows 98.  For some reason, the tool bar control
+            * sends both TTN_GETDISPINFOW and TTN_GETDISPINFOA to get
+            * the tool tip text and the tab folder control sends only
+            * TTN_GETDISPINFOW.  The fix is to handle only TTN_GETDISPINFOW,
+            * even though it should never be sent on Windows 98.
+            *
+            * NOTE:  Because the size of NMTTDISPINFO differs between
+            * Windows 98 and NT, guard against the case where the wrong
+            * kind of message occurs by inlining the memory moves and
+            * the UNICODE conversion code.
+            */
+            case OS.TTN_GETDISPINFOA:
+            case OS.TTN_GETDISPINFOW: {
+                NMTTDISPINFO lpnmtdi;
+                if (hdr.code is OS.TTN_GETDISPINFOA) {
+                    lpnmtdi = new NMTTDISPINFOA ();
+                    OS.MoveMemory ((NMTTDISPINFOA)lpnmtdi, lParam, NMTTDISPINFOA.sizeof);
+                } else {
+                    lpnmtdi = new NMTTDISPINFOW ();
+                    OS.MoveMemory ((NMTTDISPINFOW)lpnmtdi, lParam, NMTTDISPINFOW.sizeof);
+                }
+                String string = toolTipText (lpnmtdi);
+                if (string !is null) {
+                    Shell shell = getShell ();
+                    string = Display.withCrLf (string);
+                    int length = string.length ();
+                    char [] chars = new char [length + 1];
+                    string.getChars (0, length, chars, 0);
+
+                    /*
+                    * Ensure that the orientation of the tool tip matches
+                    * the orientation of the control.
+                    */
+                    int hwnd = hdr.idFrom;
+                    if (hwnd !is 0 && ((lpnmtdi.uFlags & OS.TTF_IDISHWND) !is 0)) {
+                        Control control = display.getControl (hwnd);
+                        if (control !is null) {
+                            if ((control.getStyle () & DWT.RIGHT_TO_LEFT) !is 0) {
+                                lpnmtdi.uFlags |= OS.TTF_RTLREADING;
+                            } else {
+                                lpnmtdi.uFlags &= ~OS.TTF_RTLREADING;
+                            }
+                        }
+                    }
+
+                    if (hdr.code is OS.TTN_GETDISPINFOA) {
+                        byte [] bytes = new byte [chars.length * 2];
+                        OS.WideCharToMultiByte (getCodePage (), 0, chars, chars.length, bytes, bytes.length, null, null);
+                        shell.setToolTipText (lpnmtdi, bytes);
+                        OS.MoveMemory (lParam, (NMTTDISPINFOA)lpnmtdi, NMTTDISPINFOA.sizeof);
+                    } else {
+                        shell.setToolTipText (lpnmtdi, chars);
+                        OS.MoveMemory (lParam, (NMTTDISPINFOW)lpnmtdi, NMTTDISPINFOW.sizeof);
+                    }
+                    return LRESULT.ZERO;
+                }
+                break;
+            }
+        }
+    }
+    return super.wmNotify (hdr, wParam, lParam);
+}
+
+}
+++/
\ No newline at end of file