CheckBox.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  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:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  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.
  19. //
  20. // Copyright (c) 2004 Novell, Inc.
  21. //
  22. // Authors:
  23. // Dennis Hayes [email protected]
  24. // Peter Bartok [email protected]
  25. //
  26. //
  27. // $Log: CheckBox.cs,v $
  28. // Revision 1.6 2004/09/01 20:01:24 pbartok
  29. // - Added missing default
  30. // - Added missing region mark
  31. //
  32. // Revision 1.5 2004/09/01 01:55:58 pbartok
  33. // - Fixed to match the removal of the needs_redraw concept
  34. //
  35. // Revision 1.4 2004/08/31 18:48:31 pbartok
  36. // - Finished (famous last words)
  37. //
  38. // Revision 1.3 2004/08/30 20:42:26 pbartok
  39. // - Implemented CheckBox drawing code
  40. //
  41. // Revision 1.2 2004/08/30 15:44:20 pbartok
  42. // - Updated to fix broken build. Not complete yet.
  43. //
  44. // Revision 1.1 2004/07/09 05:21:25 pbartok
  45. // - Initial check-in
  46. //
  47. //
  48. // COMPLETE
  49. using System;
  50. using System.Drawing;
  51. namespace System.Windows.Forms {
  52. public class CheckBox : ButtonBase {
  53. #region Local Variables
  54. private Appearance appearance;
  55. private bool auto_check;
  56. private ContentAlignment check_alignment;
  57. private ContentAlignment text_alignment;
  58. private CheckState check_state;
  59. private bool three_state;
  60. private int checkmark_size=13; // Keep it configurable for accessability
  61. #endregion // Local Variables
  62. #region Public Constructors
  63. public CheckBox() {
  64. appearance = Appearance.Normal;
  65. auto_check = true;
  66. check_alignment = ContentAlignment.MiddleLeft;
  67. text_alignment = ContentAlignment.MiddleLeft;
  68. }
  69. #endregion // Public Constructors
  70. #region Public Instance Properties
  71. public Appearance Appearance {
  72. get {
  73. return appearance;
  74. }
  75. set {
  76. if (value != appearance) {
  77. value = appearance;
  78. if (AppearanceChanged != null) {
  79. AppearanceChanged(this, EventArgs.Empty);
  80. }
  81. Redraw();
  82. }
  83. }
  84. }
  85. public bool AutoCheck {
  86. get {
  87. return auto_check;
  88. }
  89. set {
  90. auto_check = value;
  91. }
  92. }
  93. public ContentAlignment CheckAlign {
  94. get {
  95. return check_alignment;
  96. }
  97. set {
  98. if (value != check_alignment) {
  99. check_alignment = value;
  100. Redraw();
  101. }
  102. }
  103. }
  104. public bool Checked {
  105. get {
  106. if (check_state != CheckState.Unchecked) {
  107. return true;
  108. }
  109. return false;
  110. }
  111. set {
  112. if (value && (check_state != CheckState.Checked)) {
  113. check_state = CheckState.Checked;
  114. Redraw();
  115. OnCheckedChanged(EventArgs.Empty);
  116. } else if (!value && (check_state != CheckState.Unchecked)) {
  117. check_state = CheckState.Unchecked;
  118. Redraw();
  119. OnCheckedChanged(EventArgs.Empty);
  120. }
  121. }
  122. }
  123. public CheckState CheckState {
  124. get {
  125. return check_state;
  126. }
  127. set {
  128. if (value != check_state) {
  129. bool was_checked = (check_state != CheckState.Unchecked);
  130. check_state = value;
  131. if (was_checked != (check_state != CheckState.Unchecked)) {
  132. OnCheckedChanged(EventArgs.Empty);
  133. }
  134. OnCheckStateChanged(EventArgs.Empty);
  135. Redraw();
  136. }
  137. }
  138. }
  139. public override ContentAlignment TextAlign {
  140. get {
  141. return text_alignment;
  142. }
  143. set {
  144. if (value != text_alignment) {
  145. text_alignment = value;
  146. Redraw();
  147. }
  148. }
  149. }
  150. public bool ThreeState {
  151. get {
  152. return three_state;
  153. }
  154. set {
  155. three_state = value;
  156. }
  157. }
  158. #endregion // Public Instance Properties
  159. #region Protected Instance Properties
  160. protected override CreateParams CreateParams {
  161. get {
  162. return base.CreateParams;
  163. }
  164. }
  165. protected override Size DefaultSize {
  166. get {
  167. return new Size(104, 24);
  168. }
  169. }
  170. #endregion // Protected Instance Properties
  171. #region Public Instance Methods
  172. public override string ToString() {
  173. return base.ToString() + ", CheckState: " + (int)check_state;
  174. }
  175. #endregion // Public Instance Methods
  176. #region Protected Instance Methods
  177. protected override AccessibleObject CreateAccessibilityInstance() {
  178. return base.CreateAccessibilityInstance ();
  179. }
  180. protected virtual void OnAppearanceChanged(EventArgs e) {
  181. if (AppearanceChanged != null) {
  182. AppearanceChanged(this, e);
  183. }
  184. }
  185. protected virtual void OnCheckedChanged(EventArgs e) {
  186. if (CheckedChanged != null) {
  187. CheckedChanged(this, e);
  188. }
  189. }
  190. protected virtual void OnCheckStateChanged(EventArgs e) {
  191. if (CheckStateChanged != null) {
  192. CheckStateChanged(this, e);
  193. }
  194. }
  195. protected override void OnClick(EventArgs e) {
  196. if (auto_check) {
  197. switch(check_state) {
  198. case CheckState.Unchecked: {
  199. if (three_state) {
  200. CheckState = CheckState.Indeterminate;
  201. } else {
  202. CheckState = CheckState.Checked;
  203. }
  204. break;
  205. }
  206. case CheckState.Indeterminate: {
  207. CheckState = CheckState.Checked;
  208. break;
  209. }
  210. case CheckState.Checked: {
  211. CheckState = CheckState.Unchecked;
  212. break;
  213. }
  214. }
  215. }
  216. }
  217. protected override void OnHandleCreated(EventArgs e) {
  218. base.OnHandleCreated (e);
  219. }
  220. protected override void OnMouseUp(MouseEventArgs e) {
  221. base.OnMouseUp (e);
  222. }
  223. protected override bool ProcessMnemonic(char charCode) {
  224. return base.ProcessMnemonic (charCode);
  225. }
  226. #endregion // Protected Instance Methods
  227. #region Events
  228. public event EventHandler AppearanceChanged;
  229. public event EventHandler CheckedChanged;
  230. public event EventHandler CheckStateChanged;
  231. #endregion // Events
  232. #region Internal drawing code
  233. internal override void Redraw() {
  234. StringFormat text_format;
  235. Rectangle client_rectangle;
  236. Rectangle text_rectangle;
  237. Rectangle checkbox_rectangle;
  238. SolidBrush sb;
  239. client_rectangle = ClientRectangle;
  240. text_rectangle = client_rectangle;
  241. checkbox_rectangle = new Rectangle(text_rectangle.X, text_rectangle.Y, checkmark_size, checkmark_size);
  242. text_format = new StringFormat();
  243. text_format.Alignment=StringAlignment.Near;
  244. text_format.LineAlignment=StringAlignment.Center;
  245. /* Calculate the position of text and checkbox rectangle */
  246. if (appearance!=Appearance.Button) {
  247. switch(check_alignment) {
  248. case ContentAlignment.BottomCenter: {
  249. if (client_rectangle.Height<checkmark_size*2) {
  250. ClientSize=new Size(client_rectangle.Width, checkmark_size*2);
  251. client_rectangle = ClientRectangle;
  252. }
  253. checkbox_rectangle.X=(client_rectangle.Right-client_rectangle.Left)/2-checkmark_size/2;
  254. checkbox_rectangle.Y=client_rectangle.Bottom-checkmark_size;
  255. text_rectangle.X=client_rectangle.X;
  256. text_rectangle.Width=client_rectangle.Width;
  257. break;
  258. }
  259. case ContentAlignment.BottomLeft: {
  260. checkbox_rectangle.X=client_rectangle.Left;
  261. checkbox_rectangle.Y=client_rectangle.Bottom-checkmark_size;
  262. text_rectangle.X=client_rectangle.X+checkmark_size;
  263. text_rectangle.Width=client_rectangle.Width-checkmark_size;
  264. break;
  265. }
  266. case ContentAlignment.BottomRight: {
  267. checkbox_rectangle.X=client_rectangle.Right-checkmark_size;
  268. checkbox_rectangle.Y=client_rectangle.Bottom-checkmark_size;
  269. text_rectangle.X=client_rectangle.X;
  270. text_rectangle.Width=client_rectangle.Width-checkmark_size;
  271. break;
  272. }
  273. case ContentAlignment.MiddleCenter: {
  274. checkbox_rectangle.X=(client_rectangle.Right-client_rectangle.Left)/2-checkmark_size/2;
  275. checkbox_rectangle.Y=(client_rectangle.Bottom-client_rectangle.Top)/2-checkmark_size/2;
  276. text_rectangle.X=client_rectangle.X;
  277. text_rectangle.Width=client_rectangle.Width;
  278. break;
  279. }
  280. default:
  281. case ContentAlignment.MiddleLeft: {
  282. checkbox_rectangle.X=client_rectangle.Left;
  283. checkbox_rectangle.Y=(client_rectangle.Bottom-client_rectangle.Top)/2-checkmark_size/2;
  284. text_rectangle.X=client_rectangle.X+checkmark_size;
  285. text_rectangle.Width=client_rectangle.Width-checkmark_size;
  286. break;
  287. }
  288. case ContentAlignment.MiddleRight: {
  289. checkbox_rectangle.X=client_rectangle.Right-checkmark_size;
  290. checkbox_rectangle.Y=(client_rectangle.Bottom-client_rectangle.Top)/2-checkmark_size/2;
  291. text_rectangle.X=client_rectangle.X;
  292. text_rectangle.Width=client_rectangle.Width-checkmark_size;
  293. break;
  294. }
  295. case ContentAlignment.TopCenter: {
  296. if (client_rectangle.Height<checkmark_size*2) {
  297. ClientSize=new Size(client_rectangle.Width, checkmark_size*2);
  298. client_rectangle = ClientRectangle;
  299. }
  300. checkbox_rectangle.X=(client_rectangle.Right-client_rectangle.Left)/2-checkmark_size/2;
  301. checkbox_rectangle.Y=client_rectangle.Top;
  302. text_rectangle.X=client_rectangle.X;
  303. text_rectangle.Y=checkmark_size;
  304. text_rectangle.Width=client_rectangle.Width;
  305. text_rectangle.Height=client_rectangle.Height-checkmark_size;
  306. break;
  307. }
  308. case ContentAlignment.TopLeft: {
  309. checkbox_rectangle.X=client_rectangle.Left;
  310. checkbox_rectangle.Y=client_rectangle.Top;
  311. text_rectangle.X=client_rectangle.X+checkmark_size;
  312. text_rectangle.Width=client_rectangle.Width-checkmark_size;
  313. break;
  314. }
  315. case ContentAlignment.TopRight: {
  316. checkbox_rectangle.X=client_rectangle.Right-checkmark_size;
  317. checkbox_rectangle.Y=client_rectangle.Top;
  318. text_rectangle.X=client_rectangle.X;
  319. text_rectangle.Width=client_rectangle.Width-checkmark_size;
  320. break;
  321. }
  322. }
  323. } else {
  324. text_rectangle.X=client_rectangle.X;
  325. text_rectangle.Width=client_rectangle.Width;
  326. }
  327. /* Set the horizontal alignment of our text */
  328. switch(text_alignment) {
  329. case ContentAlignment.BottomLeft:
  330. case ContentAlignment.MiddleLeft:
  331. case ContentAlignment.TopLeft: {
  332. text_format.Alignment=StringAlignment.Near;
  333. break;
  334. }
  335. case ContentAlignment.BottomCenter:
  336. case ContentAlignment.MiddleCenter:
  337. case ContentAlignment.TopCenter: {
  338. text_format.Alignment=StringAlignment.Center;
  339. break;
  340. }
  341. case ContentAlignment.BottomRight:
  342. case ContentAlignment.MiddleRight:
  343. case ContentAlignment.TopRight: {
  344. text_format.Alignment=StringAlignment.Far;
  345. break;
  346. }
  347. }
  348. /* Set the vertical alignment of our text */
  349. switch(text_alignment) {
  350. case ContentAlignment.TopLeft:
  351. case ContentAlignment.TopCenter:
  352. case ContentAlignment.TopRight: {
  353. text_format.LineAlignment=StringAlignment.Near;
  354. break;
  355. }
  356. case ContentAlignment.BottomLeft:
  357. case ContentAlignment.BottomCenter:
  358. case ContentAlignment.BottomRight: {
  359. text_format.LineAlignment=StringAlignment.Far;
  360. break;
  361. }
  362. case ContentAlignment.MiddleLeft:
  363. case ContentAlignment.MiddleCenter:
  364. case ContentAlignment.MiddleRight: {
  365. text_format.LineAlignment=StringAlignment.Center;
  366. break;
  367. }
  368. }
  369. ButtonState state = ButtonState.Normal;
  370. if (FlatStyle == FlatStyle.Flat) {
  371. state |= ButtonState.Flat;
  372. }
  373. if (Checked) {
  374. state |= ButtonState.Checked;
  375. }
  376. if (ThreeState && (CheckState == CheckState.Indeterminate)) {
  377. state |= ButtonState.Checked;
  378. state |= ButtonState.Pushed;
  379. }
  380. // Start drawing
  381. sb=new SolidBrush(BackColor);
  382. this.DeviceContext.FillRectangle(sb, ClientRectangle);
  383. sb.Dispose();
  384. if (appearance!=Appearance.Button) {
  385. ControlPaint.DrawCheckBox(this.DeviceContext, checkbox_rectangle, state);
  386. } else {
  387. ControlPaint.DrawButton(this.DeviceContext, text_rectangle, state);
  388. }
  389. /* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
  390. sb=new SolidBrush(ForeColor);
  391. this.DeviceContext.DrawString(Text, Font, sb, text_rectangle, text_format);
  392. sb.Dispose();
  393. if (Focused) {
  394. ControlPaint.DrawFocusRectangle(this.DeviceContext, text_rectangle);
  395. }
  396. Refresh();
  397. }
  398. #endregion // Internal drawing code
  399. }
  400. }