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 Novell, Inc.
23 // Dennis Hayes dennish@raytek.com
24 // Peter Bartok pbartok@novell.com
29 // $Log: CheckBox.cs,v $
30 // Revision 1.3 2004/08/30 20:42:26 pbartok
31 // - Implemented CheckBox drawing code
33 // Revision 1.2 2004/08/30 15:44:20 pbartok
34 // - Updated to fix broken build. Not complete yet.
36 // Revision 1.1 2004/07/09 05:21:25 pbartok
46 namespace System.Windows.Forms {
47 public class CheckBox : ButtonBase {
48 private Appearance appearance;
49 private bool auto_check;
50 private ContentAlignment check_alignment;
51 private ContentAlignment text_alignment;
52 private CheckState check_state;
53 private bool three_state;
54 private int checkmark_size=13; // Keep it configurable for accessability
57 #region Public Constructors
59 appearance = Appearance.Normal;
61 check_alignment = ContentAlignment.MiddleLeft;
63 #endregion // Public Constructors
65 #region Public Instance Properties
66 public Appearance Appearance {
72 if (value != appearance) {
74 if (AppearanceChanged != null) {
75 AppearanceChanged(this, EventArgs.Empty);
81 public bool AutoCheck {
91 public ContentAlignment CheckAlign {
93 return check_alignment;
97 if (value != check_alignment) {
98 check_alignment = value;
105 public bool Checked {
107 if (check_state != CheckState.Unchecked) {
114 if (value && (check_state != CheckState.Checked)) {
115 check_state = CheckState.Checked;
117 OnCheckedChanged(EventArgs.Empty);
118 } else if (!value && (check_state != CheckState.Unchecked)) {
119 check_state = CheckState.Unchecked;
121 OnCheckedChanged(EventArgs.Empty);
126 public CheckState CheckState {
132 if (value != check_state) {
133 bool was_checked = (check_state != CheckState.Unchecked);
137 if (was_checked != (check_state != CheckState.Unchecked)) {
138 OnCheckedChanged(EventArgs.Empty);
141 OnCheckStateChanged(EventArgs.Empty);
147 public override ContentAlignment TextAlign {
149 return text_alignment;
153 if (value != text_alignment) {
154 text_alignment = value;
161 public bool ThreeState {
170 #endregion // Public Instance Properties
172 #region Protected Instance Properties
173 protected override CreateParams CreateParams {
175 return base.CreateParams;
179 protected override Size DefaultSize {
181 return new Size(104, 24);
184 #endregion // Protected Instance Properties
186 #region Public Instance Methods
187 public override string ToString() {
188 if (CheckState == CheckState.Unchecked) {
189 return "CheckBox (unchecked)";
190 } else if (CheckState == CheckState.Checked) {
191 return "CheckBox (checked)";
193 return "CheckBox (state indeterminate)";
196 #endregion // Public Instance Methods
198 #region Protected Instance Methods
199 protected override AccessibleObject CreateAccessibilityInstance() {
200 return base.CreateAccessibilityInstance ();
203 protected virtual void OnAppearanceChanged(EventArgs e) {
204 if (AppearanceChanged != null) {
205 AppearanceChanged(this, e);
209 protected virtual void OnCheckedChanged(EventArgs e) {
210 Console.WriteLine("Checked changed");
211 if (CheckedChanged != null) {
212 CheckedChanged(this, e);
216 protected virtual void OnCheckStateChanged(EventArgs e) {
217 Console.WriteLine("CheckState changed");
218 if (CheckStateChanged != null) {
219 CheckStateChanged(this, e);
223 protected override void OnClick(EventArgs e) {
224 Console.WriteLine("Got click event");
226 switch(check_state) {
227 case CheckState.Unchecked: {
229 CheckState = CheckState.Indeterminate;
231 CheckState = CheckState.Checked;
236 case CheckState.Indeterminate: {
237 CheckState = CheckState.Checked;
241 case CheckState.Checked: {
242 CheckState = CheckState.Unchecked;
251 protected override void OnHandleCreated(EventArgs e) {
252 base.OnHandleCreated (e);
255 protected override void OnMouseUp(MouseEventArgs e) {
259 protected override bool ProcessMnemonic(char charCode) {
260 return base.ProcessMnemonic (charCode);
262 #endregion // Protected Instance Methods
265 public event EventHandler AppearanceChanged;
266 public event EventHandler CheckedChanged;
267 public event EventHandler CheckStateChanged;
270 #region Internal drawing code
271 internal override bool CheckRedraw() {
\r
272 return base.CheckRedraw ();
\r
275 internal override void Redraw() {
\r
276 StringFormat text_format;
277 Rectangle client_rectangle;
278 Rectangle text_rectangle;
279 Rectangle checkbox_rectangle;
281 Console.WriteLine("REDRAWING");
282 client_rectangle = ClientRectangle;
283 text_rectangle = client_rectangle;
284 checkbox_rectangle = new Rectangle(text_rectangle.X, text_rectangle.Y, checkmark_size, checkmark_size);
286 text_format = new StringFormat();
287 text_format.Alignment=StringAlignment.Near;
288 text_format.LineAlignment=StringAlignment.Center;
290 /* Calculate the position of text and checkbox rectangle */
291 if (appearance!=Appearance.Button) {
292 switch(check_alignment) {
293 case ContentAlignment.BottomCenter: {
294 if (client_rectangle.Height<checkmark_size*2) {
295 ClientSize=new Size(client_rectangle.Width, checkmark_size*2);
296 client_rectangle = ClientRectangle;
298 checkbox_rectangle.X=(client_rectangle.Right-client_rectangle.Left)/2-checkmark_size/2;
299 checkbox_rectangle.Y=client_rectangle.Bottom-checkmark_size;
300 text_rectangle.X=client_rectangle.X;
301 text_rectangle.Width=client_rectangle.Width;
305 case ContentAlignment.BottomLeft: {
306 checkbox_rectangle.X=client_rectangle.Left;
307 checkbox_rectangle.Y=client_rectangle.Bottom-checkmark_size;
308 text_rectangle.X=client_rectangle.X+checkmark_size;
309 text_rectangle.Width=client_rectangle.Width-checkmark_size;
313 case ContentAlignment.BottomRight: {
314 checkbox_rectangle.X=client_rectangle.Right-checkmark_size;
315 checkbox_rectangle.Y=client_rectangle.Bottom-checkmark_size;
316 text_rectangle.X=client_rectangle.X;
317 text_rectangle.Width=client_rectangle.Width-checkmark_size;
321 case ContentAlignment.MiddleCenter: {
322 checkbox_rectangle.X=(client_rectangle.Right-client_rectangle.Left)/2-checkmark_size/2;
323 checkbox_rectangle.Y=(client_rectangle.Bottom-client_rectangle.Top)/2-checkmark_size/2;
324 text_rectangle.X=client_rectangle.X;
325 text_rectangle.Width=client_rectangle.Width;
330 case ContentAlignment.MiddleLeft: {
331 checkbox_rectangle.X=client_rectangle.Left;
332 checkbox_rectangle.Y=(client_rectangle.Bottom-client_rectangle.Top)/2-checkmark_size/2;
333 text_rectangle.X=client_rectangle.X+checkmark_size;
334 text_rectangle.Width=client_rectangle.Width-checkmark_size;
338 case ContentAlignment.MiddleRight: {
339 checkbox_rectangle.X=client_rectangle.Right-checkmark_size;
340 checkbox_rectangle.Y=(client_rectangle.Bottom-client_rectangle.Top)/2-checkmark_size/2;
341 text_rectangle.X=client_rectangle.X;
342 text_rectangle.Width=client_rectangle.Width-checkmark_size;
346 case ContentAlignment.TopCenter: {
347 if (client_rectangle.Height<checkmark_size*2) {
348 ClientSize=new Size(client_rectangle.Width, checkmark_size*2);
349 client_rectangle = ClientRectangle;
351 checkbox_rectangle.X=(client_rectangle.Right-client_rectangle.Left)/2-checkmark_size/2;
352 checkbox_rectangle.Y=client_rectangle.Top;
353 text_rectangle.X=client_rectangle.X;
354 text_rectangle.Y=checkmark_size;
355 text_rectangle.Width=client_rectangle.Width;
356 text_rectangle.Height=client_rectangle.Height-checkmark_size;
360 case ContentAlignment.TopLeft: {
361 checkbox_rectangle.X=client_rectangle.Left;
362 checkbox_rectangle.Y=client_rectangle.Top;
363 text_rectangle.X=client_rectangle.X+checkmark_size;
364 text_rectangle.Width=client_rectangle.Width-checkmark_size;
368 case ContentAlignment.TopRight: {
369 checkbox_rectangle.X=client_rectangle.Right-checkmark_size;
370 checkbox_rectangle.Y=client_rectangle.Top;
371 text_rectangle.X=client_rectangle.X;
372 text_rectangle.Width=client_rectangle.Width-checkmark_size;
377 text_rectangle.X=client_rectangle.X;
378 text_rectangle.Width=client_rectangle.Width;
381 /* Set the horizontal alignment of our text */
382 switch(text_alignment) {
383 case ContentAlignment.BottomLeft:
384 case ContentAlignment.MiddleLeft:
385 case ContentAlignment.TopLeft: {
386 text_format.Alignment=StringAlignment.Near;
390 case ContentAlignment.BottomCenter:
391 case ContentAlignment.MiddleCenter:
392 case ContentAlignment.TopCenter: {
393 text_format.Alignment=StringAlignment.Center;
397 case ContentAlignment.BottomRight:
398 case ContentAlignment.MiddleRight:
399 case ContentAlignment.TopRight: {
400 text_format.Alignment=StringAlignment.Far;
405 /* Set the vertical alignment of our text */
406 switch(text_alignment) {
407 case ContentAlignment.TopLeft:
408 case ContentAlignment.TopCenter:
409 case ContentAlignment.TopRight: {
410 text_format.LineAlignment=StringAlignment.Near;
414 case ContentAlignment.BottomLeft:
415 case ContentAlignment.BottomCenter:
416 case ContentAlignment.BottomRight: {
417 text_format.LineAlignment=StringAlignment.Far;
421 case ContentAlignment.MiddleLeft:
422 case ContentAlignment.MiddleCenter:
423 case ContentAlignment.MiddleRight: {
424 text_format.LineAlignment=StringAlignment.Center;
429 ButtonState state = ButtonState.Normal;
430 if (FlatStyle == FlatStyle.Flat) {
431 state |= ButtonState.Flat;
435 state |= ButtonState.Checked;
438 if (ThreeState && (CheckState == CheckState.Indeterminate)) {
439 state |= ButtonState.Checked;
440 state |= ButtonState.Pushed;
445 sb=new SolidBrush(BackColor);
446 this.DeviceContext.FillRectangle(sb, ClientRectangle);
449 if (appearance!=Appearance.Button) {
450 ControlPaint.DrawCheckBox(this.DeviceContext, checkbox_rectangle, state);
452 ControlPaint.DrawButton(this.DeviceContext, text_rectangle, state);
455 /* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
456 sb=new SolidBrush(ForeColor);
457 this.DeviceContext.DrawString(Text, Font, sb, text_rectangle, text_format);
461 ControlPaint.DrawFocusRectangle(this.DeviceContext, text_rectangle);
464 #endregion // Internal drawing code
468 public class CheckBox : ButtonBase {
471 Appearance appearance;
473 ContentAlignment checkAlign;
475 CheckState checkState;
477 ContentAlignment textAlign;
478 Rectangle text_rectangle;
479 Rectangle checkbox_rectangle;
480 StringFormat textFormat;
481 int checkmark_size=13; // Keep it configurable for accessability
485 // --- Constructor ---
486 public CheckBox() : base()
489 appearance = Appearance.Normal;
491 checkAlign = ContentAlignment.MiddleLeft;
493 checkState = CheckState.Unchecked;
496 canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
497 canvasDC = Graphics.FromImage(canvasBmp);
499 /* Set defaults for drawing text... */
500 textAlign = ContentAlignment.MiddleLeft;
501 textFormat = new StringFormat();
502 textFormat.Alignment=StringAlignment.Near;
503 textFormat.LineAlignment=StringAlignment.Center;
504 text_rectangle = ClientRectangle;
505 text_rectangle.X+=checkmark_size;
506 text_rectangle.Width-=checkmark_size;
508 /* ... and for drawing our checkbox */
509 checkbox_rectangle.X=ClientRectangle.Left;
510 checkbox_rectangle.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkmark_size/2;
511 checkbox_rectangle.Width=checkmark_size;
512 checkbox_rectangle.Height=checkmark_size;
514 SizeChanged+=new System.EventHandler(CheckboxSizeChanged);
515 GotFocus+=new System.EventHandler(CheckboxUpdate);
516 LostFocus+=new System.EventHandler(CheckboxUpdate);
517 TextChanged+=new System.EventHandler(CheckboxUpdate);
519 SubClassWndProc_ = true;
520 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
521 callWinControlProcMask &= ~(CallWinControlProcMask.MOUSE_MESSAGES | CallWinControlProcMask.KEYBOARD_MESSAGES);
524 // --- CheckBox Properties ---
526 public CheckState CheckState {
527 get { return checkState; }
529 if( checkState != value) {
532 bool oldChecked = _checked;
534 if( checkState == CheckState.Unchecked) {
541 if( oldChecked != _checked) {
542 OnCheckedChanged(new EventArgs());
545 OnCheckStateChanged(new EventArgs());
551 public override ContentAlignment TextAlign {
561 public bool ThreeState {
571 // --- CheckBox methods ---
573 protected override AccessibleObject CreateAccessibilityInstance()
575 throw new NotImplementedException ();
581 protected virtual void OnAppearanceChanged(EventArgs e)
583 if (AppearanceChanged != null) {
584 AppearanceChanged(this, e);
589 protected virtual void OnCheckedChanged(EventArgs e)
592 if(CheckedChanged != null) {
593 CheckedChanged( this, e);
598 protected virtual void OnCheckStateChanged(EventArgs e)
601 if(CheckStateChanged != null) {
602 CheckStateChanged( this, e);
607 protected override void OnClick(EventArgs e)
609 CheckState = (CheckState)Win32.SendMessage(Handle, (int)ButtonMessages.BM_GETCHECK, 0, 0);
614 protected override void OnHandleCreated(EventArgs e)
617 base.OnHandleCreated(e);
618 Win32.SendMessage(Handle, (int)ButtonMessages.BM_SETCHECK, (int)checkState, 0);
621 // protected override void OnMouseDown (MouseEventArgs e)
623 // base.OnMouseDown (e);
627 protected override void OnMouseUp(MouseEventArgs mevent)
630 switch (CheckState) {
631 case CheckState.Unchecked: {
632 CheckState = CheckState.Checked;
636 case CheckState.Indeterminate: {
637 CheckState = CheckState.Unchecked;
641 case CheckState.Checked: {
642 CheckState = CheckState.Indeterminate;
647 Checked = Checked ? false : true;
651 base.OnMouseUp(mevent);
653 // end of [event methods]
657 protected override bool ProcessMnemonic(char charCode)
660 return base.ProcessMnemonic(charCode);
664 //FIXME: do a better tostring
665 public override string ToString()
668 return "CheckBox" + " Checked";
670 return "CheckBox" + " Unchecked";
674 internal override void ButtonPaint (PaintEventArgs e)
676 if (canvasBmp!=null) {
677 e.Graphics.DrawImage(canvasBmp, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
681 /// --- CheckBox events ---
682 public event EventHandler AppearanceChanged;
683 public event EventHandler CheckedChanged;
684 public event EventHandler CheckStateChanged;
686 /// --- public class CheckBox.CheckBoxAccessibleObject : AccessibleObject ---
687 /// the class is only used for .NET framework
689 public class CheckBoxAccessibleObject : AccessibleObject {
692 private void UpdateCheckbox() {
693 /* Calculate the position of text and checkbox rectangle */
694 if (appearance!=Appearance.Button) {
696 case ContentAlignment.BottomCenter: {
697 if (ClientRectangle.Height<checkmark_size*2) {
698 ClientSize=new Size(ClientRectangle.Width, checkmark_size*2);
700 checkbox_rectangle.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkmark_size/2;
701 checkbox_rectangle.Y=ClientRectangle.Bottom-checkmark_size;
702 text_rectangle.X=ClientRectangle.X;
703 text_rectangle.Width=ClientRectangle.Width;
707 case ContentAlignment.BottomLeft: {
708 checkbox_rectangle.X=ClientRectangle.Left;
709 checkbox_rectangle.Y=ClientRectangle.Bottom-checkmark_size;
710 text_rectangle.X=ClientRectangle.X+checkmark_size;
711 text_rectangle.Width=ClientRectangle.Width-checkmark_size;
715 case ContentAlignment.BottomRight: {
716 checkbox_rectangle.X=ClientRectangle.Right-checkmark_size;
717 checkbox_rectangle.Y=ClientRectangle.Bottom-checkmark_size;
718 text_rectangle.X=ClientRectangle.X;
719 text_rectangle.Width=ClientRectangle.Width-checkmark_size;
723 case ContentAlignment.MiddleCenter: {
724 checkbox_rectangle.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkmark_size/2;
725 checkbox_rectangle.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkmark_size/2;
726 text_rectangle.X=ClientRectangle.X;
727 text_rectangle.Width=ClientRectangle.Width;
732 case ContentAlignment.MiddleLeft: {
733 checkbox_rectangle.X=ClientRectangle.Left;
734 checkbox_rectangle.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkmark_size/2;
735 text_rectangle.X=ClientRectangle.X+checkmark_size;
736 text_rectangle.Width=ClientRectangle.Width-checkmark_size;
740 case ContentAlignment.MiddleRight: {
741 checkbox_rectangle.X=ClientRectangle.Right-checkmark_size;
742 checkbox_rectangle.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkmark_size/2;
743 text_rectangle.X=ClientRectangle.X;
744 text_rectangle.Width=ClientRectangle.Width-checkmark_size;
748 case ContentAlignment.TopCenter: {
749 if (ClientRectangle.Height<checkmark_size*2) {
750 ClientSize=new Size(ClientRectangle.Width, checkmark_size*2);
752 checkbox_rectangle.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkmark_size/2;
753 checkbox_rectangle.Y=ClientRectangle.Top;
754 text_rectangle.X=ClientRectangle.X;
755 text_rectangle.Y=checkmark_size;
756 text_rectangle.Width=ClientRectangle.Width;
757 text_rectangle.Height=ClientRectangle.Height-checkmark_size;
761 case ContentAlignment.TopLeft: {
762 checkbox_rectangle.X=ClientRectangle.Left;
763 checkbox_rectangle.Y=ClientRectangle.Top;
764 text_rectangle.X=ClientRectangle.X+checkmark_size;
765 text_rectangle.Width=ClientRectangle.Width-checkmark_size;
769 case ContentAlignment.TopRight: {
770 checkbox_rectangle.X=ClientRectangle.Right-checkmark_size;
771 checkbox_rectangle.Y=ClientRectangle.Top;
772 text_rectangle.X=ClientRectangle.X;
773 text_rectangle.Width=ClientRectangle.Width-checkmark_size;
778 text_rectangle.X=ClientRectangle.X;
779 text_rectangle.Width=ClientRectangle.Width;
782 /* Set the horizontal alignment of our text */
784 case ContentAlignment.BottomLeft:
785 case ContentAlignment.MiddleLeft:
786 case ContentAlignment.TopLeft: {
787 textFormat.Alignment=StringAlignment.Near;
791 case ContentAlignment.BottomCenter:
792 case ContentAlignment.MiddleCenter:
793 case ContentAlignment.TopCenter: {
794 textFormat.Alignment=StringAlignment.Center;
798 case ContentAlignment.BottomRight:
799 case ContentAlignment.MiddleRight:
800 case ContentAlignment.TopRight: {
801 textFormat.Alignment=StringAlignment.Far;
806 /* Set the vertical alignment of our text */
808 case ContentAlignment.TopLeft:
809 case ContentAlignment.TopCenter:
810 case ContentAlignment.TopRight: {
811 textFormat.LineAlignment=StringAlignment.Near;
815 case ContentAlignment.BottomLeft:
816 case ContentAlignment.BottomCenter:
817 case ContentAlignment.BottomRight: {
818 textFormat.LineAlignment=StringAlignment.Far;
822 case ContentAlignment.MiddleLeft:
823 case ContentAlignment.MiddleCenter:
824 case ContentAlignment.MiddleRight: {
825 textFormat.LineAlignment=StringAlignment.Center;
833 private void CheckboxRedraw() {
836 /* Build the image representing the control */
838 if (canvasDC!=null) {
841 if (canvasBmp!=null) {
845 if (ClientRectangle.Width<1 || ClientRectangle.Height<1) {
848 canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
849 canvasDC = Graphics.FromImage(canvasBmp);
851 sb=new SolidBrush(BackColor);
852 canvasDC.FillRectangle(sb, ClientRectangle);
855 ButtonState state = ButtonState.Normal;
856 if (FlatStyle == FlatStyle.Flat) {
857 state |= ButtonState.Flat;
861 state |= ButtonState.Checked;
864 if (ThreeState && (CheckState == CheckState.Indeterminate)) {
865 state |= ButtonState.Checked;
866 state |= ButtonState.Pushed;
869 if (appearance!=Appearance.Button) {
870 ControlPaint.DrawCheckBox(canvasDC, checkbox_rectangle, state);
872 ControlPaint.DrawButton(canvasDC, text_rectangle, state);
875 /* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
876 sb=new SolidBrush(base.foreColor);
877 canvasDC.DrawString(Text, Font, sb, text_rectangle, textFormat);
881 ControlPaint.DrawFocusRectangle(canvasDC, text_rectangle);
885 private void CheckboxUpdate(object sender, System.EventArgs e) {
886 /* Force recalculation of text & checkbox rectangles */
890 private void CheckboxSizeChanged(object sender, System.EventArgs e)
892 /* Force recalculation of text & checkbox rectangles */
893 text_rectangle.Y=ClientRectangle.Y;
894 text_rectangle.Height=ClientRectangle.Height;