Mercurial > projects > dwt-win
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 ()); |