2 // System.Windows.Forms.CheckBox.cs
5 // stubbed out by Jaak Simm (jaaksimm@firm.ee)
6 // Dennis Hayes (dennish@Raytek.com)
8 // (C) Ximian, Inc., 2002
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 namespace System
.Windows
.Forms
{
37 /// Represents a Windows check box.
41 public class CheckBox
: ButtonBase
{
44 Appearance appearance
;
46 ContentAlignment checkAlign
;
48 CheckState checkState
;
50 ContentAlignment textAlign
;
53 StringFormat textFormat
;
54 int checkMarkSize
=13; // Keep it configurable for accessability
58 // --- Constructor ---
59 public CheckBox() : base()
62 appearance
= Appearance
.Normal
;
64 checkAlign
= ContentAlignment
.MiddleLeft
;
66 checkState
= CheckState
.Unchecked
;
69 canvasBmp
= new Bitmap(ClientRectangle
.Width
, ClientRectangle
.Height
);
70 canvasDC
= Graphics
.FromImage(canvasBmp
);
72 /* Set defaults for drawing text... */
73 textAlign
= ContentAlignment
.MiddleLeft
;
74 textFormat
= new StringFormat();
75 textFormat
.Alignment
=StringAlignment
.Near
;
76 textFormat
.LineAlignment
=StringAlignment
.Center
;
77 textRect
= ClientRectangle
;
78 textRect
.X
+=checkMarkSize
;
79 textRect
.Width
-=checkMarkSize
;
81 /* ... and for drawing our checkbox */
82 checkRect
.X
=ClientRectangle
.Left
;
83 checkRect
.Y
=(ClientRectangle
.Bottom
-ClientRectangle
.Top
)/2-checkMarkSize
/2;
84 checkRect
.Width
=checkMarkSize
;
85 checkRect
.Height
=checkMarkSize
;
87 SizeChanged
+=new System
.EventHandler(CheckboxSizeChanged
);
88 GotFocus
+=new System
.EventHandler(CheckboxUpdate
);
89 LostFocus
+=new System
.EventHandler(CheckboxUpdate
);
90 TextChanged
+=new System
.EventHandler(CheckboxUpdate
);
92 SubClassWndProc_
= true;
93 SetStyle (ControlStyles
.UserPaint
| ControlStyles
.AllPaintingInWmPaint
, true);
94 callWinControlProcMask
&= ~
(CallWinControlProcMask
.MOUSE_MESSAGES
| CallWinControlProcMask
.KEYBOARD_MESSAGES
);
97 // --- CheckBox Properties ---
98 public Appearance Appearance
{
99 get { return appearance; }
100 set { appearance=value; }
103 public bool AutoCheck
{
104 get { return autoCheck; }
105 set { autoCheck = value; }
108 public ContentAlignment CheckAlign
{
109 get { return checkAlign; }
116 public bool Checked
{
117 get { return _checked; }
119 if( _checked
!= value) {
120 CheckState
= (value) ? CheckState
.Checked
: CheckState
.Unchecked
;
125 public CheckState CheckState
{
126 get { return checkState; }
128 if( checkState
!= value) {
131 bool oldChecked
= _checked
;
133 if( checkState
== CheckState
.Unchecked
) {
140 if( oldChecked
!= _checked
) {
141 OnCheckedChanged(new EventArgs());
144 OnCheckStateChanged(new EventArgs());
150 protected override CreateParams CreateParams
{
152 CreateParams createParams
= base.CreateParams
;
154 createParams
.ClassName
= "BUTTON";
156 createParams
.Style
= (int) (
157 (int)WindowStyles
.WS_CHILD
|
158 (int)WindowStyles
.WS_VISIBLE
|
159 (int)ButtonStyles
.BS_CHECKBOX
|
160 (int)ButtonStyles
.BS_NOTIFY
|
161 (int)WindowStyles
.WS_CLIPSIBLINGS
|
162 (int)WindowStyles
.WS_CLIPCHILDREN
|
163 (int)WindowStyles
.WS_TABSTOP
|
164 (int)SS_Static_Control_Types
.SS_LEFT
);
167 createParams
.Style
|= (int)ButtonStyles
.BS_AUTOCHECKBOX
;
170 /* We need this, we draw ourselves */
171 createParams
.Style
|= (int) ButtonStyles
.BS_OWNERDRAW
;
178 protected override Size DefaultSize
{
179 get { return new Size(100,checkMarkSize); }
183 public override ContentAlignment TextAlign
{
193 public bool ThreeState
{
203 // --- CheckBox methods ---
205 protected override AccessibleObject
CreateAccessibilityInstance()
207 throw new NotImplementedException ();
213 protected virtual void OnAppearanceChanged(EventArgs e
)
215 if (AppearanceChanged
!= null) {
216 AppearanceChanged(this, e
);
221 protected virtual void OnCheckedChanged(EventArgs e
)
224 if(CheckedChanged
!= null) {
225 CheckedChanged( this, e
);
230 protected virtual void OnCheckStateChanged(EventArgs e
)
233 if(CheckStateChanged
!= null) {
234 CheckStateChanged( this, e
);
239 protected override void OnClick(EventArgs e
)
241 CheckState
= (CheckState
)Win32
.SendMessage(Handle
, (int)ButtonMessages
.BM_GETCHECK
, 0, 0);
246 protected override void OnHandleCreated(EventArgs e
)
249 base.OnHandleCreated(e
);
250 Win32
.SendMessage(Handle
, (int)ButtonMessages
.BM_SETCHECK
, (int)checkState
, 0);
253 // protected override void OnMouseDown (MouseEventArgs e)
255 // base.OnMouseDown (e);
259 protected override void OnMouseUp(MouseEventArgs mevent
)
262 switch (CheckState
) {
263 case CheckState
.Unchecked
: {
264 CheckState
= CheckState
.Checked
;
268 case CheckState
.Indeterminate
: {
269 CheckState
= CheckState
.Unchecked
;
273 case CheckState
.Checked
: {
274 CheckState
= CheckState
.Indeterminate
;
279 Checked
= Checked
? false : true;
283 base.OnMouseUp(mevent
);
285 // end of [event methods]
289 protected override bool ProcessMnemonic(char charCode
)
292 return base.ProcessMnemonic(charCode
);
296 //FIXME: do a better tostring
297 public override string ToString()
300 return "CheckBox" + " Checked";
302 return "CheckBox" + " Unchecked";
306 internal override void ButtonPaint (PaintEventArgs e
)
308 if (canvasBmp
!=null) {
309 e
.Graphics
.DrawImage(canvasBmp
, e
.ClipRectangle
, e
.ClipRectangle
, GraphicsUnit
.Pixel
);
313 /// --- CheckBox events ---
314 public event EventHandler AppearanceChanged
;
315 public event EventHandler CheckedChanged
;
316 public event EventHandler CheckStateChanged
;
318 /// --- public class CheckBox.CheckBoxAccessibleObject : AccessibleObject ---
319 /// the class is only used for .NET framework
321 public class CheckBoxAccessibleObject
: AccessibleObject
{
324 private void UpdateCheckbox() {
325 /* Calculate the position of text and checkbox rectangle */
326 if (appearance
!=Appearance
.Button
) {
328 case ContentAlignment
.BottomCenter
: {
329 if (ClientRectangle
.Height
<checkMarkSize
*2) {
330 ClientSize
=new Size(ClientRectangle
.Width
, checkMarkSize
*2);
332 checkRect
.X
=(ClientRectangle
.Right
-ClientRectangle
.Left
)/2-checkMarkSize
/2;
333 checkRect
.Y
=ClientRectangle
.Bottom
-checkMarkSize
;
334 textRect
.X
=ClientRectangle
.X
;
335 textRect
.Width
=ClientRectangle
.Width
;
339 case ContentAlignment
.BottomLeft
: {
340 checkRect
.X
=ClientRectangle
.Left
;
341 checkRect
.Y
=ClientRectangle
.Bottom
-checkMarkSize
;
342 textRect
.X
=ClientRectangle
.X
+checkMarkSize
;
343 textRect
.Width
=ClientRectangle
.Width
-checkMarkSize
;
347 case ContentAlignment
.BottomRight
: {
348 checkRect
.X
=ClientRectangle
.Right
-checkMarkSize
;
349 checkRect
.Y
=ClientRectangle
.Bottom
-checkMarkSize
;
350 textRect
.X
=ClientRectangle
.X
;
351 textRect
.Width
=ClientRectangle
.Width
-checkMarkSize
;
355 case ContentAlignment
.MiddleCenter
: {
356 checkRect
.X
=(ClientRectangle
.Right
-ClientRectangle
.Left
)/2-checkMarkSize
/2;
357 checkRect
.Y
=(ClientRectangle
.Bottom
-ClientRectangle
.Top
)/2-checkMarkSize
/2;
358 textRect
.X
=ClientRectangle
.X
;
359 textRect
.Width
=ClientRectangle
.Width
;
364 case ContentAlignment
.MiddleLeft
: {
365 checkRect
.X
=ClientRectangle
.Left
;
366 checkRect
.Y
=(ClientRectangle
.Bottom
-ClientRectangle
.Top
)/2-checkMarkSize
/2;
367 textRect
.X
=ClientRectangle
.X
+checkMarkSize
;
368 textRect
.Width
=ClientRectangle
.Width
-checkMarkSize
;
372 case ContentAlignment
.MiddleRight
: {
373 checkRect
.X
=ClientRectangle
.Right
-checkMarkSize
;
374 checkRect
.Y
=(ClientRectangle
.Bottom
-ClientRectangle
.Top
)/2-checkMarkSize
/2;
375 textRect
.X
=ClientRectangle
.X
;
376 textRect
.Width
=ClientRectangle
.Width
-checkMarkSize
;
380 case ContentAlignment
.TopCenter
: {
381 if (ClientRectangle
.Height
<checkMarkSize
*2) {
382 ClientSize
=new Size(ClientRectangle
.Width
, checkMarkSize
*2);
384 checkRect
.X
=(ClientRectangle
.Right
-ClientRectangle
.Left
)/2-checkMarkSize
/2;
385 checkRect
.Y
=ClientRectangle
.Top
;
386 textRect
.X
=ClientRectangle
.X
;
387 textRect
.Y
=checkMarkSize
;
388 textRect
.Width
=ClientRectangle
.Width
;
389 textRect
.Height
=ClientRectangle
.Height
-checkMarkSize
;
393 case ContentAlignment
.TopLeft
: {
394 checkRect
.X
=ClientRectangle
.Left
;
395 checkRect
.Y
=ClientRectangle
.Top
;
396 textRect
.X
=ClientRectangle
.X
+checkMarkSize
;
397 textRect
.Width
=ClientRectangle
.Width
-checkMarkSize
;
401 case ContentAlignment
.TopRight
: {
402 checkRect
.X
=ClientRectangle
.Right
-checkMarkSize
;
403 checkRect
.Y
=ClientRectangle
.Top
;
404 textRect
.X
=ClientRectangle
.X
;
405 textRect
.Width
=ClientRectangle
.Width
-checkMarkSize
;
410 textRect
.X
=ClientRectangle
.X
;
411 textRect
.Width
=ClientRectangle
.Width
;
414 /* Set the horizontal alignment of our text */
416 case ContentAlignment
.BottomLeft
:
417 case ContentAlignment
.MiddleLeft
:
418 case ContentAlignment
.TopLeft
: {
419 textFormat
.Alignment
=StringAlignment
.Near
;
423 case ContentAlignment
.BottomCenter
:
424 case ContentAlignment
.MiddleCenter
:
425 case ContentAlignment
.TopCenter
: {
426 textFormat
.Alignment
=StringAlignment
.Center
;
430 case ContentAlignment
.BottomRight
:
431 case ContentAlignment
.MiddleRight
:
432 case ContentAlignment
.TopRight
: {
433 textFormat
.Alignment
=StringAlignment
.Far
;
438 /* Set the vertical alignment of our text */
440 case ContentAlignment
.TopLeft
:
441 case ContentAlignment
.TopCenter
:
442 case ContentAlignment
.TopRight
: {
443 textFormat
.LineAlignment
=StringAlignment
.Near
;
447 case ContentAlignment
.BottomLeft
:
448 case ContentAlignment
.BottomCenter
:
449 case ContentAlignment
.BottomRight
: {
450 textFormat
.LineAlignment
=StringAlignment
.Far
;
454 case ContentAlignment
.MiddleLeft
:
455 case ContentAlignment
.MiddleCenter
:
456 case ContentAlignment
.MiddleRight
: {
457 textFormat
.LineAlignment
=StringAlignment
.Center
;
465 private void CheckboxRedraw() {
468 /* Build the image representing the control */
470 if (canvasDC
!=null) {
473 if (canvasBmp
!=null) {
477 if (ClientRectangle
.Width
<1 || ClientRectangle
.Height
<1) {
480 canvasBmp
= new Bitmap(ClientRectangle
.Width
, ClientRectangle
.Height
);
481 canvasDC
= Graphics
.FromImage(canvasBmp
);
483 sb
=new SolidBrush(BackColor
);
484 canvasDC
.FillRectangle(sb
, ClientRectangle
);
487 ButtonState state
= ButtonState
.Normal
;
488 if (FlatStyle
== FlatStyle
.Flat
) {
489 state
|= ButtonState
.Flat
;
493 state
|= ButtonState
.Checked
;
496 if (ThreeState
&& (CheckState
== CheckState
.Indeterminate
)) {
497 state
|= ButtonState
.ThreeState
;
500 if (appearance
!=Appearance
.Button
) {
501 ControlPaint
.DrawCheckBox(canvasDC
, checkRect
, state
);
503 ControlPaint
.DrawButton(canvasDC
, textRect
, state
);
506 /* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
507 sb
=new SolidBrush(base.foreColor
);
508 canvasDC
.DrawString(Text
, Font
, sb
, textRect
, textFormat
);
512 ControlPaint
.DrawFocusRectangle(canvasDC
, textRect
);
516 private void CheckboxUpdate(object sender
, System
.EventArgs e
) {
517 /* Force recalculation of text & checkbox rectangles */
521 private void CheckboxSizeChanged(object sender
, System
.EventArgs e
)
523 /* Force recalculation of text & checkbox rectangles */
524 textRect
.Y
=ClientRectangle
.Y
;
525 textRect
.Height
=ClientRectangle
.Height
;