|
//------------------------------------------------------------------------------
// <copyright file="DataGridViewCheckBoxCell.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
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;
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell"]/*' />
/// <devdoc>
/// <para>Identifies a checkbox cell in the DataGridView.</para>
/// </devdoc>
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);
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.DataGridViewCheckBoxCell"]/*' />
public DataGridViewCheckBoxCell() : this(false /*threeState*/)
{
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.DataGridViewCheckBoxCell2"]/*' />
public DataGridViewCheckBoxCell(bool threeState)
{
if (threeState)
{
this.flags = DATAGRIDVIEWCHECKBOXCELL_threeState;
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.IDataGridViewEditingCell.EditingCellFormattedValue"]/*' />
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));
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.IDataGridViewEditingCell.EditingCellValueChanged"]/*' />
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);
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.IDataGridViewEditingCell.GetEditingCellFormattedValue"]/*' />
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;
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.IDataGridViewEditingCell.PrepareEditingCellForEdit"]/*' />
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);
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.EditType"]/*' />
public override Type EditType
{
get
{
// Check boxes can't switch to edit mode
// This cell type must implement the IEditingCell interface
return null;
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.FalseValue"]/*' />
[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);
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.FlatStyle"]/*' />
[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);
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.FormattedValueType"]/*' />
public override Type FormattedValueType
{
get
{
if (this.ThreeState)
{
return defaultCheckStateType;
}
else
{
return defaultBooleanType;
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.IndeterminateValue"]/*' />
[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);
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.ThreeState"]/*' />
[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);
}
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.TrueValue"]/*' />
[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);
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.ValueType"]/*' />
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));
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.Clone"]/*' />
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;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.ContentClickUnsharesRow"]/*' />
protected override bool ContentClickUnsharesRow(DataGridViewCellEventArgs e)
{
return CommonContentClickUnsharesRow(e);
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.ContentDoubleClickUnsharesRow"]/*' />
protected override bool ContentDoubleClickUnsharesRow(DataGridViewCellEventArgs e)
{
return CommonContentClickUnsharesRow(e);
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.CreateAccessibilityInstance"]/*' />
protected override AccessibleObject CreateAccessibilityInstance()
{
return new DataGridViewCheckBoxCellAccessibleObject(this);
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.GetContentBounds"]/*' />
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;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.GetErrorIconBounds"]/*' />
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*/);
return errorIconBounds;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.GetFormattedValue"]/*' />
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;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.GetPreferredSize"]/*' />
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;
}
}
}
// We should consider the border size when calculating the preferred size.
DataGridViewAdvancedBorderStyle dgvabsEffective;
DataGridViewElementStates cellState;
Rectangle cellBounds;
ComputeBorderStyleCellStateAndCellBounds(rowIndex, out dgvabsEffective, out cellState, out cellBounds);
Rectangle borderWidths = BorderWidths(dgvabsEffective);
preferredSize.Width += borderWidths.X;
preferredSize.Height += borderWidths.Y;
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 + iconsWidth);
}
if (freeDimension != DataGridViewFreeDimension.Width)
{
preferredSize.Height = Math.Max(preferredSize.Height,
borderAndPaddingHeights + DATAGRIDVIEWCELL_iconMarginHeight * 2 + iconsHeight);
}
}
return preferredSize;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.KeyDownUnsharesRow"]/*' />
protected override bool KeyDownUnsharesRow(KeyEventArgs e, int rowIndex)
{
return e.KeyCode == Keys.Space && !e.Alt && !e.Control && !e.Shift;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.KeyUpUnsharesRow"]/*' />
protected override bool KeyUpUnsharesRow(KeyEventArgs e, int rowIndex)
{
return e.KeyCode == Keys.Space;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.MouseDownUnsharesRow"]/*' />
protected override bool MouseDownUnsharesRow(DataGridViewCellMouseEventArgs e)
{
return e.Button == MouseButtons.Left;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.MouseEnterUnsharesRow"]/*' />
protected override bool MouseEnterUnsharesRow(int rowIndex)
{
return this.ColumnIndex == this.DataGridView.MouseDownCellAddress.X && rowIndex == this.DataGridView.MouseDownCellAddress.Y;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.MouseLeaveUnsharesRow"]/*' />
protected override bool MouseLeaveUnsharesRow(int rowIndex)
{
return (this.ButtonState & ButtonState.Pushed) != 0;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.MouseUpUnsharesRow"]/*' />
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();
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnContentClick"]/*' />
protected override void OnContentClick(DataGridViewCellEventArgs e)
{
OnCommonContentClick(e);
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnContentDoubleClick"]/*' />
protected override void OnContentDoubleClick(DataGridViewCellEventArgs e)
{
OnCommonContentClick(e);
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnKeyDown"]/*' />
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;
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnKeyUp"]/*' />
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;
}
NotifyMASSClient(new Point(this.ColumnIndex, rowIndex));
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnLeave"]/*' />
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);
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnMouseDown"]/*' />
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);
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnMouseLeave"]/*' />
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);
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnMouseMove"]/*' />
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);
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.OnMouseUp"]/*' />
protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
{
if (this.DataGridView == null)
{
return;
}
if (e.Button == MouseButtons.Left)
{
UpdateButtonState(this.ButtonState & ~ButtonState.Pushed, e.RowIndex);
NotifyMASSClient(new Point(e.ColumnIndex, e.RowIndex));
}
}
private void NotifyMASSClient(Point position)
{
Debug.Assert((position.X >= 0) && (position.X < this.DataGridView.Columns.Count));
Debug.Assert((position.Y >= 0) && (position.Y < this.DataGridView.Rows.Count));
int visibleRowIndex = this.DataGridView.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, position.Y);
int visibleColumnIndex = this.DataGridView.Columns.ColumnIndexToActualDisplayIndex(position.X, DataGridViewElementStates.Visible);
int topHeaderRowIncrement = this.DataGridView.ColumnHeadersVisible ? 1 : 0;
int rowHeaderIncrement = this.DataGridView.RowHeadersVisible ? 1 : 0;
int objectID = visibleRowIndex + topHeaderRowIncrement // + 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 + rowHeaderIncrement; // + 1 because the column header cell is at index 0 in top header row acc obj
// same thing for the row header cell in the data grid view row acc obj
(this.DataGridView.AccessibilityObject as Control.ControlAccessibleObject).NotifyClients(AccessibleEvents.StateChange, objectID, childID);
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.Paint"]/*' />
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);
}
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);
}
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);
}
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;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.ParseFormattedValue"]/*' />
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;
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCell.ToString"]/*' />
/// <devdoc>
/// <para>
/// Gets the row Index and column Index of the cell.
/// </para>
/// </devdoc>
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));
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCellAccessibleObject"]/*' />
protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject
{
private int[] runtimeId = null; // Used by UIAutomation
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCellAccessibleObject.DataGridViewCheckBoxCellAccessibleObject"]/*' />
public DataGridViewCheckBoxCellAccessibleObject(DataGridViewCell owner) : base (owner)
{
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCellAccessibleObject.State"]/*' />
public override AccessibleStates State
{
get
{
if (((DataGridViewCheckBoxCell)Owner).EditedFormattedValue is CheckState)
{
CheckState state = (CheckState)(((DataGridViewCheckBoxCell)Owner).EditedFormattedValue);
switch (state)
{
case CheckState.Checked:
return AccessibleStates.Checked | base.State;
case CheckState.Indeterminate:
return AccessibleStates.Indeterminate | base.State;
}
}
else if (((DataGridViewCheckBoxCell)Owner).EditedFormattedValue is Boolean)
{
Boolean state = (Boolean)(((DataGridViewCheckBoxCell)Owner).EditedFormattedValue);
if (state)
{
return AccessibleStates.Checked | base.State;
}
}
return base.State;
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCellAccessibleObject.DefaultAction"]/*' />
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;
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCellAccessibleObject.DoDefaultAction"]/*' />
[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
DataGridViewCheckBoxCell checkBoxCell = Owner as DataGridViewCheckBoxCell;
if (checkBoxCell != null)
{
checkBoxCell.NotifyMASSClient(new Point(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex));
}
}
if (endEditMode)
{
dataGridView.EndEdit();
}
}
}
}
/// <include file='doc\DataGridViewCheckBoxCell.uex' path='docs/doc[@for="DataGridViewCheckBoxCellAccessibleObject.GetChildCount"]/*' />
public override int GetChildCount()
{
return 0;
}
internal override bool IsIAccessibleExSupported() {
if (AccessibilityImprovements.Level1) {
return true;
}
else {
return false;
}
}
internal override int[] RuntimeId {
get {
if (runtimeId == null) {
runtimeId = new int[2];
runtimeId[0] = RuntimeIDFirstItem; // first item is static - 0x2a
runtimeId[1] = this.GetHashCode();
}
return runtimeId;
}
}
internal override object GetPropertyValue(int propertyID) {
if (propertyID == NativeMethods.UIA_IsTogglePatternAvailablePropertyId) {
return (Object)IsPatternSupported(NativeMethods.UIA_TogglePatternId);
}
else if (propertyID == NativeMethods.UIA_ControlTypePropertyId && AccessibilityImprovements.Level2)
{
return NativeMethods.UIA_CheckBoxControlTypeId;
}
return base.GetPropertyValue(propertyID);
}
internal override bool IsPatternSupported(int patternId) {
if (patternId == NativeMethods.UIA_TogglePatternId) {
return true;
}
return base.IsPatternSupported(patternId);
}
internal override void Toggle() {
DoDefaultAction();
}
internal override UnsafeNativeMethods.ToggleState ToggleState {
get {
bool toggledState = true;
object formattedValue = this.Owner.FormattedValue;
if (formattedValue is System.Windows.Forms.CheckState) {
toggledState = ((CheckState)formattedValue) == CheckState.Checked;
}
else if (formattedValue is bool) {
toggledState = ((bool)formattedValue);
}
else {
return UnsafeNativeMethods.ToggleState.ToggleState_Indeterminate;
}
return toggledState ? UnsafeNativeMethods.ToggleState.ToggleState_On : UnsafeNativeMethods.ToggleState.ToggleState_Off;
}
}
}
}
}
|