Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / WinForms / Managed / System / WinForms / DataGridViewCheckBoxCell.cs / 1 / DataGridViewCheckBoxCell.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms { using System; using System.Diagnostics; using System.Drawing; using System.ComponentModel; using System.Windows.Forms.VisualStyles; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Windows.Forms.Internal; using System.Windows.Forms.ButtonInternal; using System.Diagnostics.CodeAnalysis; using System.Globalization; ////// /// public class DataGridViewCheckBoxCell : DataGridViewCell, IDataGridViewEditingCell { private static readonly DataGridViewContentAlignment anyLeft = DataGridViewContentAlignment.TopLeft | DataGridViewContentAlignment.MiddleLeft | DataGridViewContentAlignment.BottomLeft; private static readonly DataGridViewContentAlignment anyRight = DataGridViewContentAlignment.TopRight | DataGridViewContentAlignment.MiddleRight | DataGridViewContentAlignment.BottomRight; private static readonly DataGridViewContentAlignment anyCenter = DataGridViewContentAlignment.TopCenter | DataGridViewContentAlignment.MiddleCenter | DataGridViewContentAlignment.BottomCenter; private static readonly DataGridViewContentAlignment anyBottom = DataGridViewContentAlignment.BottomRight | DataGridViewContentAlignment.BottomCenter | DataGridViewContentAlignment.BottomLeft; private static readonly DataGridViewContentAlignment anyMiddle = DataGridViewContentAlignment.MiddleRight | DataGridViewContentAlignment.MiddleCenter | DataGridViewContentAlignment.MiddleLeft; private static readonly VisualStyleElement CheckBoxElement = VisualStyleElement.Button.CheckBox.UncheckedNormal; private static readonly int PropButtonCellState = PropertyStore.CreateKey(); private static readonly int PropTrueValue = PropertyStore.CreateKey(); private static readonly int PropFalseValue = PropertyStore.CreateKey(); private static readonly int PropFlatStyle = PropertyStore.CreateKey(); private static readonly int PropIndeterminateValue = PropertyStore.CreateKey(); private static Bitmap checkImage = null; private const byte DATAGRIDVIEWCHECKBOXCELL_threeState = 0x01; private const byte DATAGRIDVIEWCHECKBOXCELL_valueChanged = 0x02; private const byte DATAGRIDVIEWCHECKBOXCELL_checked = 0x10; private const byte DATAGRIDVIEWCHECKBOXCELL_indeterminate = 0x20; private const byte DATAGRIDVIEWCHECKBOXCELL_margin = 2; // horizontal and vertical margins for preferred sizes private byte flags; // see DATAGRIDVIEWCHECKBOXCELL_ consts above private static bool mouseInContentBounds = false; private static Type defaultCheckStateType = typeof(System.Windows.Forms.CheckState); private static Type defaultBooleanType = typeof(System.Boolean); private static Type cellType = typeof(DataGridViewCheckBoxCell); ///Identifies a checkbox cell in the DataGridView. ///public DataGridViewCheckBoxCell() : this(false /*threeState*/) { } /// public DataGridViewCheckBoxCell(bool threeState) { if (threeState) { this.flags = DATAGRIDVIEWCHECKBOXCELL_threeState; } } /// public virtual object EditingCellFormattedValue { get { return GetEditingCellFormattedValue(DataGridViewDataErrorContexts.Formatting); } set { if (this.FormattedValueType == null) { throw new ArgumentException(SR.GetString(SR.DataGridViewCell_FormattedValueTypeNull)); } if (value == null || !this.FormattedValueType.IsAssignableFrom(value.GetType())) { // Assigned formatted value may not be of the good type, in cases where the app // is feeding wrong values to the cell in virtual / databound mode. throw new ArgumentException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)); } if (value is System.Windows.Forms.CheckState) { if (((System.Windows.Forms.CheckState)value) == System.Windows.Forms.CheckState.Checked) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_checked; this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_indeterminate); } else if (((System.Windows.Forms.CheckState)value) == System.Windows.Forms.CheckState.Indeterminate) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_indeterminate; this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_checked); } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_checked); this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_indeterminate); } } else if (value is System.Boolean) { if ((bool)value) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_checked; } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_checked); } this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_indeterminate); } else { throw new ArgumentException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)); } } } /// public virtual bool EditingCellValueChanged { get { return ((this.flags & DATAGRIDVIEWCHECKBOXCELL_valueChanged) != 0x00); } set { if (value) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_valueChanged; } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_valueChanged); } } } /// public virtual object GetEditingCellFormattedValue(DataGridViewDataErrorContexts context) { if (this.FormattedValueType == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridViewCell_FormattedValueTypeNull)); } if (this.FormattedValueType.IsAssignableFrom(defaultCheckStateType)) { if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_checked) != 0x00) { if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardChecked); } return System.Windows.Forms.CheckState.Checked; } else if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_indeterminate) != 0x00) { if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardIndeterminate); } return System.Windows.Forms.CheckState.Indeterminate; } else { if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardUnchecked); } return System.Windows.Forms.CheckState.Unchecked; } } else if (this.FormattedValueType.IsAssignableFrom(defaultBooleanType)) { bool ret = (bool)((this.flags & DATAGRIDVIEWCHECKBOXCELL_checked) != 0x00); if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(ret ? SR.DataGridViewCheckBoxCell_ClipboardTrue : SR.DataGridViewCheckBoxCell_ClipboardFalse); } return ret; } else { return null; } } /// public virtual void PrepareEditingCellForEdit(bool selectAll) { } private ButtonState ButtonState { get { bool found; int buttonState = this.Properties.GetInteger(PropButtonCellState, out found); if (found) { return (ButtonState)buttonState; } return ButtonState.Normal; } set { // ButtonState.Pushed is used for mouse interaction // ButtonState.Checked is used for keyboard interaction Debug.Assert((value & ~(ButtonState.Normal | ButtonState.Pushed | ButtonState.Checked)) == 0); if (this.ButtonState != value) { this.Properties.SetInteger(PropButtonCellState, (int)value); } } } /// public override Type EditType { get { // Check boxes can't switch to edit mode // This cell type must implement the IEditingCell interface return null; } } /// [DefaultValue(null)] public object FalseValue { get { return this.Properties.GetObject(PropFalseValue); } set { if (value != null || this.Properties.ContainsObject(PropFalseValue)) { this.Properties.SetObject(PropFalseValue, value); if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal object FalseValueInternal { set { if (value != null || this.Properties.ContainsObject(PropFalseValue)) { this.Properties.SetObject(PropFalseValue, value); } } } /// [DefaultValue(FlatStyle.Standard)] public FlatStyle FlatStyle { get { bool found; int flatStyle = this.Properties.GetInteger(PropFlatStyle, out found); if (found) { return (FlatStyle)flatStyle; } return FlatStyle.Standard; } set { // Sequential enum. Valid values are 0x0 to 0x3 if (!ClientUtils.IsEnumValid(value, (int)value, (int)FlatStyle.Flat, (int)FlatStyle.System)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(FlatStyle)); } if (value != this.FlatStyle) { this.Properties.SetInteger(PropFlatStyle, (int)value); OnCommonChange(); } } } internal FlatStyle FlatStyleInternal { set { Debug.Assert(value >= FlatStyle.Flat && value <= FlatStyle.System); if (value != this.FlatStyle) { this.Properties.SetInteger(PropFlatStyle, (int)value); } } } /// public override Type FormattedValueType { get { if (this.ThreeState) { return defaultCheckStateType; } else { return defaultBooleanType; } } } /// [DefaultValue(null)] public object IndeterminateValue { get { return this.Properties.GetObject(PropIndeterminateValue); } set { if (value != null || this.Properties.ContainsObject(PropIndeterminateValue)) { this.Properties.SetObject(PropIndeterminateValue, value); if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal object IndeterminateValueInternal { set { if (value != null || this.Properties.ContainsObject(PropIndeterminateValue)) { this.Properties.SetObject(PropIndeterminateValue, value); } } } /// [DefaultValue(false)] public bool ThreeState { get { return ((this.flags & DATAGRIDVIEWCHECKBOXCELL_threeState) != 0x00); } set { if (this.ThreeState != value) { this.ThreeStateInternal = value; if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal bool ThreeStateInternal { set { if (this.ThreeState != value) { if (value) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_threeState; } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_threeState); } } } } /// [DefaultValue(null)] public object TrueValue { get { return this.Properties.GetObject(PropTrueValue); } set { if (value != null || this.Properties.ContainsObject(PropTrueValue)) { this.Properties.SetObject(PropTrueValue, value); if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal object TrueValueInternal { set { if (value != null || this.Properties.ContainsObject(PropTrueValue)) { this.Properties.SetObject(PropTrueValue, value); } } } /// public override Type ValueType { get { Type valueType = base.ValueType; if (valueType != null) { return valueType; } if (this.ThreeState) { return defaultCheckStateType; } else { return defaultBooleanType; } } set { base.ValueType = value; this.ThreeState = (value != null && defaultCheckStateType.IsAssignableFrom(value)); } } /// public override object Clone() { DataGridViewCheckBoxCell dataGridViewCell; Type thisType = this.GetType(); if (thisType == cellType) //performance improvement { dataGridViewCell = new DataGridViewCheckBoxCell(); } else { // SECREVIEW : Late-binding does not represent a security thread, see bug#411899 for more info.. // dataGridViewCell = (DataGridViewCheckBoxCell)System.Activator.CreateInstance(thisType); } base.CloneInternal(dataGridViewCell); dataGridViewCell.ThreeStateInternal = this.ThreeState; dataGridViewCell.TrueValueInternal = this.TrueValue; dataGridViewCell.FalseValueInternal = this.FalseValue; dataGridViewCell.IndeterminateValueInternal = this.IndeterminateValue; dataGridViewCell.FlatStyleInternal = this.FlatStyle; return dataGridViewCell; } private bool CommonContentClickUnsharesRow(DataGridViewCellEventArgs e) { Point ptCurrentCell = this.DataGridView.CurrentCellAddress; return ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == e.RowIndex && this.DataGridView.IsCurrentCellInEditMode; } /// protected override bool ContentClickUnsharesRow(DataGridViewCellEventArgs e) { return CommonContentClickUnsharesRow(e); } /// protected override bool ContentDoubleClickUnsharesRow(DataGridViewCellEventArgs e) { return CommonContentClickUnsharesRow(e); } /// protected override AccessibleObject CreateAccessibilityInstance() { return new DataGridViewCheckBoxCellAccessibleObject(this); } /// protected override Rectangle GetContentBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex) { if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } if (this.DataGridView == null || rowIndex < 0 || this.OwningColumn == null) { return Rectangle.Empty; } DataGridViewAdvancedBorderStyle dgvabsEffective; DataGridViewElementStates cellState; Rectangle cellBounds; ComputeBorderStyleCellStateAndCellBounds(rowIndex, out dgvabsEffective, out cellState, out cellBounds); Rectangle checkBoxBounds = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, null /*formattedValue*/, // checkBoxBounds is independent of formattedValue null /*errorText*/, // checkBoxBounds is independent of errorText cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, true /*computeContentBounds*/, false /*computeErrorIconBounds*/, false /*paint*/); #if DEBUG object value = GetValue(rowIndex); Rectangle checkBoxBoundsDebug = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, GetEditedFormattedValue(value, rowIndex, ref cellStyle, DataGridViewDataErrorContexts.Formatting), GetErrorText(rowIndex), cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, true /*computeContentBounds*/, false /*computeErrorIconBounds*/, false /*paint*/); Debug.Assert(checkBoxBoundsDebug.Equals(checkBoxBounds)); #endif return checkBoxBounds; } /// protected override Rectangle GetErrorIconBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex) { if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } if (this.DataGridView == null || rowIndex < 0 || this.OwningColumn == null || !this.DataGridView.ShowCellErrors || String.IsNullOrEmpty(GetErrorText(rowIndex))) { return Rectangle.Empty; } Point ptCurrentCell = this.DataGridView.CurrentCellAddress; if (ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == rowIndex && this.DataGridView.IsCurrentCellInEditMode) { // PaintPrivate does not paint the error icon if this is the current cell. // So don't set the ErrorIconBounds either. return Rectangle.Empty; } DataGridViewAdvancedBorderStyle dgvabsEffective; DataGridViewElementStates cellState; Rectangle cellBounds; ComputeBorderStyleCellStateAndCellBounds(rowIndex, out dgvabsEffective, out cellState, out cellBounds); Rectangle errorIconBounds = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, null /*formattedValue*/, // errorIconBounds is independent of formattedValue GetErrorText(rowIndex), cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, false /*computeContentBounds*/, true /*computeErrorIconBound*/, false /*paint*/); #if DEBUG object value = GetValue(rowIndex); Rectangle errorIconBoundsDebug = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, GetEditedFormattedValue(value, rowIndex, ref cellStyle, DataGridViewDataErrorContexts.Formatting), GetErrorText(rowIndex), cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, false /*computeContentBounds*/, true /*computeErrorIconBound*/, false /*paint*/); Debug.Assert(errorIconBoundsDebug.Equals(errorIconBounds)); #endif return errorIconBounds; } /// protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) { if (value != null) { if (this.ThreeState) { if (value.Equals(this.TrueValue) || (value is int && (int)value == (int)CheckState.Checked)) { value = CheckState.Checked; } else if (value.Equals(this.FalseValue) || (value is int && (int)value == (int)CheckState.Unchecked)) { value = CheckState.Unchecked; } else if (value.Equals(this.IndeterminateValue) || (value is int && (int)value == (int)CheckState.Indeterminate)) { value = CheckState.Indeterminate; } /* Commenting out because of bug VSWhidbey 300778 else if (this.DataGridView != null && this.FormattedValueType != null && !(value is System.DBNull) && !this.FormattedValueType.IsAssignableFrom(value.GetType())) { DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs( new FormatException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)), this.ColumnIndex, rowIndex, context); RaiseDataError(dgvdee); if (dgvdee.ThrowException) { throw dgvdee.Exception; } } */ } else { if (value.Equals(this.TrueValue) || (value is int && (int)value != 0)) { value = true; } else if (value.Equals(this.FalseValue) || (value is int && (int)value == 0)) { value = false; } /* Commenting out because of bug VSWhidbey 300778 else if (this.DataGridView != null && this.FormattedValueType != null && !(value is System.DBNull) && !this.FormattedValueType.IsAssignableFrom(value.GetType())) { DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs( new FormatException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)), this.ColumnIndex, rowIndex, context); RaiseDataError(dgvdee); if (dgvdee.ThrowException) { throw dgvdee.Exception; } } */ } } object ret = base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context); if (ret != null && (context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { if (ret is bool) { bool retBool = (bool) ret; if (retBool) { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardChecked : SR.DataGridViewCheckBoxCell_ClipboardTrue); } else { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardUnchecked : SR.DataGridViewCheckBoxCell_ClipboardFalse); } } else if (ret is CheckState) { CheckState retCheckState = (CheckState) ret; if (retCheckState == CheckState.Checked) { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardChecked : SR.DataGridViewCheckBoxCell_ClipboardTrue); } else if (retCheckState == CheckState.Unchecked) { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardUnchecked : SR.DataGridViewCheckBoxCell_ClipboardFalse); } else { Debug.Assert(retCheckState == CheckState.Indeterminate); return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardIndeterminate); } } } return ret; } /// protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize) { if (this.DataGridView == null) { return new Size(-1, -1); } if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } DataGridViewFreeDimension freeDimension = DataGridViewCell.GetFreeDimensionFromConstraint(constraintSize); Rectangle borderWidthsRect = this.StdBorderWidths; int borderAndPaddingWidths = borderWidthsRect.Left + borderWidthsRect.Width + cellStyle.Padding.Horizontal; int borderAndPaddingHeights = borderWidthsRect.Top + borderWidthsRect.Height + cellStyle.Padding.Vertical; Size preferredSize; if (this.DataGridView.ApplyVisualStylesToInnerCells) { // Assuming here that all checkbox states use the same size. We should take the largest of the state specific sizes. Size checkBoxSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal); switch (this.FlatStyle) { case FlatStyle.Standard: case FlatStyle.System: break; case FlatStyle.Flat: checkBoxSize.Width -= 3; checkBoxSize.Height -= 3; break; case FlatStyle.Popup: checkBoxSize.Width -= 2; checkBoxSize.Height -= 2; break; } switch (freeDimension) { case DataGridViewFreeDimension.Width: { preferredSize = new Size(checkBoxSize.Width + borderAndPaddingWidths + 2 * DATAGRIDVIEWCHECKBOXCELL_margin, 0); break; } case DataGridViewFreeDimension.Height: { preferredSize = new Size(0, checkBoxSize.Height + borderAndPaddingHeights + 2 * DATAGRIDVIEWCHECKBOXCELL_margin); break; } default: { preferredSize = new Size(checkBoxSize.Width + borderAndPaddingWidths + 2 * DATAGRIDVIEWCHECKBOXCELL_margin, checkBoxSize.Height + borderAndPaddingHeights + 2 * DATAGRIDVIEWCHECKBOXCELL_margin); break; } } } else { int checkBoxSize; switch (this.FlatStyle) { case FlatStyle.Flat: checkBoxSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal).Width - 3; break; case FlatStyle.Popup: checkBoxSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal).Width - 2; break; default: // FlatStyle.Standard || FlatStyle.System checkBoxSize = SystemInformation.Border3DSize.Width * 2 + 9 + 2 * DATAGRIDVIEWCHECKBOXCELL_margin; break; } switch (freeDimension) { case DataGridViewFreeDimension.Width: { preferredSize = new Size(checkBoxSize + borderAndPaddingWidths, 0); break; } case DataGridViewFreeDimension.Height: { preferredSize = new Size(0, checkBoxSize + borderAndPaddingHeights); break; } default: { preferredSize = new Size(checkBoxSize + borderAndPaddingWidths, checkBoxSize + borderAndPaddingHeights); break; } } } if (this.DataGridView.ShowCellErrors) { // Making sure that there is enough room for the potential error icon if (freeDimension != DataGridViewFreeDimension.Height) { preferredSize.Width = Math.Max(preferredSize.Width, borderAndPaddingWidths + DATAGRIDVIEWCELL_iconMarginWidth * 2 + DATAGRIDVIEWCELL_iconsWidth); } if (freeDimension != DataGridViewFreeDimension.Width) { preferredSize.Height = Math.Max(preferredSize.Height, borderAndPaddingHeights + DATAGRIDVIEWCELL_iconMarginHeight * 2 + DATAGRIDVIEWCELL_iconsHeight); } } return preferredSize; } /// protected override bool KeyDownUnsharesRow(KeyEventArgs e, int rowIndex) { return e.KeyCode == Keys.Space && !e.Alt && !e.Control && !e.Shift; } /// protected override bool KeyUpUnsharesRow(KeyEventArgs e, int rowIndex) { return e.KeyCode == Keys.Space; } /// protected override bool MouseDownUnsharesRow(DataGridViewCellMouseEventArgs e) { return e.Button == MouseButtons.Left; } /// protected override bool MouseEnterUnsharesRow(int rowIndex) { return this.ColumnIndex == this.DataGridView.MouseDownCellAddress.X && rowIndex == this.DataGridView.MouseDownCellAddress.Y; } /// protected override bool MouseLeaveUnsharesRow(int rowIndex) { return (this.ButtonState & ButtonState.Pushed) != 0; } /// protected override bool MouseUpUnsharesRow(DataGridViewCellMouseEventArgs e) { return e.Button == MouseButtons.Left; } private void NotifyDataGridViewOfValueChange() { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_valueChanged; this.DataGridView.NotifyCurrentCellDirty(true); } private void OnCommonContentClick(DataGridViewCellEventArgs e) { if (this.DataGridView == null) { return; } Point ptCurrentCell = this.DataGridView.CurrentCellAddress; if (ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == e.RowIndex && this.DataGridView.IsCurrentCellInEditMode) { if (SwitchFormattedValue()) { NotifyDataGridViewOfValueChange(); } } } /// protected override void OnContentClick(DataGridViewCellEventArgs e) { OnCommonContentClick(e); } /// protected override void OnContentDoubleClick(DataGridViewCellEventArgs e) { OnCommonContentClick(e); } /// protected override void OnKeyDown(KeyEventArgs e, int rowIndex) { if (this.DataGridView == null) { return; } if (e.KeyCode == Keys.Space && !e.Alt && !e.Control && !e.Shift) { UpdateButtonState(this.ButtonState | ButtonState.Checked, rowIndex); e.Handled = true; } } /// protected override void OnKeyUp(KeyEventArgs e, int rowIndex) { if (this.DataGridView == null) { return; } if (e.KeyCode == Keys.Space) { UpdateButtonState(this.ButtonState & ~ButtonState.Checked, rowIndex); if (!e.Alt && !e.Control && !e.Shift) { RaiseCellClick(new DataGridViewCellEventArgs(this.ColumnIndex, rowIndex)); if (this.DataGridView != null && this.ColumnIndex < this.DataGridView.Columns.Count && rowIndex < this.DataGridView.Rows.Count) { RaiseCellContentClick(new DataGridViewCellEventArgs(this.ColumnIndex, rowIndex)); } e.Handled = true; } } } /// protected override void OnLeave(int rowIndex, bool throughMouseClick) { if (this.DataGridView == null) { return; } if (this.ButtonState != ButtonState.Normal) { Debug.Assert(this.RowIndex >= 0); // Cell is not in a shared row. UpdateButtonState(ButtonState.Normal, rowIndex); } } /// protected override void OnMouseDown(DataGridViewCellMouseEventArgs e) { if (this.DataGridView == null) { return; } if (e.Button == MouseButtons.Left && mouseInContentBounds) { Debug.Assert(this.DataGridView.CellMouseDownInContentBounds); UpdateButtonState(this.ButtonState | ButtonState.Pushed, e.RowIndex); } } /// protected override void OnMouseLeave(int rowIndex) { if (this.DataGridView == null) { return; } if (mouseInContentBounds) { mouseInContentBounds = false; if (this.ColumnIndex >= 0 && rowIndex >= 0 && (this.DataGridView.ApplyVisualStylesToInnerCells || this.FlatStyle == FlatStyle.Flat || this.FlatStyle == FlatStyle.Popup)) { this.DataGridView.InvalidateCell(this.ColumnIndex, rowIndex); } } if ((this.ButtonState & ButtonState.Pushed) != 0 && this.ColumnIndex == this.DataGridView.MouseDownCellAddress.X && rowIndex == this.DataGridView.MouseDownCellAddress.Y) { UpdateButtonState(this.ButtonState & ~ButtonState.Pushed, rowIndex); } } /// protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { if (this.DataGridView == null) { return; } bool oldMouseInContentBounds = mouseInContentBounds; mouseInContentBounds = GetContentBounds(e.RowIndex).Contains(e.X, e.Y); if (oldMouseInContentBounds != mouseInContentBounds) { if (this.DataGridView.ApplyVisualStylesToInnerCells || this.FlatStyle == FlatStyle.Flat || this.FlatStyle == FlatStyle.Popup) { this.DataGridView.InvalidateCell(this.ColumnIndex, e.RowIndex); } if (e.ColumnIndex == this.DataGridView.MouseDownCellAddress.X && e.RowIndex == this.DataGridView.MouseDownCellAddress.Y && Control.MouseButtons == MouseButtons.Left) { if ((this.ButtonState & ButtonState.Pushed) == 0 && mouseInContentBounds && this.DataGridView.CellMouseDownInContentBounds) { UpdateButtonState(this.ButtonState | ButtonState.Pushed, e.RowIndex); } else if ((this.ButtonState & ButtonState.Pushed) != 0 && !mouseInContentBounds) { UpdateButtonState(this.ButtonState & ~ButtonState.Pushed, e.RowIndex); } } } base.OnMouseMove(e); } /// protected override void OnMouseUp(DataGridViewCellMouseEventArgs e) { if (this.DataGridView == null) { return; } if (e.Button == MouseButtons.Left) { UpdateButtonState(this.ButtonState & ~ButtonState.Pushed, e.RowIndex); } } /// protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } PaintPrivate(graphics, clipBounds, cellBounds, rowIndex, elementState, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts, false /*computeContentBounds*/, false /*computeErrorIconBounds*/, true /*paint*/); } // PaintPrivate is used in three places that need to duplicate the paint code: // 1. DataGridViewCell::Paint method // 2. DataGridViewCell::GetContentBounds // 3. DataGridViewCell::GetErrorIconBounds // // if computeContentBounds is true then PaintPrivate returns the contentBounds // else if computeErrorIconBounds is true then PaintPrivate returns the errorIconBounds // else it returns Rectangle.Empty; private Rectangle PaintPrivate(Graphics g, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts, bool computeContentBounds, bool computeErrorIconBounds, bool paint) { // Parameter checking. // One bit and one bit only should be turned on Debug.Assert(paint || computeContentBounds || computeErrorIconBounds); Debug.Assert(!paint || !computeContentBounds || !computeErrorIconBounds); Debug.Assert(!computeContentBounds || !computeErrorIconBounds || !paint); Debug.Assert(!computeErrorIconBounds || !paint || !computeContentBounds); Debug.Assert(cellStyle != null); Rectangle resultBounds; if (paint && DataGridViewCell.PaintBorder(paintParts)) { PaintBorder(g, clipBounds, cellBounds, cellStyle, advancedBorderStyle); } Rectangle valBounds = cellBounds; Rectangle borderWidths = BorderWidths(advancedBorderStyle); valBounds.Offset(borderWidths.X, borderWidths.Y); valBounds.Width -= borderWidths.Right; valBounds.Height -= borderWidths.Bottom; bool cellSelected = (elementState & DataGridViewElementStates.Selected) != 0; bool drawAsMixedCheckBox = false, drawErrorText = true; CheckState checkState; ButtonState bs; Point ptCurrentCell = this.DataGridView.CurrentCellAddress; if (ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == rowIndex && this.DataGridView.IsCurrentCellInEditMode) { drawErrorText = false; } if (formattedValue != null && formattedValue is CheckState) { checkState = (CheckState)formattedValue; bs = (checkState == CheckState.Unchecked) ? ButtonState.Normal : ButtonState.Checked; drawAsMixedCheckBox = (checkState == CheckState.Indeterminate); } else if (formattedValue != null && formattedValue is bool) { if ((bool)formattedValue) { checkState = CheckState.Checked; bs = ButtonState.Checked; } else { checkState = CheckState.Unchecked; bs = ButtonState.Normal; } } else { // The provided formatted value has a wrong type. We raised a DataError event while formatting. bs = ButtonState.Normal; // Default rendering of the checkbox with wrong formatted value type. checkState = CheckState.Unchecked; } if ((this.ButtonState & (ButtonState.Pushed | ButtonState.Checked)) != 0) { bs |= ButtonState.Pushed; } SolidBrush br = this.DataGridView.GetCachedBrush((DataGridViewCell.PaintSelectionBackground(paintParts) && cellSelected) ? cellStyle.SelectionBackColor : cellStyle.BackColor); if (paint && DataGridViewCell.PaintBackground(paintParts) && br.Color.A == 255) { g.FillRectangle(br, valBounds); } if (cellStyle.Padding != Padding.Empty) { if (this.DataGridView.RightToLeftInternal) { valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top); } else { valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top); } valBounds.Width -= cellStyle.Padding.Horizontal; valBounds.Height -= cellStyle.Padding.Vertical; } if (paint && DataGridViewCell.PaintFocus(paintParts) && this.DataGridView.ShowFocusCues && this.DataGridView.Focused && ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == rowIndex) { // Draw focus rectangle ControlPaint.DrawFocusRectangle(g, valBounds, Color.Empty, br.Color); } Rectangle errorBounds = valBounds; valBounds.Inflate(-DATAGRIDVIEWCHECKBOXCELL_margin, -DATAGRIDVIEWCHECKBOXCELL_margin); Size checkBoxSize; CheckBoxState themeCheckBoxState = CheckBoxState.UncheckedNormal; if (this.DataGridView.ApplyVisualStylesToInnerCells) { themeCheckBoxState = CheckBoxRenderer.ConvertFromButtonState(bs, drawAsMixedCheckBox, this.DataGridView.MouseEnteredCellAddress.Y == rowIndex && this.DataGridView.MouseEnteredCellAddress.X == this.ColumnIndex && mouseInContentBounds); checkBoxSize = CheckBoxRenderer.GetGlyphSize(g, themeCheckBoxState); switch (this.FlatStyle) { case FlatStyle.Standard: case FlatStyle.System: break; case FlatStyle.Flat: checkBoxSize.Width -= 3; checkBoxSize.Height -= 3; break; case FlatStyle.Popup: checkBoxSize.Width -= 2; checkBoxSize.Height -= 2; break; } } else { switch (this.FlatStyle) { case FlatStyle.Flat: checkBoxSize = CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.UncheckedNormal); checkBoxSize.Width -= 3; checkBoxSize.Height -= 3; break; case FlatStyle.Popup: checkBoxSize = CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.UncheckedNormal); checkBoxSize.Width -= 2; checkBoxSize.Height -= 2; break; default: // FlatStyle.Standard || FlatStyle.System checkBoxSize = new Size(SystemInformation.Border3DSize.Width * 2 + 9, SystemInformation.Border3DSize.Width * 2 + 9); break; } } if (valBounds.Width >= checkBoxSize.Width && valBounds.Height >= checkBoxSize.Height && (paint || computeContentBounds)) { int checkBoxX = 0, checkBoxY = 0; if ((!this.DataGridView.RightToLeftInternal && (cellStyle.Alignment & anyRight) != 0) || (this.DataGridView.RightToLeftInternal && (cellStyle.Alignment & anyLeft) != 0)) { checkBoxX = valBounds.Right - checkBoxSize.Width; } else if ((cellStyle.Alignment & anyCenter) != 0) { checkBoxX = valBounds.Left + (valBounds.Width - checkBoxSize.Width) / 2; } else { checkBoxX = valBounds.Left; } if ((cellStyle.Alignment & anyBottom) != 0) { checkBoxY = valBounds.Bottom - checkBoxSize.Height; } else if ((cellStyle.Alignment & anyMiddle) != 0) { checkBoxY = valBounds.Top + (valBounds.Height - checkBoxSize.Height) / 2; } else { checkBoxY = valBounds.Top; } if (this.DataGridView.ApplyVisualStylesToInnerCells && this.FlatStyle != FlatStyle.Flat && this.FlatStyle != FlatStyle.Popup) { if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { DataGridViewCheckBoxCellRenderer.DrawCheckBox(g, new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height), (int) themeCheckBoxState); } resultBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height); } else { if (this.FlatStyle == FlatStyle.System || this.FlatStyle == FlatStyle.Standard) { if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { if (drawAsMixedCheckBox) { ControlPaint.DrawMixedCheckBox(g, checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height, bs); } else { ControlPaint.DrawCheckBox(g, checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height, bs); } } resultBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height); } else if (this.FlatStyle == FlatStyle.Flat) { // CheckBox::Paint will only paint the check box differently when in FlatStyle.Flat // this code is copied from CheckBox::DrawCheckFlat. it was a lot of trouble making this function static Rectangle checkBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height); SolidBrush foreBrush = null; SolidBrush backBrush = null; Color highlight = Color.Empty; if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { foreBrush = this.DataGridView.GetCachedBrush(cellSelected ? cellStyle.SelectionForeColor : cellStyle.ForeColor); backBrush = this.DataGridView.GetCachedBrush((DataGridViewCell.PaintSelectionBackground(paintParts) && cellSelected) ? cellStyle.SelectionBackColor : cellStyle.BackColor); highlight = ControlPaint.LightLight(backBrush.Color); if (this.DataGridView.MouseEnteredCellAddress.Y == rowIndex && this.DataGridView.MouseEnteredCellAddress.X == this.ColumnIndex && mouseInContentBounds) { const float lowlight = .1f; float adjust = 1 - lowlight; if (highlight.GetBrightness() < .5) { adjust = 1 + lowlight * 2; } highlight = Color.FromArgb(ButtonInternal.ButtonBaseAdapter.ColorOptions.Adjust255(adjust, highlight.R), ButtonInternal.ButtonBaseAdapter.ColorOptions.Adjust255(adjust, highlight.G), ButtonInternal.ButtonBaseAdapter.ColorOptions.Adjust255(adjust, highlight.B)); } highlight = g.GetNearestColor(highlight); using (Pen pen = new Pen(foreBrush.Color)) { g.DrawLine(pen, checkBounds.Left, checkBounds.Top, checkBounds.Right-1, checkBounds.Top); g.DrawLine(pen, checkBounds.Left, checkBounds.Top, checkBounds.Left, checkBounds.Bottom-1); } } checkBounds.Inflate(-1, -1); checkBounds.Width++; checkBounds.Height++; if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { if (checkState == CheckState.Indeterminate) { ButtonInternal.ButtonBaseAdapter.DrawDitheredFill(g, backBrush.Color, highlight, checkBounds); } else { using (SolidBrush highBrush = new SolidBrush(highlight)) { g.FillRectangle(highBrush, checkBounds); } } // draw the check box if (checkState != CheckState.Unchecked) { Rectangle fullSize = new Rectangle(checkBoxX-1, checkBoxY-1, checkBoxSize.Width+3, checkBoxSize.Height+3); fullSize.Width++; fullSize.Height++; if (checkImage == null || checkImage.Width != fullSize.Width || checkImage.Height != fullSize.Height) { if (checkImage != null) { checkImage.Dispose(); checkImage = null; } // We draw the checkmark slightly off center to eliminate 3-D border artifacts, // and compensate below NativeMethods.RECT rcCheck = NativeMethods.RECT.FromXYWH(0, 0, fullSize.Width, fullSize.Height); Bitmap bitmap = new Bitmap(fullSize.Width, fullSize.Height); using (Graphics offscreen = Graphics.FromImage(bitmap)) { offscreen.Clear(Color.Transparent); IntPtr dc = offscreen.GetHdc(); try { SafeNativeMethods.DrawFrameControl(new HandleRef(offscreen, dc), ref rcCheck, NativeMethods.DFC_MENU, NativeMethods.DFCS_MENUCHECK); } finally { offscreen.ReleaseHdcInternal(dc); } } bitmap.MakeTransparent(); checkImage = bitmap; } fullSize.Y--; ControlPaint.DrawImageColorized(g, checkImage, fullSize, checkState == CheckState.Indeterminate ? ControlPaint.LightLight(foreBrush.Color) : foreBrush.Color); } } resultBounds = checkBounds; } else { Debug.Assert(this.FlatStyle == FlatStyle.Popup); Rectangle checkBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width - 1, checkBoxSize.Height - 1); // The CheckBoxAdapter code moves the check box down about 3 pixels so we have to take that into account checkBounds.Y -= 3; if ((this.ButtonState & (ButtonState.Pushed | ButtonState.Checked)) != 0) { // paint down ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g, true /*show3D*/, checkBoxSize.Width, checkBounds, Padding.Empty, false, cellStyle.Font, String.Empty, this.DataGridView.Enabled, DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment), this.DataGridView.RightToLeft); options.everettButtonCompat = false; ButtonBaseAdapter.LayoutData layout = options.Layout(); if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g, cellStyle.ForeColor, cellStyle.BackColor, this.DataGridView.Enabled).Calculate(); CheckBoxBaseAdapter.DrawCheckBackground(this.DataGridView.Enabled, checkState, g, layout.checkBounds, colors.windowText, colors.buttonFace, true /*disabledColors*/, colors); CheckBoxBaseAdapter.DrawPopupBorder(g, layout.checkBounds, colors); CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width, checkState == CheckState.Checked || checkState == CheckState.Indeterminate, this.DataGridView.Enabled, checkState, g, layout, colors, colors.windowText, colors.buttonFace, true /*disabledColors*/); } resultBounds = layout.checkBounds; } else if (this.DataGridView.MouseEnteredCellAddress.Y == rowIndex && this.DataGridView.MouseEnteredCellAddress.X == this.ColumnIndex && mouseInContentBounds) { // paint over ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g, true /*show3D*/, checkBoxSize.Width, checkBounds, Padding.Empty, false, cellStyle.Font, String.Empty, this.DataGridView.Enabled, DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment), this.DataGridView.RightToLeft); options.everettButtonCompat = false; ButtonBaseAdapter.LayoutData layout = options.Layout(); if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g, cellStyle.ForeColor, cellStyle.BackColor, this.DataGridView.Enabled).Calculate(); CheckBoxBaseAdapter.DrawCheckBackground(this.DataGridView.Enabled, checkState, g, layout.checkBounds, colors.windowText, colors.options.highContrast ? colors.buttonFace : colors.highlight, true /*disabledColors*/, colors); CheckBoxBaseAdapter.DrawPopupBorder(g, layout.checkBounds, colors); CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width, checkState == CheckState.Checked || checkState == CheckState.Indeterminate, this.DataGridView.Enabled, checkState, g, layout, colors, colors.windowText, colors.highlight, true /*disabledColors*/); } resultBounds = layout.checkBounds; } else { // paint up ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g, false /*show3D*/, checkBoxSize.Width, checkBounds, Padding.Empty, false, cellStyle.Font, String.Empty, this.DataGridView.Enabled, DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment), this.DataGridView.RightToLeft); options.everettButtonCompat = false; ButtonBaseAdapter.LayoutData layout = options.Layout(); if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g, cellStyle.ForeColor, cellStyle.BackColor, this.DataGridView.Enabled).Calculate(); CheckBoxBaseAdapter.DrawCheckBackground(this.DataGridView.Enabled, checkState, g, layout.checkBounds, colors.windowText, colors.options.highContrast ? colors.buttonFace : colors.highlight, true /*disabledColors*/, colors); ButtonBaseAdapter.DrawFlatBorder(g, layout.checkBounds, colors.buttonShadow); CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width, checkState == CheckState.Checked || checkState == CheckState.Indeterminate, this.DataGridView.Enabled, checkState, g, layout, colors, colors.windowText, colors.highlight, true /*disabledColors*/); } resultBounds = layout.checkBounds; } } } } else if (computeErrorIconBounds) { if (!String.IsNullOrEmpty(errorText)) { resultBounds = ComputeErrorIconBounds(errorBounds); } else { resultBounds = Rectangle.Empty; } } else { Debug.Assert(valBounds.Width < checkBoxSize.Width || valBounds.Height < checkBoxSize.Height, "the bounds are empty"); resultBounds = Rectangle.Empty; } if (paint && DataGridViewCell.PaintErrorIcon(paintParts) && drawErrorText && this.DataGridView.ShowCellErrors) { PaintErrorIcon(g, cellStyle, rowIndex, cellBounds, errorBounds, errorText); } return resultBounds; } /// public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter) { Debug.Assert(formattedValue == null || this.FormattedValueType == null || this.FormattedValueType.IsAssignableFrom(formattedValue.GetType())); if (formattedValue != null) { if (formattedValue is bool) { if ((bool) formattedValue) { if (this.TrueValue != null) { return this.TrueValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return true; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Checked; } } else { if (this.FalseValue != null) { return this.FalseValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return false; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Unchecked; } } } else if (formattedValue is CheckState) { switch ((CheckState) formattedValue) { case CheckState.Checked: if (this.TrueValue != null) { return this.TrueValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return true; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Checked; } break; case CheckState.Unchecked: if (this.FalseValue != null) { return this.FalseValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return false; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Unchecked; } break; case CheckState.Indeterminate: if (this.IndeterminateValue != null) { return this.IndeterminateValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Indeterminate; } /* case where this.ValueType.IsAssignableFrom(defaultBooleanType) is treated in base.ParseFormattedValue */ break; } } } return base.ParseFormattedValue(formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter); } [ SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes") // no much choice here. ] private bool SwitchFormattedValue() { if (this.FormattedValueType == null) { return false; } IDataGridViewEditingCell editingCell = (IDataGridViewEditingCell)this; if (this.FormattedValueType.IsAssignableFrom(typeof(System.Windows.Forms.CheckState))) { if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_checked) != 0x00) { editingCell.EditingCellFormattedValue = System.Windows.Forms.CheckState.Indeterminate; } else if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_indeterminate) != 0x00) { editingCell.EditingCellFormattedValue = System.Windows.Forms.CheckState.Unchecked; } else { editingCell.EditingCellFormattedValue = System.Windows.Forms.CheckState.Checked; } } else if (this.FormattedValueType.IsAssignableFrom(defaultBooleanType)) { editingCell.EditingCellFormattedValue = !((bool)editingCell.GetEditingCellFormattedValue(DataGridViewDataErrorContexts.Formatting)); } return true; } /// /// /// public override string ToString() { return "DataGridViewCheckBoxCell { ColumnIndex=" + this.ColumnIndex.ToString(CultureInfo.CurrentCulture) + ", RowIndex=" + this.RowIndex.ToString(CultureInfo.CurrentCulture) + " }"; } private void UpdateButtonState(ButtonState newButtonState, int rowIndex) { this.ButtonState = newButtonState; this.DataGridView.InvalidateCell(this.ColumnIndex, rowIndex); } private class DataGridViewCheckBoxCellRenderer { static VisualStyleRenderer visualStyleRenderer; private DataGridViewCheckBoxCellRenderer() { } public static VisualStyleRenderer CheckBoxRenderer { get { if (visualStyleRenderer == null) { visualStyleRenderer = new VisualStyleRenderer(CheckBoxElement); } return visualStyleRenderer; } } public static void DrawCheckBox(Graphics g, Rectangle bounds, int state) { CheckBoxRenderer.SetParameters(CheckBoxElement.ClassName, CheckBoxElement.Part, (int) state); CheckBoxRenderer.DrawBackground(g, bounds, Rectangle.Truncate(g.ClipBounds)); } } ////// Gets the row Index and column Index of the cell. /// ///protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject { /// public DataGridViewCheckBoxCellAccessibleObject(DataGridViewCell owner) : base (owner) { } /// public override string DefaultAction { get { if (!this.Owner.ReadOnly) { // determine if we switch to Checked/Unchecked value // vsw 533813. bool switchToCheckedState = true; object formattedValue = this.Owner.FormattedValue; if (formattedValue is System.Windows.Forms.CheckState) { switchToCheckedState = ((CheckState) formattedValue) == CheckState.Unchecked; } else if (formattedValue is bool) { switchToCheckedState = !((bool) formattedValue); } if (switchToCheckedState) { return SR.GetString(SR.DataGridView_AccCheckBoxCellDefaultActionCheck); } else { return SR.GetString(SR.DataGridView_AccCheckBoxCellDefaultActionUncheck); } } else { return String.Empty; } } } /// [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public override void DoDefaultAction() { DataGridViewCheckBoxCell dataGridViewCell = (DataGridViewCheckBoxCell) this.Owner; DataGridView dataGridView = dataGridViewCell.DataGridView; if (dataGridView != null && dataGridViewCell.RowIndex == -1) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_InvalidOperationOnSharedCell)); } if (!dataGridViewCell.ReadOnly && dataGridViewCell.OwningColumn != null && dataGridViewCell.OwningRow != null) { dataGridView.CurrentCell = dataGridViewCell; bool endEditMode = false; if (!dataGridView.IsCurrentCellInEditMode) { endEditMode = true; dataGridView.BeginEdit(false /*selectAll*/); } if (dataGridView.IsCurrentCellInEditMode) { if (dataGridViewCell.SwitchFormattedValue()) { dataGridViewCell.NotifyDataGridViewOfValueChange(); dataGridView.InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); // notify MSAA clients that the default action changed int visibleRowIndex = dataGridView.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, dataGridViewCell.RowIndex); int visibleColumnIndex = dataGridView.Columns.ColumnIndexToActualDisplayIndex(dataGridViewCell.ColumnIndex, DataGridViewElementStates.Visible); bool columnHeadersVisible = dataGridView.ColumnHeadersVisible; bool rowHeadersVisible = dataGridView.RowHeadersVisible; int objectID = visibleRowIndex + (columnHeadersVisible ? 1:0) // + 1 because the top header row acc obj is at index 0 + 1; // + 1 because objectID's need to be positive and non-zero int childID = visibleColumnIndex + (rowHeadersVisible ? 1:0); // + 1 because the row header cell is at index 0 in row header row acc obj Control.ControlAccessibleObject controlAccObj = (Control.ControlAccessibleObject)dataGridView.AccessibilityObject; controlAccObj.NotifyClients(AccessibleEvents.DefaultActionChange, objectID, childID); } if (endEditMode) { dataGridView.EndEdit(); } } } } /// public override int GetChildCount() { return 0; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms { using System; using System.Diagnostics; using System.Drawing; using System.ComponentModel; using System.Windows.Forms.VisualStyles; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Windows.Forms.Internal; using System.Windows.Forms.ButtonInternal; using System.Diagnostics.CodeAnalysis; using System.Globalization; ////// /// public class DataGridViewCheckBoxCell : DataGridViewCell, IDataGridViewEditingCell { private static readonly DataGridViewContentAlignment anyLeft = DataGridViewContentAlignment.TopLeft | DataGridViewContentAlignment.MiddleLeft | DataGridViewContentAlignment.BottomLeft; private static readonly DataGridViewContentAlignment anyRight = DataGridViewContentAlignment.TopRight | DataGridViewContentAlignment.MiddleRight | DataGridViewContentAlignment.BottomRight; private static readonly DataGridViewContentAlignment anyCenter = DataGridViewContentAlignment.TopCenter | DataGridViewContentAlignment.MiddleCenter | DataGridViewContentAlignment.BottomCenter; private static readonly DataGridViewContentAlignment anyBottom = DataGridViewContentAlignment.BottomRight | DataGridViewContentAlignment.BottomCenter | DataGridViewContentAlignment.BottomLeft; private static readonly DataGridViewContentAlignment anyMiddle = DataGridViewContentAlignment.MiddleRight | DataGridViewContentAlignment.MiddleCenter | DataGridViewContentAlignment.MiddleLeft; private static readonly VisualStyleElement CheckBoxElement = VisualStyleElement.Button.CheckBox.UncheckedNormal; private static readonly int PropButtonCellState = PropertyStore.CreateKey(); private static readonly int PropTrueValue = PropertyStore.CreateKey(); private static readonly int PropFalseValue = PropertyStore.CreateKey(); private static readonly int PropFlatStyle = PropertyStore.CreateKey(); private static readonly int PropIndeterminateValue = PropertyStore.CreateKey(); private static Bitmap checkImage = null; private const byte DATAGRIDVIEWCHECKBOXCELL_threeState = 0x01; private const byte DATAGRIDVIEWCHECKBOXCELL_valueChanged = 0x02; private const byte DATAGRIDVIEWCHECKBOXCELL_checked = 0x10; private const byte DATAGRIDVIEWCHECKBOXCELL_indeterminate = 0x20; private const byte DATAGRIDVIEWCHECKBOXCELL_margin = 2; // horizontal and vertical margins for preferred sizes private byte flags; // see DATAGRIDVIEWCHECKBOXCELL_ consts above private static bool mouseInContentBounds = false; private static Type defaultCheckStateType = typeof(System.Windows.Forms.CheckState); private static Type defaultBooleanType = typeof(System.Boolean); private static Type cellType = typeof(DataGridViewCheckBoxCell); ///Identifies a checkbox cell in the DataGridView. ///public DataGridViewCheckBoxCell() : this(false /*threeState*/) { } /// public DataGridViewCheckBoxCell(bool threeState) { if (threeState) { this.flags = DATAGRIDVIEWCHECKBOXCELL_threeState; } } /// public virtual object EditingCellFormattedValue { get { return GetEditingCellFormattedValue(DataGridViewDataErrorContexts.Formatting); } set { if (this.FormattedValueType == null) { throw new ArgumentException(SR.GetString(SR.DataGridViewCell_FormattedValueTypeNull)); } if (value == null || !this.FormattedValueType.IsAssignableFrom(value.GetType())) { // Assigned formatted value may not be of the good type, in cases where the app // is feeding wrong values to the cell in virtual / databound mode. throw new ArgumentException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)); } if (value is System.Windows.Forms.CheckState) { if (((System.Windows.Forms.CheckState)value) == System.Windows.Forms.CheckState.Checked) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_checked; this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_indeterminate); } else if (((System.Windows.Forms.CheckState)value) == System.Windows.Forms.CheckState.Indeterminate) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_indeterminate; this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_checked); } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_checked); this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_indeterminate); } } else if (value is System.Boolean) { if ((bool)value) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_checked; } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_checked); } this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_indeterminate); } else { throw new ArgumentException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)); } } } /// public virtual bool EditingCellValueChanged { get { return ((this.flags & DATAGRIDVIEWCHECKBOXCELL_valueChanged) != 0x00); } set { if (value) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_valueChanged; } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_valueChanged); } } } /// public virtual object GetEditingCellFormattedValue(DataGridViewDataErrorContexts context) { if (this.FormattedValueType == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridViewCell_FormattedValueTypeNull)); } if (this.FormattedValueType.IsAssignableFrom(defaultCheckStateType)) { if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_checked) != 0x00) { if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardChecked); } return System.Windows.Forms.CheckState.Checked; } else if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_indeterminate) != 0x00) { if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardIndeterminate); } return System.Windows.Forms.CheckState.Indeterminate; } else { if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardUnchecked); } return System.Windows.Forms.CheckState.Unchecked; } } else if (this.FormattedValueType.IsAssignableFrom(defaultBooleanType)) { bool ret = (bool)((this.flags & DATAGRIDVIEWCHECKBOXCELL_checked) != 0x00); if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { return SR.GetString(ret ? SR.DataGridViewCheckBoxCell_ClipboardTrue : SR.DataGridViewCheckBoxCell_ClipboardFalse); } return ret; } else { return null; } } /// public virtual void PrepareEditingCellForEdit(bool selectAll) { } private ButtonState ButtonState { get { bool found; int buttonState = this.Properties.GetInteger(PropButtonCellState, out found); if (found) { return (ButtonState)buttonState; } return ButtonState.Normal; } set { // ButtonState.Pushed is used for mouse interaction // ButtonState.Checked is used for keyboard interaction Debug.Assert((value & ~(ButtonState.Normal | ButtonState.Pushed | ButtonState.Checked)) == 0); if (this.ButtonState != value) { this.Properties.SetInteger(PropButtonCellState, (int)value); } } } /// public override Type EditType { get { // Check boxes can't switch to edit mode // This cell type must implement the IEditingCell interface return null; } } /// [DefaultValue(null)] public object FalseValue { get { return this.Properties.GetObject(PropFalseValue); } set { if (value != null || this.Properties.ContainsObject(PropFalseValue)) { this.Properties.SetObject(PropFalseValue, value); if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal object FalseValueInternal { set { if (value != null || this.Properties.ContainsObject(PropFalseValue)) { this.Properties.SetObject(PropFalseValue, value); } } } /// [DefaultValue(FlatStyle.Standard)] public FlatStyle FlatStyle { get { bool found; int flatStyle = this.Properties.GetInteger(PropFlatStyle, out found); if (found) { return (FlatStyle)flatStyle; } return FlatStyle.Standard; } set { // Sequential enum. Valid values are 0x0 to 0x3 if (!ClientUtils.IsEnumValid(value, (int)value, (int)FlatStyle.Flat, (int)FlatStyle.System)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(FlatStyle)); } if (value != this.FlatStyle) { this.Properties.SetInteger(PropFlatStyle, (int)value); OnCommonChange(); } } } internal FlatStyle FlatStyleInternal { set { Debug.Assert(value >= FlatStyle.Flat && value <= FlatStyle.System); if (value != this.FlatStyle) { this.Properties.SetInteger(PropFlatStyle, (int)value); } } } /// public override Type FormattedValueType { get { if (this.ThreeState) { return defaultCheckStateType; } else { return defaultBooleanType; } } } /// [DefaultValue(null)] public object IndeterminateValue { get { return this.Properties.GetObject(PropIndeterminateValue); } set { if (value != null || this.Properties.ContainsObject(PropIndeterminateValue)) { this.Properties.SetObject(PropIndeterminateValue, value); if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal object IndeterminateValueInternal { set { if (value != null || this.Properties.ContainsObject(PropIndeterminateValue)) { this.Properties.SetObject(PropIndeterminateValue, value); } } } /// [DefaultValue(false)] public bool ThreeState { get { return ((this.flags & DATAGRIDVIEWCHECKBOXCELL_threeState) != 0x00); } set { if (this.ThreeState != value) { this.ThreeStateInternal = value; if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal bool ThreeStateInternal { set { if (this.ThreeState != value) { if (value) { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_threeState; } else { this.flags = (byte)(this.flags & ~DATAGRIDVIEWCHECKBOXCELL_threeState); } } } } /// [DefaultValue(null)] public object TrueValue { get { return this.Properties.GetObject(PropTrueValue); } set { if (value != null || this.Properties.ContainsObject(PropTrueValue)) { this.Properties.SetObject(PropTrueValue, value); if (this.DataGridView != null) { if (this.RowIndex != -1) { this.DataGridView.InvalidateCell(this); } else { this.DataGridView.InvalidateColumnInternal(this.ColumnIndex); } } } } } internal object TrueValueInternal { set { if (value != null || this.Properties.ContainsObject(PropTrueValue)) { this.Properties.SetObject(PropTrueValue, value); } } } /// public override Type ValueType { get { Type valueType = base.ValueType; if (valueType != null) { return valueType; } if (this.ThreeState) { return defaultCheckStateType; } else { return defaultBooleanType; } } set { base.ValueType = value; this.ThreeState = (value != null && defaultCheckStateType.IsAssignableFrom(value)); } } /// public override object Clone() { DataGridViewCheckBoxCell dataGridViewCell; Type thisType = this.GetType(); if (thisType == cellType) //performance improvement { dataGridViewCell = new DataGridViewCheckBoxCell(); } else { // SECREVIEW : Late-binding does not represent a security thread, see bug#411899 for more info.. // dataGridViewCell = (DataGridViewCheckBoxCell)System.Activator.CreateInstance(thisType); } base.CloneInternal(dataGridViewCell); dataGridViewCell.ThreeStateInternal = this.ThreeState; dataGridViewCell.TrueValueInternal = this.TrueValue; dataGridViewCell.FalseValueInternal = this.FalseValue; dataGridViewCell.IndeterminateValueInternal = this.IndeterminateValue; dataGridViewCell.FlatStyleInternal = this.FlatStyle; return dataGridViewCell; } private bool CommonContentClickUnsharesRow(DataGridViewCellEventArgs e) { Point ptCurrentCell = this.DataGridView.CurrentCellAddress; return ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == e.RowIndex && this.DataGridView.IsCurrentCellInEditMode; } /// protected override bool ContentClickUnsharesRow(DataGridViewCellEventArgs e) { return CommonContentClickUnsharesRow(e); } /// protected override bool ContentDoubleClickUnsharesRow(DataGridViewCellEventArgs e) { return CommonContentClickUnsharesRow(e); } /// protected override AccessibleObject CreateAccessibilityInstance() { return new DataGridViewCheckBoxCellAccessibleObject(this); } /// protected override Rectangle GetContentBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex) { if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } if (this.DataGridView == null || rowIndex < 0 || this.OwningColumn == null) { return Rectangle.Empty; } DataGridViewAdvancedBorderStyle dgvabsEffective; DataGridViewElementStates cellState; Rectangle cellBounds; ComputeBorderStyleCellStateAndCellBounds(rowIndex, out dgvabsEffective, out cellState, out cellBounds); Rectangle checkBoxBounds = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, null /*formattedValue*/, // checkBoxBounds is independent of formattedValue null /*errorText*/, // checkBoxBounds is independent of errorText cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, true /*computeContentBounds*/, false /*computeErrorIconBounds*/, false /*paint*/); #if DEBUG object value = GetValue(rowIndex); Rectangle checkBoxBoundsDebug = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, GetEditedFormattedValue(value, rowIndex, ref cellStyle, DataGridViewDataErrorContexts.Formatting), GetErrorText(rowIndex), cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, true /*computeContentBounds*/, false /*computeErrorIconBounds*/, false /*paint*/); Debug.Assert(checkBoxBoundsDebug.Equals(checkBoxBounds)); #endif return checkBoxBounds; } /// protected override Rectangle GetErrorIconBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex) { if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } if (this.DataGridView == null || rowIndex < 0 || this.OwningColumn == null || !this.DataGridView.ShowCellErrors || String.IsNullOrEmpty(GetErrorText(rowIndex))) { return Rectangle.Empty; } Point ptCurrentCell = this.DataGridView.CurrentCellAddress; if (ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == rowIndex && this.DataGridView.IsCurrentCellInEditMode) { // PaintPrivate does not paint the error icon if this is the current cell. // So don't set the ErrorIconBounds either. return Rectangle.Empty; } DataGridViewAdvancedBorderStyle dgvabsEffective; DataGridViewElementStates cellState; Rectangle cellBounds; ComputeBorderStyleCellStateAndCellBounds(rowIndex, out dgvabsEffective, out cellState, out cellBounds); Rectangle errorIconBounds = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, null /*formattedValue*/, // errorIconBounds is independent of formattedValue GetErrorText(rowIndex), cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, false /*computeContentBounds*/, true /*computeErrorIconBound*/, false /*paint*/); #if DEBUG object value = GetValue(rowIndex); Rectangle errorIconBoundsDebug = PaintPrivate(graphics, cellBounds, cellBounds, rowIndex, cellState, GetEditedFormattedValue(value, rowIndex, ref cellStyle, DataGridViewDataErrorContexts.Formatting), GetErrorText(rowIndex), cellStyle, dgvabsEffective, DataGridViewPaintParts.ContentForeground, false /*computeContentBounds*/, true /*computeErrorIconBound*/, false /*paint*/); Debug.Assert(errorIconBoundsDebug.Equals(errorIconBounds)); #endif return errorIconBounds; } /// protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) { if (value != null) { if (this.ThreeState) { if (value.Equals(this.TrueValue) || (value is int && (int)value == (int)CheckState.Checked)) { value = CheckState.Checked; } else if (value.Equals(this.FalseValue) || (value is int && (int)value == (int)CheckState.Unchecked)) { value = CheckState.Unchecked; } else if (value.Equals(this.IndeterminateValue) || (value is int && (int)value == (int)CheckState.Indeterminate)) { value = CheckState.Indeterminate; } /* Commenting out because of bug VSWhidbey 300778 else if (this.DataGridView != null && this.FormattedValueType != null && !(value is System.DBNull) && !this.FormattedValueType.IsAssignableFrom(value.GetType())) { DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs( new FormatException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)), this.ColumnIndex, rowIndex, context); RaiseDataError(dgvdee); if (dgvdee.ThrowException) { throw dgvdee.Exception; } } */ } else { if (value.Equals(this.TrueValue) || (value is int && (int)value != 0)) { value = true; } else if (value.Equals(this.FalseValue) || (value is int && (int)value == 0)) { value = false; } /* Commenting out because of bug VSWhidbey 300778 else if (this.DataGridView != null && this.FormattedValueType != null && !(value is System.DBNull) && !this.FormattedValueType.IsAssignableFrom(value.GetType())) { DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs( new FormatException(SR.GetString(SR.DataGridViewCheckBoxCell_InvalidValueType)), this.ColumnIndex, rowIndex, context); RaiseDataError(dgvdee); if (dgvdee.ThrowException) { throw dgvdee.Exception; } } */ } } object ret = base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context); if (ret != null && (context & DataGridViewDataErrorContexts.ClipboardContent) != 0) { if (ret is bool) { bool retBool = (bool) ret; if (retBool) { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardChecked : SR.DataGridViewCheckBoxCell_ClipboardTrue); } else { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardUnchecked : SR.DataGridViewCheckBoxCell_ClipboardFalse); } } else if (ret is CheckState) { CheckState retCheckState = (CheckState) ret; if (retCheckState == CheckState.Checked) { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardChecked : SR.DataGridViewCheckBoxCell_ClipboardTrue); } else if (retCheckState == CheckState.Unchecked) { return SR.GetString(this.ThreeState ? SR.DataGridViewCheckBoxCell_ClipboardUnchecked : SR.DataGridViewCheckBoxCell_ClipboardFalse); } else { Debug.Assert(retCheckState == CheckState.Indeterminate); return SR.GetString(SR.DataGridViewCheckBoxCell_ClipboardIndeterminate); } } } return ret; } /// protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize) { if (this.DataGridView == null) { return new Size(-1, -1); } if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } DataGridViewFreeDimension freeDimension = DataGridViewCell.GetFreeDimensionFromConstraint(constraintSize); Rectangle borderWidthsRect = this.StdBorderWidths; int borderAndPaddingWidths = borderWidthsRect.Left + borderWidthsRect.Width + cellStyle.Padding.Horizontal; int borderAndPaddingHeights = borderWidthsRect.Top + borderWidthsRect.Height + cellStyle.Padding.Vertical; Size preferredSize; if (this.DataGridView.ApplyVisualStylesToInnerCells) { // Assuming here that all checkbox states use the same size. We should take the largest of the state specific sizes. Size checkBoxSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal); switch (this.FlatStyle) { case FlatStyle.Standard: case FlatStyle.System: break; case FlatStyle.Flat: checkBoxSize.Width -= 3; checkBoxSize.Height -= 3; break; case FlatStyle.Popup: checkBoxSize.Width -= 2; checkBoxSize.Height -= 2; break; } switch (freeDimension) { case DataGridViewFreeDimension.Width: { preferredSize = new Size(checkBoxSize.Width + borderAndPaddingWidths + 2 * DATAGRIDVIEWCHECKBOXCELL_margin, 0); break; } case DataGridViewFreeDimension.Height: { preferredSize = new Size(0, checkBoxSize.Height + borderAndPaddingHeights + 2 * DATAGRIDVIEWCHECKBOXCELL_margin); break; } default: { preferredSize = new Size(checkBoxSize.Width + borderAndPaddingWidths + 2 * DATAGRIDVIEWCHECKBOXCELL_margin, checkBoxSize.Height + borderAndPaddingHeights + 2 * DATAGRIDVIEWCHECKBOXCELL_margin); break; } } } else { int checkBoxSize; switch (this.FlatStyle) { case FlatStyle.Flat: checkBoxSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal).Width - 3; break; case FlatStyle.Popup: checkBoxSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal).Width - 2; break; default: // FlatStyle.Standard || FlatStyle.System checkBoxSize = SystemInformation.Border3DSize.Width * 2 + 9 + 2 * DATAGRIDVIEWCHECKBOXCELL_margin; break; } switch (freeDimension) { case DataGridViewFreeDimension.Width: { preferredSize = new Size(checkBoxSize + borderAndPaddingWidths, 0); break; } case DataGridViewFreeDimension.Height: { preferredSize = new Size(0, checkBoxSize + borderAndPaddingHeights); break; } default: { preferredSize = new Size(checkBoxSize + borderAndPaddingWidths, checkBoxSize + borderAndPaddingHeights); break; } } } if (this.DataGridView.ShowCellErrors) { // Making sure that there is enough room for the potential error icon if (freeDimension != DataGridViewFreeDimension.Height) { preferredSize.Width = Math.Max(preferredSize.Width, borderAndPaddingWidths + DATAGRIDVIEWCELL_iconMarginWidth * 2 + DATAGRIDVIEWCELL_iconsWidth); } if (freeDimension != DataGridViewFreeDimension.Width) { preferredSize.Height = Math.Max(preferredSize.Height, borderAndPaddingHeights + DATAGRIDVIEWCELL_iconMarginHeight * 2 + DATAGRIDVIEWCELL_iconsHeight); } } return preferredSize; } /// protected override bool KeyDownUnsharesRow(KeyEventArgs e, int rowIndex) { return e.KeyCode == Keys.Space && !e.Alt && !e.Control && !e.Shift; } /// protected override bool KeyUpUnsharesRow(KeyEventArgs e, int rowIndex) { return e.KeyCode == Keys.Space; } /// protected override bool MouseDownUnsharesRow(DataGridViewCellMouseEventArgs e) { return e.Button == MouseButtons.Left; } /// protected override bool MouseEnterUnsharesRow(int rowIndex) { return this.ColumnIndex == this.DataGridView.MouseDownCellAddress.X && rowIndex == this.DataGridView.MouseDownCellAddress.Y; } /// protected override bool MouseLeaveUnsharesRow(int rowIndex) { return (this.ButtonState & ButtonState.Pushed) != 0; } /// protected override bool MouseUpUnsharesRow(DataGridViewCellMouseEventArgs e) { return e.Button == MouseButtons.Left; } private void NotifyDataGridViewOfValueChange() { this.flags |= (byte)DATAGRIDVIEWCHECKBOXCELL_valueChanged; this.DataGridView.NotifyCurrentCellDirty(true); } private void OnCommonContentClick(DataGridViewCellEventArgs e) { if (this.DataGridView == null) { return; } Point ptCurrentCell = this.DataGridView.CurrentCellAddress; if (ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == e.RowIndex && this.DataGridView.IsCurrentCellInEditMode) { if (SwitchFormattedValue()) { NotifyDataGridViewOfValueChange(); } } } /// protected override void OnContentClick(DataGridViewCellEventArgs e) { OnCommonContentClick(e); } /// protected override void OnContentDoubleClick(DataGridViewCellEventArgs e) { OnCommonContentClick(e); } /// protected override void OnKeyDown(KeyEventArgs e, int rowIndex) { if (this.DataGridView == null) { return; } if (e.KeyCode == Keys.Space && !e.Alt && !e.Control && !e.Shift) { UpdateButtonState(this.ButtonState | ButtonState.Checked, rowIndex); e.Handled = true; } } /// protected override void OnKeyUp(KeyEventArgs e, int rowIndex) { if (this.DataGridView == null) { return; } if (e.KeyCode == Keys.Space) { UpdateButtonState(this.ButtonState & ~ButtonState.Checked, rowIndex); if (!e.Alt && !e.Control && !e.Shift) { RaiseCellClick(new DataGridViewCellEventArgs(this.ColumnIndex, rowIndex)); if (this.DataGridView != null && this.ColumnIndex < this.DataGridView.Columns.Count && rowIndex < this.DataGridView.Rows.Count) { RaiseCellContentClick(new DataGridViewCellEventArgs(this.ColumnIndex, rowIndex)); } e.Handled = true; } } } /// protected override void OnLeave(int rowIndex, bool throughMouseClick) { if (this.DataGridView == null) { return; } if (this.ButtonState != ButtonState.Normal) { Debug.Assert(this.RowIndex >= 0); // Cell is not in a shared row. UpdateButtonState(ButtonState.Normal, rowIndex); } } /// protected override void OnMouseDown(DataGridViewCellMouseEventArgs e) { if (this.DataGridView == null) { return; } if (e.Button == MouseButtons.Left && mouseInContentBounds) { Debug.Assert(this.DataGridView.CellMouseDownInContentBounds); UpdateButtonState(this.ButtonState | ButtonState.Pushed, e.RowIndex); } } /// protected override void OnMouseLeave(int rowIndex) { if (this.DataGridView == null) { return; } if (mouseInContentBounds) { mouseInContentBounds = false; if (this.ColumnIndex >= 0 && rowIndex >= 0 && (this.DataGridView.ApplyVisualStylesToInnerCells || this.FlatStyle == FlatStyle.Flat || this.FlatStyle == FlatStyle.Popup)) { this.DataGridView.InvalidateCell(this.ColumnIndex, rowIndex); } } if ((this.ButtonState & ButtonState.Pushed) != 0 && this.ColumnIndex == this.DataGridView.MouseDownCellAddress.X && rowIndex == this.DataGridView.MouseDownCellAddress.Y) { UpdateButtonState(this.ButtonState & ~ButtonState.Pushed, rowIndex); } } /// protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { if (this.DataGridView == null) { return; } bool oldMouseInContentBounds = mouseInContentBounds; mouseInContentBounds = GetContentBounds(e.RowIndex).Contains(e.X, e.Y); if (oldMouseInContentBounds != mouseInContentBounds) { if (this.DataGridView.ApplyVisualStylesToInnerCells || this.FlatStyle == FlatStyle.Flat || this.FlatStyle == FlatStyle.Popup) { this.DataGridView.InvalidateCell(this.ColumnIndex, e.RowIndex); } if (e.ColumnIndex == this.DataGridView.MouseDownCellAddress.X && e.RowIndex == this.DataGridView.MouseDownCellAddress.Y && Control.MouseButtons == MouseButtons.Left) { if ((this.ButtonState & ButtonState.Pushed) == 0 && mouseInContentBounds && this.DataGridView.CellMouseDownInContentBounds) { UpdateButtonState(this.ButtonState | ButtonState.Pushed, e.RowIndex); } else if ((this.ButtonState & ButtonState.Pushed) != 0 && !mouseInContentBounds) { UpdateButtonState(this.ButtonState & ~ButtonState.Pushed, e.RowIndex); } } } base.OnMouseMove(e); } /// protected override void OnMouseUp(DataGridViewCellMouseEventArgs e) { if (this.DataGridView == null) { return; } if (e.Button == MouseButtons.Left) { UpdateButtonState(this.ButtonState & ~ButtonState.Pushed, e.RowIndex); } } /// protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { if (cellStyle == null) { throw new ArgumentNullException("cellStyle"); } PaintPrivate(graphics, clipBounds, cellBounds, rowIndex, elementState, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts, false /*computeContentBounds*/, false /*computeErrorIconBounds*/, true /*paint*/); } // PaintPrivate is used in three places that need to duplicate the paint code: // 1. DataGridViewCell::Paint method // 2. DataGridViewCell::GetContentBounds // 3. DataGridViewCell::GetErrorIconBounds // // if computeContentBounds is true then PaintPrivate returns the contentBounds // else if computeErrorIconBounds is true then PaintPrivate returns the errorIconBounds // else it returns Rectangle.Empty; private Rectangle PaintPrivate(Graphics g, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts, bool computeContentBounds, bool computeErrorIconBounds, bool paint) { // Parameter checking. // One bit and one bit only should be turned on Debug.Assert(paint || computeContentBounds || computeErrorIconBounds); Debug.Assert(!paint || !computeContentBounds || !computeErrorIconBounds); Debug.Assert(!computeContentBounds || !computeErrorIconBounds || !paint); Debug.Assert(!computeErrorIconBounds || !paint || !computeContentBounds); Debug.Assert(cellStyle != null); Rectangle resultBounds; if (paint && DataGridViewCell.PaintBorder(paintParts)) { PaintBorder(g, clipBounds, cellBounds, cellStyle, advancedBorderStyle); } Rectangle valBounds = cellBounds; Rectangle borderWidths = BorderWidths(advancedBorderStyle); valBounds.Offset(borderWidths.X, borderWidths.Y); valBounds.Width -= borderWidths.Right; valBounds.Height -= borderWidths.Bottom; bool cellSelected = (elementState & DataGridViewElementStates.Selected) != 0; bool drawAsMixedCheckBox = false, drawErrorText = true; CheckState checkState; ButtonState bs; Point ptCurrentCell = this.DataGridView.CurrentCellAddress; if (ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == rowIndex && this.DataGridView.IsCurrentCellInEditMode) { drawErrorText = false; } if (formattedValue != null && formattedValue is CheckState) { checkState = (CheckState)formattedValue; bs = (checkState == CheckState.Unchecked) ? ButtonState.Normal : ButtonState.Checked; drawAsMixedCheckBox = (checkState == CheckState.Indeterminate); } else if (formattedValue != null && formattedValue is bool) { if ((bool)formattedValue) { checkState = CheckState.Checked; bs = ButtonState.Checked; } else { checkState = CheckState.Unchecked; bs = ButtonState.Normal; } } else { // The provided formatted value has a wrong type. We raised a DataError event while formatting. bs = ButtonState.Normal; // Default rendering of the checkbox with wrong formatted value type. checkState = CheckState.Unchecked; } if ((this.ButtonState & (ButtonState.Pushed | ButtonState.Checked)) != 0) { bs |= ButtonState.Pushed; } SolidBrush br = this.DataGridView.GetCachedBrush((DataGridViewCell.PaintSelectionBackground(paintParts) && cellSelected) ? cellStyle.SelectionBackColor : cellStyle.BackColor); if (paint && DataGridViewCell.PaintBackground(paintParts) && br.Color.A == 255) { g.FillRectangle(br, valBounds); } if (cellStyle.Padding != Padding.Empty) { if (this.DataGridView.RightToLeftInternal) { valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top); } else { valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top); } valBounds.Width -= cellStyle.Padding.Horizontal; valBounds.Height -= cellStyle.Padding.Vertical; } if (paint && DataGridViewCell.PaintFocus(paintParts) && this.DataGridView.ShowFocusCues && this.DataGridView.Focused && ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == rowIndex) { // Draw focus rectangle ControlPaint.DrawFocusRectangle(g, valBounds, Color.Empty, br.Color); } Rectangle errorBounds = valBounds; valBounds.Inflate(-DATAGRIDVIEWCHECKBOXCELL_margin, -DATAGRIDVIEWCHECKBOXCELL_margin); Size checkBoxSize; CheckBoxState themeCheckBoxState = CheckBoxState.UncheckedNormal; if (this.DataGridView.ApplyVisualStylesToInnerCells) { themeCheckBoxState = CheckBoxRenderer.ConvertFromButtonState(bs, drawAsMixedCheckBox, this.DataGridView.MouseEnteredCellAddress.Y == rowIndex && this.DataGridView.MouseEnteredCellAddress.X == this.ColumnIndex && mouseInContentBounds); checkBoxSize = CheckBoxRenderer.GetGlyphSize(g, themeCheckBoxState); switch (this.FlatStyle) { case FlatStyle.Standard: case FlatStyle.System: break; case FlatStyle.Flat: checkBoxSize.Width -= 3; checkBoxSize.Height -= 3; break; case FlatStyle.Popup: checkBoxSize.Width -= 2; checkBoxSize.Height -= 2; break; } } else { switch (this.FlatStyle) { case FlatStyle.Flat: checkBoxSize = CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.UncheckedNormal); checkBoxSize.Width -= 3; checkBoxSize.Height -= 3; break; case FlatStyle.Popup: checkBoxSize = CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.UncheckedNormal); checkBoxSize.Width -= 2; checkBoxSize.Height -= 2; break; default: // FlatStyle.Standard || FlatStyle.System checkBoxSize = new Size(SystemInformation.Border3DSize.Width * 2 + 9, SystemInformation.Border3DSize.Width * 2 + 9); break; } } if (valBounds.Width >= checkBoxSize.Width && valBounds.Height >= checkBoxSize.Height && (paint || computeContentBounds)) { int checkBoxX = 0, checkBoxY = 0; if ((!this.DataGridView.RightToLeftInternal && (cellStyle.Alignment & anyRight) != 0) || (this.DataGridView.RightToLeftInternal && (cellStyle.Alignment & anyLeft) != 0)) { checkBoxX = valBounds.Right - checkBoxSize.Width; } else if ((cellStyle.Alignment & anyCenter) != 0) { checkBoxX = valBounds.Left + (valBounds.Width - checkBoxSize.Width) / 2; } else { checkBoxX = valBounds.Left; } if ((cellStyle.Alignment & anyBottom) != 0) { checkBoxY = valBounds.Bottom - checkBoxSize.Height; } else if ((cellStyle.Alignment & anyMiddle) != 0) { checkBoxY = valBounds.Top + (valBounds.Height - checkBoxSize.Height) / 2; } else { checkBoxY = valBounds.Top; } if (this.DataGridView.ApplyVisualStylesToInnerCells && this.FlatStyle != FlatStyle.Flat && this.FlatStyle != FlatStyle.Popup) { if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { DataGridViewCheckBoxCellRenderer.DrawCheckBox(g, new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height), (int) themeCheckBoxState); } resultBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height); } else { if (this.FlatStyle == FlatStyle.System || this.FlatStyle == FlatStyle.Standard) { if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { if (drawAsMixedCheckBox) { ControlPaint.DrawMixedCheckBox(g, checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height, bs); } else { ControlPaint.DrawCheckBox(g, checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height, bs); } } resultBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height); } else if (this.FlatStyle == FlatStyle.Flat) { // CheckBox::Paint will only paint the check box differently when in FlatStyle.Flat // this code is copied from CheckBox::DrawCheckFlat. it was a lot of trouble making this function static Rectangle checkBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width, checkBoxSize.Height); SolidBrush foreBrush = null; SolidBrush backBrush = null; Color highlight = Color.Empty; if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { foreBrush = this.DataGridView.GetCachedBrush(cellSelected ? cellStyle.SelectionForeColor : cellStyle.ForeColor); backBrush = this.DataGridView.GetCachedBrush((DataGridViewCell.PaintSelectionBackground(paintParts) && cellSelected) ? cellStyle.SelectionBackColor : cellStyle.BackColor); highlight = ControlPaint.LightLight(backBrush.Color); if (this.DataGridView.MouseEnteredCellAddress.Y == rowIndex && this.DataGridView.MouseEnteredCellAddress.X == this.ColumnIndex && mouseInContentBounds) { const float lowlight = .1f; float adjust = 1 - lowlight; if (highlight.GetBrightness() < .5) { adjust = 1 + lowlight * 2; } highlight = Color.FromArgb(ButtonInternal.ButtonBaseAdapter.ColorOptions.Adjust255(adjust, highlight.R), ButtonInternal.ButtonBaseAdapter.ColorOptions.Adjust255(adjust, highlight.G), ButtonInternal.ButtonBaseAdapter.ColorOptions.Adjust255(adjust, highlight.B)); } highlight = g.GetNearestColor(highlight); using (Pen pen = new Pen(foreBrush.Color)) { g.DrawLine(pen, checkBounds.Left, checkBounds.Top, checkBounds.Right-1, checkBounds.Top); g.DrawLine(pen, checkBounds.Left, checkBounds.Top, checkBounds.Left, checkBounds.Bottom-1); } } checkBounds.Inflate(-1, -1); checkBounds.Width++; checkBounds.Height++; if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { if (checkState == CheckState.Indeterminate) { ButtonInternal.ButtonBaseAdapter.DrawDitheredFill(g, backBrush.Color, highlight, checkBounds); } else { using (SolidBrush highBrush = new SolidBrush(highlight)) { g.FillRectangle(highBrush, checkBounds); } } // draw the check box if (checkState != CheckState.Unchecked) { Rectangle fullSize = new Rectangle(checkBoxX-1, checkBoxY-1, checkBoxSize.Width+3, checkBoxSize.Height+3); fullSize.Width++; fullSize.Height++; if (checkImage == null || checkImage.Width != fullSize.Width || checkImage.Height != fullSize.Height) { if (checkImage != null) { checkImage.Dispose(); checkImage = null; } // We draw the checkmark slightly off center to eliminate 3-D border artifacts, // and compensate below NativeMethods.RECT rcCheck = NativeMethods.RECT.FromXYWH(0, 0, fullSize.Width, fullSize.Height); Bitmap bitmap = new Bitmap(fullSize.Width, fullSize.Height); using (Graphics offscreen = Graphics.FromImage(bitmap)) { offscreen.Clear(Color.Transparent); IntPtr dc = offscreen.GetHdc(); try { SafeNativeMethods.DrawFrameControl(new HandleRef(offscreen, dc), ref rcCheck, NativeMethods.DFC_MENU, NativeMethods.DFCS_MENUCHECK); } finally { offscreen.ReleaseHdcInternal(dc); } } bitmap.MakeTransparent(); checkImage = bitmap; } fullSize.Y--; ControlPaint.DrawImageColorized(g, checkImage, fullSize, checkState == CheckState.Indeterminate ? ControlPaint.LightLight(foreBrush.Color) : foreBrush.Color); } } resultBounds = checkBounds; } else { Debug.Assert(this.FlatStyle == FlatStyle.Popup); Rectangle checkBounds = new Rectangle(checkBoxX, checkBoxY, checkBoxSize.Width - 1, checkBoxSize.Height - 1); // The CheckBoxAdapter code moves the check box down about 3 pixels so we have to take that into account checkBounds.Y -= 3; if ((this.ButtonState & (ButtonState.Pushed | ButtonState.Checked)) != 0) { // paint down ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g, true /*show3D*/, checkBoxSize.Width, checkBounds, Padding.Empty, false, cellStyle.Font, String.Empty, this.DataGridView.Enabled, DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment), this.DataGridView.RightToLeft); options.everettButtonCompat = false; ButtonBaseAdapter.LayoutData layout = options.Layout(); if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g, cellStyle.ForeColor, cellStyle.BackColor, this.DataGridView.Enabled).Calculate(); CheckBoxBaseAdapter.DrawCheckBackground(this.DataGridView.Enabled, checkState, g, layout.checkBounds, colors.windowText, colors.buttonFace, true /*disabledColors*/, colors); CheckBoxBaseAdapter.DrawPopupBorder(g, layout.checkBounds, colors); CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width, checkState == CheckState.Checked || checkState == CheckState.Indeterminate, this.DataGridView.Enabled, checkState, g, layout, colors, colors.windowText, colors.buttonFace, true /*disabledColors*/); } resultBounds = layout.checkBounds; } else if (this.DataGridView.MouseEnteredCellAddress.Y == rowIndex && this.DataGridView.MouseEnteredCellAddress.X == this.ColumnIndex && mouseInContentBounds) { // paint over ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g, true /*show3D*/, checkBoxSize.Width, checkBounds, Padding.Empty, false, cellStyle.Font, String.Empty, this.DataGridView.Enabled, DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment), this.DataGridView.RightToLeft); options.everettButtonCompat = false; ButtonBaseAdapter.LayoutData layout = options.Layout(); if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g, cellStyle.ForeColor, cellStyle.BackColor, this.DataGridView.Enabled).Calculate(); CheckBoxBaseAdapter.DrawCheckBackground(this.DataGridView.Enabled, checkState, g, layout.checkBounds, colors.windowText, colors.options.highContrast ? colors.buttonFace : colors.highlight, true /*disabledColors*/, colors); CheckBoxBaseAdapter.DrawPopupBorder(g, layout.checkBounds, colors); CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width, checkState == CheckState.Checked || checkState == CheckState.Indeterminate, this.DataGridView.Enabled, checkState, g, layout, colors, colors.windowText, colors.highlight, true /*disabledColors*/); } resultBounds = layout.checkBounds; } else { // paint up ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g, false /*show3D*/, checkBoxSize.Width, checkBounds, Padding.Empty, false, cellStyle.Font, String.Empty, this.DataGridView.Enabled, DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment), this.DataGridView.RightToLeft); options.everettButtonCompat = false; ButtonBaseAdapter.LayoutData layout = options.Layout(); if (paint && DataGridViewCell.PaintContentForeground(paintParts)) { ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g, cellStyle.ForeColor, cellStyle.BackColor, this.DataGridView.Enabled).Calculate(); CheckBoxBaseAdapter.DrawCheckBackground(this.DataGridView.Enabled, checkState, g, layout.checkBounds, colors.windowText, colors.options.highContrast ? colors.buttonFace : colors.highlight, true /*disabledColors*/, colors); ButtonBaseAdapter.DrawFlatBorder(g, layout.checkBounds, colors.buttonShadow); CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width, checkState == CheckState.Checked || checkState == CheckState.Indeterminate, this.DataGridView.Enabled, checkState, g, layout, colors, colors.windowText, colors.highlight, true /*disabledColors*/); } resultBounds = layout.checkBounds; } } } } else if (computeErrorIconBounds) { if (!String.IsNullOrEmpty(errorText)) { resultBounds = ComputeErrorIconBounds(errorBounds); } else { resultBounds = Rectangle.Empty; } } else { Debug.Assert(valBounds.Width < checkBoxSize.Width || valBounds.Height < checkBoxSize.Height, "the bounds are empty"); resultBounds = Rectangle.Empty; } if (paint && DataGridViewCell.PaintErrorIcon(paintParts) && drawErrorText && this.DataGridView.ShowCellErrors) { PaintErrorIcon(g, cellStyle, rowIndex, cellBounds, errorBounds, errorText); } return resultBounds; } /// public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter) { Debug.Assert(formattedValue == null || this.FormattedValueType == null || this.FormattedValueType.IsAssignableFrom(formattedValue.GetType())); if (formattedValue != null) { if (formattedValue is bool) { if ((bool) formattedValue) { if (this.TrueValue != null) { return this.TrueValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return true; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Checked; } } else { if (this.FalseValue != null) { return this.FalseValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return false; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Unchecked; } } } else if (formattedValue is CheckState) { switch ((CheckState) formattedValue) { case CheckState.Checked: if (this.TrueValue != null) { return this.TrueValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return true; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Checked; } break; case CheckState.Unchecked: if (this.FalseValue != null) { return this.FalseValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultBooleanType)) { return false; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Unchecked; } break; case CheckState.Indeterminate: if (this.IndeterminateValue != null) { return this.IndeterminateValue; } else if (this.ValueType != null && this.ValueType.IsAssignableFrom(defaultCheckStateType)) { return CheckState.Indeterminate; } /* case where this.ValueType.IsAssignableFrom(defaultBooleanType) is treated in base.ParseFormattedValue */ break; } } } return base.ParseFormattedValue(formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter); } [ SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes") // no much choice here. ] private bool SwitchFormattedValue() { if (this.FormattedValueType == null) { return false; } IDataGridViewEditingCell editingCell = (IDataGridViewEditingCell)this; if (this.FormattedValueType.IsAssignableFrom(typeof(System.Windows.Forms.CheckState))) { if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_checked) != 0x00) { editingCell.EditingCellFormattedValue = System.Windows.Forms.CheckState.Indeterminate; } else if ((this.flags & DATAGRIDVIEWCHECKBOXCELL_indeterminate) != 0x00) { editingCell.EditingCellFormattedValue = System.Windows.Forms.CheckState.Unchecked; } else { editingCell.EditingCellFormattedValue = System.Windows.Forms.CheckState.Checked; } } else if (this.FormattedValueType.IsAssignableFrom(defaultBooleanType)) { editingCell.EditingCellFormattedValue = !((bool)editingCell.GetEditingCellFormattedValue(DataGridViewDataErrorContexts.Formatting)); } return true; } /// /// /// public override string ToString() { return "DataGridViewCheckBoxCell { ColumnIndex=" + this.ColumnIndex.ToString(CultureInfo.CurrentCulture) + ", RowIndex=" + this.RowIndex.ToString(CultureInfo.CurrentCulture) + " }"; } private void UpdateButtonState(ButtonState newButtonState, int rowIndex) { this.ButtonState = newButtonState; this.DataGridView.InvalidateCell(this.ColumnIndex, rowIndex); } private class DataGridViewCheckBoxCellRenderer { static VisualStyleRenderer visualStyleRenderer; private DataGridViewCheckBoxCellRenderer() { } public static VisualStyleRenderer CheckBoxRenderer { get { if (visualStyleRenderer == null) { visualStyleRenderer = new VisualStyleRenderer(CheckBoxElement); } return visualStyleRenderer; } } public static void DrawCheckBox(Graphics g, Rectangle bounds, int state) { CheckBoxRenderer.SetParameters(CheckBoxElement.ClassName, CheckBoxElement.Part, (int) state); CheckBoxRenderer.DrawBackground(g, bounds, Rectangle.Truncate(g.ClipBounds)); } } ////// Gets the row Index and column Index of the cell. /// ///protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject { /// public DataGridViewCheckBoxCellAccessibleObject(DataGridViewCell owner) : base (owner) { } /// public override string DefaultAction { get { if (!this.Owner.ReadOnly) { // determine if we switch to Checked/Unchecked value // vsw 533813. bool switchToCheckedState = true; object formattedValue = this.Owner.FormattedValue; if (formattedValue is System.Windows.Forms.CheckState) { switchToCheckedState = ((CheckState) formattedValue) == CheckState.Unchecked; } else if (formattedValue is bool) { switchToCheckedState = !((bool) formattedValue); } if (switchToCheckedState) { return SR.GetString(SR.DataGridView_AccCheckBoxCellDefaultActionCheck); } else { return SR.GetString(SR.DataGridView_AccCheckBoxCellDefaultActionUncheck); } } else { return String.Empty; } } } /// [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public override void DoDefaultAction() { DataGridViewCheckBoxCell dataGridViewCell = (DataGridViewCheckBoxCell) this.Owner; DataGridView dataGridView = dataGridViewCell.DataGridView; if (dataGridView != null && dataGridViewCell.RowIndex == -1) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_InvalidOperationOnSharedCell)); } if (!dataGridViewCell.ReadOnly && dataGridViewCell.OwningColumn != null && dataGridViewCell.OwningRow != null) { dataGridView.CurrentCell = dataGridViewCell; bool endEditMode = false; if (!dataGridView.IsCurrentCellInEditMode) { endEditMode = true; dataGridView.BeginEdit(false /*selectAll*/); } if (dataGridView.IsCurrentCellInEditMode) { if (dataGridViewCell.SwitchFormattedValue()) { dataGridViewCell.NotifyDataGridViewOfValueChange(); dataGridView.InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); // notify MSAA clients that the default action changed int visibleRowIndex = dataGridView.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, dataGridViewCell.RowIndex); int visibleColumnIndex = dataGridView.Columns.ColumnIndexToActualDisplayIndex(dataGridViewCell.ColumnIndex, DataGridViewElementStates.Visible); bool columnHeadersVisible = dataGridView.ColumnHeadersVisible; bool rowHeadersVisible = dataGridView.RowHeadersVisible; int objectID = visibleRowIndex + (columnHeadersVisible ? 1:0) // + 1 because the top header row acc obj is at index 0 + 1; // + 1 because objectID's need to be positive and non-zero int childID = visibleColumnIndex + (rowHeadersVisible ? 1:0); // + 1 because the row header cell is at index 0 in row header row acc obj Control.ControlAccessibleObject controlAccObj = (Control.ControlAccessibleObject)dataGridView.AccessibilityObject; controlAccObj.NotifyClients(AccessibleEvents.DefaultActionChange, objectID, childID); } if (endEditMode) { dataGridView.EndEdit(); } } } } /// public override int GetChildCount() { return 0; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ListView.cs
- DetailsViewInsertEventArgs.cs
- IPAddressCollection.cs
- SmiEventStream.cs
- WebScriptEndpoint.cs
- ContextBase.cs
- PathFigureCollection.cs
- UntrustedRecipientException.cs
- SmiConnection.cs
- PropertyInformationCollection.cs
- ListControlConvertEventArgs.cs
- DoubleCollectionValueSerializer.cs
- EastAsianLunisolarCalendar.cs
- MexTcpBindingCollectionElement.cs
- XmlTextReader.cs
- OdbcErrorCollection.cs
- securitymgrsite.cs
- Part.cs
- IndexOutOfRangeException.cs
- HtmlLink.cs
- MenuRendererClassic.cs
- RegisteredDisposeScript.cs
- ProfileEventArgs.cs
- BamlWriter.cs
- SqlCacheDependency.cs
- PrintingPermission.cs
- QuerySettings.cs
- Clause.cs
- SmiMetaData.cs
- ContextStaticAttribute.cs
- TableLayoutPanelCellPosition.cs
- SID.cs
- ISFClipboardData.cs
- EncoderBestFitFallback.cs
- PlainXmlDeserializer.cs
- BitmapMetadataBlob.cs
- BaseConfigurationRecord.cs
- TableCellAutomationPeer.cs
- SqlInternalConnectionSmi.cs
- UnicodeEncoding.cs
- XmlTextWriter.cs
- ContractType.cs
- ColumnCollection.cs
- EnumValAlphaComparer.cs
- SHA512.cs
- FontWeights.cs
- CodeDirectiveCollection.cs
- ResourceAttributes.cs
- RelatedView.cs
- Base64Stream.cs
- _TimerThread.cs
- BorderGapMaskConverter.cs
- XmlLoader.cs
- PageCache.cs
- SynchronizationFilter.cs
- NamedElement.cs
- CurrentTimeZone.cs
- UdpDiscoveryEndpointElement.cs
- ReadOnlyDictionary.cs
- TextBoxAutoCompleteSourceConverter.cs
- GridToolTip.cs
- ManualResetEvent.cs
- AdornerLayer.cs
- StringConverter.cs
- TreeNodeCollection.cs
- DecimalAnimationUsingKeyFrames.cs
- Bits.cs
- ParameterCollection.cs
- XdrBuilder.cs
- DrawListViewSubItemEventArgs.cs
- IsolatedStorageFile.cs
- GridViewDeletedEventArgs.cs
- QueryOutputWriter.cs
- ObjectConverter.cs
- DefaultIfEmptyQueryOperator.cs
- ThreadExceptionEvent.cs
- FontDifferentiator.cs
- TextTrailingWordEllipsis.cs
- QueryReaderSettings.cs
- AppSettingsExpressionBuilder.cs
- WebResourceAttribute.cs
- ConnectionStringsExpressionEditor.cs
- _FtpDataStream.cs
- TemplateBamlRecordReader.cs
- InstanceLockedException.cs
- CompilerError.cs
- XslCompiledTransform.cs
- JsonMessageEncoderFactory.cs
- BindableTemplateBuilder.cs
- Emitter.cs
- documentsequencetextcontainer.cs
- TextEditorCopyPaste.cs
- MessageBodyMemberAttribute.cs
- CompositeFontParser.cs
- DataGridViewRowHeaderCell.cs
- EntityProviderServices.cs
- DataService.cs
- EnumMemberAttribute.cs
- WebPartsSection.cs
- CustomWebEventKey.cs