diff dwt/widgets/Button.d @ 213:36f5cb12e1a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Sat, 17 May 2008 17:34:28 +0200
parents ab60f3309436
children 43b41c7fe84a
line wrap: on
line diff
--- a/dwt/widgets/Button.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Button.d	Sat May 17 17:34:28 2008 +0200
@@ -63,7 +63,7 @@
     String text = "", message = "";
     Image image, image2, disabledImage;
     ImageList imageList;
-    bool ignoreMouse;
+    bool ignoreMouse, grayed;
     static const int MARGIN = 4;
     private static /+const+/ int CHECK_WIDTH, CHECK_HEIGHT;
     static const int ICON_WIDTH = 128, ICON_HEIGHT = 128;
@@ -504,8 +504,36 @@
 }
 
 override void createHandle () {
+    /*
+    * Feature in Windows.  When a button is created,
+    * it clears the UI state for all controls in the
+    * shell by sending WM_CHANGEUISTATE with UIS_SET,
+    * UISF_HIDEACCEL and UISF_HIDEFOCUS to the parent.
+    * This is undocumented and unexpected.  The fix
+    * is to ignore the WM_CHANGEUISTATE, when sent
+    * from CreateWindowEx().
+    */
+    parent.state |= IGNORE_WM_CHANGEUISTATE;
     super.createHandle ();
-    if ((style & DWT.PUSH) is 0) state |= THEME_BACKGROUND;
+    parent.state &= ~IGNORE_WM_CHANGEUISTATE;
+
+    /* Set the theme background */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        /*
+        * NOTE: On Vista this causes problems when the tab
+        * key is pressed for push buttons so disable the
+        * theme background drawing for these widgets for
+        * now.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+            state |= THEME_BACKGROUND;
+        } else {
+            if ((style & (DWT.PUSH | DWT.TOGGLE)) is 0) {
+                state |= THEME_BACKGROUND;
+            }
+        }
+    }
+
     /*
     * Bug in Windows.  For some reason, the HBRUSH that
     * is returned from WM_CTRLCOLOR is misaligned when
@@ -521,6 +549,23 @@
     if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
         if ((style & DWT.RADIO) !is 0) state |= DRAW_BACKGROUND;
     }
+
+    /*
+    * Feature in Windows.  Push buttons draw border around
+    * the button using the default background color instead
+    * of using the color provided by WM_CTRLCOLOR.  The fix
+    * is to draw the background in WM_CTRLCOLOR.
+    *
+    * NOTE: On Vista this causes problems when the tab key
+    * is pressed for push buttons so disable the fix for now.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+            if ((style & (DWT.PUSH | DWT.TOGGLE)) !is 0) {
+                state |= DRAW_BACKGROUND;
+            }
+        }
+    }
 }
 
 override int defaultBackground () {
@@ -625,6 +670,24 @@
 }
 
 /**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the widget does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @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 bool getGrayed () {
+    checkWidget();
+    if ((style & DWT.CHECK) is 0) return false;
+    return grayed;
+}
+
+/**
  * Returns the receiver's image if it has one, or null
  * if it does not.
  *
@@ -682,8 +745,8 @@
 public bool getSelection () {
     checkWidget ();
     if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return false;
-    int state = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
-    return (state & OS.BST_CHECKED) !is 0;
+    int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+    return flags !is OS.BST_UNCHECKED;
 }
 
 /**
@@ -705,8 +768,7 @@
 }
 
 override bool isTabItem () {
-    //TEMPORARY CODE
-    //if ((style & DWT.PUSH) !is 0) return true;
+    if ((style & DWT.PUSH) !is 0) return isTabGroup ();
     return super.isTabItem ();
 }
 
@@ -728,6 +790,20 @@
     return CharacterToUpper (key) is CharacterToUpper (mnemonic);
 }
 
+void printWidget (HWND hwnd, HDC hDC) {
+    /*
+    * Bug in Windows.  For some reason, PrintWindow() fails
+    * when it is called on a push button.  The fix is to
+    * detect the failure and use WM_PRINT instead.  Note
+    * that WM_PRINT cannot be used all the time because it
+    * fails for browser controls when the browser has focus.
+    */
+    if (!OS.PrintWindow (hwnd, hDC, 0)) {
+        int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND | OS.PRF_CHILDREN;
+        OS.SendMessage (hwnd, OS.WM_PRINT, hDC, flags);
+    }
+}
+
 override void releaseWidget () {
     super.releaseWidget ();
     if (imageList !is null) imageList.dispose ();
@@ -906,6 +982,30 @@
 }
 
 /**
+ * Sets the grayed state of the receiver.  This state change
+ * only applies if the control was created with the DWT.CHECK
+ * style.
+ *
+ * @param grayed the new grayed 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>
+ */
+public void setGrayed (bool grayed) {
+    checkWidget ();
+    if ((style & DWT.CHECK) is 0) return;
+    this.grayed = grayed;
+    int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+    if (grayed) {
+        if (flags is OS.BST_CHECKED) updateSelection (OS.BST_INDETERMINATE);
+    } else {
+        if (flags is OS.BST_INDETERMINATE) updateSelection (OS.BST_CHECKED);
+    }
+}
+
+/**
  * Sets the widget message. When the widget is created
  * with the style <code>DWT.COMMAND</code>, the message text
  * is displayed to provide further information for the user.
@@ -980,16 +1080,10 @@
     checkWidget ();
     if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return;
     int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED;
-    /*
-    * Feature in Windows. When BM_SETCHECK is used
-    * to set the checked state of a radio or check
-    * button, it sets the WM_TABSTOP style.  This
-    * is undocumented and unwanted.  The fix is
-    * to save and restore the window style bits.
-    */
-    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-    OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
-    OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    if ((style & DWT.CHECK) !is 0) {
+        if (selected && grayed) flags = OS.BST_INDETERMINATE;
+    }
+    updateSelection (flags);
 }
 
 /**
@@ -1038,6 +1132,35 @@
     _setText (string);
 }
 
+void updateSelection (int flags) {
+    if (flags !is OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0)) {
+        /*
+        * Feature in Windows. When BM_SETCHECK is used
+        * to set the checked state of a radio or check
+        * button, it sets the WM_TABSTOP style.  This
+        * is undocumented and unwanted.  The fix is
+        * to save and restore the window style bits.
+        */
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((style & DWT.CHECK) !is 0) {
+            if (flags is OS.BST_INDETERMINATE) {
+                bits &= ~OS.BS_CHECKBOX;
+                bits |= OS.BS_3STATE;
+            } else {
+                bits |= OS.BS_CHECKBOX;
+                bits &= ~OS.BS_3STATE;
+            }
+            if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+                OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+            }
+        }
+        OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
+        if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+            OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        }
+    }
+}
+
 override int widgetStyle () {
     int bits = super.widgetStyle ();
     if ((style & DWT.FLAT) !is 0) bits |= OS.BS_FLAT;
@@ -1184,7 +1307,7 @@
             }
             if (redraw) {
                 OS.InvalidateRect (handle, null, false);
-                int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+                int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
                 return new LRESULT (code);
             }
         }
@@ -1193,7 +1316,7 @@
 }
 
 override LRESULT wmCommandChild (int wParam, int lParam) {
-    int code = wParam >> 16;
+    int code = OS.HIWORD (wParam);
     switch (code) {
         case OS.BN_CLICKED:
         case OS.BN_DOUBLECLICKED: