1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
26 using System.ComponentModel;
27 using System.ComponentModel.Design;
29 using System.Drawing.Text;
30 using System.Runtime.InteropServices;
32 namespace System.Windows.Forms {
34 [ClassInterface (ClassInterfaceType.AutoDispatch)]
36 [Designer ("System.Windows.Forms.Design.ButtonBaseDesigner, " + Consts.AssemblySystem_Design,
37 "System.ComponentModel.Design.IDesigner")]
39 public abstract class ButtonBase : Control
41 #region Local Variables
42 private FlatStyle flat_style;
43 private int image_index;
45 internal ImageList image_list;
46 private ContentAlignment image_alignment;
47 internal ContentAlignment text_alignment;
48 private bool is_default;
49 internal bool is_pressed;
50 private bool enter_state;
51 internal StringFormat text_format;
52 internal bool paint_as_acceptbutton;
54 // Properties are 2.0, but variables used in 1.1 for common drawing code
55 private bool auto_ellipsis;
56 private FlatButtonAppearance flat_button_appearance;
57 private string image_key;
58 private TextImageRelation text_image_relation;
59 private TextFormatFlags text_format_flags;
60 private bool use_mnemonic;
61 private bool use_visual_style_back_color;
62 #endregion // Local Variables
64 #region ButtonBaseAccessibleObject sub-class
66 public class ButtonBaseAccessibleObject : ControlAccessibleObject {
67 #region ButtonBaseAccessibleObject Local Variables
68 private new Control owner;
69 #endregion // ButtonBaseAccessibleObject Local Variables
71 #region ButtonBaseAccessibleObject Constructors
72 public ButtonBaseAccessibleObject (Control owner)
76 throw new ArgumentNullException ("owner");
78 default_action = "Press";
79 role = AccessibleRole.PushButton;
81 #endregion // ButtonBaseAccessibleObject Constructors
83 #region ButtonBaseAccessibleObject Methods
84 public override void DoDefaultAction() {
85 ((ButtonBase)owner).PerformClick();
87 #endregion // ButtonBaseAccessibleObject Methods
89 #endregion // ButtonBaseAccessibleObject sub-class
91 #region Private Properties and Methods
92 internal ButtonState ButtonState {
94 ButtonState ret = ButtonState.Normal;
97 // Popup style is only followed as long as the mouse isn't "in" the control
99 if (flat_style == FlatStyle.Flat) {
100 ret |= ButtonState.Flat;
103 if (flat_style == FlatStyle.Flat || flat_style == FlatStyle.Popup) {
104 ret |= ButtonState.Flat;
108 if (is_entered && is_pressed) {
109 ret |= ButtonState.Pushed;
112 ret |= ButtonState.Inactive;
113 if ((flat_style == FlatStyle.Flat) || (flat_style == FlatStyle.Popup)) {
114 ret |= ButtonState.Flat;
121 internal void Redraw() {
125 // Derived classes should override Draw method and we dont want
126 // to break the control signature, hence this approach.
127 internal virtual void Draw (PaintEventArgs pevent) {
128 ThemeEngine.Current.DrawButtonBase (pevent.Graphics, pevent.ClipRectangle, this);
131 internal virtual void HaveDoubleClick() {
135 private void RedrawEvent(object sender, System.EventArgs e) {
139 #endregion // Private Properties and Methods
141 #region Public Constructors
142 protected ButtonBase() : base()
144 flat_style = FlatStyle.Standard;
146 flat_button_appearance = new FlatButtonAppearance (this);
147 this.image_key = string.Empty;
148 this.text_image_relation = TextImageRelation.Overlay;
149 this.use_mnemonic = true;
154 image_alignment = ContentAlignment.MiddleCenter;
155 ImeMode = ImeMode.Disable;
156 text_alignment = ContentAlignment.MiddleCenter;
159 text_format = new StringFormat();
160 text_format.Alignment = StringAlignment.Center;
161 text_format.LineAlignment = StringAlignment.Center;
162 text_format.HotkeyPrefix = HotkeyPrefix.Show;
164 text_format_flags = TextFormatFlags.HorizontalCenter;
165 text_format_flags |= TextFormatFlags.VerticalCenter;
167 TextChanged+=new System.EventHandler(RedrawEvent);
168 SizeChanged+=new EventHandler(RedrawEvent);
170 SetStyle(ControlStyles.ResizeRedraw |
171 ControlStyles.Opaque |
172 ControlStyles.UserMouse |
173 ControlStyles.SupportsTransparentBackColor |
174 ControlStyles.CacheText |
176 ControlStyles.OptimizedDoubleBuffer, true);
178 ControlStyles.DoubleBuffer, true);
180 SetStyle(ControlStyles.StandardClick, false);
182 #endregion // Public Constructors
184 #region Public Instance Properties
186 [DefaultValue(FlatStyle.Standard)]
187 [MWFDescription("Determines look of button"), MWFCategory("Appearance")]
188 public FlatStyle FlatStyle {
199 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
206 FlatButtonAppearance FlatAppearance
208 get { return flat_button_appearance; }
212 [MWFDescription("Sets image to be displayed on button face"), MWFCategory("Appearance")]
215 if (this.image != null)
218 if (this.image_index >= 0)
219 if (this.image_list != null)
220 return this.image_list.Images[this.image_index];
223 if (!string.IsNullOrEmpty (this.image_key))
224 if (this.image_list != null)
225 return this.image_list.Images[this.image_key];
230 if (this.image != value) {
232 this.image_index = -1;
233 this.image_key = string.Empty;
234 this.image_list = null;
241 [DefaultValue(ContentAlignment.MiddleCenter)]
242 [MWFDescription("Sets the alignment of the image to be displayed on button face"), MWFCategory("Appearance")]
243 public ContentAlignment ImageAlign {
245 return image_alignment;
249 image_alignment=value;
256 [Editor("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
257 [TypeConverter(typeof(ImageIndexConverter))]
258 [MWFDescription("Index of image to display, if ImageList is used for button face images"), MWFCategory("Appearance")]
260 [RefreshProperties (RefreshProperties.Repaint)]
262 public int ImageIndex {
264 if (image_list==null) {
271 if (this.image_index != value) {
272 this.image_index = value;
274 this.image_key = string.Empty;
281 [MWFDescription("ImageList used for ImageIndex"), MWFCategory("Appearance")]
283 [RefreshProperties (RefreshProperties.Repaint)]
285 public ImageList ImageList {
302 [EditorBrowsable (EditorBrowsableState.Never)]
303 public new ImeMode ImeMode {
304 get { return base.ImeMode; }
305 set { base.ImeMode = value; }
309 [DefaultValue(ContentAlignment.MiddleCenter)]
310 [MWFDescription("Alignment for button text"), MWFCategory("Appearance")]
311 public virtual ContentAlignment TextAlign {
313 return text_alignment;
317 if (text_alignment != value) {
318 text_alignment = value;
320 text_format_flags &= ~TextFormatFlags.Bottom;
321 text_format_flags &= ~TextFormatFlags.Top;
322 text_format_flags &= ~TextFormatFlags.Left;
323 text_format_flags &= ~TextFormatFlags.Right;
324 text_format_flags &= ~TextFormatFlags.HorizontalCenter;
325 text_format_flags &= ~TextFormatFlags.VerticalCenter;
327 switch(text_alignment) {
328 case ContentAlignment.TopLeft:
329 text_format.Alignment=StringAlignment.Near;
330 text_format.LineAlignment=StringAlignment.Near;
333 case ContentAlignment.TopCenter:
334 text_format.Alignment=StringAlignment.Center;
335 text_format.LineAlignment=StringAlignment.Near;
336 text_format_flags |= TextFormatFlags.HorizontalCenter;
339 case ContentAlignment.TopRight:
340 text_format.Alignment=StringAlignment.Far;
341 text_format.LineAlignment=StringAlignment.Near;
342 text_format_flags |= TextFormatFlags.Right;
345 case ContentAlignment.MiddleLeft:
346 text_format.Alignment=StringAlignment.Near;
347 text_format.LineAlignment=StringAlignment.Center;
348 text_format_flags |= TextFormatFlags.VerticalCenter;
351 case ContentAlignment.MiddleCenter:
352 text_format.Alignment=StringAlignment.Center;
353 text_format.LineAlignment=StringAlignment.Center;
354 text_format_flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter;
357 case ContentAlignment.MiddleRight:
358 text_format.Alignment=StringAlignment.Far;
359 text_format.LineAlignment=StringAlignment.Center;
360 text_format_flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Right;
363 case ContentAlignment.BottomLeft:
364 text_format.Alignment=StringAlignment.Near;
365 text_format.LineAlignment=StringAlignment.Far;
366 text_format_flags |= TextFormatFlags.Bottom;
369 case ContentAlignment.BottomCenter:
370 text_format.Alignment=StringAlignment.Center;
371 text_format.LineAlignment=StringAlignment.Far;
372 text_format_flags |= TextFormatFlags.HorizontalCenter | TextFormatFlags.Bottom;
375 case ContentAlignment.BottomRight:
376 text_format.Alignment=StringAlignment.Far;
377 text_format.LineAlignment=StringAlignment.Far;
378 text_format_flags |= TextFormatFlags.Bottom | TextFormatFlags.Right;
386 #endregion // Public Instance Properties
388 #region Protected Instance Properties
389 protected override CreateParams CreateParams {
391 return base.CreateParams;
395 protected override ImeMode DefaultImeMode {
396 get { return ImeMode.Disable; }
399 protected override Size DefaultSize {
401 return ThemeEngine.Current.ButtonBaseDefaultSize;
405 protected bool IsDefault {
411 if (is_default != value) {
417 #endregion // Public Instance Properties
419 #region Protected Instance Methods
420 protected override AccessibleObject CreateAccessibilityInstance ()
422 return new ButtonBaseAccessibleObject (this);
425 protected override void Dispose(bool disposing) {
426 base.Dispose(disposing);
429 protected override void OnEnabledChanged(EventArgs e) {
430 base.OnEnabledChanged(e);
433 protected override void OnGotFocus(EventArgs e) {
438 protected override void OnKeyDown(KeyEventArgs kevent) {
439 if (kevent.KeyData == Keys.Space) {
440 enter_state = is_entered;
442 OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, 2, 2, 0));
445 base.OnKeyDown(kevent);
448 protected override void OnKeyUp(KeyEventArgs kevent) {
449 if (kevent.KeyData == Keys.Space) {
450 OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, 2, 2, 0));
451 is_entered = enter_state;
454 base.OnKeyUp(kevent);
457 protected override void OnLostFocus(EventArgs e) {
462 protected override void OnMouseDown(MouseEventArgs mevent) {
463 if ((mevent.Button & MouseButtons.Left) != 0) {
469 base.OnMouseDown(mevent);
472 protected override void OnMouseEnter(EventArgs e) {
474 base.OnMouseEnter(e);
477 protected override void OnMouseLeave(EventArgs e) {
479 base.OnMouseLeave(e);
482 protected override void OnMouseMove(MouseEventArgs mevent) {
488 mevent.X < this.ClientSize.Width &&
489 mevent.Y <= this.ClientSize.Height) {
493 // If the button was pressed and we leave, release the button press and vice versa
494 if ((mevent.Button & MouseButtons.Left) != 0) {
495 if (this.Capture && (inside != is_pressed)) {
501 if (is_entered != inside) {
510 base.OnMouseMove(mevent);
513 protected override void OnMouseUp(MouseEventArgs mevent) {
514 if (this.Capture && ((mevent.Button & MouseButtons.Left) != 0)) {
515 this.Capture = false;
520 } else if ((this.flat_style == FlatStyle.Flat) || (this.flat_style == FlatStyle.Popup)) {
526 mevent.X < this.ClientSize.Width &&
527 mevent.Y <= this.ClientSize.Height) {
528 OnClick(EventArgs.Empty);
531 base.OnMouseUp(mevent);
534 internal override void OnPaintBackgroundInternal(PaintEventArgs e) {
535 base.OnPaintBackground (e);
538 protected override void OnPaint(PaintEventArgs pevent) {
540 base.OnPaint (pevent);
543 protected override void OnParentChanged(EventArgs e) {
544 base.OnParentChanged(e);
547 protected override void OnTextChanged(EventArgs e) {
549 base.OnTextChanged(e);
552 protected override void OnVisibleChanged(EventArgs e) {
557 base.OnVisibleChanged(e);
560 protected void ResetFlagsandPaint() {
561 // Nothing to do; MS internal
562 // Should we do Invalidate (); ?
565 protected override void WndProc(ref Message m) {
567 case Msg.WM_LBUTTONDBLCLK: {
572 case Msg.WM_MBUTTONDBLCLK: {
577 case Msg.WM_RBUTTONDBLCLK: {
582 base.WndProc (ref m);
584 #endregion // Public Instance Properties
586 #region Internal Instance Properties
587 internal bool Pressed {
588 get { return this.is_pressed; }
591 // The flags to be used for MeasureText and DrawText
592 internal TextFormatFlags TextFormatFlags {
593 get { return this.text_format_flags; }
597 #region Internal Methods
598 private void PerformClick() {
599 OnClick(EventArgs.Empty);
601 #endregion // Internal Methods
606 [EditorBrowsable (EditorBrowsableState.Always)]
607 public new event EventHandler AutoSizeChanged {
608 add { base.AutoSizeChanged += value; }
609 remove { base.AutoSizeChanged -= value; }
614 [EditorBrowsable (EditorBrowsableState.Never)]
615 public new event EventHandler ImeModeChanged {
616 add { base.ImeModeChanged += value; }
617 remove { base.ImeModeChanged -= value; }
622 #region .NET 2.0 Public Instance Properties
624 [DefaultValue (false)]
625 [EditorBrowsable (EditorBrowsableState.Always)]
632 get { return this.auto_ellipsis; }
634 if (this.auto_ellipsis != value) {
635 this.auto_ellipsis = value;
637 if (this.auto_ellipsis) {
638 text_format_flags |= TextFormatFlags.EndEllipsis;
639 text_format_flags &= ~TextFormatFlags.WordBreak;
642 text_format_flags &= ~TextFormatFlags.EndEllipsis;
643 text_format_flags |= TextFormatFlags.WordBreak;
653 [EditorBrowsable (EditorBrowsableState.Always)]
654 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
655 public override bool AutoSize {
656 get { return base.AutoSize; }
657 set { base.AutoSize = value; }
660 public override Color BackColor {
661 get { return base.BackColor; }
662 set { base.BackColor = value; }
667 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
668 [RefreshProperties (RefreshProperties.Repaint)]
669 public string ImageKey {
670 get { return this.image_key; }
672 if (this.image_key != value) {
674 this.image_index = -1;
675 this.image_key = value;
682 [DefaultValue (TextImageRelation.Overlay)]
687 TextImageRelation TextImageRelation {
688 get { return this.text_image_relation; }
690 if (!Enum.IsDefined (typeof (TextImageRelation), value))
691 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextImageRelation", value));
693 if (this.text_image_relation != value) {
694 this.text_image_relation = value;
700 [DefaultValue (true)]
707 get { return this.use_mnemonic; }
709 if (this.use_mnemonic != value) {
710 this.use_mnemonic = value;
712 if (this.use_mnemonic)
713 text_format_flags &= ~TextFormatFlags.NoPrefix;
715 text_format_flags |= TextFormatFlags.NoPrefix;
727 bool UseVisualStyleBackColor {
728 get { return use_visual_style_back_color; }
729 set { use_visual_style_back_color = value; }
732 [DefaultValue (false)]
738 bool UseCompatibleTextRendering {
739 get { return use_compatible_text_rendering; }
740 set { use_compatible_text_rendering = value; }
744 [SettingsBindable (true)]
745 [Editor ("System.ComponentModel.Design.MultilineStringEditor, " + Consts.AssemblySystem_Design,
746 "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
747 public override string Text {