comparison 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
comparison
equal deleted inserted replaced
212:ab60f3309436 213:36f5cb12e1a2
61 61
62 alias extern(Windows) int function( HWND, uint, uint, int ) TWindowProc; 62 alias extern(Windows) int function( HWND, uint, uint, int ) TWindowProc;
63 String text = "", message = ""; 63 String text = "", message = "";
64 Image image, image2, disabledImage; 64 Image image, image2, disabledImage;
65 ImageList imageList; 65 ImageList imageList;
66 bool ignoreMouse; 66 bool ignoreMouse, grayed;
67 static const int MARGIN = 4; 67 static const int MARGIN = 4;
68 private static /+const+/ int CHECK_WIDTH, CHECK_HEIGHT; 68 private static /+const+/ int CHECK_WIDTH, CHECK_HEIGHT;
69 static const int ICON_WIDTH = 128, ICON_HEIGHT = 128; 69 static const int ICON_WIDTH = 128, ICON_HEIGHT = 128;
70 static const bool COMMAND_LINK = false; 70 static const bool COMMAND_LINK = false;
71 private static /+const+/ TWindowProc ButtonProc; 71 private static /+const+/ TWindowProc ButtonProc;
502 height += border * 2; 502 height += border * 2;
503 return new Point (width, height); 503 return new Point (width, height);
504 } 504 }
505 505
506 override void createHandle () { 506 override void createHandle () {
507 /*
508 * Feature in Windows. When a button is created,
509 * it clears the UI state for all controls in the
510 * shell by sending WM_CHANGEUISTATE with UIS_SET,
511 * UISF_HIDEACCEL and UISF_HIDEFOCUS to the parent.
512 * This is undocumented and unexpected. The fix
513 * is to ignore the WM_CHANGEUISTATE, when sent
514 * from CreateWindowEx().
515 */
516 parent.state |= IGNORE_WM_CHANGEUISTATE;
507 super.createHandle (); 517 super.createHandle ();
508 if ((style & DWT.PUSH) is 0) state |= THEME_BACKGROUND; 518 parent.state &= ~IGNORE_WM_CHANGEUISTATE;
519
520 /* Set the theme background */
521 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
522 /*
523 * NOTE: On Vista this causes problems when the tab
524 * key is pressed for push buttons so disable the
525 * theme background drawing for these widgets for
526 * now.
527 */
528 if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
529 state |= THEME_BACKGROUND;
530 } else {
531 if ((style & (DWT.PUSH | DWT.TOGGLE)) is 0) {
532 state |= THEME_BACKGROUND;
533 }
534 }
535 }
536
509 /* 537 /*
510 * Bug in Windows. For some reason, the HBRUSH that 538 * Bug in Windows. For some reason, the HBRUSH that
511 * is returned from WM_CTRLCOLOR is misaligned when 539 * is returned from WM_CTRLCOLOR is misaligned when
512 * the button uses it to draw. If the brush is a solid 540 * the button uses it to draw. If the brush is a solid
513 * color, this does not matter. However, if the brush 541 * color, this does not matter. However, if the brush
518 * drawing in WM_ERASEBKGND will draw on top of the 546 * drawing in WM_ERASEBKGND will draw on top of the
519 * text of the control. 547 * text of the control.
520 */ 548 */
521 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { 549 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
522 if ((style & DWT.RADIO) !is 0) state |= DRAW_BACKGROUND; 550 if ((style & DWT.RADIO) !is 0) state |= DRAW_BACKGROUND;
551 }
552
553 /*
554 * Feature in Windows. Push buttons draw border around
555 * the button using the default background color instead
556 * of using the color provided by WM_CTRLCOLOR. The fix
557 * is to draw the background in WM_CTRLCOLOR.
558 *
559 * NOTE: On Vista this causes problems when the tab key
560 * is pressed for push buttons so disable the fix for now.
561 */
562 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
563 if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
564 if ((style & (DWT.PUSH | DWT.TOGGLE)) !is 0) {
565 state |= DRAW_BACKGROUND;
566 }
567 }
523 } 568 }
524 } 569 }
525 570
526 override int defaultBackground () { 571 override int defaultBackground () {
527 if ((style & (DWT.PUSH | DWT.TOGGLE)) !is 0) { 572 if ((style & (DWT.PUSH | DWT.TOGGLE)) !is 0) {
623 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 668 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
624 return (bits & OS.BS_DEFPUSHBUTTON) !is 0; 669 return (bits & OS.BS_DEFPUSHBUTTON) !is 0;
625 } 670 }
626 671
627 /** 672 /**
673 * Returns <code>true</code> if the receiver is grayed,
674 * and false otherwise. When the widget does not have
675 * the <code>CHECK</code> style, return false.
676 *
677 * @return the grayed state of the checkbox
678 *
679 * @exception DWTException <ul>
680 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
681 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
682 * </ul>
683 */
684 public bool getGrayed () {
685 checkWidget();
686 if ((style & DWT.CHECK) is 0) return false;
687 return grayed;
688 }
689
690 /**
628 * Returns the receiver's image if it has one, or null 691 * Returns the receiver's image if it has one, or null
629 * if it does not. 692 * if it does not.
630 * 693 *
631 * @return the receiver's image 694 * @return the receiver's image
632 * 695 *
680 * </ul> 743 * </ul>
681 */ 744 */
682 public bool getSelection () { 745 public bool getSelection () {
683 checkWidget (); 746 checkWidget ();
684 if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return false; 747 if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return false;
685 int state = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0); 748 int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
686 return (state & OS.BST_CHECKED) !is 0; 749 return flags !is OS.BST_UNCHECKED;
687 } 750 }
688 751
689 /** 752 /**
690 * Returns the receiver's text, which will be an empty 753 * Returns the receiver's text, which will be an empty
691 * string if it has never been set or if the receiver is 754 * string if it has never been set or if the receiver is
703 if ((style & DWT.ARROW) !is 0) return ""; 766 if ((style & DWT.ARROW) !is 0) return "";
704 return text; 767 return text;
705 } 768 }
706 769
707 override bool isTabItem () { 770 override bool isTabItem () {
708 //TEMPORARY CODE 771 if ((style & DWT.PUSH) !is 0) return isTabGroup ();
709 //if ((style & DWT.PUSH) !is 0) return true;
710 return super.isTabItem (); 772 return super.isTabItem ();
711 } 773 }
712 774
713 override bool mnemonicHit (wchar ch) { 775 override bool mnemonicHit (wchar ch) {
714 if (!setFocus ()) return false; 776 if (!setFocus ()) return false;
724 786
725 override bool mnemonicMatch (wchar key) { 787 override bool mnemonicMatch (wchar key) {
726 wchar mnemonic = findMnemonic (getText ()); 788 wchar mnemonic = findMnemonic (getText ());
727 if (mnemonic is '\0') return false; 789 if (mnemonic is '\0') return false;
728 return CharacterToUpper (key) is CharacterToUpper (mnemonic); 790 return CharacterToUpper (key) is CharacterToUpper (mnemonic);
791 }
792
793 void printWidget (HWND hwnd, HDC hDC) {
794 /*
795 * Bug in Windows. For some reason, PrintWindow() fails
796 * when it is called on a push button. The fix is to
797 * detect the failure and use WM_PRINT instead. Note
798 * that WM_PRINT cannot be used all the time because it
799 * fails for browser controls when the browser has focus.
800 */
801 if (!OS.PrintWindow (hwnd, hDC, 0)) {
802 int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND | OS.PRF_CHILDREN;
803 OS.SendMessage (hwnd, OS.WM_PRINT, hDC, flags);
804 }
729 } 805 }
730 806
731 override void releaseWidget () { 807 override void releaseWidget () {
732 super.releaseWidget (); 808 super.releaseWidget ();
733 if (imageList !is null) imageList.dispose (); 809 if (imageList !is null) imageList.dispose ();
904 // } 980 // }
905 _setImage (image); 981 _setImage (image);
906 } 982 }
907 983
908 /** 984 /**
985 * Sets the grayed state of the receiver. This state change
986 * only applies if the control was created with the DWT.CHECK
987 * style.
988 *
989 * @param grayed the new grayed state
990 *
991 * @exception DWTException <ul>
992 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
993 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
994 * </ul>
995 */
996 public void setGrayed (bool grayed) {
997 checkWidget ();
998 if ((style & DWT.CHECK) is 0) return;
999 this.grayed = grayed;
1000 int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
1001 if (grayed) {
1002 if (flags is OS.BST_CHECKED) updateSelection (OS.BST_INDETERMINATE);
1003 } else {
1004 if (flags is OS.BST_INDETERMINATE) updateSelection (OS.BST_CHECKED);
1005 }
1006 }
1007
1008 /**
909 * Sets the widget message. When the widget is created 1009 * Sets the widget message. When the widget is created
910 * with the style <code>DWT.COMMAND</code>, the message text 1010 * with the style <code>DWT.COMMAND</code>, the message text
911 * is displayed to provide further information for the user. 1011 * is displayed to provide further information for the user.
912 * 1012 *
913 * @param message the new message 1013 * @param message the new message
978 */ 1078 */
979 public void setSelection (bool selected) { 1079 public void setSelection (bool selected) {
980 checkWidget (); 1080 checkWidget ();
981 if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return; 1081 if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return;
982 int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED; 1082 int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED;
983 /* 1083 if ((style & DWT.CHECK) !is 0) {
984 * Feature in Windows. When BM_SETCHECK is used 1084 if (selected && grayed) flags = OS.BST_INDETERMINATE;
985 * to set the checked state of a radio or check 1085 }
986 * button, it sets the WM_TABSTOP style. This 1086 updateSelection (flags);
987 * is undocumented and unwanted. The fix is
988 * to save and restore the window style bits.
989 */
990 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
991 OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
992 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
993 } 1087 }
994 1088
995 /** 1089 /**
996 * Sets the receiver's text. 1090 * Sets the receiver's text.
997 * <p> 1091 * <p>
1036 // } 1130 // }
1037 // } 1131 // }
1038 _setText (string); 1132 _setText (string);
1039 } 1133 }
1040 1134
1135 void updateSelection (int flags) {
1136 if (flags !is OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0)) {
1137 /*
1138 * Feature in Windows. When BM_SETCHECK is used
1139 * to set the checked state of a radio or check
1140 * button, it sets the WM_TABSTOP style. This
1141 * is undocumented and unwanted. The fix is
1142 * to save and restore the window style bits.
1143 */
1144 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1145 if ((style & DWT.CHECK) !is 0) {
1146 if (flags is OS.BST_INDETERMINATE) {
1147 bits &= ~OS.BS_CHECKBOX;
1148 bits |= OS.BS_3STATE;
1149 } else {
1150 bits |= OS.BS_CHECKBOX;
1151 bits &= ~OS.BS_3STATE;
1152 }
1153 if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
1154 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
1155 }
1156 }
1157 OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
1158 if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
1159 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
1160 }
1161 }
1162 }
1163
1041 override int widgetStyle () { 1164 override int widgetStyle () {
1042 int bits = super.widgetStyle (); 1165 int bits = super.widgetStyle ();
1043 if ((style & DWT.FLAT) !is 0) bits |= OS.BS_FLAT; 1166 if ((style & DWT.FLAT) !is 0) bits |= OS.BS_FLAT;
1044 if ((style & DWT.ARROW) !is 0) return bits | OS.BS_OWNERDRAW; 1167 if ((style & DWT.ARROW) !is 0) return bits | OS.BS_OWNERDRAW;
1045 if ((style & DWT.LEFT) !is 0) bits |= OS.BS_LEFT; 1168 if ((style & DWT.LEFT) !is 0) bits |= OS.BS_LEFT;
1182 } 1305 }
1183 if (!redraw) redraw = findBackgroundControl () !is null; 1306 if (!redraw) redraw = findBackgroundControl () !is null;
1184 } 1307 }
1185 if (redraw) { 1308 if (redraw) {
1186 OS.InvalidateRect (handle, null, false); 1309 OS.InvalidateRect (handle, null, false);
1187 int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); 1310 int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
1188 return new LRESULT (code); 1311 return new LRESULT (code);
1189 } 1312 }
1190 } 1313 }
1191 } 1314 }
1192 return result; 1315 return result;
1193 } 1316 }
1194 1317
1195 override LRESULT wmCommandChild (int wParam, int lParam) { 1318 override LRESULT wmCommandChild (int wParam, int lParam) {
1196 int code = wParam >> 16; 1319 int code = OS.HIWORD (wParam);
1197 switch (code) { 1320 switch (code) {
1198 case OS.BN_CLICKED: 1321 case OS.BN_CLICKED:
1199 case OS.BN_DOUBLECLICKED: 1322 case OS.BN_DOUBLECLICKED:
1200 if ((style & (DWT.CHECK | DWT.TOGGLE)) !is 0) { 1323 if ((style & (DWT.CHECK | DWT.TOGGLE)) !is 0) {
1201 setSelection (!getSelection ()); 1324 setSelection (!getSelection ());