File: winforms\Managed\System\WinForms\DataGridViewMethods.cs
Project: ndp\fx\src\System.Windows.Forms.csproj (System.Windows.Forms)
//------------------------------------------------------------------------------
// <copyright file="DataGridViewMethods.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>            
//------------------------------------------------------------------------------
 
namespace System.Windows.Forms
{
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.ComponentModel;
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Security;
    using System.Security.Permissions;
    using System.Collections;
    using System.Windows.Forms.Design;    
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Windows.Forms.ComponentModel;
    using System.Globalization;
    using System.Diagnostics;
    using System.Windows.Forms.VisualStyles;
    using System.Windows.Forms.Layout;
    using Microsoft.Win32;
    using System.Collections.Specialized;
    using System.Windows.Forms.Internal;
    using System.Runtime.Versioning;
    using Runtime.CompilerServices;
 
    /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView"]/*' />
    public partial class DataGridView
    {
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AccessibilityNotifyCurrentCellChanged"]/*' />
        protected virtual void AccessibilityNotifyCurrentCellChanged(Point cellAddress)
        {
            if (cellAddress.X < 0 || cellAddress.X >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("cellAddress");
            }
 
            if (cellAddress.Y < 0 || cellAddress.Y >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("cellAddress");
            }
 
            int visibleRowIndex = this.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, cellAddress.Y);
            int visibleColumnIndex = this.Columns.ColumnIndexToActualDisplayIndex(cellAddress.X, DataGridViewElementStates.Visible);
 
            int topHeaderRowIncrement = this.ColumnHeadersVisible ? 1 : 0;
            int rowHeaderIncrement = this.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
 
            if (this.ContainsFocus)
            {
                this.AccessibilityNotifyClients(AccessibleEvents.Focus, objectID, childID);
 
                if (AccessibilityImprovements.Level3)
                {
                    CurrentCell?.AccessibilityObject.SetFocus();
                }
 
            }
            this.AccessibilityNotifyClients(AccessibleEvents.Selection, objectID, childID);
        }
 
        internal void ActivateToolTip(bool activate, string toolTipText, int columnIndex, int rowIndex)
        {
            this.toolTipCaption = toolTipText;
            this.ptToolTipCell = new Point(columnIndex, rowIndex);
            this.toolTipControl.Activate(activate);
        }
 
        internal void AddNewRow(bool createdByEditing)
        {
            Debug.Assert(this.Columns.Count > 0);
            Debug.Assert(this.newRowIndex == -1);
 
            this.Rows.AddInternal(true /*newRow*/, null /*values*/);
            this.newRowIndex = this.Rows.Count - 1;
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowCreatedByEditing] = createdByEditing;
 
            if (createdByEditing)
            {
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(this.Rows[this.newRowIndex]);
                OnUserAddedRow(dgvre);
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AdjustColumnHeaderBorderStyle"]/*' />
        [
            EditorBrowsable(EditorBrowsableState.Advanced)
        ]
        public virtual DataGridViewAdvancedBorderStyle AdjustColumnHeaderBorderStyle(DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStyleInput,
                                                                         DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder,
                                                                         bool isFirstDisplayedColumn, 
                                                                         bool isLastVisibleColumn)
        {
            if (this.ApplyVisualStylesToHeaderCells)
            {
                switch (dataGridViewAdvancedBorderStyleInput.All)
                {
                    case DataGridViewAdvancedCellBorderStyle.OutsetPartial:
                    case DataGridViewAdvancedCellBorderStyle.OutsetDouble:
                        if (this.RightToLeftInternal)
                        {
                            dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None;
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.Outset;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None;
                            }
                        }
                        else
                        {
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None;
                            }
                            dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None;
                        }
                        dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                        dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Outset;
                        return dataGridViewAdvancedBorderStylePlaceholder;
 
                    case DataGridViewAdvancedCellBorderStyle.InsetDouble:
                        if (this.RightToLeftInternal)
                        {
                            dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None;
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.Inset;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None;
                            }
                        }
                        else
                        {
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.InsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None;
                            }
                            dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None;
                        }
                        dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.InsetDouble;
                        dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Inset;
                        return dataGridViewAdvancedBorderStylePlaceholder;
 
                    case DataGridViewAdvancedCellBorderStyle.Single:
                    case DataGridViewAdvancedCellBorderStyle.Outset:
                    case DataGridViewAdvancedCellBorderStyle.Inset:
                        if (!isFirstDisplayedColumn || this.RowHeadersVisible)
                        {
                            dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None;
                            dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None;
                            dataGridViewAdvancedBorderStylePlaceholder.TopInternal = dataGridViewAdvancedBorderStyleInput.All;
                            dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = dataGridViewAdvancedBorderStyleInput.All;
                            return dataGridViewAdvancedBorderStylePlaceholder;
                        }
                        else
                        {
                            // isFirstDisplayedColumn == true && this.RowHeadersVisible == false
                            if (this.RightToLeftInternal)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None;
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = dataGridViewAdvancedBorderStyleInput.All;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = dataGridViewAdvancedBorderStyleInput.All;
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None;
                            }
                            dataGridViewAdvancedBorderStylePlaceholder.TopInternal = dataGridViewAdvancedBorderStyleInput.All;
                            dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = dataGridViewAdvancedBorderStyleInput.All;
                            return dataGridViewAdvancedBorderStylePlaceholder;
                        }
                }
            }
            else
            {
                switch (dataGridViewAdvancedBorderStyleInput.All)
                {
                    case DataGridViewAdvancedCellBorderStyle.OutsetPartial:
                        if (this.RightToLeftInternal)
                        {
                            dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = isLastVisibleColumn ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetPartial;
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.OutsetPartial;
                            }
                        }
                        else
                        {
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.OutsetPartial;
                            }
                            dataGridViewAdvancedBorderStylePlaceholder.RightInternal = isLastVisibleColumn ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetPartial;
                        }
                        dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                        dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Outset;
                        return dataGridViewAdvancedBorderStylePlaceholder;
 
                    case DataGridViewAdvancedCellBorderStyle.OutsetDouble:
                        if (this.RightToLeftInternal)
                        {
                            dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Outset;
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Outset;
                            }
                        }
                        else
                        {
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Outset;
                            }
                            dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Outset;
                        }
                        dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.OutsetDouble;
                        dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Outset;
                        return dataGridViewAdvancedBorderStylePlaceholder;
 
                    case DataGridViewAdvancedCellBorderStyle.InsetDouble:
                        if (this.RightToLeftInternal)
                        {
                            dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Inset;
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Inset : DataGridViewAdvancedCellBorderStyle.InsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Inset;
                            }
                        }
                        else
                        {
                            if (isFirstDisplayedColumn)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Inset : DataGridViewAdvancedCellBorderStyle.InsetDouble;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Inset;
                            }
                            dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Inset;
                        }
                        dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.InsetDouble;
                        dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Inset;
                        return dataGridViewAdvancedBorderStylePlaceholder;
 
                    case DataGridViewAdvancedCellBorderStyle.Single:
                        if (!isFirstDisplayedColumn || this.RowHeadersVisible)
                        {
                            if (this.RightToLeftInternal)
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Single;
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None;
                            }
                            else
                            {
                                dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None;
                                dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Single;
                            }
                            dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.Single;
                            dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Single;
                            return dataGridViewAdvancedBorderStylePlaceholder;
                        }
                        break;
                }
            }
 
            return dataGridViewAdvancedBorderStyleInput;
        }
 
        private bool AdjustExpandingColumn(DataGridViewColumn dataGridViewColumn, int rowIndex)
        {
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(rowIndex > -1);
            Debug.Assert(rowIndex < this.Rows.Count);
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return false;
            }
 
            bool ret = false; // No autosizing occurs by default.
            try
            {
                this.noAutoSizeCount++;
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                int preferredThickness = dataGridViewRow.Cells[dataGridViewColumn.Index].GetPreferredWidth(rowIndex, dataGridViewRow.GetHeight(rowIndex));
                if (preferredThickness > DataGridViewBand.maxBandThickness)
                {
                    preferredThickness = DataGridViewBand.maxBandThickness;
                }
                if (dataGridViewColumn.Width < preferredThickness)
                {
                    // Column needs to be expanded
                    dataGridViewColumn.ThicknessInternal = preferredThickness;
                    ret = true;
                }
            }
            finally
            {
                Debug.Assert(this.noAutoSizeCount > 0);
                this.noAutoSizeCount--;
            }
            
            return ret;
        }
 
        private bool AdjustExpandingColumns(DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter, int rowIndex)
        {
            Debug.Assert(autoSizeColumnCriteriaFilter != DataGridViewAutoSizeColumnCriteriaInternal.None);
            Debug.Assert((autoSizeColumnCriteriaFilter & DataGridViewAutoSizeColumnCriteriaInternal.Fill) == 0);
 
            bool ret = false; // No column autosizes by default
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            while (dataGridViewColumn != null)
            {
                DataGridViewAutoSizeColumnCriteriaInternal inheritedAutoSizeColumnCriteria = (DataGridViewAutoSizeColumnCriteriaInternal)dataGridViewColumn.InheritedAutoSizeMode;
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = (inheritedAutoSizeColumnCriteria & autoSizeColumnCriteriaFilter);
                if (autoSizeColumnCriteriaFiltered != 0)
                {
                    ret |= AdjustExpandingColumn(dataGridViewColumn, rowIndex);
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None);
            }
            return ret;
        }
 
        private int AdjustExpandingRow(int rowIndex, int columnIndex, bool fixedWidth)
        {
            Debug.Assert(columnIndex >= -1 && columnIndex < this.Columns.Count);
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
            Debug.Assert(this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedHeaders ||
                         this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders ||
                         this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedCells);
 
            // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
            // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows.
            int width = 0;
            DataGridViewCell dataGridViewCell;
            if (columnIndex > -1 && (((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
            {
                dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                if (fixedWidth)
                {
                    width = this.Columns[columnIndex].Thickness;
                }
            }
            else
            {
                Debug.Assert(columnIndex == -1);
                Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0);
                dataGridViewCell = this.Rows.SharedRow(rowIndex).HeaderCell;
                if (fixedWidth)
                {
                    Debug.Assert(this.RowHeadersWidth > 0);
                    Debug.Assert(this.RowHeadersVisible);
                    width = this.RowHeadersWidth;
                }
            }
            int preferredThickness;
            if (fixedWidth)
            {
                preferredThickness = dataGridViewCell.GetPreferredHeight(rowIndex, width);
            }
            else
            {
                preferredThickness = dataGridViewCell.GetPreferredSize(rowIndex).Height;
            }
            int height, minimumHeight;
            this.Rows.SharedRow(rowIndex).GetHeightInfo(rowIndex, out height, out minimumHeight);
            if (preferredThickness < height)
            {
                preferredThickness = height;
            }
            Debug.Assert(preferredThickness >= minimumHeight);
            if (preferredThickness > DataGridViewBand.maxBandThickness)
            {
                preferredThickness = DataGridViewBand.maxBandThickness;
            }
            if (height != preferredThickness)
            {
                Debug.Assert(this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None);
                this.Rows[rowIndex].Thickness = preferredThickness;   // unsharing the resized row
            }
            return preferredThickness;
        }
 
        [SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops")] // Can't cache DataGridViewRow object because rowIndex is changing in loop.
        private void AdjustExpandingRows(int columnIndex, bool fixedWidth)
        {
            if ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0 ||
                ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0 && this.RowHeadersVisible))
            {
                if (!this.IsHandleCreated)
                {
                    // auto sizing causes handle creation.
                    // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                    return;
                }
 
                // Very expensive processing - the developer should avoid this scenario.
                // Switch to batch operation
                this.inBulkPaintCount++;
                try
                {
                    if ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllRows) != 0)
                    {
                        this.inBulkLayoutCount++;
                        try
                        {
                            for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                                rowIndex != -1;
                                rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                            {
                                int width = 0;
                                DataGridViewCell dataGridViewCell;
                                if (columnIndex > -1 && (((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
                                {
                                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                                    if (fixedWidth)
                                    {
                                        width = this.Columns[columnIndex].Thickness;
                                    }
                                }
                                else
                                {
                                    //Debug.Assert(columnIndex == -1);
                                    Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0);
                                    dataGridViewCell = this.Rows.SharedRow(rowIndex).HeaderCell;
                                    if (fixedWidth)
                                    {
                                        Debug.Assert(this.RowHeadersWidth > 0);
                                        Debug.Assert(this.RowHeadersVisible);
                                        width = this.RowHeadersWidth;
                                    }
                                }
                                int preferredHeight;
                                if (fixedWidth)
                                {
                                    preferredHeight = dataGridViewCell.GetPreferredHeight(rowIndex, width);
                                }
                                else
                                {
                                    preferredHeight = dataGridViewCell.GetPreferredSize(rowIndex).Height;
                                }
                                if (this.Rows.SharedRow(rowIndex).Height < preferredHeight)
                                {
                                    this.Rows[rowIndex].Height = preferredHeight;  // unsharing the row to be resized
                                }
                            }
                        }
                        finally
                        {
                            ExitBulkLayout(false /*invalidInAdjustFillingColumns*/);
                        }
                    }
                    else
                    {
                        Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0);
                        int displayHeight = this.layout.Data.Height;
                        int cy = 0;
 
                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        while (rowIndex != -1 && cy < displayHeight)
                        {
                            cy += AdjustExpandingRow(rowIndex, columnIndex, fixedWidth);
                            rowIndex = this.Rows.GetNextRow(rowIndex,
                                DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        }
 
                        if (cy < displayHeight)
                        {
                            rowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                            while (rowIndex != -1 && cy < displayHeight)
                            {
                                cy += AdjustExpandingRow(rowIndex, columnIndex, fixedWidth);
                                rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                            }
                        }
                    }
                }
                finally
                {
                    ExitBulkPaint(-1, -1);
                }
            }
        }
 
        internal void AdjustFillingColumn(DataGridViewColumn dataGridViewColumn, int width)
        {
            if (this.InAdjustFillingColumns)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter));
            }
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumn] = true;
 
            try
            {
                Debug.Assert(dataGridViewColumn != null);
                Debug.Assert(dataGridViewColumn.Visible);
                Debug.Assert(!dataGridViewColumn.Frozen);
                Debug.Assert(dataGridViewColumn.MinimumWidth <= width);
                Debug.Assert(dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill);
                Debug.Assert(!this.layout.dirty);
 
                if (this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) > this.layout.Data.Width)
                {
                    // Columns are scrolling - this means that all columns have reached their minimum width.
                    // Do not affect their width or fill weight
                    Debug.Assert(dataGridViewColumn.MinimumWidth == dataGridViewColumn.Width);
                    return;
                }
 
                int availableWidth = this.layout.Data.Width;  // Width available for auto-filled columns
 
                // Check if the column is the first or last visible scrolling column
                if (this.DesignMode ||
                    dataGridViewColumn == this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) ||
                    dataGridViewColumn == this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen))
                {
                    // Changing the width is equivalent to adjusting the FillWeight when:
                    //  - the column is not scrolling and is the first non-frozen visible column
                    //  - the column is not scrolling and is the last non-frozen visible column
 
                    float weightSum = 0;        // Weights of all auto filled visible columns.
                    int widthSum = 0;           // Sum of widths of visible auto filled columns.
                    int imposedWidthSum = 0;    // Minimum width required for all other columns.
                    bool otherFillingColumnExists = false;
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Visible)
                        {
                            if (dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                            {
                                Debug.Assert(!dataGridViewColumnTmp.Frozen);
                                widthSum += dataGridViewColumnTmp.Width;
                                if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index)
                                {
                                    imposedWidthSum += dataGridViewColumnTmp.MinimumWidth;
                                    otherFillingColumnExists = true;
                                }
                                weightSum += dataGridViewColumnTmp.FillWeight;
                            }
                            else
                            {
                                imposedWidthSum += dataGridViewColumnTmp.Width;
                                availableWidth -= dataGridViewColumnTmp.Width;
                            }
                        }
                    }
 
                    if (!otherFillingColumnExists)
                    {
                        // The resized column is the only one that is filling. This is a no-op operation.
                        // Neither the width nor the fill weight can change
                        return;
                    }
 
                    int maximumPossibleWidth = this.layout.Data.Width - imposedWidthSum;
                    if (width > maximumPossibleWidth)
                    {
                        width = maximumPossibleWidth;
                    }
 
                    // Determine fill weight equivalent to 'width'
                    float oldWeight = dataGridViewColumn.FillWeight;
                    float newWeight = (float)(width * weightSum) / (float)widthSum;
                    bool desiredWidthTooSmall = false;
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index &&
                            dataGridViewColumnTmp.Visible &&
                            dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                        {
                            dataGridViewColumnTmp.FillWeightInternal = (weightSum - newWeight) * dataGridViewColumnTmp.FillWeight / (weightSum - oldWeight);
 
                            if (dataGridViewColumnTmp.FillWeight < (dataGridViewColumnTmp.MinimumWidth * weightSum) / (float)widthSum)
                            {
                                desiredWidthTooSmall = true;
                                dataGridViewColumnTmp.DesiredFillWidth = -1;
                            }
                            else
                            {
                                dataGridViewColumnTmp.DesiredFillWidth = 0;
                            }
                        }
                    }
 
                    dataGridViewColumn.FillWeightInternal = newWeight;
 
                    if (desiredWidthTooSmall)
                    {
                        // At least one column hits its minimum width
                        // Adjust UsedFillWeight values are adjusted FillWeight values
                        float usedWeightSumNoneMinimal = weightSum;
                        float weightSumNoneMinimal = weightSum;
                        float usedFillWeights = 0F;
                        foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                        {
                            if (dataGridViewColumnTmp.Visible &&
                                dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                            {
                                if (dataGridViewColumnTmp.Index == dataGridViewColumn.Index)
                                {
                                    dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight;
                                    usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight;
                                    weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight;
                                    usedFillWeights += dataGridViewColumnTmp.UsedFillWeight;
                                }
                                else if (dataGridViewColumnTmp.DesiredFillWidth == -1)
                                {
                                    dataGridViewColumnTmp.UsedFillWeight = weightSum * dataGridViewColumnTmp.MinimumWidth / widthSum;
                                    usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight;
                                    weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight;
                                    usedFillWeights += dataGridViewColumnTmp.UsedFillWeight;
                                }
                            }
                        }
                        foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                        {
                            if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index &&
                                dataGridViewColumnTmp.Visible &&
                                dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && 
                                dataGridViewColumnTmp.DesiredFillWidth != -1)
                            {
                                dataGridViewColumnTmp.UsedFillWeight = Math.Max(dataGridViewColumnTmp.FillWeight * usedWeightSumNoneMinimal / weightSumNoneMinimal,
                                                                                weightSum * dataGridViewColumnTmp.MinimumWidth / widthSum);
                                usedFillWeights += dataGridViewColumnTmp.UsedFillWeight;
                            }
                        }
                        dataGridViewColumn.UsedFillWeight += weightSum - usedFillWeights;
                    }
                    else
                    {
                        // No column hits its minimum width
                        // Each UsedFillWeight simply equals the FillWeight
                        foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                        {
                            if (dataGridViewColumnTmp.Visible &&
                                dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                            {
                                dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight;
                            }
                        }
                    }
    #if DEBUG
                    float weightSumDbg = 0F;
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Visible &&
                            dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                        {
                            weightSumDbg += dataGridViewColumnTmp.UsedFillWeight;
                        }
                    }
                    Debug.Assert(Math.Abs(weightSum - weightSumDbg) < 1.0F);
    #endif
                }
                else
                {
                    // This column is not the first nor the last visible non-frozen column
                    // Changing its width only affects the width and weight of the columns displayed after it
 
                    // First figure out the maximum possible width
                    int imposedWidthSum = 0;    // Minimum width required for all other columns
                    float weightSum = 0;        // Weights of all auto filled visible columns.
                    float oldWeightSum = 0F;    // Fill weights of the columns displayed after this resized column
                    bool otherFillingColumnExists = false;
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Visible)
                        {
                            if (dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                            {
                                Debug.Assert(!dataGridViewColumnTmp.Frozen);
                                if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index)
                                {
                                    if (this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index))
                                    {
                                        imposedWidthSum += dataGridViewColumnTmp.MinimumWidth;   // Column is allowed to shrink down to its minimum
                                        oldWeightSum += dataGridViewColumnTmp.FillWeight;
                                    }
                                    else
                                    {
                                        // Column is displayed before 'dataGridViewColumn', it is not allowed to shrink at all
                                        imposedWidthSum += dataGridViewColumnTmp.Width;
                                    }
                                    otherFillingColumnExists = true;
                                }
                                weightSum += dataGridViewColumnTmp.FillWeight;
                            }
                            else
                            {
                                imposedWidthSum += dataGridViewColumnTmp.Width;
                                availableWidth -= dataGridViewColumnTmp.Width;
                            }
                        }
                    }
 
                    if (!otherFillingColumnExists)
                    {
                        // The resized column is the only one that is filling. This is a no-op operation.
                        // Neither the width nor the fill weight can change
                        return;
                    }
 
                    int maximumPossibleWidth = this.layout.Data.Width - imposedWidthSum;
                    if (width > maximumPossibleWidth)
                    {
                        width = maximumPossibleWidth;
                    }
 
                    // Then figure out the target fill weights
                    float oldWeight = dataGridViewColumn.FillWeight;
                    float newWeight = weightSum * width / availableWidth;
                    float newWeightSum = oldWeightSum + oldWeight - newWeight;
                    Debug.Assert(newWeightSum > 0);
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index &&
                            dataGridViewColumnTmp.Visible &&
                            dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill &&
                            this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index))
                        {
                            dataGridViewColumnTmp.FillWeightInternal = dataGridViewColumnTmp.FillWeight * newWeightSum / oldWeightSum;
                        }
                    }
 
                    dataGridViewColumn.FillWeightInternal = newWeight;
 
                    bool desiredWidthTooSmall = false;
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Visible &&
                            dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                        {
                            if (dataGridViewColumnTmp.FillWeight < (dataGridViewColumnTmp.MinimumWidth * weightSum) / (float)availableWidth)
                            {
                                desiredWidthTooSmall = true;
                                dataGridViewColumnTmp.DesiredFillWidth = -1;
                            }
                            else
                            {
                                dataGridViewColumnTmp.DesiredFillWidth = 0;
                            }
                        }
                    }
 
                    if (desiredWidthTooSmall)
                    {
                        // At least one column hits its minimum width
                        // Adjust UsedFillWeight values are adjusted FillWeight values
                        float usedWeightSumNoneMinimal = weightSum;
                        float weightSumNoneMinimal = weightSum;
                        float usedFillWeights = 0F;
                        foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                        {
                            if (dataGridViewColumnTmp.Visible &&
                                dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                            {
                                if (dataGridViewColumnTmp.Index == dataGridViewColumn.Index ||
                                    this.Columns.DisplayInOrder(dataGridViewColumnTmp.Index, dataGridViewColumn.Index))
                                {
                                    if (dataGridViewColumnTmp.Index == dataGridViewColumn.Index)
                                    {
                                        dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight;
                                    }
                                    else
                                    {
                                        dataGridViewColumnTmp.UsedFillWeight = weightSum * dataGridViewColumnTmp.Width / availableWidth;
                                    }
                                    usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight;
                                    weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight;
                                    usedFillWeights += dataGridViewColumnTmp.UsedFillWeight;
                                }
                                else if (dataGridViewColumnTmp.DesiredFillWidth == -1)
                                {
                                    dataGridViewColumnTmp.UsedFillWeight = weightSum * dataGridViewColumnTmp.MinimumWidth / availableWidth;
                                    usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight;
                                    weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight;
                                    usedFillWeights += dataGridViewColumnTmp.UsedFillWeight;
                                }
                            }
                        }
                        foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                        {
                            if (this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index) &&
                                dataGridViewColumnTmp.Visible &&
                                dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill &&
                                dataGridViewColumnTmp.DesiredFillWidth != -1)
                            {
                                dataGridViewColumnTmp.UsedFillWeight = Math.Max(dataGridViewColumnTmp.FillWeight * usedWeightSumNoneMinimal / weightSumNoneMinimal,
                                                                                weightSum * dataGridViewColumnTmp.MinimumWidth / availableWidth);
                                usedFillWeights += dataGridViewColumnTmp.UsedFillWeight;
                            }
                        }
                        dataGridViewColumn.UsedFillWeight += weightSum - usedFillWeights;
                    }
                    else
                    {
                        // No column hits its minimum width
                        // Each UsedFillWeight simply equals the FillWeight
                        foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                        {
                            if (dataGridViewColumnTmp.Visible &&
                                dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                            {
                                dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight;
                            }
                        }
                    }
    #if DEBUG
                    float weightSumDbg = 0F;
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Visible &&
                            dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                        {
                            weightSumDbg += dataGridViewColumnTmp.UsedFillWeight;
                        }
                    }
                    Debug.Assert(Math.Abs(weightSum - weightSumDbg) < 1.0F);
    #endif
                }
 
                // UsedFillWeight properties are up-to-date
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = false;
                this.availableWidthForFillColumns = availableWidth;
                // AdjustFillingColumns() will resize columns based on the UsedFillWeight values
                PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumn] = false;
            }
        }
 
        private bool AdjustFillingColumns()
        {
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumns])
            {
                // No need to auto fill columns while we're already doing it.
                return false;
            }
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumns] = true;
 
            bool columnsAdjusted = false;
            try
            {
                // Determine free space for filling columns.
                int numVisibleFillColumns = 0;  // number of visible columns that are auto filled.
                int imposedWidthSum = 0;        // total width of columns that don't have a flexible width.
                int requiredWidthSum = 0;       // total of the minimum widths of the visible auto filled columns.
                float weightSum = 0F;           // total of the weights of the visible auto filled columns.
                ArrayList autoFillColumns = null;
                foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
                {
                    if (dataGridViewColumn.Visible)
                    {
                        if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                        {
                            Debug.Assert(!dataGridViewColumn.Frozen);
                            numVisibleFillColumns++;
                            requiredWidthSum += dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth;
                            weightSum += dataGridViewColumn.FillWeight;
                            if (autoFillColumns == null)
                            {
                                autoFillColumns = new ArrayList(this.Columns.Count);
                            }
                            autoFillColumns.Add(dataGridViewColumn);
                        }
                        else
                        {
                            imposedWidthSum += dataGridViewColumn.Width;
                        }
                    }
                }
 
                if (numVisibleFillColumns > 0)
                {
                    // Assuming no vertical scrollbar has been accounted for yet
                    Debug.Assert(this.layout.Data.Width == this.layout.Inside.Width - this.layout.RowHeaders.Width - (this.SingleVerticalBorderAdded ? 1 : 0));
                    int availableWidth = this.layout.Data.Width - imposedWidthSum;
                    if ((this.scrollBars == ScrollBars.Both || this.scrollBars == ScrollBars.Vertical) /*&&
                        (availableWidth > requiredWidthSum || this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty])*/)
                    {
                        int totalVisibleRowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible);
                        int totalVisibleHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible);
                        int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
 
                        // Assuming there is no horizontal scrollbar, is a vertical scrollbar required?
                        ComputeVisibleRows(); // Make sure this.displayedBandsInfo.FirstDisplayedScrollingRow and other row count info variables have been set
 
                        if (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) &&
                            this.displayedBandsInfo.NumTotallyDisplayedScrollingRows != totalVisibleRowCount - this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) &&
                            (totalVisibleHeight - totalVisibleFrozenHeight != ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) &&
                            this.layout.Data.Height > totalVisibleFrozenHeight &&
                            SystemInformation.VerticalScrollBarWidth <= this.layout.Data.Width)
                        {
                            // Vertical scrollbar is required, even when there is not horizontal one.
                            availableWidth -= SystemInformation.VerticalScrollBarWidth;
                        }
                    }
                    
                    int columnEntry;
                    
                    if (availableWidth <= requiredWidthSum)
                    {
                        // All auto filled columns need to take their minimum width. If (availableWidth < requiredWidthSum) a horizontal scrollbar appears.
                        availableWidth = 0;
                        for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                        {
                            DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                            int minimumWidth = dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth;
                            if (dataGridViewColumn.Thickness != minimumWidth)
                            {
                                columnsAdjusted = true;
                                dataGridViewColumn.ThicknessInternal = minimumWidth;
                            }
                            availableWidth += dataGridViewColumn.Thickness;
                        }
                        //if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty])
                        {
                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                            {
                                // Make sure the UsedFillWeight correspond to the actual column width
                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                dataGridViewColumn.UsedFillWeight = dataGridViewColumn.Width * weightSum / availableWidth;
                            }
                            this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = false;
                            this.availableWidthForFillColumns = availableWidth;
                        }
                        return columnsAdjusted;
                    }
 
                    // Auto filling columns can share some real estate.
 
                    int usedWidth = 0;
 
                    // Update the UsedFillWeight value if dirty
                    if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty])
                    {
                        // Assign desired widths
                        Debug.Assert(weightSum > 0);
                        bool desiredWidthTooSmall = false;
                        for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                        {
                            DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                            if (columnEntry == autoFillColumns.Count - 1)
                            {
                                dataGridViewColumn.DesiredFillWidth = availableWidth - usedWidth;
                            }
                            else
                            {
                                float desiredFillWidth = (dataGridViewColumn.FillWeight / weightSum) * availableWidth;
                                dataGridViewColumn.DesiredFillWidth = (int)Math.Round(desiredFillWidth, MidpointRounding.AwayFromZero);
                                usedWidth += dataGridViewColumn.DesiredFillWidth;
                            }
                            int minimumWidth = dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth;
                            if (dataGridViewColumn.DesiredFillWidth < minimumWidth)
                            {
                                desiredWidthTooSmall = true;
                                dataGridViewColumn.DesiredFillWidth = -1;
                            }
                        }
 
                        if (desiredWidthTooSmall)
                        {
                            // At least one column hits its minimum width
                            // Adjust UsedFillWeight values are adjusted FillWeight values
                            float usedWeightSumNoneMinimal = weightSum;
                            float weightSumNoneMinimal = weightSum;
                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                            {
                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                if (dataGridViewColumn.DesiredFillWidth == -1)
                                {
                                    int minimumWidth = dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth;
                                    dataGridViewColumn.UsedFillWeight = weightSum * minimumWidth / availableWidth;
                                    usedWeightSumNoneMinimal -= dataGridViewColumn.UsedFillWeight;
                                    weightSumNoneMinimal -= dataGridViewColumn.FillWeight;
                                }
                            }
                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                            {
                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                if (dataGridViewColumn.DesiredFillWidth != -1)
                                {
                                    dataGridViewColumn.UsedFillWeight = dataGridViewColumn.FillWeight * usedWeightSumNoneMinimal / weightSumNoneMinimal;
                                }
                            }
                        }
                        else
                        {
                            // No column hits its minimum width
                            // Each UsedFillWeight simply equals the FillWeight
                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                            {
                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                dataGridViewColumn.UsedFillWeight = dataGridViewColumn.FillWeight;
                            }
                        }
 
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = false;
                        this.availableWidthForFillColumns = availableWidth;
                    }
                    else if (availableWidth != this.availableWidthForFillColumns)
                    {
                        // The available width for auto-filled columns has changed - UsedFillWeight values need to be adjusted.
                        if (availableWidth > this.availableWidthForFillColumns)
                        {
                            // Available width increased
                            int widthGain = availableWidth - this.availableWidthForFillColumns;
                            // Allocate additional width according to UsedFillWeight and FillWeight values
                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                            {
                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                dataGridViewColumn.DesiredFillWidth = dataGridViewColumn.Width;
                            }
                            float[] floatDesiredWidths = new float[autoFillColumns.Count];
                            for (int gain = 0; gain < widthGain; gain++)
                            {
                                float fillWeightRatioSum = 0F;
                                bool minimumColumnExists = false;
                                for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                                {
                                    DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                    fillWeightRatioSum += dataGridViewColumn.FillWeight / dataGridViewColumn.UsedFillWeight;
                                    if (dataGridViewColumn.DesiredFillWidth <= dataGridViewColumn.MinimumWidth)
                                    {
                                        minimumColumnExists = true;
                                    }
                                }
                                for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                                {
                                    DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                    if (gain == 0)
                                    {
                                        floatDesiredWidths[columnEntry] = this.availableWidthForFillColumns * dataGridViewColumn.UsedFillWeight / weightSum;
                                    }
                                    if (minimumColumnExists)
                                    {
                                        floatDesiredWidths[columnEntry] += dataGridViewColumn.FillWeight / dataGridViewColumn.UsedFillWeight / fillWeightRatioSum;
                                    }
                                    else
                                    {
                                        floatDesiredWidths[columnEntry] += dataGridViewColumn.FillWeight / weightSum;
                                    }
                                }
                            }
                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                            {
                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                dataGridViewColumn.UsedFillWeight = weightSum / availableWidth * floatDesiredWidths[columnEntry];
                            }
                        }
                        else
                        {
                            // availableWidth < this.availableWidthForFillColumns - Available width decreased
                            int totalWidthLoss = this.availableWidthForFillColumns - availableWidth;
                            int cumulatedWidthLoss = 0;
                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                            {
                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                dataGridViewColumn.DesiredFillWidth = dataGridViewColumn.Width;
                            }
                            // the width loss is accounted for in steps of 10% (see VSWhidbey 568343)
                            do
                            {
                                int stepDownAvailableWidthForFillColumns = this.availableWidthForFillColumns - cumulatedWidthLoss;
                                int widthLoss = Math.Min(stepDownAvailableWidthForFillColumns - availableWidth, Math.Max(1, (int)(stepDownAvailableWidthForFillColumns * 0.1F)));
                                cumulatedWidthLoss += widthLoss;
                                bool changeDone;
                                do
                                {
                                    changeDone = false;
                                    // Determine which column deserves to shrink the most
                                    float biggestWeightDeficiency = 0F, fillWeightRatioSum = 0F, fillWeightRatio;
                                    DataGridViewColumn mostDeservingDataGridViewColumn = null;
                                    for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                                    {
                                        DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                        if (dataGridViewColumn.DesiredFillWidth > dataGridViewColumn.MinimumWidth)
                                        {
                                            fillWeightRatio = dataGridViewColumn.UsedFillWeight / dataGridViewColumn.FillWeight;
                                            fillWeightRatioSum += fillWeightRatio;
                                            if (fillWeightRatio > biggestWeightDeficiency)
                                            {
                                                mostDeservingDataGridViewColumn = dataGridViewColumn;
                                                biggestWeightDeficiency = fillWeightRatio;
                                            }
                                        }
                                    }
                                    if (mostDeservingDataGridViewColumn != null)
                                    {
                                        float floatDesiredWidth = (stepDownAvailableWidthForFillColumns * mostDeservingDataGridViewColumn.UsedFillWeight / weightSum) - widthLoss * mostDeservingDataGridViewColumn.UsedFillWeight / mostDeservingDataGridViewColumn.FillWeight / fillWeightRatioSum;
                                        if (floatDesiredWidth < (float)mostDeservingDataGridViewColumn.MinimumWidth)
                                        {
                                            floatDesiredWidth = (int)mostDeservingDataGridViewColumn.MinimumWidth;
                                        }
                                        int oldDesiredWidth = mostDeservingDataGridViewColumn.DesiredFillWidth;
                                        mostDeservingDataGridViewColumn.DesiredFillWidth = Math.Min(oldDesiredWidth, (int)Math.Round(floatDesiredWidth, MidpointRounding.AwayFromZero));
                                        changeDone = (oldDesiredWidth != mostDeservingDataGridViewColumn.DesiredFillWidth);
                                        if (!changeDone && widthLoss == 1 && oldDesiredWidth > mostDeservingDataGridViewColumn.MinimumWidth)
                                        {
                                            mostDeservingDataGridViewColumn.DesiredFillWidth--;
                                            changeDone = true;
                                        }
                                        Debug.Assert(oldDesiredWidth >= mostDeservingDataGridViewColumn.DesiredFillWidth);
                                        widthLoss -= oldDesiredWidth - mostDeservingDataGridViewColumn.DesiredFillWidth;
                                        if (changeDone)
                                        {
                                            stepDownAvailableWidthForFillColumns -= oldDesiredWidth - mostDeservingDataGridViewColumn.DesiredFillWidth;
                                            for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                                            {
                                                DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                                dataGridViewColumn.UsedFillWeight = weightSum / stepDownAvailableWidthForFillColumns * dataGridViewColumn.DesiredFillWidth;
                                            }
                                        }
                                        Debug.Assert(widthLoss >= 0);
                                    }
                                }
                                while (changeDone && widthLoss > 0);
                            }
                            while (cumulatedWidthLoss < totalWidthLoss);
                        }
                        this.availableWidthForFillColumns = availableWidth;
                    }
 
#if DEBUG
                    float weightSumDbg = 0F;
                    for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                    {
                        DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                        weightSumDbg += dataGridViewColumn.UsedFillWeight;
 
                    }
                    Debug.Assert(Math.Abs(weightSum - weightSumDbg) < 1.0F);
#endif
 
                    // Finally update the columns' width according the UsedFillWeight values.
                    try
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_allowHorizontalScrollbar] = false;
                        usedWidth = 0;
                        float carryover = 0F;
                        while (autoFillColumns.Count > 0)
                        {
                            DataGridViewColumn mostDeservingDataGridViewColumn = null;
                            if (autoFillColumns.Count == 1)
                            {
                                mostDeservingDataGridViewColumn = (DataGridViewColumn)autoFillColumns[0];
                                mostDeservingDataGridViewColumn.DesiredFillWidth = Math.Max(availableWidth - usedWidth, mostDeservingDataGridViewColumn.MinimumWidth);
                                autoFillColumns.Clear();
                            }
                            else
                            {
                                float biggestWeightDiscrepancy = 0F, weightDiscrepancy;
                                for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++)
                                {
                                    DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry];
                                    weightDiscrepancy = Math.Abs(dataGridViewColumn.UsedFillWeight - dataGridViewColumn.FillWeight) / dataGridViewColumn.FillWeight;
                                    if (weightDiscrepancy > biggestWeightDiscrepancy || mostDeservingDataGridViewColumn == null)
                                    {
                                        mostDeservingDataGridViewColumn = dataGridViewColumn;
                                        biggestWeightDiscrepancy = weightDiscrepancy;
                                    }
                                }
                                float floatDesiredWidth = (mostDeservingDataGridViewColumn.UsedFillWeight * availableWidth / weightSum) + carryover;
                                mostDeservingDataGridViewColumn.DesiredFillWidth = Math.Max(mostDeservingDataGridViewColumn.MinimumWidth, (int)Math.Round(floatDesiredWidth, MidpointRounding.AwayFromZero));
                                carryover = floatDesiredWidth - mostDeservingDataGridViewColumn.DesiredFillWidth;
                                usedWidth += mostDeservingDataGridViewColumn.DesiredFillWidth;
                                autoFillColumns.Remove(mostDeservingDataGridViewColumn);
                            }
                            if (mostDeservingDataGridViewColumn.DesiredFillWidth != mostDeservingDataGridViewColumn.Thickness)
                            {
                                columnsAdjusted = true;
                                mostDeservingDataGridViewColumn.ThicknessInternal = mostDeservingDataGridViewColumn.DesiredFillWidth;
                            }
                        }
                    }
                    finally
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_allowHorizontalScrollbar] = true;
                    }
                }
#if DEBUG
                if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty])
                {
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (dataGridViewColumnTmp.Visible &&
                            dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                        {
                            Debug.Assert(Math.Abs(dataGridViewColumnTmp.UsedFillWeight * this.availableWidthForFillColumns - weightSum * dataGridViewColumnTmp.Width) / weightSum / dataGridViewColumnTmp.Width <= 1.25F / dataGridViewColumnTmp.Width);
                        }
                    }
                }
 
                bool nonMinColumnExists = false;
                int widthSum = 0;
                foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                {
                    if (dataGridViewColumnTmp.Visible &&
                        dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                    {
                        widthSum += dataGridViewColumnTmp.Width;
                        if (dataGridViewColumnTmp.Width > dataGridViewColumnTmp.MinimumWidth)
                        {
                            nonMinColumnExists = true;
                        }
                    }
                }
                if (nonMinColumnExists)
                {
                    Debug.Assert(widthSum == this.availableWidthForFillColumns);
                }
#endif
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumns] = false;
            }
 
            return columnsAdjusted;
        }
 
        private void AdjustShrinkingRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode, bool fixedWidth, bool internalAutosizing)
        {
            if ((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0 ||
                ((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0 && this.RowHeadersVisible))
            {
                // Switch to batch operation
                this.inBulkPaintCount++;
                try
                {
                    if ((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllRows) != 0)
                    {
                        // Very expensive processing - the developer should avoid this scenario.
                        this.inBulkLayoutCount++;
                        try
                        {
                            for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                                rowIndex != -1;
                                rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                            {
                                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing);
                            }
                        }
                        finally
                        {
                            ExitBulkLayout(false /*invalidInAdjustFillingColumns*/);
                        }
                    }
                    else
                    {
                        Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0);
                        int displayHeight = this.layout.Data.Height;
                        int cy = 0;
 
                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        while (rowIndex != -1 && cy < displayHeight)
                        {
                            AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing);
                            cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                            rowIndex = this.Rows.GetNextRow(rowIndex,
                                DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        }
 
                        if (cy < displayHeight)
                        {
                            int cyFrozen = cy;
                            int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                            rowIndex = oldFirstVisibleScrollingRow;
                            while (rowIndex != -1 && 
                                cy < displayHeight &&
                                oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow)
                            {
                                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing);
                                cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                                rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                            }
 
                            do
                            {
                                oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                                if (cy < displayHeight)
                                {
                                    int rowAboveFirstVisibleScrollingRow = this.Rows.GetPreviousRow(this.displayedBandsInfo.FirstDisplayedScrollingRow, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                                    if (rowAboveFirstVisibleScrollingRow != -1)
                                    {
                                        AutoResizeRowInternal(rowAboveFirstVisibleScrollingRow, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing);
                                    }
                                }
                                cy = cyFrozen;
                                rowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                                while (rowIndex != -1 && cy < displayHeight)
                                {
                                    AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing);
                                    cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                                    rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                                }
                            }
                            while (oldFirstVisibleScrollingRow != this.displayedBandsInfo.FirstDisplayedScrollingRow);
                        }
                    }
                }
                finally
                {
                    ExitBulkPaint(-1, -1);
                }
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AreAllCellsSelected"]/*' />
        // Does not seem to be a valid fxcop violation report. Contacting fxcop team to double-check.
        [SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops")] 
        public bool AreAllCellsSelected(bool includeInvisibleCells)
        {
            if (this.Columns.Count == 0 && this.Rows.Count == 0)
            {
                return true;
            }
            if (!includeInvisibleCells &&
                (this.Rows.GetFirstRow(DataGridViewElementStates.Visible) == -1 ||
                 this.Columns.GetFirstColumn(DataGridViewElementStates.Visible) == null))
            {
                return true;
            }
 
            DataGridViewRow dataGridViewRow = null;
            bool allCellsSelected;
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.CellSelect:
                {
                    allCellsSelected = this.individualSelectedCells.Count == this.Columns.Count * this.Rows.Count;
                    if (allCellsSelected || includeInvisibleCells)
                    {
                        return allCellsSelected;
                    }
                    else
                    {
                        for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                             rowIndex != -1;
                             rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                        {
                            dataGridViewRow = this.Rows[rowIndex]; // unshares this row
 
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                            while (dataGridViewColumn != null)
                            {
                                if (!dataGridViewRow.Cells[dataGridViewColumn.Index].Selected)
                                {
                                    return false;
                                }
                                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                                    DataGridViewElementStates.Visible,
                                    DataGridViewElementStates.None);
                            }
                        }
                        return true;
                    }
                }
                case DataGridViewSelectionMode.FullColumnSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                {
                    allCellsSelected = this.selectedBandIndexes.Count * this.Rows.Count + this.individualSelectedCells.Count == this.Columns.Count * this.Rows.Count;
                    if (allCellsSelected || includeInvisibleCells)
                    {
                        return allCellsSelected;
                    }
                    else
                    {
                        DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                        while (dataGridViewColumn != null)
                        {
                            if (!this.selectedBandIndexes.Contains(dataGridViewColumn.Index))
                            {
                                for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                                    rowIndex != -1;
                                    rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                                {
                                    dataGridViewRow = this.Rows[rowIndex]; // unshares this row
                                    if (!dataGridViewRow.Cells[dataGridViewColumn.Index].Selected)
                                    {
                                        return false;
                                    }
                                }
                            }
                            dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                                DataGridViewElementStates.Visible,
                                DataGridViewElementStates.None);
                        }
                        return true;
                    }
                }
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect:
                {
                    allCellsSelected = this.selectedBandIndexes.Count * this.Columns.Count + this.individualSelectedCells.Count == this.Columns.Count * this.Rows.Count;
                    if (allCellsSelected || includeInvisibleCells)
                    {
                        return allCellsSelected;
                    }
                    else
                    {
                        for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                            rowIndex != -1;
                            rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                        {
                            Debug.Assert(this.selectedBandIndexes.Contains(rowIndex) ==
                                         ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0));
                            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) == 0)
                            {
                                dataGridViewRow = this.Rows[rowIndex]; // unshares this row
                                DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                                while (dataGridViewColumn != null)
                                {
                                    if (!dataGridViewRow.Cells[dataGridViewColumn.Index].Selected)
                                    {
                                        return false;
                                    }
                                    dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                                        DataGridViewElementStates.Visible,
                                        DataGridViewElementStates.None);
                                }
                            }
                        }
                        return true;
                    }
                }
            }
            Debug.Fail("DataGridView.AreAllCellsSelected - Shouldn't reach this code");
            return false;
        }
 
        /// <devdoc>
        ///    <para>Assigns a new parent control to the DataGridView.</para>
        /// </devdoc>
        internal override void AssignParent(Control value)
        {
            if (this.toolTipControl.Activated)
            {
                this.toolTipControl.Activate(false /*activate*/);
            }
            base.AssignParent(value);
        }
 
        private void AutoGenerateDataBoundColumns(DataGridViewColumn[] boundColumns)
        {
            DataGridViewColumnCollection dataGridViewCols = this.Columns;
            DataGridViewColumn[] clonedColumns = new DataGridViewColumn[dataGridViewCols.Count];
            int clonedColumnsCount = 0;
            int i;
 
 
            // 1. Clone all the columns which are currently bound and will also be bound under the new DataSource/DataMember combination.
            // 2. Delete all the currently bound columns.
            // 3. Sort the cloned columns in order of their DisplayIndex.
            // 4. Add the new data bound columns. Here are the rules:
            //      a. if the cloned collection contains (possible multiple) columns with DataProperyHame == current data field,
            //          add the first cloned column that maps to the data field.
            //      b. other wise add the new bound column.
            // 5. Add the remaining cloned columns in the order of their DisplayIndex.
 
            // 1. Clone all the currently bound columns.
            // 
            // We can't do 1. and 2. in the same loop because we need to save the DisplayIndex.
            for (i = 0; i < dataGridViewCols.Count; i++)
            {
                if (this.DataSource != null &&
                    !String.IsNullOrEmpty(dataGridViewCols[i].DataPropertyName) &&
                    !dataGridViewCols[i].IsDataBound)
                {
                    MapDataGridViewColumnToDataBoundField(dataGridViewCols[i]);
                }
 
                if (dataGridViewCols[i].IsDataBound)
                {
                    // We only clone columns which are data bound w/ the new DataSource/DataMember combination.
                    if (this.dataConnection != null && this.dataConnection.BoundColumnIndex(dataGridViewCols[i].DataPropertyName) != -1)
                    {
                        clonedColumns[clonedColumnsCount] = (DataGridViewColumn) dataGridViewCols[i].Clone();
                        clonedColumns[clonedColumnsCount].DisplayIndex = dataGridViewCols[i].DisplayIndex;
                        clonedColumnsCount ++;
                    }
                }
            }
 
            i = 0;
            // 2. Delete all the currently bound columns.
            while (i < dataGridViewCols.Count)
            {
                if (dataGridViewCols[i].IsDataBound)
                {
                    dataGridViewCols.RemoveAtInternal(i, true /*force*/);
                }
                else
                {
                     i++;
                }
            }
 
            // 3. Sort the cloned columns in the order of their DisplayIndex.
 
            // Sort the cloned columns array by the display index.
            // We need to copy the cloned columns into a possibly smaller array.
            DataGridViewColumn[] finalClonedColumns;
            if (clonedColumns.Length == clonedColumnsCount)
            {
                finalClonedColumns = clonedColumns;
            }
            else
            {
                finalClonedColumns = new DataGridViewColumn[clonedColumnsCount];
                Array.Copy(clonedColumns, finalClonedColumns, clonedColumnsCount);
            }
 
            // Sort the array.
            Array.Sort(finalClonedColumns, System.Windows.Forms.DataGridViewColumnCollection.ColumnCollectionOrderComparer);
 
            // 4. Add new columns for the Fields which were not data bound previously ( ie, for fields which do not have a clone ).
            if (boundColumns != null)
            {
                for (int j = 0; j < boundColumns.Length; j ++)
                {
                    if (boundColumns[j] != null && boundColumns[j].IsBrowsableInternal)
                    {
                        bool addNewColumn = true;
                        // Go thru the list of cloned columns and see if there is another column w/ the same data property name.
                        int clonedColIndex = 0;
                        for (; clonedColIndex < clonedColumnsCount; clonedColIndex ++) 
                        {
                            if (finalClonedColumns[clonedColIndex] != null &&
                                String.Compare(finalClonedColumns[clonedColIndex].DataPropertyName,
                                    boundColumns[j].DataPropertyName,
                                    true /*ignoreCase*/,
                                    CultureInfo.InvariantCulture) == 0)
                            {
                                addNewColumn = false;
                                break;
                            }
                        }
 
                        if (addNewColumn)
                        {
                            dataGridViewCols.Add(boundColumns[j]);
                        }
                        else
                        {
                            // add the cloned column.
                            dataGridViewCols.Add(finalClonedColumns[clonedColIndex]);
                            MapDataGridViewColumnToDataBoundField(finalClonedColumns[clonedColIndex]);
                            Debug.Assert(finalClonedColumns[clonedColIndex].IsDataBound);
                            finalClonedColumns[clonedColIndex] = null;
                        }
                    }
                }
            }
            #if DEBUG
            else
            {
                // If there are no data bound columns then there are no cloned columns either.
                Debug.Assert(finalClonedColumns.Length == 0);
                Debug.Assert(clonedColumnsCount == 0);
            }
            #endif // DEBUG
 
            // 5. Add remaining cloned columns.
            if (clonedColumnsCount > 0)
            {
                for (int k = 0; k < finalClonedColumns.Length; k++)
                {
                    if (finalClonedColumns[k] != null)
                    {
                        dataGridViewCols.Add(finalClonedColumns[k]);
                        MapDataGridViewColumnToDataBoundField(finalClonedColumns[k]);
                        Debug.Assert(finalClonedColumns[k].IsDataBound);
                    }
                }
            }
        }
 
        private bool AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter, bool fixedHeight)
        {
            Debug.Assert(autoSizeColumnCriteriaFilter != DataGridViewAutoSizeColumnCriteriaInternal.None);
            Debug.Assert((autoSizeColumnCriteriaFilter & DataGridViewAutoSizeColumnCriteriaInternal.Fill) == 0);
 
            bool ret = false; // No column autosizes by default
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            while (dataGridViewColumn != null)
            {
                DataGridViewAutoSizeColumnCriteriaInternal inheritedAutoSizeColumnCriteria = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode;
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = (inheritedAutoSizeColumnCriteria & autoSizeColumnCriteriaFilter);
                if (autoSizeColumnCriteriaFiltered != 0)
                {
                    ret |= AutoResizeColumnInternal(dataGridViewColumn.Index, inheritedAutoSizeColumnCriteria, fixedHeight);
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None);
            }
            return ret;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumn0"]/*' />
        public void AutoResizeColumn(int columnIndex)
        {
            AutoResizeColumn(columnIndex, DataGridViewAutoSizeColumnMode.AllCells);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumn1"]/*' />
        public void AutoResizeColumn(int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode)
        {
            AutoResizeColumn(columnIndex, autoSizeColumnMode, true);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumn2"]/*' />
        protected void AutoResizeColumn(int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode, bool fixedHeight)
        {
            if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.NotSet ||
                autoSizeColumnMode == DataGridViewAutoSizeColumnMode.None ||
                autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_NeedColumnAutoSizingCriteria, "autoSizeColumnMode"));
            }
            
            switch (autoSizeColumnMode)
            {
                case DataGridViewAutoSizeColumnMode.NotSet:
                case DataGridViewAutoSizeColumnMode.None:
                case DataGridViewAutoSizeColumnMode.ColumnHeader:
                case DataGridViewAutoSizeColumnMode.AllCellsExceptHeader:
                case DataGridViewAutoSizeColumnMode.AllCells:
                case DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader:
                case DataGridViewAutoSizeColumnMode.DisplayedCells:
                case DataGridViewAutoSizeColumnMode.Fill:
                    break;
                default:
                    throw new InvalidEnumArgumentException("autoSizeColumnMode", (int)autoSizeColumnMode, typeof(DataGridViewAutoSizeColumnMode));
            }
 
            if (columnIndex < 0 || columnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("columnIndex");
            }
 
            if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.ColumnHeader && !this.ColumnHeadersVisible)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeInvisibleColumnHeader));
            }
 
            AutoResizeColumnInternal(columnIndex, (DataGridViewAutoSizeColumnCriteriaInternal) autoSizeColumnMode, fixedHeight);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumnHeadersHeight1"]/*' />
        public void AutoResizeColumnHeadersHeight()
        {
            AutoResizeColumnHeadersHeight(true, true);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumnHeadersHeight2"]/*' />
        public void AutoResizeColumnHeadersHeight(int columnIndex)
        {
            AutoResizeColumnHeadersHeight(columnIndex, true, true);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumnHeadersHeight3"]/*' />
        protected void AutoResizeColumnHeadersHeight(bool fixedRowHeadersWidth, bool fixedColumnsWidth)
        {
            if (!this.ColumnHeadersVisible)
            {
                return;
            }
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return;
            }
 
            try
            {
                this.noAutoSizeCount++;
                // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
                // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows.
                int preferredHeight = 0;
                if (this.layout.TopLeftHeader.Width > 0)
                {
                    if (fixedRowHeadersWidth)
                    {
                        preferredHeight = this.TopLeftHeaderCell.GetPreferredHeight(-1, this.layout.TopLeftHeader.Width);
                    }
                    else
                    {
                        preferredHeight = this.TopLeftHeaderCell.GetPreferredSize(-1).Height;
                    }
                }
                int columnsCount = this.Columns.Count;
                for (int columnIndex = 0; columnIndex < columnsCount; columnIndex++)
                {
                    if (this.Columns[columnIndex].Visible)
                    {
                        if (fixedColumnsWidth)
                        {
                            preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndex].HeaderCell.GetPreferredHeight(-1, this.Columns[columnIndex].Thickness));
                        }
                        else
                        {
                            preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndex].HeaderCell.GetPreferredSize(-1).Height);
                        }
                    }
                }
                if (preferredHeight < minimumColumnHeadersHeight)
                {
                    preferredHeight = minimumColumnHeadersHeight;
                }
                if (preferredHeight > maxHeadersThickness)
                {
                    preferredHeight = maxHeadersThickness;
                }
                if (preferredHeight != this.ColumnHeadersHeight)
                {
                    SetColumnHeadersHeightInternal(preferredHeight, !fixedColumnsWidth /*invalidInAdjustFillingColumns*/);
                }
            }
            finally
            {
                Debug.Assert(this.noAutoSizeCount > 0);
                this.noAutoSizeCount--;
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumnHeadersHeight4"]/*' />
        protected void AutoResizeColumnHeadersHeight(int columnIndex, bool fixedRowHeadersWidth, bool fixedColumnWidth)
        {
            if (columnIndex < -1 || columnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("columnIndex");
            }
 
            if (!this.ColumnHeadersVisible)
            {
                return;
            }
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return;
            }
 
            try
            {
                this.noAutoSizeCount++;
                // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
                // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows.
                int preferredHeight = 0;
                if (this.layout.TopLeftHeader.Width > 0)
                {
                    if (columnIndex != -1 || fixedRowHeadersWidth)
                    {
                        preferredHeight = this.TopLeftHeaderCell.GetPreferredHeight(-1, this.layout.TopLeftHeader.Width);
                    }
                    else
                    {
                        preferredHeight = this.TopLeftHeaderCell.GetPreferredSize(-1).Height;
                    }
                }
                int columnsCount = this.Columns.Count;
                for (int columnIndexTmp = 0; columnIndexTmp < columnsCount; columnIndexTmp++)
                {
                    if (this.Columns[columnIndexTmp].Visible)
                    {
                        if (columnIndex != columnIndexTmp || fixedColumnWidth)
                        {
                            preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndexTmp].HeaderCell.GetPreferredHeight(-1, this.Columns[columnIndexTmp].Thickness));
                        }
                        else
                        {
                            preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndexTmp].HeaderCell.GetPreferredSize(-1).Height);
                        }
                    }
                }
                if (preferredHeight < minimumColumnHeadersHeight)
                {
                    preferredHeight = minimumColumnHeadersHeight;
                }
                if (preferredHeight > maxHeadersThickness)
                {
                    preferredHeight = maxHeadersThickness;
                }
                if (preferredHeight != this.ColumnHeadersHeight)
                {
                    SetColumnHeadersHeightInternal(preferredHeight, !fixedColumnWidth /*invalidInAdjustFillingColumns*/);
                }
            }
            finally
            {
                Debug.Assert(this.noAutoSizeCount > 0);
                this.noAutoSizeCount--;
            }
        }
 
        private bool AutoResizeColumnInternal(int columnIndex, DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal, bool fixedHeight)
        {
            Debug.Assert(autoSizeColumnCriteriaInternal == DataGridViewAutoSizeColumnCriteriaInternal.Header ||
                autoSizeColumnCriteriaInternal == DataGridViewAutoSizeColumnCriteriaInternal.AllRows ||
                autoSizeColumnCriteriaInternal == DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows ||
                autoSizeColumnCriteriaInternal == (DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows) ||
                autoSizeColumnCriteriaInternal == (DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows));
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count);
            Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Header || this.ColumnHeadersVisible);
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return false;
            }
 
            bool ret = false; // No autosizing occurs by default.
            try
            {
                this.noAutoSizeCount++;
                // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
                // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns.
                // Note: Even none-resizable column can programmatically be resized.
                DataGridViewColumn dataGridViewColumn = this.Columns[columnIndex];
                int preferredColumnWidth = dataGridViewColumn.GetPreferredWidth((DataGridViewAutoSizeColumnMode) autoSizeColumnCriteriaInternal, fixedHeight);
                if (preferredColumnWidth < dataGridViewColumn.MinimumThickness)
                {
                    preferredColumnWidth = dataGridViewColumn.MinimumThickness;
                }
                if (preferredColumnWidth > DataGridViewBand.maxBandThickness)
                {
                    preferredColumnWidth = DataGridViewBand.maxBandThickness;
                }
                if (preferredColumnWidth != dataGridViewColumn.Thickness)
                {
                    if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                    {
                        AdjustFillingColumn(dataGridViewColumn, preferredColumnWidth);
                    }
                    else
                    {
                        this.Columns[columnIndex].ThicknessInternal = preferredColumnWidth;
                    }
                    ret = true;
                }
            }
            finally
            {
                Debug.Assert(this.noAutoSizeCount > 0);
                this.noAutoSizeCount--;
            }
            return ret;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumns0"]/*' />
        public void AutoResizeColumns()
        {
            AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumns1"]/*' />
        public void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode)
        {
            AutoResizeColumns(autoSizeColumnsMode, true);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeColumns2"]/*' />
        protected void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode, bool fixedHeight)
        {
            for (int columnIndex = 0; columnIndex < this.Columns.Count; columnIndex++)
            {
                AutoResizeColumn(columnIndex, (DataGridViewAutoSizeColumnMode)autoSizeColumnsMode, fixedHeight);
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRow0"]/*' />
        public void AutoResizeRow(int rowIndex)
        {
            AutoResizeRow(rowIndex, DataGridViewAutoSizeRowMode.AllCells);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRow1"]/*' />
        public void AutoResizeRow(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode)
        {
            AutoResizeRow(rowIndex, autoSizeRowMode, true /*fixedWidth*/);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRow2"]/*' />
        protected void AutoResizeRow(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth)
        {
            if (rowIndex < 0 || rowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("rowIndex");
            }
            // not using ClientUtils here because it's a flags enum, masking instead.
            if (((DataGridViewAutoSizeRowCriteriaInternal) autoSizeRowMode & invalidDataGridViewAutoSizeRowCriteriaInternalMask) != 0)
            {
                throw new InvalidEnumArgumentException("autoSizeRowMode", (int) autoSizeRowMode, typeof(DataGridViewAutoSizeRowMode));
            }
            if (autoSizeRowMode == DataGridViewAutoSizeRowMode.RowHeader && !this.RowHeadersVisible)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeRowInvisibleRowHeader));
            }
            AutoResizeRowInternal(rowIndex, autoSizeRowMode, fixedWidth, false /*internalAutosizing*/);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRowHeadersWidth1"]/*' />
        // User can override this if there is a quicker way to determine preferred row headers width
        public void AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode)
        {
            AutoResizeRowHeadersWidth(rowHeadersWidthSizeMode,
                                      true /*fixedColumnHeadersHeight*/,
                                      true /*fixedRowsHeight*/);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRowHeadersWidth2"]/*' />
        // User can override this if there is a quicker way to determine preferred row headers width
        protected void AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode,
                                                 bool fixedColumnHeadersHeight, 
                                                 bool fixedRowsHeight)
        {
            if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing ||
                rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_NeedAutoSizingCriteria, "rowHeadersWidthSizeMode"));
            }
            // custom range checking, not using ClientUtils.
            if (rowHeadersWidthSizeMode < DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders || rowHeadersWidthSizeMode > DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader)
            {     
                throw new InvalidEnumArgumentException("rowHeadersWidthSizeMode", (int)rowHeadersWidthSizeMode, typeof(DataGridViewRowHeadersWidthSizeMode)); 
            }
 
          
            if (!this.RowHeadersVisible)
            {
                return;
            }
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return;
            }
 
            try
            {
                this.noAutoSizeCount++;
                // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
                // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows.
                int preferredWidth = 0, rowIndex;
                if (this.layout.TopLeftHeader.Width > 0)
                {
                    if (fixedColumnHeadersHeight)
                    {
                        preferredWidth = this.TopLeftHeaderCell.GetPreferredWidth(-1, this.layout.TopLeftHeader.Height);
                    }
                    else
                    {
                        preferredWidth = this.TopLeftHeaderCell.GetPreferredSize(-1).Width;
                    }
                }
                switch (rowHeadersWidthSizeMode)
                {
                    case DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader:
                    {
                        rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                        if (rowIndex != -1)
                        {
                            if (fixedRowsHeight)
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredWidth(rowIndex, this.Rows.SharedRow(rowIndex).GetHeight(rowIndex)));
                            }
                            else
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredSize(rowIndex).Width);
                            }
                        }
                        break;
                    }
                    case DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders:
                    {
                        int displayHeight = this.layout.Data.Height, cy = 0;
                        rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        while (rowIndex != -1 && cy < displayHeight)
                        {
                            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                            int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndex);
                            cy += dataGridViewRowHeight;
                            if (fixedRowsHeight)
                            {
                                preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndex, dataGridViewRowHeight));
                            }
                            else
                            {
                                preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndex).Width);
                            }
                            rowIndex = this.Rows.GetNextRow(rowIndex,
                                                            DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        }
                        if (cy < displayHeight)
                        {
                            rowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                            while (rowIndex != -1 && cy < displayHeight)
                            {
                                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                                int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndex);
                                cy += dataGridViewRowHeight;
                                if (fixedRowsHeight)
                                {
                                    preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndex, dataGridViewRowHeight));
                                }
                                else
                                {
                                    preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndex).Width);
                                }
                                rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                            }
                        }
                        break;
                    }
                    case DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders:
                    {
                        for (rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                            rowIndex != -1;
                            rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                        {
                            if (fixedRowsHeight)
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredWidth(rowIndex, this.Rows.SharedRow(rowIndex).GetHeight(rowIndex)));
                            }
                            else
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredSize(rowIndex).Width);
                            }
                        }
                        break;
                    }
                    default:
                    {
                        Debug.Fail("Unexpected rowHeadersWidthSizeMode value in AutoResizeRowHeadersWidth");
                        break;
                    }
                }
                if (preferredWidth < minimumRowHeadersWidth)
                {
                    preferredWidth = minimumRowHeadersWidth;
                }
                if (preferredWidth != this.RowHeadersWidth)
                {
                    this.RowHeadersWidthInternal = preferredWidth;
                }
            }
            finally
            {
                Debug.Assert(this.noAutoSizeCount > 0);
                this.noAutoSizeCount--;
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRowHeadersWidth3"]/*' />
        public void AutoResizeRowHeadersWidth(int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode)
        {
            AutoResizeRowHeadersWidth(rowIndex,
                                      rowHeadersWidthSizeMode,
                                      true /*fixedColumnHeadersHeight*/, 
                                      true /*fixedRowHeight*/);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRowHeadersWidth4"]/*' />
        protected void AutoResizeRowHeadersWidth(int rowIndex,
                                                 DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode,
                                                 bool fixedColumnHeadersHeight, 
                                                 bool fixedRowHeight)
        {
            if (rowIndex < -1 || rowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("rowIndex");
            }
            if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing ||
                rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_NeedAutoSizingCriteria, "rowHeadersWidthSizeMode"));
            }
            if (rowHeadersWidthSizeMode < DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders || rowHeadersWidthSizeMode > DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader) 
            {
                 throw new InvalidEnumArgumentException("rowHeadersWidthSizeMode", (int)rowHeadersWidthSizeMode, typeof(DataGridViewRowHeadersWidthSizeMode)); 
            }
           
            if (!this.RowHeadersVisible)
            {
                return;
            }
            if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader &&
                rowIndex != -1 &&
                rowIndex != this.Rows.GetFirstRow(DataGridViewElementStates.Visible))
            {
                return;
            }
            if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders &&
                rowIndex != -1)
            {
                DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
                bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0;
                if (!rowDisplayed)
                {
                    return;
                }
            }
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return;
            }
 
            try
            {
                this.noAutoSizeCount++;
                // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
                // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows.
                int preferredWidth = 0, rowIndexTmp;
                if (this.layout.TopLeftHeader.Width > 0)
                {
                    if (rowIndex != -1 || fixedColumnHeadersHeight)
                    {
                        preferredWidth = this.TopLeftHeaderCell.GetPreferredWidth(-1, this.layout.TopLeftHeader.Height);
                    }
                    else
                    {
                        preferredWidth = this.TopLeftHeaderCell.GetPreferredSize(-1).Width;
                    }
                }
                switch (rowHeadersWidthSizeMode)
                {
                    case DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader:
                    {
                        rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                        if (rowIndexTmp != -1)
                        {
                            if (rowIndex != rowIndexTmp || fixedRowHeight)
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredWidth(rowIndexTmp, this.Rows.SharedRow(rowIndexTmp).GetHeight(rowIndexTmp)));
                            }
                            else
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredSize(rowIndexTmp).Width);
                            }
                        }
                        break;
                    }
                    case DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders:
                    {
                        int displayHeight = this.layout.Data.Height, cy = 0;
                        rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        while (rowIndexTmp != -1 && cy < displayHeight)
                        {
                            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndexTmp);
                            int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndexTmp);
                            cy += dataGridViewRowHeight;
                            if (rowIndex != rowIndexTmp || fixedRowHeight)
                            {
                                preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndexTmp, dataGridViewRowHeight));
                            }
                            else
                            {
                                preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndexTmp).Width);
                            }
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp,
                                                            DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        }
                        if (cy < displayHeight)
                        {
                            rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                            while (rowIndexTmp != -1 && cy < displayHeight)
                            {
                                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndexTmp);
                                int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndexTmp);
                                cy += dataGridViewRowHeight;
                                if (rowIndex != rowIndexTmp || fixedRowHeight)
                                {
                                    preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndexTmp, dataGridViewRowHeight));
                                }
                                else
                                {
                                    preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndexTmp).Width);
                                }
                                rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                            }
                        }
                        break;
                    }
                    case DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders:
                    {
                        for (rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                            rowIndexTmp != -1;
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible))
                        {
                            if (rowIndex != rowIndexTmp || fixedRowHeight)
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredWidth(rowIndexTmp, this.Rows.SharedRow(rowIndexTmp).GetHeight(rowIndexTmp)));
                            }
                            else
                            {
                                preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredSize(rowIndexTmp).Width);
                            }
                        }
                        break;
                    }
                    default:
                    {
                        Debug.Fail("Unexpected rowHeadersWidthSizeMode value in AutoResizeRowHeadersWidth");
                        break;
                    }
                }
                if (preferredWidth < minimumRowHeadersWidth)
                {
                    preferredWidth = minimumRowHeadersWidth;
                }
                if (preferredWidth != this.RowHeadersWidth)
                {
                    this.RowHeadersWidthInternal = preferredWidth;
                }
            }
            finally
            {
                Debug.Assert(this.noAutoSizeCount > 0);
                this.noAutoSizeCount--;
            }
        }
 
        private void AutoResizeRowInternal(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth, bool internalAutosizing)
        {
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
            Debug.Assert(((DataGridViewAutoSizeRowCriteriaInternal) autoSizeRowMode & invalidDataGridViewAutoSizeRowCriteriaInternalMask) == 0);
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return;
            }
 
            try
            {
                this.noAutoSizeCount++;
                // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
                // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows.
                // Note: Even none-resizable row can programmatically be resized.
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                int height, minimumHeight;
                dataGridViewRow.GetHeightInfo(rowIndex, out height, out minimumHeight);
                int preferredThickness = dataGridViewRow.GetPreferredHeight(rowIndex, autoSizeRowMode, fixedWidth);
                if (preferredThickness < minimumHeight)
                {
                    preferredThickness = minimumHeight;
                }
                if (preferredThickness > DataGridViewBand.maxBandThickness)
                {
                    preferredThickness = DataGridViewBand.maxBandThickness;
                }
                if (height != preferredThickness)
                {
                    if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                    {
                        if (!OnRowHeightInfoPushed(rowIndex, preferredThickness, minimumHeight))
                        {
                            this.Rows[rowIndex].ThicknessInternal = preferredThickness;   // unsharing the resized row
                        }
                    }
                    else
                    {
                        if (internalAutosizing)
                        {
                            this.Rows[rowIndex].ThicknessInternal = preferredThickness;   // unsharing the resized row
                        }
                        else
                        {
                            this.Rows[rowIndex].Thickness = preferredThickness;   // unsharing the resized row
                        }
                    }
                }
            }
            finally
            {
                Debug.Assert(this.noAutoSizeCount > 0);
                this.noAutoSizeCount--;
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRows0"]/*' />
        public void AutoResizeRows()
        {
            AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCells);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRows1"]/*' />
        public void AutoResizeRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode)
        {
            AutoResizeRows(autoSizeRowsMode, true /*fixedWidth*/);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRows2"]/*' />
        protected void AutoResizeRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode, bool fixedWidth)
        {
            switch (autoSizeRowsMode) 
            { 
                case DataGridViewAutoSizeRowsMode.None:
                case DataGridViewAutoSizeRowsMode.AllHeaders:
                case DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders:
                case DataGridViewAutoSizeRowsMode.AllCells:
                case DataGridViewAutoSizeRowsMode.DisplayedHeaders:
                case DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders:
                case DataGridViewAutoSizeRowsMode.DisplayedCells:
                    break;
                default: 
                    throw new InvalidEnumArgumentException("value", (int)autoSizeRowsMode, typeof(DataGridViewAutoSizeRowsMode)); 
            }
 
            if (autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_NeedAutoSizingCriteria, "autoSizeRowsMode"));
            }
 
            if ((autoSizeRowsMode == DataGridViewAutoSizeRowsMode.AllHeaders || autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedHeaders) &&
                !this.RowHeadersVisible)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeRowsInvisibleRowHeader));
            }
 
            AdjustShrinkingRows(autoSizeRowsMode, fixedWidth, false /*internalAutosizing*/);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.AutoResizeRows3"]/*' />
        protected void AutoResizeRows(int rowIndexStart, int rowsCount, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth)
        {
            // not using ClientUtils.IsEnumValid here because DataGridViewAutoSizeRowCriteriaInternal is a flags enum.
            if (((DataGridViewAutoSizeRowCriteriaInternal) autoSizeRowMode & invalidDataGridViewAutoSizeRowCriteriaInternalMask) != 0)
            {
                throw new InvalidEnumArgumentException("autoSizeRowMode", (int) autoSizeRowMode, typeof(DataGridViewAutoSizeRowMode));
            }
 
            if (autoSizeRowMode == DataGridViewAutoSizeRowMode.RowHeader && !this.RowHeadersVisible)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeRowsInvisibleRowHeader));
            }
 
            if (rowsCount < 0)
            {
                throw new ArgumentOutOfRangeException("rowsCount");
            }
 
            if (rowIndexStart < 0)
            {
                throw new ArgumentOutOfRangeException("rowIndexStart");
            }
 
            if (!this.IsHandleCreated)
            {
                // auto sizing causes handle creation.
                // don't create the handle inside InitializeComponent because that causes problems w/ data binding
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true;
                return;
            }
 
            this.inBulkPaintCount++;
            this.inBulkLayoutCount++;
            try
            {
                int rowIndex = this.Rows.GetNextRow(rowIndexStart - 1, DataGridViewElementStates.Visible);
                int autoSizedCount = 0;
                while (rowIndex != -1 && autoSizedCount < rowsCount)
                {
                    AutoResizeRowInternal(rowIndex, autoSizeRowMode, fixedWidth, false /*internalAutosizing*/);
                    autoSizedCount++;
                    if (autoSizedCount < rowsCount)
                    {
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                    }
                }
            }
            finally
            {
                ExitBulkLayout(true /*invalidInAdjustFillingColumns*/);
                ExitBulkPaint(-1, -1);
            }
        }
 
        private void BeginColumnHeadersResize(int mouseY, int mouseBarOffset)
        {
            if (this.IsKeyboardOperationActive())
            {
                return;
            }
 
            Rectangle clip = Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data);
            if (this.layout.TopLeftHeader.Width > 0)
            {
                clip = Rectangle.Union(this.layout.TopLeftHeader, clip);
            }
            clip.Y += minimumColumnHeadersHeight - mouseBarOffset - 1;
            // No need to limit the bottom edge of the cursor clip since maxHeadersThickness is very large.
            CaptureMouse(clip);
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] = true;
            this.trackRowAnchor = mouseY;
            this.mouseBarOffset = mouseBarOffset;
            Debug.Assert(this.lastRowSplitBar == -1);
            this.currentRowSplitBar = mouseY;
            Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar));
        }
 
        private void BeginColumnRelocation(int mouseX, int index) 
        {
            if (this.IsKeyboardOperationActive())
            {
                return;
            }
 
            Rectangle cursorClip = this.layout.ColumnHeaders;
            int frozenWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            int scrollingWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) - frozenWidth;
            if (this.Columns[index].Frozen)
            {
                // A frozen column cannot be relocated into an unfrozen area
                if (this.RightToLeftInternal)
                {
                    cursorClip.X += cursorClip.Width - frozenWidth;
                }
                cursorClip.Width = Math.Min(frozenWidth, this.layout.Data.Width);
            }
            else
            {
                // An unfrozen column cannot be relocated into a frozen area
                if (!this.RightToLeftInternal)
                {
                    cursorClip.X += frozenWidth;
                }
                else if (this.layout.Data.Width > frozenWidth + scrollingWidth)
                {
                    cursorClip.X += this.layout.Data.Width - frozenWidth - scrollingWidth;
                }
                cursorClip.Width = Math.Min(scrollingWidth, this.layout.Data.Width);
            }
            CaptureMouse(cursorClip);
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] = true;
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = false;
            this.trackColumn = index;
            this.trackColumnEdge = -1;
 
            this.mouseBarOffset = GetColumnXFromIndex(index) - mouseX;
            this.lastHeaderShadow = mouseX;
            Invalidate(this.layout.ColumnHeaders);
        }
 
        private void BeginColumnResize(int x, int columnIndex)
        {
            this.trackColAnchor = x;
            this.trackColumn = columnIndex;
 
            this.currentColSplitBar = x;
            Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar));
        }
 
        private void BeginMouseColumnResize(int mouseX, int mouseBarOffset, int index) 
        {
            if (this.IsKeyboardOperationActive())
            {
                return;
            }
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] = true;
            this.mouseBarOffset = mouseBarOffset;
            this.resizeClipRectangle = GetResizeClipRectangle(index);
            CaptureMouse(this.resizeClipRectangle);
 
            BeginColumnResize(mouseX, index);
        }
 
        private void BeginKeyboardColumnResize(int columnIndex)
        {
            if (this.IsMouseOperationActive())
            {
                return;
            }
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackKeyboardColResize] = true;
            this.mouseBarOffset = 0;
            this.resizeClipRectangle = GetResizeClipRectangle(columnIndex);
            this.keyboardResizeStep = this.ScaleToCurrentDpi(this.RightToLeftInternal ? -1 : 1);
            int x = GetColumnXFromIndex(columnIndex);
            x += this.RightToLeftInternal ? -this.Columns[columnIndex].Width : this.Columns[columnIndex].Width;
 
            BeginColumnResize(x, columnIndex);
        }
 
        private Rectangle GetResizeClipRectangle(int columnIndex)
        {
            Rectangle clip = Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data);
            int leftEdge = GetColumnXFromIndex(columnIndex);
            if (this.RightToLeftInternal)
            {
                clip.X = this.layout.Data.X - this.mouseBarOffset - 1;
                clip.Width = leftEdge - this.Columns[columnIndex].MinimumThickness - this.layout.Data.X + 3;
                int overflowWidth = leftEdge - this.mouseBarOffset - clip.Left - DataGridViewBand.maxBandThickness + 1;
                if (overflowWidth > 0)
                {
                    clip.X += overflowWidth;
                    clip.Width -= overflowWidth;
                }
            }
            else
            {
                clip.X = leftEdge + this.Columns[columnIndex].MinimumThickness - this.mouseBarOffset - 1;
                clip.Width = this.layout.Data.Right - leftEdge - 1;
                int overflowWidth = clip.Right + this.mouseBarOffset - leftEdge - DataGridViewBand.maxBandThickness;
                if (overflowWidth > 0)
                {
                    clip.Width -= overflowWidth;
                }
            }
 
            return clip;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.BeginEdit"]/*' />
        public virtual bool BeginEdit(bool selectAll)
        {
            if (this.ptCurrentCell.X == -1)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_NoCurrentCell));
            }
 
            if (this.IsCurrentCellInEditMode)
            {
                return true;
            }
 
            return BeginEditInternal(selectAll);
        }
 
        private bool BeginEditInternal(bool selectAll)
        {
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inBeginEdit])
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_BeginEditNotReentrant));
            }
            try
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inBeginEdit] = true;
                Debug.Assert(this.ptCurrentCell.X >= 0 && this.ptCurrentCell.X < this.Columns.Count);
                Debug.Assert(this.ptCurrentCell.Y >= 0 && this.ptCurrentCell.Y < this.Rows.Count);
                Debug.Assert(!this.IsCurrentCellInEditMode);
 
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                Debug.Assert(dataGridViewCell != null);
 
                if (IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) ||
                    !ColumnEditable(this.ptCurrentCell.X))
                {
                    return false;
                }
 
                Type editControlType = dataGridViewCell.EditType;
                if (editControlType == null)
                {
                    // Current cell does not have an editing control. Does it implement IDataGridViewEditingCell?
                    Type editingCellInterface = dataGridViewCell.GetType().GetInterface("System.Windows.Forms.IDataGridViewEditingCell");
                    if (editingCellInterface == null)
                    {
                        return false;
                    }
                }
 
                DataGridViewCellCancelEventArgs dgvcce = new DataGridViewCellCancelEventArgs(this.ptCurrentCell.X, this.ptCurrentCell.Y);
                OnCellBeginEdit(dgvcce);
                if (dgvcce.Cancel)
                {
                    return false;
                }
                Debug.Assert(!this.IsCurrentCellInEditMode);
 
                if (this.ptCurrentCell.X > -1)
                {
                    DataGridViewCell previousCurrentCell = dataGridViewCell;
                    dataGridViewCell = this.CurrentCellInternal;
                    if (previousCurrentCell != dataGridViewCell)
                    {
                        // VSWhidbey 555494. The new current cell can be a whole different cell. 
                        // In that case, all tests previously done are no longer valid.
                        if (IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) ||
                            !ColumnEditable(this.ptCurrentCell.X))
                        {
                            return false;
                        }
 
                        editControlType = dataGridViewCell.EditType;
                        if (editControlType == null)
                        {
                            // Current cell does not have an editing control. Does it implement IDataGridViewEditingCell?
                            Type editingCellInterface = dataGridViewCell.GetType().GetInterface("System.Windows.Forms.IDataGridViewEditingCell");
                            if (editingCellInterface == null)
                            {
                                return false;
                            }
                        }
                    }
                }
                else
                {
                    return false;
                }
 
                DataGridViewCellStyle dataGridViewCellStyle = dataGridViewCell.GetInheritedStyle(null, this.ptCurrentCell.Y, true);
 
                if (editControlType == null)
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode] = true;
                    InitializeEditingCellValue(ref dataGridViewCellStyle, ref dataGridViewCell);
                    ((IDataGridViewEditingCell)dataGridViewCell).PrepareEditingCellForEdit(selectAll);
                    return true;
                }
 
                Type editingCtrlInterface = editControlType.GetInterface("System.Windows.Forms.IDataGridViewEditingControl");
                if (!editControlType.IsSubclassOf(Type.GetType("System.Windows.Forms.Control")) ||
                    editingCtrlInterface == null)
                {
                    throw new InvalidCastException(SR.GetString(SR.DataGridView_InvalidEditingControl));
                }
                if (this.latestEditingControl != null &&
                    editControlType.IsInstanceOfType(this.latestEditingControl) &&
                    !this.latestEditingControl.GetType().IsSubclassOf(editControlType))
                {
                    this.editingControl = this.latestEditingControl;
                    Debug.Assert(((IDataGridViewEditingControl)this.editingControl).EditingControlDataGridView == this);
                }
                else
                {
                    Debug.Assert(this.editingControl == null);
                    this.editingControl = (Control)SecurityUtils.SecureCreateInstance(editControlType);
                    Debug.Assert(this.editingControl != null);
 
                    ((IDataGridViewEditingControl)this.editingControl).EditingControlDataGridView = this;
                    if (this.latestEditingControl != null)
                    {
                        this.latestEditingControl.Dispose();
                        this.latestEditingControl = null;
                    }
                }
 
                Debug.Assert(this.editingControl != null);
                if (String.IsNullOrEmpty(this.editingControl.AccessibleName))
                {
                    this.editingControl.AccessibleName = SR.GetString(SR.DataGridView_AccEditingControlAccName);
                }
                this.editingControl.ImeMode = this.ImeMode;
 
                ((IDataGridViewEditingControl)this.editingControl).EditingControlRowIndex = this.ptCurrentCell.Y;
 
                InitializeEditingControlValue(ref dataGridViewCellStyle, dataGridViewCell);
 
                WireEditingControlEvents();
 
                Debug.Assert(this.editingControl != null);
                Debug.Assert(this.editingPanel != null);
                DataGridViewEditingControlShowingEventArgs dgvese = new DataGridViewEditingControlShowingEventArgs(this.editingControl, dataGridViewCellStyle);
                OnEditingControlShowing(dgvese);
                Debug.Assert(dgvese.CellStyle != null);
                if (this.editingPanel == null || this.editingControl == null)
                {
                    return false;
                }
                this.editingPanel.BackColor = dgvese.CellStyle.BackColor;
                ((IDataGridViewEditingControl)this.editingControl).ApplyCellStyleToEditingControl(dgvese.CellStyle);
 
                // Get rid of the tooltip if it's showing for the current cell
                if (this.toolTipControl.Activated && this.ptToolTipCell == this.ptCurrentCell)
                {
                    this.toolTipControl.Activate(false /*activate*/);
                }
 
                PositionEditingControl(true, true, true);
 
                // Guarding against bugs in customer code.
                // For example setting the CurrentCell to null in DataGridView_OnLostFocus(...) causes this.editingControl
                // to become null.
                if (this.editingPanel == null || this.editingControl == null)
                {
                    return false;
                }
                else
                {
                    ((IDataGridViewEditingControl)this.editingControl).PrepareEditingControlForEdit(selectAll);
                    InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y);
                    return true;
                }
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inBeginEdit] = false;
            }
        }
 
        private void BeginRowHeadersResize(int mouseX, int mouseBarOffset)
        {
            if (this.IsKeyboardOperationActive())
            {
                return;
            }
 
            Rectangle clip = Rectangle.Union(this.layout.RowHeaders, this.layout.Data);
            if (this.layout.TopLeftHeader.Width > 0)
            {
                clip = Rectangle.Union(this.layout.TopLeftHeader, clip);
            }
            if (this.RightToLeftInternal)
            {
                clip.X -= mouseBarOffset + 1;
                clip.Width -= minimumRowHeadersWidth - 1;
                // No need to limit the left edge of the cursor clip since maxHeadersThickness is very large.
            }
            else
            {
                clip.X += minimumRowHeadersWidth - mouseBarOffset - 1;
                // No need to limit the right edge of the cursor clip since maxHeadersThickness is very large.
            }
            CaptureMouse(clip);
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] = true;
            this.trackColAnchor = mouseX;
            this.mouseBarOffset = mouseBarOffset;
            Debug.Assert(this.lastColSplitBar == -1);
            this.currentColSplitBar = mouseX;
            Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar));
        }
 
        private void BeginRowResize(int mouseY, int mouseBarOffset, int index)
        {
            if (this.IsKeyboardOperationActive())
            {
                return;
            }
 
            Rectangle clip = Rectangle.Union(this.layout.RowHeaders, this.layout.Data);
            int topEdge = GetRowYFromIndex(index);
            clip.Y = topEdge + this.Rows.SharedRow(index).GetMinimumHeight(index) - mouseBarOffset - 1;
            clip.Height = this.layout.Data.Y + this.layout.Data.Height - topEdge - 1;
            CaptureMouse(clip);
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] = true;
            this.trackRowAnchor = mouseY;
            this.trackRow = index;
 
            this.mouseBarOffset = mouseBarOffset;
            Debug.Assert(this.lastRowSplitBar == -1);
            this.currentRowSplitBar = mouseY;
            Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar));
        }
 
        private void BuildInheritedColumnHeaderCellStyle(DataGridViewCellStyle inheritedCellStyle, DataGridViewCell cell)
        {
            Debug.Assert(inheritedCellStyle != null);
            
            DataGridViewCellStyle cellStyle = null;
            if (cell.HasStyle)
            {
                cellStyle = cell.Style;
                Debug.Assert(cellStyle != null);
            }
 
            DataGridViewCellStyle columnHeadersStyle = this.ColumnHeadersDefaultCellStyle;
            Debug.Assert(columnHeadersStyle != null);
 
            DataGridViewCellStyle dataGridViewStyle = this.DefaultCellStyle;
            Debug.Assert(dataGridViewStyle != null);
 
            if (cellStyle != null && !cellStyle.BackColor.IsEmpty)
            {
                inheritedCellStyle.BackColor = cellStyle.BackColor;
            } 
            else if (!columnHeadersStyle.BackColor.IsEmpty)
            {
                inheritedCellStyle.BackColor = columnHeadersStyle.BackColor;
            }
            else
            {
                inheritedCellStyle.BackColor = dataGridViewStyle.BackColor;
            }
 
            if (cellStyle != null && !cellStyle.ForeColor.IsEmpty)
            {
                inheritedCellStyle.ForeColor = cellStyle.ForeColor;
            } 
            else if (!columnHeadersStyle.ForeColor.IsEmpty)
            {
                inheritedCellStyle.ForeColor = columnHeadersStyle.ForeColor;
            }
            else
            {
                inheritedCellStyle.ForeColor = dataGridViewStyle.ForeColor;
            }
 
            if (cellStyle != null && !cellStyle.SelectionBackColor.IsEmpty)
            {
                inheritedCellStyle.SelectionBackColor = cellStyle.SelectionBackColor;
            } 
            else if (!columnHeadersStyle.SelectionBackColor.IsEmpty)
            {
                inheritedCellStyle.SelectionBackColor = columnHeadersStyle.SelectionBackColor;
            }
            else
            {
                inheritedCellStyle.SelectionBackColor = dataGridViewStyle.SelectionBackColor;
            }
 
            if (cellStyle != null && !cellStyle.SelectionForeColor.IsEmpty)
            {
                inheritedCellStyle.SelectionForeColor = cellStyle.SelectionForeColor;
            } 
            else if (!columnHeadersStyle.SelectionForeColor.IsEmpty)
            {
                inheritedCellStyle.SelectionForeColor = columnHeadersStyle.SelectionForeColor;
            }
            else
            {
                inheritedCellStyle.SelectionForeColor = dataGridViewStyle.SelectionForeColor;
            }
 
            if (cellStyle != null && cellStyle.Font != null)
            {
                inheritedCellStyle.Font = cellStyle.Font;
            } 
            else if (columnHeadersStyle.Font != null)
            {
                inheritedCellStyle.Font = columnHeadersStyle.Font;
            }
            else
            {
                inheritedCellStyle.Font = dataGridViewStyle.Font;
            }
 
            if (cellStyle != null && !cellStyle.IsNullValueDefault)
            {
                inheritedCellStyle.NullValue = cellStyle.NullValue;
            }
            else if (!columnHeadersStyle.IsNullValueDefault)
            {
                inheritedCellStyle.NullValue = columnHeadersStyle.NullValue;
            }
            else
            {
                inheritedCellStyle.NullValue = dataGridViewStyle.NullValue;
            }
 
            if (cellStyle != null && !cellStyle.IsDataSourceNullValueDefault)
            {
                inheritedCellStyle.DataSourceNullValue = cellStyle.DataSourceNullValue;
            }
            else if (!columnHeadersStyle.IsDataSourceNullValueDefault)
            {
                inheritedCellStyle.DataSourceNullValue = columnHeadersStyle.DataSourceNullValue;
            }
            else
            {
                inheritedCellStyle.DataSourceNullValue = dataGridViewStyle.DataSourceNullValue;
            }
 
            if (cellStyle != null && cellStyle.Format.Length != 0)
            {
                inheritedCellStyle.Format = cellStyle.Format;
            } 
            else if (columnHeadersStyle.Format.Length != 0)
            {
                inheritedCellStyle.Format = columnHeadersStyle.Format;
            }
            else
            {
                inheritedCellStyle.Format = dataGridViewStyle.Format;
            }
 
            if (cellStyle != null && !cellStyle.IsFormatProviderDefault)
            {
                inheritedCellStyle.FormatProvider = cellStyle.FormatProvider;
            }
            else if (!columnHeadersStyle.IsFormatProviderDefault)
            {
                inheritedCellStyle.FormatProvider = columnHeadersStyle.FormatProvider;
            }
            else
            {
                inheritedCellStyle.FormatProvider = dataGridViewStyle.FormatProvider;
            }
 
            if (cellStyle != null && cellStyle.Alignment != DataGridViewContentAlignment.NotSet)
            {
                inheritedCellStyle.AlignmentInternal = cellStyle.Alignment;
            } 
            else if (columnHeadersStyle != null && columnHeadersStyle.Alignment != DataGridViewContentAlignment.NotSet)
            {
                inheritedCellStyle.AlignmentInternal = columnHeadersStyle.Alignment;
            }
            else
            {
                Debug.Assert(dataGridViewStyle.Alignment != DataGridViewContentAlignment.NotSet);
                inheritedCellStyle.AlignmentInternal = dataGridViewStyle.Alignment;
            }
 
            if (cellStyle != null && cellStyle.WrapMode != DataGridViewTriState.NotSet)
            {
                inheritedCellStyle.WrapModeInternal = cellStyle.WrapMode;
            } 
            else if (columnHeadersStyle != null && columnHeadersStyle.WrapMode != DataGridViewTriState.NotSet)
            {
                inheritedCellStyle.WrapModeInternal = columnHeadersStyle.WrapMode;
            }
            else
            {
                Debug.Assert(dataGridViewStyle.WrapMode != DataGridViewTriState.NotSet);
                inheritedCellStyle.WrapModeInternal = dataGridViewStyle.WrapMode;
            }
 
            if (cellStyle != null && cellStyle.Tag != null)
            {
                inheritedCellStyle.Tag = cellStyle.Tag;
            }
            else if (columnHeadersStyle.Tag != null)
            {
                inheritedCellStyle.Tag = columnHeadersStyle.Tag;
            }
            else
            {
                inheritedCellStyle.Tag = dataGridViewStyle.Tag;
            }
 
            if (cellStyle != null && cellStyle.Padding != Padding.Empty)
            {
                inheritedCellStyle.PaddingInternal = cellStyle.Padding;
            }
            else if (columnHeadersStyle.Padding != Padding.Empty)
            {
                inheritedCellStyle.PaddingInternal = columnHeadersStyle.Padding;
            }
            else
            {
                inheritedCellStyle.PaddingInternal = dataGridViewStyle.Padding;
            }
        }
 
        private Rectangle CalcColRelocationFeedbackRect(int mouseX) 
        {
            Rectangle r, inside = this.layout.ColumnHeaders;
            if (this.layout.TopLeftHeader.Width > 0)
            {
                inside = Rectangle.Union(this.layout.TopLeftHeader, inside);
            }
            if (this.RightToLeftInternal)
            {
                r = new Rectangle(mouseX + this.mouseBarOffset - this.Columns[this.trackColumn].Thickness + 1, 
                                  inside.Y,
                                  this.Columns[this.trackColumn].Thickness, 
                                  inside.Height);
                r.X = Math.Max(inside.Left, r.X);
                r.X = Math.Min(r.X, inside.Right - r.Width);
            }
            else
            {
                r = new Rectangle(mouseX + this.mouseBarOffset - 1, inside.Y, this.Columns[this.trackColumn].Thickness, inside.Height);
                r.X = Math.Min(inside.Right - r.Width, r.X);
                r.X = Math.Max(r.X, inside.Left);
            }
            return r;
        }
 
        private Rectangle CalcColResizeFeedbackRect(int mouseX) 
        {
            Rectangle inside = this.layout.Data;
            Rectangle r = new Rectangle(mouseX + this.mouseBarOffset - 1, inside.Y, 3, inside.Height);
            if (this.RightToLeftInternal)
            {
                r.X = Math.Max(inside.Left, r.X);
            }
            else
            {
                r.X = Math.Min(inside.Right - 3, r.X);
                r.X = Math.Max(r.X, 0);
            }
            return r;
        }
 
        private Rectangle CalcRowResizeFeedbackRect(int mouseY) 
        {
            Rectangle inside = this.layout.Data;
            Rectangle r = new Rectangle(inside.X, mouseY + this.mouseBarOffset - 1, inside.Width, 3);
            r.Y = Math.Min(inside.Bottom - 3, r.Y);
            r.Y = Math.Max(r.Y, 0);
            return r;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.CancelEdit"]/*' />
        public bool CancelEdit()
        {
            return CancelEdit(false /*endEdit, DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.InitialValueRestoration*/);
        }
 
        private bool CancelEdit(bool endEdit /*, DataGridViewDataErrorContexts context*/)
        {
            if (this.ptCurrentCell.X != -1)
            {
                Debug.Assert(this.ptCurrentCell.Y != -1);
 
                int oldCurrentCellX = this.ptCurrentCell.X;
                DataGridViewDataErrorEventArgs dgvdee = CancelEditPrivate(/*ref dataGridViewCurrentCell, context*/);
 
                if (null != dgvdee)
                {
                    if (dgvdee.ThrowException)
                    {
                        throw dgvdee.Exception;
                    }
 
                    if (dgvdee.Cancel)
                    {
                        return false;
                    }
                }
 
                if (this.IsCurrentCellInEditMode)
                {
                    if (endEdit && this.EditMode != DataGridViewEditMode.EditOnEnter && this.editingControl != null)
                    {
                        bool success = EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.InitialValueRestoration, 
                                               DataGridViewValidateCellInternal.Never /*validateCell*/, 
                                               false /*fireCellLeave*/, 
                                               false /*fireCellEnter*/, 
                                               false /*fireRowLeave*/, 
                                               false /*fireRowEnter*/, 
                                               false /*fireLeave*/, 
                                               true /*keepFocus*/, 
                                               true /*resetCurrentCell unused here*/,
                                               true /*resetAnchorCell unused here*/);
                        Debug.Assert(success);
                    }
                    else
                    {
                        DataGridViewDataErrorEventArgs dgvdee2 = null;
                        IDataGridViewEditingCell dataGridViewEditingCell = null;
                        try
                        {
                            this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true;
                            if (this.editingControl != null)
                            {
                                ((IDataGridViewEditingControl)this.editingControl).EditingControlFormattedValue = this.uneditedFormattedValue;
                                ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged = false;
                            }
                            else
                            {
                                Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]);
                                dataGridViewEditingCell = this.CurrentCellInternal as IDataGridViewEditingCell;
                                Debug.Assert(dataGridViewEditingCell != null);
                                dataGridViewEditingCell.EditingCellFormattedValue = this.uneditedFormattedValue;
                                dataGridViewEditingCell.EditingCellValueChanged = false;
                            }
                        }
                        catch (Exception exception)
                        {
                            if (ClientUtils.IsCriticalException(exception))
                            {
                                throw;
                            }
                            dgvdee2 = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X,
                                this.ptCurrentCell.Y,
                                DataGridViewDataErrorContexts.InitialValueRestoration);
                        }
                        finally
                        {
                            this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false;
                        }
                        if (dgvdee2 != null)
                        {
                            OnDataErrorInternal(dgvdee2);
                            if (dgvdee2.ThrowException)
                            {
                                throw dgvdee2.Exception;
                            }
                        }
 
                        if (this.editingControl != null)
                        {
                            ((IDataGridViewEditingControl) this.editingControl).PrepareEditingControlForEdit(true /*selectAll*/);
                        }
                        else
                        {
                            Debug.Assert(dataGridViewEditingCell != null);
                            dataGridViewEditingCell.PrepareEditingCellForEdit(true /*selectAll*/);
                            InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y);
                        }
                    }
                }
                else if (this.ptCurrentCell.X == -1 && this.Focused)
                {
                    Debug.Assert((this.AllowUserToAddRowsInternal && this.Rows.Count == 1) ||
                                 (!this.AllowUserToAddRowsInternal && this.Rows.Count == 0));
                    if (this.Rows.Count > 0)
                    {
                        if (this.Columns.Count > oldCurrentCellX && this.Columns[oldCurrentCellX].Visible)
                        {
                            int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                            if (rowIndex != -1)
                            {
                                bool success = SetAndSelectCurrentCellAddress(oldCurrentCellX,
                                                                              rowIndex,
                                                                              true /*setAnchorCellAddress*/,
                                                                              false /*validateCurrentCell*/,
                                                                              false /*throughMouseClick*/,
                                                                              false /*clearSelection*/,
                                                                              false /*forceCurrentCellSelection*/);
                                Debug.Assert(success);
                            }
                        }
                        else
                        {
                            MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/);
                        }
                    }
                }
            }
            return true;
        }
 
        private DataGridViewDataErrorEventArgs CancelEditPrivate(/*ref DataGridViewCell dataGridViewCurrentCell, DataGridViewDataErrorContexts context*/)
        {
            bool currentCellDirty = this.IsCurrentCellDirty;
            bool currentRowDirty = this.IsCurrentRowDirty;
 
            if (this.IsCurrentCellInEditMode)
            {
                /* Do not push original value back into the cell - VS Whidbey bug 328624
                Exception exception;
                if (!PushFormattedValue(ref dataGridViewCurrentCell, this.uneditedFormattedValue, out exception))
                {
                    Debug.Assert(dataGridViewCurrentCell.RowIndex > -1);
                    DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(exception, 
                                                                                dataGridViewCurrentCell.ColumnIndex, 
                                                                                dataGridViewCurrentCell.RowIndex, 
                                                                                // dataGridViewCurrentCell.Value,
                                                                                // this.uneditedFormattedValue,
                                                                                context);
                    dgvdee.Cancel = true;
                    OnDataErrorInternal(dgvdee);
                    return dgvdee;
                }
                */
                if (this.editingControl != null)
                {
                    ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged = false;
                }
                else
                {
                    Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]);
                    ((IDataGridViewEditingCell)this.CurrentCellInternal).EditingCellValueChanged = false;
                }
                this.IsCurrentCellDirtyInternal = false;
            }
 
            if (this.DataSource != null || this.VirtualMode)
            {
                if ((currentRowDirty && !currentCellDirty) || 
                    (this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] && 
                    !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editedRowChanged]))
                {
                    bool discardNewRow = this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited];
                    this.IsCurrentRowDirtyInternal = false;
                    if (this.VirtualMode)
                    {
                        QuestionEventArgs qe = new QuestionEventArgs(discardNewRow);
                        OnCancelRowEdit(qe);
                        discardNewRow &= qe.Response;
                    }
                    if (this.DataSource != null)
                    {
                        int oldCurrentCellX = this.ptCurrentCell.X;
                        this.dataConnection.CancelRowEdit(true /*restoreRow*/, this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited]/*addNewFinished*/);
                        if (this.dataConnection.List.Count == 0)
                        {
                            // There are no rows left in the back end.
                            if (currentCellDirty || this.ptCurrentCell.Y == -1 || this.ptCurrentCell.X == -1)
                            {
                                if (!IsColumnOutOfBounds(oldCurrentCellX) && this.Columns[oldCurrentCellX].Visible)
                                {
                                    Debug.Assert(0 == this.Rows.GetFirstRow(DataGridViewElementStates.Visible));
                                    // Setting the current cell to the current column in the first row
                                    // will create the new row if the user was editing the cell.
                                    SetAndSelectCurrentCellAddress(oldCurrentCellX,
                                                                   0,
                                                                   true,  /*setAnchorCellAddress*/
                                                                   false, /*validateCurrentCell*/
                                                                   false,  /*throughMouseClick*/
                                                                   true /*clearSelecttion*/,
                                                                   false /*forceCurrentCellSelection (unused)*/);
                                }
                            }
                            else
                            {
                                // Else, simply add a new row.
                                this.dataConnection.OnNewRowNeeded();
                            }
                        }
 
                        // CancelRowEdit discarded the new row if we were editing the new row.
                        discardNewRow = false;
                    }
                    if (this.ptCurrentCell.Y > -1)
                    {
                        InvalidateRowPrivate(this.ptCurrentCell.Y);
                        DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                        if (this.IsCurrentCellInEditMode)
                        {
                            DataGridViewCellStyle dataGridViewCellStyle = dataGridViewCell.GetInheritedStyle(null, this.ptCurrentCell.Y, true);
                            if (this.editingControl != null)
                            {
                                InitializeEditingControlValue(ref dataGridViewCellStyle, dataGridViewCell);
                                if (((IDataGridViewEditingControl) this.editingControl).RepositionEditingControlOnValueChange)
                                {
                                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                                }
                            }
                            else
                            {
                                Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]);
                                InitializeEditingCellValue(ref dataGridViewCellStyle, ref dataGridViewCell);
                            }
                        }
                    }
                    if (discardNewRow && this.ptCurrentCell.Y == this.newRowIndex - 1)
                    {
                        DiscardNewRow();
                    }
                }
            }
            else
            {
                if (!this.IsCurrentRowDirty && 
                    this.ptCurrentCell.Y == this.newRowIndex - 1 &&
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowCreatedByEditing])
                {
                    DiscardNewRow();
                }
            }
            return null;
        }
 
        internal bool CancelToolTipPopup(ToolTip toolTip)
        {
            if (this.toolTipControl.ToolTip == toolTip)
            {
                // Our own tool tip wants to show its text.
                return false;
            }
            else
            {
                // This is an external tool tip control which wants to show a tool tip over the DataGridView.
                // ToolTips from the data Grid view ( the error text, or the formatted text that does not fit in, or the tool tip text from the cell)
                // and the ShowCellToolTips take precedence over the external tool tip.
                return String.IsNullOrEmpty(this.toolTipCaption) && this.ShowCellToolTips;
            }
        }
 
        private bool CanSort(DataGridViewColumn dataGridViewColumn)
        {
            return dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && (!VirtualMode || dataGridViewColumn.IsDataBound);
        }
 
        private bool IsSortable(DataGridViewColumn dataGridViewColumn)
        {
            return dataGridViewColumn.SortMode != DataGridViewColumnSortMode.NotSortable && (!VirtualMode || dataGridViewColumn.IsDataBound);
        }
 
        // determines if a data bound cell can be validated or not
        private bool CanValidateDataBoundDataGridViewCell(DataGridViewCell dataGridViewCurrentCell)
        {
            if (dataGridViewCurrentCell == null)
            {
                if (this.ptCurrentCell.X > -1)
                {
                    dataGridViewCurrentCell = this.CurrentCellInternal;
                }
            }
 
            if (dataGridViewCurrentCell == null)
            {
                return true;
            }
 
            Debug.Assert(dataGridViewCurrentCell.OwningColumn != null);
 
            if (!dataGridViewCurrentCell.OwningColumn.IsDataBoundInternal)
            {
                // we are not data bound so it's not up to us to decide to stop validation
                return true;
            }
 
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose])
            {
                // Dispose is not the place to validate data. Also, chances are that the data source is also disposing itself.
                return false;
            }
 
            if (this.dataConnection == null)
            {
                // if there is no dataConnection then it is not up to this function to stop validation.
                return true;
            }
 
            /////////////////////////////////////////////////////////////////////////////////////////////////
            //                                                                                             //
            // FROM HERE DOWN THE DATA CONNECTION DETERMINES IF THE DATAGRIDVIEW SHOULD VALIDATE THE CELL. //
            //                                                                                             //
            /////////////////////////////////////////////////////////////////////////////////////////////////
 
            if (this.dataConnection.ProcessingMetaDataChanges)
            {
                // don't validate a cell in a data bound column while the property descriptors change under us
                return false;
            }
 
            if (this.dataConnection.CancellingRowEdit && !this.dataConnection.RestoreRow)
            {
                // don't validate a cell in a data bound column while we are cancelling a row edit and the old row is not restored
                return false;
            }
 
            if (this.dataConnection.CurrencyManager.Count <= this.ptCurrentCell.Y)
            {
                // don't validate a row beyond the last row in the back end list
                return false;
            }
 
            if (this.dataConnection.PositionChangingOutsideDataGridView)
            {
                // the position changed outside the data grid view and we haven't validated the data grid view cell already
                // we can't validate it now because if the user cancels validation then we end up 
                // with a position different than the position in the currency manager
                return false;
            }
 
            if (this.dataConnection.ListWasReset)
            {
                // The list was reset outside data grid view.
                // We can't validate it now because we would be pushing a value into a different object ( possibly located in a different list ).
                return false;
            }
 
            return true;
        }
 
        private void CaptureMouse(Rectangle cursorClip)
        {
            this.CaptureInternal = true;
            Cursor.ClipInternal = RectangleToScreen(cursorClip);
        }
 
        private void ClearRegionCache() 
        {
            this.cachedScrollableRegion = null;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.ClearSelection"]/*' />
        public void ClearSelection()
        {
            this.noDimensionChangeCount++;
            this.noSelectionChangeCount++;
 
            bool switchedToBulkPaint = false;
 
            if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold ||
                this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold)
            {
                this.inBulkPaintCount++;
                switchedToBulkPaint = true;
            }
            try
            {
                RemoveIndividuallySelectedCells();
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                    {
                        // If we change the design and start using this.selectedBandIndexes in this SelectionMode,
                        // we'll have to clear those selections too.
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullRowSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    {
                        while(this.selectedBandIndexes.Count > 0)
                        {
                            SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false);
                        }
                        
                        // Force repainting of the current collumn's header cell to remove highlighting
                        if (this.ptCurrentCell.X != -1 && 
                            this.SelectionMode == DataGridViewSelectionMode.FullRowSelect && 
                            AccessibilityImprovements.Level2)
                        { 
                            InvalidateCellPrivate(this.ptCurrentCell.X, -1);
                        }
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                    {
                        while(this.selectedBandIndexes.Count > 0)
                        {
                            SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false);
                        }
                        break;
                    }
                }
            }
            finally
            {
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0);
                this.NoSelectionChangeCount--;
                if (switchedToBulkPaint)
                {
                    ExitBulkPaint(-1, -1);
                }
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.ClearSelection2"]/*' />
        protected void ClearSelection(int columnIndexException, int rowIndexException, bool selectExceptionElement)
        {
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.CellSelect:
                case DataGridViewSelectionMode.FullColumnSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                {
                    if (columnIndexException < 0 || columnIndexException >= this.Columns.Count)
                    {
                        throw new ArgumentOutOfRangeException("columnIndexException");
                    }
                    break;
                }
 
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect:
                {
                    if (columnIndexException < -1 || columnIndexException >= this.Columns.Count)
                    {
                        throw new ArgumentOutOfRangeException("columnIndexException");
                    }
                    break;
                }
            }
            
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.CellSelect:
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect:
                {
                    if (rowIndexException < 0 || rowIndexException >= this.Rows.Count)
                    {
                        throw new ArgumentOutOfRangeException("rowIndexException");
                    }
                    break;
                }
 
                case DataGridViewSelectionMode.FullColumnSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                {
                    if (rowIndexException < -1 || rowIndexException >= this.Rows.Count)
                    {
                        throw new ArgumentOutOfRangeException("rowIndexException");
                    }
                    break;
                }
            }
 
            // Clears all selection except the row/column/cell specified as parameter
            this.noDimensionChangeCount++;
            this.noSelectionChangeCount++;
 
            bool switchedToBulkPaint = false;
 
            if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold ||
                this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold)
            {
                this.inBulkPaintCount++;
                switchedToBulkPaint = true;
            }
            try
            {
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                    {
                        // If we change the design and start using this.selectedBandIndexes in this SelectionMode,
                        // we'll have to clear those selections too.
                        RemoveIndividuallySelectedCells(columnIndexException, rowIndexException);
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullRowSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    {
                        int bandIndex = 0;
                        while (bandIndex < this.selectedBandIndexes.Count)
                        {
                            if (this.selectedBandIndexes[bandIndex] != rowIndexException)
                            {
                                // deselect currently selected row
                                SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false);
                            }
                            else
                            {
                                bandIndex++;
                            }
                        }
                        if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                        {
                            RemoveIndividuallySelectedCells(columnIndexException, rowIndexException);
                        }
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                    {
                        int bandIndex = 0;
                        while (bandIndex < this.selectedBandIndexes.Count)
                        {
                            if (this.selectedBandIndexes[bandIndex] != columnIndexException)
                            {
                                // deselect currently selected column
                                SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false);
                            }
                            else
                            {
                                bandIndex++;
                            }
                        }
                        if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)
                        {
                            RemoveIndividuallySelectedCells(columnIndexException, rowIndexException);
                        }
                        break;
                    }
                }
                if (selectExceptionElement)
                {
                    SetSelectedElementCore(columnIndexException, rowIndexException, true);
                }
            }
            finally
            {
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0);
                this.NoSelectionChangeCount--;
                if (switchedToBulkPaint)
                {
                    ExitBulkPaint(-1, -1);
                }
            }
        }
 
        private bool ColumnEditable(int columnIndex)
        {
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count, "Invalid columnIndex: " + columnIndex );
            if (this.Columns[columnIndex].IsDataBound &&
                this.dataConnection != null &&
                !this.dataConnection.AllowEdit)
            {
                return false;
            }
            return true;
        }
 
        private bool ColumnNeedsDisplayedState(DataGridViewColumn dataGridViewColumn)
        {
            Debug.Assert(dataGridViewColumn != null);
 
            if (!dataGridViewColumn.Visible)
            {
                return false;
            }
 
            if (dataGridViewColumn.Frozen)
            {
                DataGridViewColumn firstVisibleFrozenColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                Debug.Assert(firstVisibleFrozenColumn != null);
                if (firstVisibleFrozenColumn.Index == dataGridViewColumn.Index)
                {
                    return this.displayedBandsInfo.NumDisplayedFrozenCols > 0;
                }
                Debug.Assert(this.Columns.DisplayInOrder(firstVisibleFrozenColumn.Index, dataGridViewColumn.Index));
                return this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, firstVisibleFrozenColumn.Index, dataGridViewColumn.Index) < this.displayedBandsInfo.NumDisplayedFrozenCols;
            }
            else
            {
                int firstDisplayedScrollingColumnIndex = this.displayedBandsInfo.FirstDisplayedScrollingCol;
                if (firstDisplayedScrollingColumnIndex != -1)
                {
                    if (firstDisplayedScrollingColumnIndex == dataGridViewColumn.Index)
                    {
                        return this.displayedBandsInfo.NumDisplayedScrollingCols > 0;
                    }
                    if (this.Columns.DisplayInOrder(firstDisplayedScrollingColumnIndex, dataGridViewColumn.Index))
                    {
                        return this.Columns.GetColumnCount(DataGridViewElementStates.Visible, firstDisplayedScrollingColumnIndex, dataGridViewColumn.Index) < this.displayedBandsInfo.NumDisplayedScrollingCols;
                    }
                }
            }
            return false;
        }
 
        private bool ColumnRelocationTarget(MouseEventArgs e, HitTestInfo hti, out int previousColumnIndex)
        {
            previousColumnIndex = -1;
            if (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeader ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderRight)
            {
                Debug.Assert(hti.col != -1);
                if (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom ||
                    hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeader)
                {
                    int xColumnLeftEdge = GetColumnXFromIndex(hti.col);
                    int wColumn = this.Columns[hti.col].Width;
                    if ((this.RightToLeftInternal && e.X < xColumnLeftEdge - wColumn / 2) || 
                        (!this.RightToLeftInternal && e.X > xColumnLeftEdge + wColumn / 2))
                    {
                        // Insert column on the right of hti.col
                        previousColumnIndex = hti.col;
                    }
                    else
                    {
                        // Insert column on the left of hti.col
                        DataGridViewColumn dataGridViewColumnPrev = this.Columns.GetPreviousColumn(this.Columns[hti.col],
                                                                                                            DataGridViewElementStates.Visible,
                                                                                                            DataGridViewElementStates.None);
                        if (dataGridViewColumnPrev != null)
                        {
                            previousColumnIndex = dataGridViewColumnPrev.Index;
                        }
                    }
                }
                else
                {
                    previousColumnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderRight) ? 
                                          hti.col : hti.adjacentCol;
                }
                DataGridViewColumn dataGridViewColumnNext = null;
                if (previousColumnIndex != -1)
                {
                    dataGridViewColumnNext = this.Columns.GetNextColumn(this.Columns[previousColumnIndex],
                                                                                 DataGridViewElementStates.Visible,
                                                                                 DataGridViewElementStates.None);
                }
                if (this.trackColumn != previousColumnIndex &&
                    !(previousColumnIndex == -1 && hti.col == this.trackColumn) &&
                    (dataGridViewColumnNext == null || this.trackColumn != dataGridViewColumnNext.Index))
                {
                    return true; 
                }
            }
            else if (hti.typeInternal == DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft ||
                     hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight)
            {
                Debug.Assert(hti.col != -1);
                if (hti.col != this.trackColumn)
                {
                    return true; 
                }
            }
            return false;
        }
 
        private static bool ColumnsDisplayInOrder(int columnIndex1, 
            int columnDisplayIndex1, 
            int columnIndex2,
            int columnDisplayIndex2)
        {
            return columnDisplayIndex1 < columnDisplayIndex2 ||
                (columnDisplayIndex1 == columnDisplayIndex2 && columnIndex1 < columnIndex2);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.CommitEdit"]/*' />
        public bool CommitEdit(DataGridViewDataErrorContexts context)
        {
            if (this.IsCurrentCellInEditMode)
            {
                DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal;
                DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, 
                    context, 
                    DataGridViewValidateCellInternal.Never,
                    false /*fireCellLeave*/,
                    false /*fireCellEnter*/,
                    false /*fireRowLeave*/,
                    false /*fireRowEnter*/, 
                    false /*fireLeave*/);
                if (null != dgvdee)
                {
                    if (dgvdee.ThrowException)
                    {
                        throw dgvdee.Exception;
                    }
                    if (dgvdee.Cancel)
                    {
                        return false;
                    }
                }
            }
            return true;
        }
 
        private DataGridViewDataErrorEventArgs CommitEdit(ref DataGridViewCell dataGridViewCurrentCell, 
            DataGridViewDataErrorContexts context, 
            DataGridViewValidateCellInternal validateCell,
            bool fireCellLeave,
            bool fireCellEnter,
            bool fireRowLeave,
            bool fireRowEnter,
            bool fireLeave)
        {
            if (validateCell == DataGridViewValidateCellInternal.Always)
            {
                Debug.Assert(this.ptCurrentCell.X > -1);
                if (fireCellLeave)
                {
                    if (this.ptCurrentCell.X == -1)
                    {
                        return null;
                    }
                    OnCellLeave(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                }
                if (fireRowLeave)
                {
                    if (this.ptCurrentCell.X == -1)
                    {
                        return null;
                    }
                    OnRowLeave(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                }
                if (fireLeave)
                {
                    base.OnLeave(EventArgs.Empty);
 
                    // Microsoft: can we be smarter about this? What if validating the current cell below forces a repaint on the cell?
                    // we would end up repainting the current cell twice.
                    //
                    // invalidate the current cell so the data grid view does not paint the focus rectangle any longer
                    if (this.ptCurrentCell.X > -1 && this.ptCurrentCell.Y > -1)
                    {
                        InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/);
                    }
                }
                // OnCellValidating returns true if the dev cancelled the validation.
                bool validateFormattedValue = CanValidateDataBoundDataGridViewCell(dataGridViewCurrentCell);
                if (validateFormattedValue)
                {
                    if (this.ptCurrentCell.X == -1)
                    {
                        return null;
                    }
                    if (OnCellValidating(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, context))
                    {
                        if (fireRowEnter)
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                return null;
                            }
                            OnRowEnter(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, true /*canCreateNewRow*/, true /*validationFailureOccurred*/);
                        }
                        if (fireCellEnter)
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                return null;
                            }
                            OnCellEnter(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                        }
                        if (this.ptCurrentCell.X == -1)
                        {
                            return null;
                        }
                        DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(null, 
                                                                                    this.ptCurrentCell.X, 
                                                                                    this.ptCurrentCell.Y, 
                                                                                    // null, 
                                                                                    // null, 
                                                                                    context);
                        dgvdee.Cancel = true;
                        return dgvdee;
                    }
 
                    if (!this.IsCurrentCellInEditMode || !this.IsCurrentCellDirty)
                    {
                        if (this.ptCurrentCell.X == -1)
                        {
                            return null;
                        }
                        OnCellValidated(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                    }
                }
            }
 
            if (this.ptCurrentCell.X == -1 || !this.IsCurrentCellInEditMode)
            {
                return null;
            }
 
            Debug.Assert(
                 (
                  (this.editingControl != null && ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged) ||
                  (this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode] && ((IDataGridViewEditingCell)this.CurrentCellInternal).EditingCellValueChanged)
                 ) == this.IsCurrentCellDirty ||
                 this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges]);
 
            if (this.IsCurrentCellDirty)
            {
                bool validateAndPushFormattedValue = CanValidateDataBoundDataGridViewCell(dataGridViewCurrentCell);
                if (validateAndPushFormattedValue)
                {
                    if (validateCell == DataGridViewValidateCellInternal.WhenChanged)
                    {
                        Debug.Assert(this.ptCurrentCell.X > -1);
                        if (this.ptCurrentCell.X == -1)
                        {
                            return null;
                        }
                        if (OnCellValidating(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, context))
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                return null;
                            }
                            DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(null, 
                                                                                                       this.ptCurrentCell.X, 
                                                                                                       this.ptCurrentCell.Y, 
                                                                                                       context);
                            dgvdee.Cancel = true;
                            return dgvdee;
                        }
                    }
 
                    Exception exception;
                    object formattedValue;
 
                    if (this.editingControl != null)
                    {
                        formattedValue = ((IDataGridViewEditingControl)this.editingControl).GetEditingControlFormattedValue(context);
                    }
                    else
                    {
                        Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]);
                        formattedValue = ((IDataGridViewEditingCell)this.CurrentCellInternal).GetEditingCellFormattedValue(context);
                    }
 
                    if (!PushFormattedValue(ref dataGridViewCurrentCell, formattedValue, out exception))
                    {
                        if (this.ptCurrentCell.X == -1)
                        {
                            return null;
                        }
                        DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(exception, 
                                                                                    this.ptCurrentCell.X, 
                                                                                    this.ptCurrentCell.Y, 
                                                                                    // dataGridViewCurrentCell.Value,
                                                                                    // formattedValue,
                                                                                    context);
                        dgvdee.Cancel = true;
                        OnDataErrorInternal(dgvdee);
                        return dgvdee;
                    }
                    if (!this.IsCurrentCellInEditMode)
                    {
                        return null;
                    }
                    this.uneditedFormattedValue = formattedValue;
                }
 
                if (this.editingControl != null)
                {
                    ((IDataGridViewEditingControl) this.editingControl).EditingControlValueChanged = false;
                }
                else
                {
                    Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]);
                    ((IDataGridViewEditingCell) this.CurrentCellInternal).EditingCellValueChanged = false;
                }
                this.IsCurrentCellDirtyInternal = false;
                this.IsCurrentRowDirtyInternal = true;
 
                if (validateAndPushFormattedValue)
                {
                    if (validateCell == DataGridViewValidateCellInternal.Always || 
                        validateCell == DataGridViewValidateCellInternal.WhenChanged)
                    {
                        if (this.ptCurrentCell.X == -1)
                        {
                            return null;
                        }
                        OnCellValidated(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                    }
                }
            }
            return null;
        }
 
        private bool CommitEdit(DataGridViewDataErrorContexts context, 
                                bool forCurrentCellChange, 
                                bool forCurrentRowChange)
        {
            // If we're already within a CellValidating event handler, don't try to commit the cell again.
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating])
            {
                return false;
            }
 
            DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal;
            DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, 
                context, 
                forCurrentCellChange ? DataGridViewValidateCellInternal.Always : DataGridViewValidateCellInternal.WhenChanged /*validateCell*/,
                forCurrentCellChange /*fireCellLeave*/,
                forCurrentCellChange /*fireCellEnter*/,
                forCurrentRowChange /*fireRowLeave*/,
                forCurrentRowChange /*fireRowEnter*/,
                false /*fireLeave*/);
            if (null != dgvdee)
            {
                if (dgvdee.ThrowException)
                {
                    throw dgvdee.Exception;
                }
                if (dgvdee.Cancel)
                {
                    return false;
                }
                dgvdee = CancelEditPrivate(/*ref dataGridViewCurrentCell, 
                                           DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll*/);    // restore old value
                if (null != dgvdee)
                {
                    if (dgvdee.ThrowException)
                    {
                        throw dgvdee.Exception;
                    }
                    if (dgvdee.Cancel)
                    {
                        return false;
                    }
                }
            }
 
            // See if we can leave the row
            if (forCurrentRowChange && forCurrentCellChange)
            {
                Debug.Assert(this.ptCurrentCell.X > -1);
                if (this.ptCurrentCell.X == -1)
                {
                    return false;
                }
                int columnIndex = this.ptCurrentCell.X;
                int rowIndex = this.ptCurrentCell.Y;
                // OnRowValidating returns true when the row validation was cancelled.
                if (OnRowValidating(ref dataGridViewCurrentCell, columnIndex, rowIndex))
                {
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                    {
                        return false;
                    }
                    OnRowEnter(ref dataGridViewCurrentCell, columnIndex, rowIndex, true /*canCreateNewRow*/, true /*validationFailureOccurred*/);
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                    {
                        return false;
                    }
                    OnCellEnter(ref dataGridViewCurrentCell, columnIndex, rowIndex);
                    return false;
                }
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                {
                    return false;
                }
                OnRowValidated(ref dataGridViewCurrentCell, columnIndex, rowIndex);
            }
            return true;
        }
 
        private bool CommitEditForOperation(int columnIndex, int rowIndex, bool forCurrentCellChange)
        {
            if (forCurrentCellChange)
            {
                if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange,
                                DataGridViewValidateCellInternal.Always /*validateCell*/, 
                                true /*fireCellLeave*/, 
                                true /*fireCellEnter*/, 
                                this.ptCurrentCell.Y != rowIndex /*fireRowLeave*/, 
                                this.ptCurrentCell.Y != rowIndex /*fireRowEnter*/, 
                                false /*fireLeave*/, 
                                this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/, 
                                false /*resetCurrentCell*/,
                                false /*resetAnchorCell unused here*/))
                {
                    return false;
                }
                if (this.ptCurrentCell.Y != rowIndex && this.ptCurrentCell.Y != -1)
                {
                    DataGridViewCell dataGridViewCellTmp = null;
                    int columnIndexTmp = this.ptCurrentCell.X;
                    int rowIndexTmp = this.ptCurrentCell.Y;
                    if (OnRowValidating(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp))
                    {
                        // Row validation was cancelled
                        if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp))
                        {
                            return false;
                        }
                        OnRowEnter(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp, true /*canCreateNewRow*/, true /*validationFailureOccurred*/);
                        if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp))
                        {
                            return false;
                        }
                        OnCellEnter(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp);
                        if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp))
                        {
                            return false;
                        }
 
                        // Re-enter editing mode if needed
                        if (this.Focused &&
                            (!this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter ||
                            (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))))
                        {
                            BeginEditInternal(true /*selectAll*/);
                        }
                        
                        return false;
                    }
                    if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp))
                    {
                        return false;
                    }
                    OnRowValidated(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp);
                }
            }
            else
            {
                if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                false /*forCurrentCellChange*/, 
                                this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/))
                {
                    return false;
                }
            }
 
            // Row validation was not cancelled, but operation needs to be re-evaluated.
            Debug.Assert(columnIndex < this.Columns.Count);
            if (IsColumnOutOfBounds(columnIndex))
            {
                return false;
            }
            if (rowIndex >= this.Rows.Count)
            {
                // CurrentCell was reset because the commit deleted row(s).
                // Since the user wants to change the current cell, we don't
                // want to end up with no CurrentCell. We pick the last visible 
                // row in the grid which may be the 'new row'.
                int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                if (forCurrentCellChange &&
                    this.ptCurrentCell.X == -1 && 
                    lastVisibleRowIndex != -1)
                {
                    bool success = SetAndSelectCurrentCellAddress(columnIndex, lastVisibleRowIndex, true, false, false, false /*clearSelection*/, false /*forceCurrentCellSelection*/);
                    Debug.Assert(success);
                }
                // Interrupt operation because it has become invalid.
                return false;
            }
            if (rowIndex > -1 && (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) == 0)
            {
                // Interrupt operation because target row has become invisible.
                return false;
            }
            return true;
        }
 
        internal void CompleteCellsCollection(DataGridViewRow dataGridViewRow)
        {
            Debug.Assert(dataGridViewRow != null);
            int cellsInCollection = dataGridViewRow.Cells.Count;
            if (this.Columns.Count > cellsInCollection)
            {
                int cellCount = 0;
                DataGridViewCell[] cells = new DataGridViewCell[this.Columns.Count - cellsInCollection];
                for (int columnIndex = cellsInCollection; columnIndex < this.Columns.Count; columnIndex++)
                {
                    if (this.Columns[columnIndex].CellTemplate == null)
                    {
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_AColumnHasNoCellTemplate));
                    }
                    DataGridViewCell dgvcNew = (DataGridViewCell) this.Columns[columnIndex].CellTemplate.Clone();
                    cells[cellCount] = dgvcNew;
                    cellCount ++;
                }
                dataGridViewRow.Cells.AddRange(cells);
            }
        }
 
        /// <devdoc>
        ///      Determines which column is the first visible scrolling 
        ///      column given the object's horizontalOffset.
        /// </devdoc>
        private int ComputeFirstVisibleScrollingColumn() 
        {
            if (this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) >= this.layout.Data.Width)
            {
                // Not enough room for scrolling columns.
                this.negOffset = 0;
                return -1;
            }
 
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
 
            if (this.horizontalOffset == 0)
            {
                this.negOffset = 0;
                return (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            }
 
            int cx = 0;
            while (dataGridViewColumn != null)
            {
                cx += dataGridViewColumn.Thickness;
                if (cx > this.horizontalOffset)
                {
                    break;
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None);
            }
 
            if (dataGridViewColumn == null)
            {
                Debug.Assert(cx <= this.horizontalOffset);
                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                if (dataGridViewColumn == null)
                {
                    this.negOffset = 0;
                    return -1;
                }
                else
                {
                    if (this.negOffset != this.horizontalOffset)
                    {
                        this.negOffset = 0;
                    }
                    return dataGridViewColumn.Index;
                }
            }
            else
            {
                this.negOffset = dataGridViewColumn.Thickness - (cx - this.horizontalOffset);
                return dataGridViewColumn.Index;
            }
        }
 
        private int ComputeHeightOfFittingTrailingScrollingRows(int totalVisibleFrozenHeight)
        {
            // 
            int displayHeight = this.layout.Data.Height - totalVisibleFrozenHeight;
            int rowHeight = 0, rowHeights = 0;
            int indexTmp = this.Rows.Count;
   
            if (indexTmp == 0 || displayHeight <= 0)
            {
                return 0;
            }
            else
            {
                indexTmp--;
            }
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(indexTmp);
            if ((rowState & DataGridViewElementStates.Frozen) != 0)
            {
                return 0;
            }
            if ((rowState & DataGridViewElementStates.Visible) == 0)
            {
                indexTmp = this.Rows.GetPreviousRow(indexTmp,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
            }
 
            if (indexTmp != -1)
            {
                rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                if (rowHeight > displayHeight)
                {
                    return rowHeight;
                }
            }
 
            while (indexTmp != -1 && rowHeights + rowHeight <= displayHeight)
            {
                rowHeights += rowHeight;
                indexTmp = this.Rows.GetPreviousRow(indexTmp, 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
                if (indexTmp != -1)
                {
                    rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                }
            }
 
            return rowHeights;
        }
 
        private int ComputeHeightOfScrolledOffRows()
        {
            // 
            int height = 0;
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0)
            {
                int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                if (rowIndex != -1)
                {
                    while (rowIndex != this.displayedBandsInfo.FirstDisplayedScrollingRow)
                    {
                        Debug.Assert(rowIndex < this.displayedBandsInfo.FirstDisplayedScrollingRow);
                        height += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                    }
                }
            }
            return height;
        }
 
        private int ComputeHeightOfTrailingScrollingRows()
        {
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0)
            {
                int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                return this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, lastVisibleRowIndex) +
                       this.Rows.SharedRow(lastVisibleRowIndex).GetHeight(lastVisibleRowIndex);
            }
            return 0;
        }
 
        private bool ComputeLayout() 
        {
            ClearRegionCache();
 
            LayoutData newLayout = new LayoutData(this.layout);
            Rectangle oldResizeRect = this.layout.ResizeBoxRect;
 
            // Inside region
            if (this.normalClientRectangle.Width > 0 || this.normalClientRectangle.Height > 0)
            {
                newLayout.Inside = this.normalClientRectangle;
            }
            else
            {
                newLayout.Inside = this.ClientRectangle;
            }
            Rectangle inside = newLayout.Inside;
            int borderWidth = this.BorderWidth;
            inside.Inflate(-borderWidth, -borderWidth);
            if (inside.Height < 0)
            {
                inside.Height = 0;
            }
            if (inside.Width < 0)
            {
                inside.Width = 0;
            }
 
            Rectangle insideLeft = inside;
 
            // Headers
            if (this.layout.ColumnHeadersVisible) 
            {
                Rectangle colHeaders = insideLeft;
                colHeaders.Height = Math.Min(this.columnHeadersHeight, colHeaders.Height);
                insideLeft.Y += colHeaders.Height;
                insideLeft.Height -= colHeaders.Height;
                Debug.Assert(insideLeft.Height >= 0);
                newLayout.ColumnHeaders = colHeaders;
            }
            else 
            {
                newLayout.ColumnHeaders = Rectangle.Empty;
            }
 
            if (this.layout.RowHeadersVisible) 
            {
                Rectangle rowHeaders = insideLeft;
                rowHeaders.Width = Math.Min(this.rowHeadersWidth, rowHeaders.Width);
                if (this.RightToLeftInternal)
                {
                    rowHeaders.X += insideLeft.Width - rowHeaders.Width;
                }
                else
                {
                    insideLeft.X += rowHeaders.Width;
                }
                insideLeft.Width -= rowHeaders.Width;
                Debug.Assert(insideLeft.Width >= 0);
                newLayout.RowHeaders = rowHeaders;
 
                if (this.layout.ColumnHeadersVisible) 
                {
                    Rectangle topLeft;
                    Rectangle colHeaders = newLayout.ColumnHeaders;
                    topLeft = colHeaders;
                    topLeft.Width = Math.Min(this.rowHeadersWidth, topLeft.Width);
                    colHeaders.Width -= topLeft.Width;
                    if (this.RightToLeftInternal)
                    {
                        topLeft.X += insideLeft.Width;
                    }
                    else
                    {
                        colHeaders.X += topLeft.Width;
                    }
                    Debug.Assert(colHeaders.Width >= 0);
                    newLayout.TopLeftHeader = topLeft;
                    newLayout.ColumnHeaders = colHeaders;
                }
                else
                {
                    newLayout.TopLeftHeader = Rectangle.Empty;
                }
            }
            else 
            {
                newLayout.RowHeaders = Rectangle.Empty;
                newLayout.TopLeftHeader = Rectangle.Empty;
            }
 
            // Adjust insideLeft in case static top / left edge needs to be painted
            if (this.SingleVerticalBorderAdded)
            {
                if (!this.RightToLeftInternal)
                {
                    insideLeft.X++;
                }
                if (insideLeft.Width > 0)
                {
                    insideLeft.Width--;
                }
            }
            if (this.SingleHorizontalBorderAdded)
            {
                insideLeft.Y++;
                if (insideLeft.Height > 0)
                {
                    insideLeft.Height--;
                }
            }
            
            // Data region
            newLayout.Data = insideLeft;
            newLayout.Inside = inside;
 
            Debug.Assert(newLayout.Data.X >= 0);
            Debug.Assert(newLayout.Data.Y >= 0);
            Debug.Assert(newLayout.Data.Width >= 0);
            Debug.Assert(newLayout.Data.Height >= 0);
 
            this.layout = newLayout;
            this.layout.dirty = false;
 
            bool columnsAdjusted = AdjustFillingColumns();
 
            this.layout = newLayout;
            Debug.Assert(!this.layout.dirty);
            LayoutScrollBars();
 
            // if the user shrank the grid client area, then OnResize invalidated the old
            // resize area. however, we need to invalidate the left upper corner in the new ResizeArea
            // note that we can't take the Invalidate call from the OnResize method, because if the
            // user enlarges the form then the old area will not be invalidated.
            // 
            if (!oldResizeRect.Equals(this.layout.ResizeBoxRect) && !this.layout.ResizeBoxRect.IsEmpty)
            {
                Invalidate(this.layout.ResizeBoxRect);
            }
 
            return columnsAdjusted;
        }
 
        private void ComputeLayoutShortcut(bool computeVisibleRows)
        {
            // Called instead of ComputeLayout when a row is added, inserted or deleted beyond the limits of 
            // the layout.Data area. 
            // this.layout is unchanged - only the potential vertical scrollbar is affected.
 
            if (computeVisibleRows)
            {
                ComputeVisibleRows();
            }
            #if DEBUG
            else
            {
                int oldNumTotallyVisibleFrozenRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows;
                int oldNumVisibleScrollingRows = this.displayedBandsInfo.NumDisplayedScrollingRows;
                int oldNumTotallyVisibleScrollingRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows;
                int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                ComputeVisibleRows();
                Debug.Assert(oldNumTotallyVisibleFrozenRows == this.displayedBandsInfo.NumTotallyDisplayedFrozenRows);
                Debug.Assert(oldNumVisibleScrollingRows == this.displayedBandsInfo.NumDisplayedScrollingRows);
                Debug.Assert(oldNumTotallyVisibleScrollingRows == this.displayedBandsInfo.NumTotallyDisplayedScrollingRows);
                Debug.Assert(oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow);
            }
            #endif
 
            #if DEBUG
                int newFirstVisibleScrollingCol = ComputeFirstVisibleScrollingColumn();
                Debug.Assert(newFirstVisibleScrollingCol == this.displayedBandsInfo.FirstDisplayedScrollingCol);
 
                int oldLastTotallyVisibleScrollingCol = this.displayedBandsInfo.LastTotallyDisplayedScrollingCol;
                int oldFirstVisibleScrollingCol = this.displayedBandsInfo.FirstDisplayedScrollingCol;
                ComputeVisibleColumns();
                Debug.Assert(oldLastTotallyVisibleScrollingCol == this.displayedBandsInfo.LastTotallyDisplayedScrollingCol);
                Debug.Assert(oldFirstVisibleScrollingCol == this.displayedBandsInfo.FirstDisplayedScrollingCol);
            #endif
 
            if (this.vertScrollBar.Enabled)
            {
                int totalVisibleHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible);
                int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                int oldVertScrollBarValue = this.vertScrollBar.Value;
                int oldThumbHeight = Math.Max(((this.vertScrollBar.Height - 2*SystemInformation.VerticalScrollBarArrowHeight) * this.vertScrollBar.LargeChange) / this.vertScrollBar.Maximum, 8);
 
                this.vertScrollBar.Maximum = totalVisibleHeight - totalVisibleFrozenHeight;
                Debug.Assert(this.vertScrollBar.Maximum > 0);
                this.vertScrollBar.Value = ComputeHeightOfScrolledOffRows();
                this.vertScrollBar.LargeChange = this.layout.Data.Height - totalVisibleFrozenHeight;
                this.verticalOffset = this.vertScrollBar.Value;
 
                if (this.vertScrollBar.Visible &&
                    (oldVertScrollBarValue != this.verticalOffset ||
                     oldThumbHeight != Math.Max(((this.vertScrollBar.Height - 2*SystemInformation.VerticalScrollBarArrowHeight) * this.vertScrollBar.LargeChange) / this.vertScrollBar.Maximum, 8)))
                {
                    // Only update the vertical scroll bar is the thumb moved or resized.
                    this.vertScrollBar.Invalidate();
                }
                Debug.Assert(this.verticalOffset == this.vertScrollBar.Value);
            }
        }
 
        /* Unused for now
        private int ComputeScrolledOffRowCount(int scrolledOffRowsHeight)
        {
            int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
            if (rowIndex == -1)
            {
                // No scrolling rows
                return 0;
            }
            else
            {
                int height = 0;
                int rowCount = 0;
                while (rowIndex != -1 && height < scrolledOffRowsHeight)
                {
                    height += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                    if (height <= scrolledOffRowsHeight)
                    {
                        rowCount++;
                    }
                    rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                }
                return rowCount;
            }
        }
        */
 
        private void ComputeVisibleColumns() 
        {
            DataGridViewColumn dataGridViewColumn = null;
            int numVisibleScrollingCols = 0, visibleScrollingColumnsTmp = 0;
            int displayWidth = this.layout.Data.Width, cx = 0;
            int numDisplayedFrozenCols = 0, firstDisplayedFrozenCol = -1, lastDisplayedFrozenCol = -1;
            int firstDisplayedScrollingCol = this.displayedBandsInfo.FirstDisplayedScrollingCol;
 
            // the same problem with negative numbers:
            // if the width passed in is negative, then return 0
            if (displayWidth <= 0 || this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0)
            {
                this.displayedBandsInfo.FirstDisplayedFrozenCol = -1;
                this.displayedBandsInfo.NumDisplayedFrozenCols = 0;
                this.displayedBandsInfo.FirstDisplayedScrollingCol = -1;
                this.displayedBandsInfo.NumDisplayedScrollingCols = 0;
                this.displayedBandsInfo.LastDisplayedFrozenCol = -1;
                this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1;
                return;
            }
 
            dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.None);
            while (dataGridViewColumn != null)
            {
                if (!dataGridViewColumn.Frozen && dataGridViewColumn.Visible)
                {
                    break;
                }
                if (dataGridViewColumn.Visible)
                {
                    if (firstDisplayedFrozenCol == -1)
                    {
                        firstDisplayedFrozenCol = dataGridViewColumn.Index;
                    }
                    cx += dataGridViewColumn.Width;
                    numDisplayedFrozenCols++;
                    lastDisplayedFrozenCol = dataGridViewColumn.Index;
                    if (cx >= displayWidth)
                    {
                        break;
                    }
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.None, DataGridViewElementStates.None);
            }
 
            Debug.Assert(cx <= this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen));
 
            if (cx < displayWidth && firstDisplayedScrollingCol >= 0)
            {
                dataGridViewColumn = this.Columns[firstDisplayedScrollingCol];
                if (dataGridViewColumn.Frozen)
                {
                    dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible,
                        DataGridViewElementStates.Frozen);
                    this.negOffset = 0;
                    if (dataGridViewColumn == null)
                    {
                        this.displayedBandsInfo.FirstDisplayedFrozenCol = firstDisplayedFrozenCol;
                        this.displayedBandsInfo.LastDisplayedFrozenCol = lastDisplayedFrozenCol;
                        this.displayedBandsInfo.NumDisplayedFrozenCols = numDisplayedFrozenCols;
                        this.displayedBandsInfo.FirstDisplayedScrollingCol = this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1;
                        this.displayedBandsInfo.NumDisplayedScrollingCols = 0;
                        return;
                    }
                    else
                    {
                        firstDisplayedScrollingCol = dataGridViewColumn.Index;
                    }
                }
 
                cx -= this.negOffset;
                while (cx < displayWidth && dataGridViewColumn != null)
                {
                    cx += dataGridViewColumn.Thickness;
                    visibleScrollingColumnsTmp++;
                    dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.None);
                }
                numVisibleScrollingCols = visibleScrollingColumnsTmp;
 
                // if we inflate the data area then we paint columns to the left of firstDisplayedScrollingCol
                if (cx < displayWidth)
                {
                    bool invalidate = false;
                    Debug.Assert(firstDisplayedScrollingCol >= 0);
                    //first minimize value of this.negOffset
                    if (this.negOffset > 0)
                    {
                        invalidate = true;
                        if (displayWidth - cx > this.negOffset)
                        {
                            cx += this.negOffset;
                            this.horizontalOffset -= this.negOffset;
                            this.negOffset = 0;
                        }
                        else
                        {
                            this.horizontalOffset -= displayWidth - cx;
                            this.negOffset -= displayWidth - cx;
                            cx = displayWidth;
                        }
                    }
                    // second try to scroll entire columns
                    if (cx < displayWidth && this.horizontalOffset > 0)
                    {
                        Debug.Assert(this.negOffset == 0);
                        dataGridViewColumn = this.Columns.GetPreviousColumn((this.Columns[firstDisplayedScrollingCol]),
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.Frozen);
                        while (dataGridViewColumn != null && cx + dataGridViewColumn.Thickness <= displayWidth)
                        {
                            cx += dataGridViewColumn.Thickness;
                            visibleScrollingColumnsTmp++;
                            invalidate = true;
                            firstDisplayedScrollingCol = dataGridViewColumn.Index;
                            this.horizontalOffset -= dataGridViewColumn.Thickness;
                            dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn,
                                DataGridViewElementStates.Visible,
                                DataGridViewElementStates.Frozen);
                        }
                    }
                    // third try to partially scroll in first scrolled off column
                    if (cx < displayWidth && this.horizontalOffset > 0 && firstDisplayedScrollingCol != 0)
                    {
                        Debug.Assert(this.negOffset == 0);
                        dataGridViewColumn = this.Columns.GetPreviousColumn((this.Columns[firstDisplayedScrollingCol]),
                                                                            DataGridViewElementStates.Visible,
                                                                            DataGridViewElementStates.Frozen);
                        Debug.Assert(dataGridViewColumn != null);
                        Debug.Assert(dataGridViewColumn.Thickness > displayWidth - cx);
                        firstDisplayedScrollingCol = dataGridViewColumn.Index;
                        this.negOffset = dataGridViewColumn.Thickness - displayWidth + cx;
                        this.horizontalOffset -= displayWidth - cx;
                        visibleScrollingColumnsTmp++;
                        invalidate = true;
                        cx = displayWidth;
                        Debug.Assert(this.negOffset == GetNegOffsetFromHorizontalOffset(this.horizontalOffset));
                    }
 
                    // update the number of visible columns to the new reality
                    Debug.Assert(numVisibleScrollingCols <= visibleScrollingColumnsTmp, "the number of displayed columns can only grow");
                    numVisibleScrollingCols = visibleScrollingColumnsTmp;
 
                    if (invalidate)
                    {
                        InvalidateData();
                        Invalidate(this.layout.ColumnHeaders);
                    }
                }
 
                int jumpFromFirstVisibleScrollingCol = numVisibleScrollingCols - 1;
                if (cx > displayWidth)
                {
                    jumpFromFirstVisibleScrollingCol--;
                }
 
                Debug.Assert(jumpFromFirstVisibleScrollingCol >= -1);
 
                if (jumpFromFirstVisibleScrollingCol < 0)
                {
                    this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1; // no totally visible scrolling column at all
                }
                else
                {
                    Debug.Assert(firstDisplayedScrollingCol >= 0);
                    dataGridViewColumn = this.Columns[firstDisplayedScrollingCol];
                    for (int jump = 0; jump < jumpFromFirstVisibleScrollingCol; jump++)
                    {
                        dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None);
                        Debug.Assert(dataGridViewColumn != null);
                    }
                    this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = dataGridViewColumn.Index;
                }
            }
            else
            {
                this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1;
            }
            this.displayedBandsInfo.FirstDisplayedFrozenCol = firstDisplayedFrozenCol;
            this.displayedBandsInfo.LastDisplayedFrozenCol = lastDisplayedFrozenCol;
            this.displayedBandsInfo.NumDisplayedFrozenCols = numDisplayedFrozenCols;
            this.displayedBandsInfo.FirstDisplayedScrollingCol = firstDisplayedScrollingCol;
            this.displayedBandsInfo.NumDisplayedScrollingCols = numVisibleScrollingCols;
            Debug.Assert((this.displayedBandsInfo.NumDisplayedScrollingCols > 0  && this.displayedBandsInfo.FirstDisplayedScrollingCol != -1) ||
                         (this.displayedBandsInfo.NumDisplayedScrollingCols == 0 && this.displayedBandsInfo.FirstDisplayedScrollingCol == -1));
        }
    
        private void ComputeVisibleRows() 
        {
            int firstDisplayedFrozenRow = -1;
            int firstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
            int lastDisplayedFrozenRow = -1, lastDisplayedScrollingRow = -1;
            int numTotallyDisplayedFrozenRows = 0;
            int displayHeight = this.layout.Data.Height;
            int cy = 0;
            int visibleScrollingRows = 0;
            int nRows = this.Rows.Count;
            int rowIndex;
 
            // when minimizing the dataGridView window, we will get negative values for the
            // layout.Data.Width and layout.Data.Height ( is this a bug or not? if layout.Data.Height == 0 in that case,
            // the old code would have worked )
            //
            // if this is the case, set numTotallyDisplayedFrozenRows = numDisplayedScrollingRows = numTotallyDisplayedScrollingRows = 0;
            //
            if (displayHeight <= 0 || nRows == 0)
            {
                this.displayedBandsInfo.NumDisplayedFrozenRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows =
                    this.displayedBandsInfo.NumDisplayedScrollingRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = 0;
                this.displayedBandsInfo.FirstDisplayedFrozenRow = this.displayedBandsInfo.FirstDisplayedScrollingRow =
                    this.displayedBandsInfo.LastDisplayedFrozenRow = this.displayedBandsInfo.LastDisplayedScrollingRow = -1;
                return;
            }
 
            for (rowIndex = 0; rowIndex < nRows; rowIndex++)
            {
                Debug.Assert(cy < displayHeight);
                DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
                if ((rowState & DataGridViewElementStates.Frozen) == 0 &&
                    (rowState & DataGridViewElementStates.Visible) != 0)
                {
                    break;
                }
                if ((rowState & DataGridViewElementStates.Visible) != 0)
                {
                    cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                    if (firstDisplayedFrozenRow == -1)
                    {
                        firstDisplayedFrozenRow = rowIndex;
                    }
                    lastDisplayedFrozenRow = rowIndex;
                    if (cy <= displayHeight)
                    {
                        numTotallyDisplayedFrozenRows++;
                    }
                    if (cy >= displayHeight)
                    {
                        break;
                    }
                }
            }
 
            if (cy > displayHeight)
            {
                this.displayedBandsInfo.NumDisplayedFrozenRows = numTotallyDisplayedFrozenRows + 1;
            }
            else
            {
                this.displayedBandsInfo.NumDisplayedFrozenRows = numTotallyDisplayedFrozenRows;
            }
 
            // loop exited when:
            // - all rows are frozen and fit in displayHeight: rowIndex == nRows, cy <= displayHeight
            // - rowIndex is not frozen: rowIndex < nRows, cy <= displayHeight
            // - there are more frozen rows than can fit in displayHeight: rowIndex <= nRows, cy > displayHeight
 
            if (cy < displayHeight && rowIndex < nRows)
            {
                if (firstDisplayedScrollingRow == -1)
                {
                    firstDisplayedScrollingRow = rowIndex;
                }
 
                while (firstDisplayedScrollingRow < nRows &&
                    (
                    (this.Rows.GetRowState(firstDisplayedScrollingRow) & DataGridViewElementStates.Frozen) != 0 ||
                    (this.Rows.GetRowState(firstDisplayedScrollingRow) & DataGridViewElementStates.Visible) == 0
                    )
                    )
                {
                    firstDisplayedScrollingRow++;
                }
 
                for (int i = firstDisplayedScrollingRow; i < nRows; i++)
                {
                    if ((this.Rows.GetRowState(i) & DataGridViewElementStates.Visible) != 0)
                    {
                        cy += this.Rows.SharedRow(i).GetHeight(i);
                        visibleScrollingRows++;
                        lastDisplayedScrollingRow = i;
                    }
                    if (cy >= displayHeight)
                    {
                        break;
                    }
                }
 
                if (cy < displayHeight) 
                {
                    for (int i = firstDisplayedScrollingRow - 1; i >= numTotallyDisplayedFrozenRows; i--)
                    {
                        if ((this.Rows.GetRowState(i) & (DataGridViewElementStates.Frozen | DataGridViewElementStates.Visible)) == DataGridViewElementStates.Visible)
                        {
                            int height = this.Rows.SharedRow(i).GetHeight(i);
                            if (cy + height > displayHeight)
                            {
                                break;
                            }
                            cy += height;
                            firstDisplayedScrollingRow = i;
                            visibleScrollingRows++;
                            lastDisplayedScrollingRow = i;
                        }
                    }
                }
 
                this.displayedBandsInfo.NumDisplayedScrollingRows = visibleScrollingRows;
                if (cy > displayHeight)
                {
                    this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = visibleScrollingRows - 1;
                }
                else
                {
                    this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = visibleScrollingRows;
                }
                if (visibleScrollingRows == 0)
                {
                    firstDisplayedScrollingRow = -1;
                    Debug.Assert(lastDisplayedScrollingRow == -1);
                }
            }
            else
            {
                this.displayedBandsInfo.NumDisplayedScrollingRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = 0;
                firstDisplayedScrollingRow = -1;
            }
 
            Debug.Assert(firstDisplayedFrozenRow < nRows, "firstDisplayedFrozenRow larger than number of rows");
            Debug.Assert(lastDisplayedFrozenRow < nRows, "lastDisplayedFrozenRow larger than number of rows");
            Debug.Assert(lastDisplayedScrollingRow < nRows, "lastDisplayedScrollingRow larger than number of rows");
 
            this.displayedBandsInfo.FirstDisplayedFrozenRow = firstDisplayedFrozenRow;
            this.displayedBandsInfo.FirstDisplayedScrollingRow = firstDisplayedScrollingRow;
            this.displayedBandsInfo.NumTotallyDisplayedFrozenRows = numTotallyDisplayedFrozenRows;
            this.displayedBandsInfo.LastDisplayedFrozenRow = lastDisplayedFrozenRow;
            this.displayedBandsInfo.LastDisplayedScrollingRow = lastDisplayedScrollingRow;
            
            Debug.Assert(this.displayedBandsInfo.NumTotallyDisplayedFrozenRows >= 0, "the number of visible frozen rows can't be negative");
            Debug.Assert(this.displayedBandsInfo.NumDisplayedScrollingRows >= 0, "the number of visible scrolling rows can't be negative");
            Debug.Assert(this.displayedBandsInfo.NumTotallyDisplayedScrollingRows >= 0, "the number of totally visible scrolling rows can't be negative");
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow < nRows, "firstDisplayedScrollingRow larger than number of rows");
        }
 
        private Point ConvertCellToGridCoord(int columnIndex, int rowIndex, int x, int y)
        {
            int columnX, rowY;
            if (columnIndex > -1)
            {
                columnX = GetColumnXFromIndex(columnIndex);
                if (this.RightToLeftInternal)
                {
                    columnX -= this.Columns[columnIndex].Width;
                }
            }
            else
            {
                if (this.RightToLeftInternal)
                {
                    columnX = this.layout.RowHeaders.Left - 1;
                }
                else
                {
                    columnX = this.layout.RowHeaders.Left;
                }
            }
            
            if (rowIndex > -1)
            {
                rowY = GetRowYFromIndex(rowIndex);
            }
            else
            {
                rowY = this.layout.ColumnHeaders.Top;
            }
            
            return new Point(columnX + x, rowY + y);
        }
 
        private void CorrectColumnDisplayIndexesAfterDeletion(DataGridViewColumn dataGridViewColumn)
        {
            // Column indexes have already been adjusted.
            // This column has already been detached and has retained its old Index and DisplayIndex
 
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(dataGridViewColumn.DataGridView == null);
            Debug.Assert(dataGridViewColumn.Index >= 0);
            Debug.Assert(dataGridViewColumn.DisplayIndex >= 0);
 
            try
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = true;
 
                // All remaining columns with a DisplayIndex greater than dataGridViewColumn.DisplayIndex need to be decremented
                foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                {
                    if (dataGridViewColumnTmp.DisplayIndex > dataGridViewColumn.DisplayIndex)
                    {
                        dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex - 1;
                        dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on
                    }
                }
 
#if DEBUG
                Debug.Assert(this.Columns.VerifyColumnDisplayIndexes());
#endif
                // Now raise all the OnColumnDisplayIndexChanged events
                FlushDisplayIndexChanged(true /*raiseEvent*/);
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = false;
                FlushDisplayIndexChanged(false /*raiseEvent*/);
            }
        }
 
        private void CorrectColumnDisplayIndexesAfterInsertion(DataGridViewColumn dataGridViewColumn)
        {
            Debug.Assert(dataGridViewColumn != null); 
            Debug.Assert(dataGridViewColumn.DataGridView == this);
            // dataGridViewColumn.DisplayIndex has been set already.
            Debug.Assert(dataGridViewColumn.DisplayIndex >= 0);
            Debug.Assert(dataGridViewColumn.DisplayIndex < this.Columns.Count);
 
            try
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = true;
 
                // All other columns with a DisplayIndex equal or greater than dataGridViewColumn.DisplayIndex need to be incremented
                foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                {
                    if (dataGridViewColumnTmp != dataGridViewColumn && dataGridViewColumnTmp.DisplayIndex >= dataGridViewColumn.DisplayIndex)
                    {
                        dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex + 1;
                        dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on
                    }
                }
 
#if DEBUG
                Debug.Assert(this.Columns.VerifyColumnDisplayIndexes());
#endif
                // Now raise all the OnColumnDisplayIndexChanged events
                FlushDisplayIndexChanged(true /*raiseEvent*/);
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = false;
                FlushDisplayIndexChanged(false /*raiseEvent*/);
            }
        }
 
        private void CorrectColumnFrozenState(DataGridViewColumn dataGridViewColumn, int anticipatedColumnIndex)
        {
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(anticipatedColumnIndex >= 0 && anticipatedColumnIndex <= this.Columns.Count);
 
            int anticipatedColumnDisplayIndex;
            if (dataGridViewColumn.DisplayIndex == -1 || dataGridViewColumn.DisplayIndex > this.Columns.Count)
            {
                anticipatedColumnDisplayIndex = anticipatedColumnIndex; // By default, we pick the Index as the DisplayIndex.
            }
            else
            {
                Debug.Assert(dataGridViewColumn.DisplayIndex >= 0 && dataGridViewColumn.DisplayIndex <= this.Columns.Count);
                anticipatedColumnDisplayIndex = dataGridViewColumn.DisplayIndex; // The specified DisplayIndex is just fine.
            }
 
            DataGridViewColumn dataGridViewColumnPrev;
            int displayIndex = anticipatedColumnDisplayIndex-1;
            do
            {
                dataGridViewColumnPrev = this.Columns.GetColumnAtDisplayIndex(displayIndex);
                displayIndex--;
            }
            while (displayIndex >= 0 && (dataGridViewColumnPrev == null || !dataGridViewColumnPrev.Visible));
            if (dataGridViewColumnPrev != null && !dataGridViewColumnPrev.Frozen && dataGridViewColumn.Frozen)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddFrozenColumn));
            }
            else
            {
                DataGridViewColumn dataGridViewColumnNext;
                displayIndex = anticipatedColumnDisplayIndex;
                do
                {
                    dataGridViewColumnNext = this.Columns.GetColumnAtDisplayIndex(displayIndex);
                    displayIndex++;
                }
                while (displayIndex < this.Columns.Count && (dataGridViewColumnNext == null || !dataGridViewColumnNext.Visible));
                if (dataGridViewColumnNext != null && dataGridViewColumnNext.Frozen && !dataGridViewColumn.Frozen)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddNonFrozenColumn));
                }
            }
        }
 
        private void CorrectColumnFrozenStates(DataGridViewColumn[] dataGridViewColumns)
        {
            DataGridView dataGridViewTmp = new DataGridView();
            DataGridViewColumn dataGridViewColumnClone;
            foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
            {
                dataGridViewColumnClone = (DataGridViewColumn) dataGridViewColumn.Clone();
                // DataGridViewColumn.Clone does not replicate the DisplayIndex value.
                dataGridViewColumnClone.DisplayIndex = dataGridViewColumn.DisplayIndex;
                dataGridViewTmp.Columns.Add(dataGridViewColumnClone);
            }
            foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns)
            {
                dataGridViewColumnClone = (DataGridViewColumn) dataGridViewColumn.Clone();
                dataGridViewColumnClone.DisplayIndex = dataGridViewColumn.DisplayIndex;
                dataGridViewTmp.Columns.Add(dataGridViewColumnClone);
            }
        }
 
        private void CorrectColumnFrozenStates(DataGridViewColumn dataGridViewColumn, bool frozenStateChanging)
        {
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewColumn dataGridViewColumnTmp;
            if ((dataGridViewColumn.Frozen && !frozenStateChanging) ||
                (!dataGridViewColumn.Frozen && frozenStateChanging))
            {
                // make sure the previous visible columns are frozen as well
                dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumn,
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                    DataGridViewElementStates.None);
                if (dataGridViewColumnTmp == null)
                {
                    DataGridViewColumn dataGridViewColumnFirst = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                    if (dataGridViewColumnFirst != dataGridViewColumn)
                    {
                        dataGridViewColumnTmp = dataGridViewColumnFirst;
                    }
                }
                while (dataGridViewColumnTmp != null && this.Columns.DisplayInOrder(dataGridViewColumnTmp.Index, dataGridViewColumn.Index))
                {
                    dataGridViewColumnTmp.Frozen = true;
                    dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp,
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.Frozen);
                }
            }
            else
            {
                // make sure the next visible columns are not frozen
                dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumn,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
                if (dataGridViewColumnTmp == null)
                {
                    DataGridViewColumn dataGridViewColumnLast = dataGridViewColumn;
                    do
                    {
                        dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnLast,
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None);
                        if (dataGridViewColumnTmp != null)
                        {
                            dataGridViewColumnLast = dataGridViewColumnTmp;
                        }
                    }
                    while (dataGridViewColumnTmp != null);
                    if (dataGridViewColumnLast != dataGridViewColumn)
                    {
                        dataGridViewColumnTmp = dataGridViewColumnLast;
                    }
                }
                while (dataGridViewColumnTmp != null && this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index))
                {
                    dataGridViewColumnTmp.Frozen = false;
                    dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp,
                        DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                        DataGridViewElementStates.None);
                }
            }
        }
        
        private void CorrectColumnFrozenStatesForMove(DataGridViewColumn dataGridViewColumn, int newDisplayIndex)
        {
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(newDisplayIndex != dataGridViewColumn.DisplayIndex);
            Debug.Assert(!this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]);
 
            // No check necessary when:
            // - column is invisible.
            // - DisplayIndex decreases and column is frozen.
            // - DisplayIndex increases and column is unfrozen.
 
            if (!dataGridViewColumn.Visible ||
                (newDisplayIndex < dataGridViewColumn.DisplayIndex && dataGridViewColumn.Frozen) ||
                (newDisplayIndex > dataGridViewColumn.DisplayIndex && !dataGridViewColumn.Frozen))
            {
                return;
            }
 
            int colCount = this.Columns.Count, displayIndex;
 
            if (newDisplayIndex < dataGridViewColumn.DisplayIndex)
            {
                // DisplayIndex decreases.
                // Throw an exception if the visible unfrozen column is placed before a frozen column
                // Get the closest visible column placed after the displaced column
                DataGridViewColumn dataGridViewColumnNext;
                displayIndex = newDisplayIndex;
                do 
                {
                    dataGridViewColumnNext = this.Columns.GetColumnAtDisplayIndex(displayIndex);
                    displayIndex++;
                }
                while (displayIndex < colCount && (dataGridViewColumnNext == null || dataGridViewColumnNext == dataGridViewColumn || !dataGridViewColumnNext.Visible));
 
                if (dataGridViewColumnNext != null && dataGridViewColumnNext.Frozen)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMoveNonFrozenColumn));
                }
            }
            else
            {
                // DisplayIndex increases.
                // Throw an exception if the visible frozen column is placed after a non-frozen column
                // Get the closest visible column placed before the displaced column
                DataGridViewColumn dataGridViewColumnPrev;
                displayIndex = newDisplayIndex;
                do
                {
                    dataGridViewColumnPrev = this.Columns.GetColumnAtDisplayIndex(displayIndex);
                    displayIndex--;
                }
                while (displayIndex >= 0 && (dataGridViewColumnPrev == null || !dataGridViewColumnPrev.Visible));
 
                if (dataGridViewColumnPrev != null && !dataGridViewColumnPrev.Frozen)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMoveFrozenColumn));
                }
            }
        }
 
        private void CorrectColumnIndexesAfterDeletion(DataGridViewColumn dataGridViewColumn)
        {
            Debug.Assert(dataGridViewColumn != null);
            for (int columnIndex = dataGridViewColumn.Index; columnIndex < this.Columns.Count; columnIndex++)
            {
                this.Columns[columnIndex].IndexInternal = this.Columns[columnIndex].Index - 1;
                Debug.Assert(this.Columns[columnIndex].Index == columnIndex);
            }
        }
 
        private void CorrectColumnIndexesAfterInsertion(DataGridViewColumn dataGridViewColumn, int insertionCount)
        {
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(insertionCount > 0);
            for (int columnIndex = dataGridViewColumn.Index + insertionCount; columnIndex < this.Columns.Count; columnIndex++)
            {
                this.Columns[columnIndex].IndexInternal = columnIndex;
            }
        }
 
        private void CorrectFocus(bool onlyIfGridHasFocus)
        {
            if ((!onlyIfGridHasFocus || this.Focused) && this.editingControl != null)
            {
                Debug.Assert(this.CurrentCellInternal != null);
                //Debug.Assert(this.editingControl.CanFocus);
                this.editingControl.FocusInternal();
            }
        }
 
        private void CorrectRowFrozenState(DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, int anticipatedRowIndex)
        {
            Debug.Assert(dataGridViewRow != null);
            Debug.Assert(anticipatedRowIndex >= 0 && anticipatedRowIndex <= this.Rows.Count);
 
            int previousRowIndex = this.Rows.GetPreviousRow(anticipatedRowIndex,
                                                            DataGridViewElementStates.Visible,
                                                            DataGridViewElementStates.None);
            if (previousRowIndex != -1 && 
                (this.Rows.GetRowState(previousRowIndex) & DataGridViewElementStates.Frozen) == 0 &&
                (rowState & DataGridViewElementStates.Frozen) != 0)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddFrozenRow));
            }
            else
            {
                int nextRowIndex = this.Rows.GetNextRow((previousRowIndex == -1) ? anticipatedRowIndex - 1 : previousRowIndex,
                                                        DataGridViewElementStates.Visible,
                                                        DataGridViewElementStates.None);
                if (nextRowIndex != -1 && 
                    (this.Rows.GetRowState(nextRowIndex) & DataGridViewElementStates.Frozen) != 0 &&
                    (rowState & DataGridViewElementStates.Frozen) == 0)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddNonFrozenRow));
                }
            }
        }
 
        private void CorrectRowFrozenStates(DataGridViewRow[] dataGridViewRows, int rowIndexInserted)
        {
            bool nextVisibleRowPresent = false, previousRowFrozen = true, nextRowFrozen = false, currentRowFrozen;
 
            // Check if there is a visible row before the insertion point, and if it's frozen
            int rowIndexTmp = this.Rows.GetPreviousRow(rowIndexInserted, DataGridViewElementStates.Visible);
            if (rowIndexTmp != -1)
            {
                previousRowFrozen = (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen;
            }
 
            // Check if there is a visible row at or after the insertion point, and if it's frozen
            rowIndexTmp = this.Rows.GetNextRow(rowIndexInserted - 1, DataGridViewElementStates.Visible);
            if (rowIndexTmp != -1)
            {
                nextVisibleRowPresent = true;
                nextRowFrozen = (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen;
            }
 
            for (int arrayIndex = 0; arrayIndex < dataGridViewRows.Length; arrayIndex++)
            {
                currentRowFrozen = ((DataGridViewRow)dataGridViewRows[arrayIndex]).Frozen;
                if (!previousRowFrozen && currentRowFrozen)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddFrozenRow));
                }
                previousRowFrozen = currentRowFrozen;
                if (arrayIndex == dataGridViewRows.Length - 1 &&
                    !currentRowFrozen &&
                    nextVisibleRowPresent &&
                    nextRowFrozen)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddNonFrozenRow));
                }
            }
        }
 
        private void CorrectRowFrozenStates(DataGridViewRow dataGridViewRow, int rowIndex, bool frozenStateChanging)
        {
            Debug.Assert(dataGridViewRow != null);
            int rowIndexTmp;
            if (((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) != 0 && !frozenStateChanging) ||
                ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) == 0 && frozenStateChanging))
            {
                // make sure the previous visible rows are frozen as well
                rowIndexTmp = this.Rows.GetPreviousRow(rowIndex,
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                if (rowIndexTmp == -1)
                {
                    int dataGridViewRowFirst = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                    if (dataGridViewRowFirst != rowIndex)
                    {
                        rowIndexTmp = dataGridViewRowFirst;
                    }
                }
                while (rowIndexTmp != -1 && rowIndexTmp < rowIndex)
                {
                    this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Frozen, true);
                    rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp,
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.Frozen);
                }
            }
            else
            {
                // make sure the next visible rows are not frozen
                rowIndexTmp = this.Rows.GetNextRow(rowIndex,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
                if (rowIndexTmp == -1)
                {
                    int dataGridViewRowLast = rowIndex;
                    do
                    {
                        rowIndexTmp = this.Rows.GetNextRow(dataGridViewRowLast,
                            DataGridViewElementStates.Visible);
                        if (rowIndexTmp != -1)
                        {
                            dataGridViewRowLast = rowIndexTmp;
                        }
                    }
                    while (rowIndexTmp != -1);
                    if (dataGridViewRowLast != rowIndex)
                    {
                        rowIndexTmp = dataGridViewRowLast;
                    }
                }
                while (rowIndexTmp != -1 && rowIndexTmp > rowIndex)
                {
                    this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Frozen, false);
                    rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp,
                        DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                }
            }
        }
 
        private void CorrectRowIndexesAfterDeletion(int rowIndexDeleted)
        {
            Debug.Assert(rowIndexDeleted >= 0);
            int rowsCount = this.Rows.Count;
            for (int rowIndex = rowIndexDeleted; rowIndex < rowsCount; rowIndex++)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                if (dataGridViewRow.Index >= 0)
                {
                    dataGridViewRow.IndexInternal = dataGridViewRow.Index - 1;
                    Debug.Assert(dataGridViewRow.Index == rowIndex);
                }
            }
 
            // Fix 'new' row index if existant
            if (this.newRowIndex == rowIndexDeleted)
            {
                this.newRowIndex = -1; // No more 'new' row.
            }
            else if (this.newRowIndex != -1)
            {
                this.newRowIndex--;
            }
        }
 
        private void CorrectRowIndexesAfterInsertion(int rowIndexInserted, int insertionCount)
        {
            Debug.Assert(rowIndexInserted >= 0);
            Debug.Assert(insertionCount > 0);
            int rowsCount = this.Rows.Count;
            for (int rowIndex = rowIndexInserted + insertionCount; rowIndex < rowsCount; rowIndex++)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                if (dataGridViewRow.Index >= 0)
                {
                    dataGridViewRow.IndexInternal = dataGridViewRow.Index + insertionCount;
                    Debug.Assert(dataGridViewRow.Index == rowIndex);
                }
            }
 
            // Lastly update the 'new' row index if needed.
            if (this.newRowIndex != -1)
            {
                this.newRowIndex += insertionCount;
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.CreateAccessibilityInstance"]/*' />
        protected override AccessibleObject CreateAccessibilityInstance()
        {
            return new DataGridViewAccessibleObject(this);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.CreateControlsInstance"]/*' />
        protected override Control.ControlCollection CreateControlsInstance()
        {
            return new DataGridViewControlCollection(this);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.CreateColumnsInstance"]/*' />
        /// <devdoc>
        ///     Constructs the new instance of the Columns collection objects. Subclasses
        ///     should not call base.CreateColumnsInstance.
        /// </devdoc>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        protected virtual DataGridViewColumnCollection CreateColumnsInstance()
        {
            return new DataGridViewColumnCollection(this);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.CreateRowsInstance"]/*' />
        /// <devdoc>
        ///     Constructs the new instance of the Rows collection objects. Subclasses
        ///     should not call base.CreateRowsInstance.
        /// </devdoc>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        protected virtual DataGridViewRowCollection CreateRowsInstance()
        {
            return new DataGridViewRowCollection(this);
        }
 
        private NativeMethods.RECT[] CreateScrollableRegion(Rectangle scroll) 
        {
            if (this.cachedScrollableRegion != null) 
            {
                return this.cachedScrollableRegion;
            }
 
            using (Region region = new Region(scroll))
            {
                IntPtr handle = IntPtr.Zero;
                using (Graphics graphics = CreateGraphicsInternal())
                {
                    handle = region.GetHrgn(graphics);
                }
                if (handle != IntPtr.Zero)
                {
                    this.cachedScrollableRegion = UnsafeNativeMethods.GetRectsFromRegion(handle);
 
                    // SECREVIEW : This assert is safe since we created the native region.
                    //
                    IntSecurity.ObjectFromWin32Handle.Assert();
                    try
                    {
                        region.ReleaseHrgn(handle);
                    }
                    finally
                    {
                        CodeAccessPermission.RevertAssert();
                    }
                }
            }
            return this.cachedScrollableRegion;
        }
 
        private void DiscardNewRow()
        {
            Debug.Assert(this.Rows.Count > 1);
            Debug.Assert(this.newRowIndex != -1);
 
            DataGridViewRowCancelEventArgs dgvrce = new DataGridViewRowCancelEventArgs(this.Rows[this.newRowIndex]);
            OnUserDeletingRow(dgvrce);
            if (dgvrce.Cancel)
            {
                return;
            }
 
            // Delete the 'new' row
            Debug.Assert(this.newRowIndex == this.Rows.Count - 1);
            DataGridViewRow dataGridViewRow = this.Rows[this.newRowIndex];
            this.Rows.RemoveAtInternal(this.newRowIndex, false /*force*/);
            Debug.Assert(dataGridViewRow.Index == -1);
            DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
            OnUserDeletedRow(dgvre);
            // CorrectRowIndexesAfterDeletion resets this.newRowIndex to -1.
            Debug.Assert(this.newRowIndex == -1);
 
            if (this.AllowUserToAddRowsInternal)
            {
                this.newRowIndex = this.Rows.Count - 1;
                Debug.Assert((this.Rows.GetRowState(this.newRowIndex) & DataGridViewElementStates.Visible) != 0);
                Debug.Assert(this.ptCurrentCell.Y == this.newRowIndex);
 
                OnDefaultValuesNeeded(new DataGridViewRowEventArgs(this.Rows[this.newRowIndex]));
                InvalidateRowPrivate(this.newRowIndex);
            }
        }
 
        private void DiscardZonesInScrollingArea(ref Rectangle rectScrollingArea, 
                                                 int emptyBackgroundWidth, 
                                                 int emptyBackgroundHeight, 
                                                 int frozenVisibleRowsHeight,
                                                 bool discardFrozenColumns, 
                                                 bool discardFrozenRows)
        {
            // Discard empty background
            rectScrollingArea.Width -= emptyBackgroundWidth;
            rectScrollingArea.Height -= emptyBackgroundHeight;
            if (this.RightToLeftInternal)
            {
                rectScrollingArea.X += emptyBackgroundWidth;
            }
 
            if (discardFrozenColumns)
            {
                // Discard frozen columns
                int frozenVisibleColumnsWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                if (!this.RightToLeftInternal)
                {
                    rectScrollingArea.X += frozenVisibleColumnsWidth;
                }
                rectScrollingArea.Width -= frozenVisibleColumnsWidth;
            }
            if (discardFrozenRows)
            {
                // Discard frozen rows
                rectScrollingArea.Y += frozenVisibleRowsHeight;
                rectScrollingArea.Height -= frozenVisibleRowsHeight;
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.DisplayedColumnCount"]/*' />
        public int DisplayedColumnCount(bool includePartialColumns)
        {
            int cxMax = this.layout.Data.Width, cx = 0;
            int completeColumns = 0, partialColumns = 0;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            while (dataGridViewColumn != null && cx < cxMax)
            {
                partialColumns++;
                cx += dataGridViewColumn.Thickness;
                if (cx <= cxMax)
                {
                    completeColumns++;
                    dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                        DataGridViewElementStates.None);
                }
            }
 
            if (cx < cxMax && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0)
            {
                if (this.negOffset > 0)
                {
                    cx -= this.negOffset;
                    completeColumns--;
                }
                dataGridViewColumn = (DataGridViewColumn)this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen);
 
                while (dataGridViewColumn != null && cx < cxMax)
                {
                    partialColumns++;
                    cx += dataGridViewColumn.Thickness;
                    if (cx <= cxMax)
                    {
                        completeColumns++;
                        dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None);
                    }
                }
            }
 
            return includePartialColumns ? partialColumns : completeColumns;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.DisplayedRowCount"]/*' />
        public int DisplayedRowCount(bool includePartialRow)
        {
            return includePartialRow ? (this.displayedBandsInfo.NumDisplayedFrozenRows + this.displayedBandsInfo.NumDisplayedScrollingRows) :
                (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows + this.displayedBandsInfo.NumTotallyDisplayedScrollingRows);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.Dispose"]/*' />
        protected override void Dispose(bool disposing) 
        {
            if (disposing)
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] = true;
                try
                {
                    // Remove any Columns contained in this control
                    for (int i = 0; i < this.Columns.Count; i ++)
                    {
                        this.Columns[i].Dispose();
                    }
 
                    this.Columns.Clear();
 
                    UnwireScrollBarsEvents();
                    if (this.vertScrollBar != null)
                    {
                        this.vertScrollBar.Dispose();
                        this.vertScrollBar = null;
                    }
                    if (this.horizScrollBar != null)
                    {
                        this.horizScrollBar.Dispose();
                        this.horizScrollBar = null;
                    }
 
                    if (this.pens != null)
                    {
                        int nPenEntries = this.pens.Count;
                        if (nPenEntries > 0)
                        {
                            foreach (Pen pen in this.pens.Values)
                            {
                                pen.Dispose();
                            }
                            this.pens.Clear();
                        }
                        this.pens = null;
                    }
 
                    if (this.brushes != null)
                    {
                        int nBrushEntries = this.brushes.Count;
                        if (nBrushEntries > 0)
                        {
                            foreach (SolidBrush brush in this.brushes.Values)
                            {
                                brush.Dispose();
                            }
                            this.brushes.Clear();
                        }
                        this.brushes = null;
                    }
 
                    if (this.placeholderStringFormat != null)
                    {
                        this.placeholderStringFormat.Dispose();
                        this.placeholderStringFormat = null;
                    }
 
                    if (this.latestEditingControl != null)
                    {
                        this.latestEditingControl.Dispose();
                        this.latestEditingControl = null;
                    }
                    if (this.editingControl != null)
                    {
                        this.editingControl.Dispose();
                        this.editingControl = null;
                    }
                    if (this.editingPanel != null)
                    {
                        this.editingPanel.Dispose();
                        this.editingPanel = null;
                    }
                    if (this.gridPen != null)
                    {
                        this.gridPen.Dispose();
                        this.gridPen = null;
                    }
                    Debug.Assert(this.noSelectionChangeCount == 0);
 
                    if (this.dataConnection != null)
                    {
                        this.dataConnection.Dispose();
                    }
 
                    // DGV should dispose the tool tip control before disposing itself.
                    // vsw 559812.
                    this.toolTipControl.Dispose();
                }
                finally
                {
                    this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] = false;
                }
            }
            base.Dispose(disposing);
        }
 
        private void DrawColHeaderShadow(Graphics g, int mouseX)
        {
            Rectangle r = CalcColRelocationFeedbackRect(mouseX);
            DrawShadowRect(r);
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion])
            {
                Rectangle rectInsertionBar = new Rectangle(0, this.layout.ColumnHeaders.Top, DATAGRIDVIEW_insertionBarWidth, this.layout.ColumnHeaders.Height);
                // this.trackColumnEdge is the column preceeding the insertion point
                if (this.trackColumnEdge == -1)
                {
                    // Insert as first column
                    rectInsertionBar.X = GetColumnXFromIndex(this.Columns.GetFirstColumn(DataGridViewElementStates.Visible).Index);
                    if (this.RightToLeftInternal)
                    {
                        rectInsertionBar.X -= DATAGRIDVIEW_insertionBarWidth;
                    }
                }
                else
                {
                    int offsetFromCenter = 0;
                    if (this.Columns.GetNextColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None) == null)
                    {
                        if (!this.RightToLeftInternal)
                        {
                            offsetFromCenter = DATAGRIDVIEW_insertionBarWidth;
                        }
                    }
                    else
                    {
                        if (this.RightToLeftInternal)
                        {
                            offsetFromCenter = DATAGRIDVIEW_insertionBarWidth / 2 - 1;
                        }
                        else
                        {
                            offsetFromCenter = DATAGRIDVIEW_insertionBarWidth / 2 + 1;
                        }
                    }
                    if (this.RightToLeftInternal)
                    {
                        rectInsertionBar.X = Math.Max(this.layout.ColumnHeaders.X, 
                                                      GetColumnXFromIndex(this.trackColumnEdge) - this.Columns[this.trackColumnEdge].Width - offsetFromCenter);
                    }
                    else
                    {
                        rectInsertionBar.X = Math.Min(GetColumnXFromIndex(this.trackColumnEdge) + this.Columns[this.trackColumnEdge].Width - offsetFromCenter,
                                                      this.layout.ColumnHeaders.Right - DATAGRIDVIEW_insertionBarWidth);
                    }
                }
                if (this.ApplyVisualStylesToHeaderCells)
                {
                    g.FillRectangle(GetCachedBrush(SystemColors.HotTrack), rectInsertionBar);
                }
                else
                {
                    ControlPaint.FillReversibleRectangle(RectangleToScreen(rectInsertionBar), Color.White);
                }
            }
        }
 
        /// <devdoc>
        ///      Draws an XOR region to give UI feedback for Column Resizing.
        ///      This looks just like the Splitter control's UI when resizing.
        /// </devdoc>
        private void DrawColSplitBar(int mouseX)
        {
            Rectangle r = CalcColResizeFeedbackRect(mouseX);
            DrawSplitBar(r);
        }
 
        /// <devdoc>
        ///      Draws an XOR region to give UI feedback for Row Resizing.
        ///      This looks just like the Splitter control's UI when resizing.
        /// </devdoc>
        private void DrawRowSplitBar(int mouseY)
        {
            Rectangle r = CalcRowResizeFeedbackRect(mouseY);
            DrawSplitBar(r);
        }
 
        private void DrawShadowRect(Rectangle r)
        {
            const byte DATAGRIDVIEW_shadowEdgeThickness = 3;
 
            IntPtr parentHandle = this.Handle;
            IntPtr dc = UnsafeNativeMethods.GetDCEx(new HandleRef(this, parentHandle), NativeMethods.NullHandleRef, NativeMethods.DCX_CACHE | NativeMethods.DCX_LOCKWINDOWUPDATE);
            IntPtr halftone = ControlPaint.CreateHalftoneHBRUSH();
            IntPtr saveBrush = SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, halftone));
 
            SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y, r.Width, DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT);
            SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y + r.Height - DATAGRIDVIEW_shadowEdgeThickness, r.Width, DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT);
            SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y + DATAGRIDVIEW_shadowEdgeThickness, DATAGRIDVIEW_shadowEdgeThickness, r.Height - 2 * DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT);
            SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X + r.Width - DATAGRIDVIEW_shadowEdgeThickness, r.Y + DATAGRIDVIEW_shadowEdgeThickness, DATAGRIDVIEW_shadowEdgeThickness, r.Height - 2 * DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT);
 
            SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, saveBrush));
            SafeNativeMethods.DeleteObject(new HandleRef(null, halftone));
            UnsafeNativeMethods.ReleaseDC(new HandleRef(this, parentHandle), new HandleRef(this, dc));
        }
 
        /// <devdoc>
        ///      Draws an XOR region to give UI feedback for Column/Row Resizing.
        ///      This looks just like the Splitter control's UI when resizing.
        /// </devdoc>
        private void DrawSplitBar(Rectangle r)
        {
            IntPtr parentHandle = this.Handle;
            IntPtr dc = UnsafeNativeMethods.GetDCEx(new HandleRef(this, parentHandle), NativeMethods.NullHandleRef, NativeMethods.DCX_CACHE | NativeMethods.DCX_LOCKWINDOWUPDATE);
            IntPtr halftone = ControlPaint.CreateHalftoneHBRUSH();
            IntPtr saveBrush = SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, halftone));
            SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y, r.Width, r.Height, NativeMethods.PATINVERT);
            SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, saveBrush));
            SafeNativeMethods.DeleteObject(new HandleRef(null, halftone));
            UnsafeNativeMethods.ReleaseDC(new HandleRef(this, parentHandle), new HandleRef(this, dc));
        }
 
        private void EditingControls_CommonMouseEventHandler(object sender, MouseEventArgs e, DataGridViewMouseEvent dgvme)
        {
            Debug.Assert(this.ptCurrentCell.X != -1);
            int adjustedX = this.editingPanel.Location.X + e.X; 
            int adjustedY = this.editingPanel.Location.Y + e.Y;
            if (sender == this.editingControl)
            {
                adjustedX += this.editingControl.Location.X;
                adjustedY += this.editingControl.Location.Y;
            }
 
            if (dgvme == DataGridViewMouseEvent.MouseDown && e.Clicks == 1)
            {
                // Reset the flag that records single-click exposed as double-click.
                this.dataGridViewOper[DATAGRIDVIEWOPER_lastEditCtrlClickDoubled] = false;
            }
 
            MouseEventArgs me = new MouseEventArgs(e.Button, 
                                                   e.Clicks, 
                                                   adjustedX, 
                                                   adjustedY, 
                                                   e.Delta);
 
            HitTestInfo hti = HitTest(me.X, me.Y);
            int mouseX = me.X - hti.ColumnX;
            if (this.RightToLeftInternal)
            {
                mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness);
            }
            DataGridViewCellMouseEventArgs dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, me.Y - hti.RowY, me);
 
            try
            {
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] = true;
                // Check to see if this is a CellMouseDoubleClick situation
                if ((dgvme == DataGridViewMouseEvent.MouseDown || 
                     dgvme == DataGridViewMouseEvent.Click || 
                     dgvme == DataGridViewMouseEvent.MouseClick) &&
                    (DateTime.Now.Ticks - this.lastMouseClickInfo.timeStamp) / 10000 <= SystemInformation.DoubleClickTime &&
                    e.Button == this.lastMouseClickInfo.button &&
                    e.Clicks == 1 &&
                    dgvcme.ColumnIndex == this.lastMouseClickInfo.col &&
                    dgvcme.RowIndex == this.lastMouseClickInfo.row)
                {
                    Size hotDoubleClickZone = SystemInformation.DoubleClickSize;
                    if (Math.Abs(dgvcme.X - this.lastMouseClickInfo.x) <= hotDoubleClickZone.Width / 2 &&
                        Math.Abs(dgvcme.Y - this.lastMouseClickInfo.y) <= hotDoubleClickZone.Height / 2)
                    {
                        me = new MouseEventArgs(e.Button,
                                                2,
                                                adjustedX,
                                                adjustedY,
                                                e.Delta);
                        dgvcme = new DataGridViewCellMouseEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex, dgvcme.X, dgvcme.Y, me);
                        switch (dgvme)
                        {
                            case DataGridViewMouseEvent.MouseDown:
                            {
                                OnMouseDown(me);
                                if (dgvcme.ColumnIndex < this.Columns.Count &&
                                    dgvcme.RowIndex < this.Rows.Count)
                                {
                                    OnCellMouseDown(dgvcme);
                                }
                                break;
                            }
                            case DataGridViewMouseEvent.Click:
                            {
                                OnDoubleClick(me);
                                if (e.Button == MouseButtons.Left && 
                                    dgvcme.ColumnIndex < this.Columns.Count &&
                                    dgvcme.RowIndex < this.Rows.Count)
                                {
                                    OnCellDoubleClick(new DataGridViewCellEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex));
                                }
                                break;
                            }
                            case DataGridViewMouseEvent.MouseClick:
                            {
                                // Set the flag that prevents the triple-click to be exposed as a double-click
                                this.dataGridViewOper[DATAGRIDVIEWOPER_lastEditCtrlClickDoubled] = true;
 
                                OnMouseDoubleClick(me);
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                                {
                                    OnCellMouseDoubleClick(dgvcme);
                                }
                                break;
                            }
                        }
                        return;
                    }
                }
 
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_lastEditCtrlClickDoubled])
                {
                    // Make sure that the triple-click is exposed as a single-click and not a double-click.
                    if (e.Clicks == 2)
                    {
                        me = new MouseEventArgs(e.Button,
                                                1,
                                                adjustedX,
                                                adjustedY,
                                                e.Delta);
                        dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, me.Y - hti.RowY, me);
                    }
                    switch (dgvme)
                    {
                        case DataGridViewMouseEvent.DoubleClick:
                            dgvme = DataGridViewMouseEvent.Click;
                            break;
                        case DataGridViewMouseEvent.MouseDoubleClick:
                            dgvme = DataGridViewMouseEvent.MouseClick;
                            break;
                    }
                }
 
                switch (dgvme)
                {
                    case DataGridViewMouseEvent.Click:
                        OnClick(me);
                        if (e.Button == MouseButtons.Left &&
                            dgvcme.ColumnIndex < this.Columns.Count &&
                            dgvcme.RowIndex < this.Rows.Count)
                        {
                            OnCellClick(new DataGridViewCellEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex));
                        }
                        break;
                    case DataGridViewMouseEvent.DoubleClick:
                        OnDoubleClick(me);
                        if (e.Button == MouseButtons.Left &&
                            dgvcme.ColumnIndex < this.Columns.Count &&
                            dgvcme.RowIndex < this.Rows.Count)
                        {
                            OnCellDoubleClick(new DataGridViewCellEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex));
                        }
                        break;
                    case DataGridViewMouseEvent.MouseClick:
                        OnMouseClick(me);
                        if (dgvcme.ColumnIndex < this.Columns.Count &&
                            dgvcme.RowIndex < this.Rows.Count)
                        {
                            OnCellMouseClick(dgvcme);
                        }
                        break;
                    case DataGridViewMouseEvent.MouseDoubleClick:
                        OnMouseDoubleClick(me);
                        if (dgvcme.ColumnIndex < this.Columns.Count &&
                            dgvcme.RowIndex < this.Rows.Count)
                        {
                            OnCellMouseDoubleClick(dgvcme);
                        }
                        break;
                    case DataGridViewMouseEvent.MouseDown:
                        OnMouseDown(me);
                        if (dgvcme.ColumnIndex < this.Columns.Count &&
                            dgvcme.RowIndex < this.Rows.Count)
                        {
                            OnCellMouseDown(dgvcme);
                        }
                        break;
                    case DataGridViewMouseEvent.MouseUp:
                        if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble])
                        {
                            MouseEventArgs meTmp = new MouseEventArgs(e.Button,
                                                                      2,
                                                                      adjustedX,
                                                                      adjustedY,
                                                                      e.Delta);
                            dgvcme = new DataGridViewCellMouseEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex, dgvcme.X, dgvcme.Y, meTmp);
                        }
                        OnCellMouseUp(dgvcme);
                        OnMouseUp(me);
                        break;
                    case DataGridViewMouseEvent.MouseMove:
                        OnCellMouseMove(dgvcme);
                        break;
                }
            }
            finally
            {
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] = false;
            }
        }
 
        private void EditingControls_Click(object sender, System.EventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            Debug.Assert(this.ptCurrentCell.X != -1);
            System.Windows.Forms.MouseEventArgs me = e as System.Windows.Forms.MouseEventArgs;
            if (me != null)
            {
                EditingControls_CommonMouseEventHandler(sender, me, DataGridViewMouseEvent.Click);
            }
        }
 
        private void EditingControls_DoubleClick(object sender, System.EventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            Debug.Assert(this.ptCurrentCell.X != -1);
            System.Windows.Forms.MouseEventArgs me = e as System.Windows.Forms.MouseEventArgs;
            if (me != null)
            {
                EditingControls_CommonMouseEventHandler(sender, me, DataGridViewMouseEvent.DoubleClick);
            }
        }
 
        private void EditingControls_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseClick);
        }
 
        private void EditingControls_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseDoubleClick);
        }
 
        private void EditingControls_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseDown);
        }
 
        private void EditingControls_MouseEnter(object sender, System.EventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            if (sender == this.editingPanel)
            {
                Debug.Assert(this.editingControl != null);
                Debug.Assert(!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]);
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true;
                this.oldCursor = this.Cursor;
                this.CursorInternal = ((IDataGridViewEditingControl)this.editingControl).EditingPanelCursor;
            }
 
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected])
            {
                OnMouseEnter(EventArgs.Empty);
            }
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
        }
 
        private void EditingControls_MouseLeave(object sender, System.EventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            if (sender == this.editingPanel)
            {
                Debug.Assert(this.editingControl != null);
                if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet])
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false;
                    this.CursorInternal = this.oldCursor;
                }
            }
 
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
 
            Point ptMouse = PointToClient(Control.MousePosition);
            if (!this.ClientRectangle.Contains(ptMouse))
            {
                OnMouseLeave(EventArgs.Empty);
            }
        }
 
        private void EditingControls_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseMove);
        }
 
        private void EditingControls_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Debug.Assert(sender == this.editingControl || sender == this.editingPanel);
            EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseUp);
        }
 
        private void EndColumnHeadersResize(MouseEventArgs e) 
        {
            try 
            {
                if (this.currentRowSplitBar != -1)
                {
                    Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar), true);
                    this.lastRowSplitBar = this.currentRowSplitBar = -1;
                }
 
                int y = Math.Min(e.Y + this.mouseBarOffset, this.layout.Data.Bottom - 1);
                int delta = y - this.layout.ColumnHeaders.Y - this.ColumnHeadersHeight + 1;
                if (this.trackRowAnchor != y && delta != 0)
                {
                    this.ColumnHeadersHeight += delta;
                }
            }
            finally 
            {
                RealeaseMouse();
            }
        }
 
        private void EndColumnRelocation(MouseEventArgs e, HitTestInfo hti) 
        {
            try 
            {
                if (this.lastHeaderShadow != -1) 
                {
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = false;
                    this.trackColumnEdge = -1;
                    this.lastHeaderShadow = -1;
                    Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders));
                }
 
                int previousColumnIndex;
                if (ColumnRelocationTarget(e, hti, out previousColumnIndex))
                {
                    if (previousColumnIndex == -1)
                    {
                        this.Columns[this.trackColumn].DisplayIndex = 0;
                    }
                    else if (this.Columns[this.trackColumn].DisplayIndex > this.Columns[previousColumnIndex].DisplayIndex)
                    {
                        this.Columns[this.trackColumn].DisplayIndex = this.Columns[previousColumnIndex].DisplayIndex + 1;
                    }
                    else
                    {
                        this.Columns[this.trackColumn].DisplayIndex = this.Columns[previousColumnIndex].DisplayIndex;
                    }
                }
            }
            finally 
            {
                RealeaseMouse();
            }
        }
 
        private void EndColumnResize(MouseEventArgs e)
        {
            try
            {
                EndColumnResize(e.X);
            }
            finally
            {
                RealeaseMouse();
            }
        }
 
        private void EndColumnResize(int x)
        {
            int newX, delta;
            if (this.RightToLeftInternal)
            {
                newX = Math.Max(x + this.mouseBarOffset, this.layout.Data.X);
                delta = GetColumnXFromIndex(this.trackColumn) - this.Columns[this.trackColumn].Thickness - newX + 1;
            }
            else
            {
                newX = Math.Min(x + this.mouseBarOffset, this.layout.Data.Right - 1);
                delta = newX - (GetColumnXFromIndex(this.trackColumn) + this.Columns[this.trackColumn].Thickness) + 1;
            }
 
            if (this.trackColAnchor != newX && delta != 0)
            {
                int proposed = this.Columns[this.trackColumn].Thickness + delta;
                Debug.Assert(proposed >= this.Columns[this.trackColumn].MinimumThickness);
                Debug.Assert(proposed <= DataGridViewBand.maxBandThickness);
                this.Columns[this.trackColumn].Thickness = proposed;
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.EndEdit1"]/*' />
        public bool EndEdit()
        {
            return EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit);
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.EndEdit2"]/*' />
        public bool EndEdit(DataGridViewDataErrorContexts context)
        {
            if (this.EditMode == DataGridViewEditMode.EditOnEnter)
            {
                return CommitEdit(context);
            }
            else
            {
                return EndEdit(context, 
                    DataGridViewValidateCellInternal.Never /*validateCell*/, 
                    false /*fireCellLeave*/,
                    false /*fireCellEnter*/,
                    false /*fireRowLeave*/,
                    false /*fireRowEnter*/,
                    false /*fireLeave*/, 
                    true /*keepFocus*/,
                    true /*resetCurrentCell*/,
                    true /*resetAnchorCell*/);
            }
        }
 
        private bool EndEdit(DataGridViewDataErrorContexts context, 
            DataGridViewValidateCellInternal validateCell,
            bool fireCellLeave,
            bool fireCellEnter,
            bool fireRowLeave,
            bool fireRowEnter,
            bool fireLeave,
            bool keepFocus,
            bool resetCurrentCell,
            bool resetAnchorCell)
        {
            if (this.ptCurrentCell.X == -1)
            {
                return true;
            }
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_inEndEdit] = true;
            try
            {
                int curRowIndex = this.ptCurrentCell.Y;
                int curColIndex = this.ptCurrentCell.X;
                DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal;
                DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, context, validateCell,
                    fireCellLeave, fireCellEnter, fireRowLeave, fireRowEnter, fireLeave);
                if (dgvdee != null)
                {
                    if (dgvdee.ThrowException)
                    {
                        throw dgvdee.Exception;
                    }
                    if (dgvdee.Cancel)
                    {
                        return false;
                    }
                    dgvdee = CancelEditPrivate(/*ref dataGridViewCurrentCell, context*/);    // restore old value
                    if (null != dgvdee)
                    {
                        if (dgvdee.ThrowException)
                        {
                            throw dgvdee.Exception;
                        }
                        if (dgvdee.Cancel)
                        {
                            return false;
                        }
                    }
                }
 
                if (!this.IsCurrentCellInEditMode)
                {
                    return true;
                }
 
                if (curRowIndex != this.ptCurrentCell.Y || curColIndex != this.ptCurrentCell.X)
                {
                    return true;
                }
 
                if (this.editingControl != null)
                {
                    UnwireEditingControlEvents();
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] = this.MouseOverEditingControl;
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] = this.MouseOverEditingPanel;
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true;
                    try
                    {
                        dataGridViewCurrentCell.DetachEditingControl();
                    }
                    finally
                    {
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = false;
                    }
 
                    ImeMode editingControlImeMode = this.editingControl.CachedImeMode; // If in restricted mode, ImeMode will be Disable.
                    this.latestEditingControl = this.editingControl;
                    Debug.Assert(this.editingPanel == null || this.editingPanel.Controls.Count == 0);
                    this.editingControl = null;
                    InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y);
 
                    if (this.EditMode == DataGridViewEditMode.EditOnEnter)
                    {
                        if (resetCurrentCell)
                        {
                            bool success = SetCurrentCellAddressCore(-1, -1, resetAnchorCell, false, false);
                            Debug.Assert(success);
                        }
                    }
                    if (keepFocus)
                    {
                        // Debug.Assert(this.CanFocus || this.Focused); // Invalid assertion (VS Whidbey 325154)
                        FocusInternal();
                    }
                    this.ImeMode = editingControlImeMode;
                }
                else
                {
                    Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]);
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode] = false;
                    InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y);
                }
 
                if (!IsInnerCellOutOfBounds(curColIndex, curRowIndex))
                {
                    DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(curColIndex, curRowIndex);
                    OnCellEndEdit(dgvce);
                }
 
                return true;
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inEndEdit] = false;
            }
        }
 
        private void EndRowHeadersResize(MouseEventArgs e) 
        {
            try 
            {
                if (this.currentColSplitBar != -1)
                {
                    Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar), true);
                    this.lastColSplitBar = this.currentColSplitBar = -1;
                }
 
                int x, delta;
                if (this.RightToLeftInternal)
                {
                    x = Math.Max(e.X + this.mouseBarOffset, this.layout.Data.Left - 1);
                    delta = this.layout.RowHeaders.Right - this.RowHeadersWidth - x - 1;
                }
                else
                {
                    x = Math.Min(e.X + this.mouseBarOffset, this.layout.Data.Right - 1);
                    delta = x - this.layout.RowHeaders.X - this.RowHeadersWidth + 1;
                }
                if (this.trackColAnchor != x && delta != 0)
                {
                    this.RowHeadersWidth += delta;
                }
            }
            finally 
            {
                RealeaseMouse();
            }
        }
 
        private void EndRowResize(MouseEventArgs e)
        {
            try 
            {
                if (this.currentRowSplitBar != -1)
                {
                    Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar), true);
                    this.lastRowSplitBar = this.currentRowSplitBar = -1;
                }
 
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(this.trackRow);
                int height, minimumHeight;
                dataGridViewRow.GetHeightInfo(this.trackRow, out height, out minimumHeight);
                int y = Math.Min(e.Y + this.mouseBarOffset, this.layout.Data.Bottom - 1);
                int delta = y - (GetRowYFromIndex(this.trackRow) + height) + 1;
                if (this.trackRowAnchor != y && delta != 0) 
                {
                    int proposedHeight = height + delta;
                    proposedHeight = Math.Max(proposedHeight, minimumHeight);
                    if (!OnRowHeightInfoPushed(this.trackRow, proposedHeight, minimumHeight))
                    {
                        if (dataGridViewRow.Index == -1)
                        {
                            dataGridViewRow = this.Rows[this.trackRow];  // Unsharing row
                        }
                        Debug.Assert(this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None);
                        dataGridViewRow.ThicknessInternal = proposedHeight;
                    }
                }
            } 
            finally 
            {
                RealeaseMouse();
            }
        }
 
        private void ExitBulkLayout(bool invalidInAdjustFillingColumns)
        {
            if (this.inBulkLayoutCount > 0)
            {
                this.inBulkLayoutCount--;
                if (this.inBulkLayoutCount == 0)
                {
                    PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/);
                }
            }
        }
 
        private void ExitBulkPaint(int columnIndex, int rowIndex)
        {
            if (this.inBulkPaintCount > 0)
            {
                this.inBulkPaintCount--;
                if (this.inBulkPaintCount == 0)
                {
                    if (columnIndex >= 0)
                    {
                        InvalidateColumnInternal(columnIndex);
                    }
                    else if (rowIndex >= 0)
                    {
                        InvalidateRowPrivate(rowIndex);
                    }
                    else
                    {
                        Invalidate();
                    }
                }
            }
        }
 
        private void FirstVisibleScrollingRowTempted(int rowIndex)
        {
            Debug.Assert(rowIndex >= 0);
            Debug.Assert(rowIndex < this.Rows.Count);
            Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0);
            Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) == 0);
 
            int displayHeight = this.layout.Data.Height;
            if (displayHeight <= 0)
            {
                return;
            }
 
            int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            if (totalVisibleFrozenHeight < displayHeight)
            {
                this.displayedBandsInfo.FirstDisplayedScrollingRow = rowIndex;
            }
        }
 
        private void FlushDisplayedChanged()
        {
            if (this.displayedBandsInfo.Dirty && this.Visible)
            {
                // Handle the rows
 
                if (!this.RowHeadersVisible && this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0)
                {
                    // All rows are hidden
                    UpdateRowsDisplayedState(false /*displayed*/);
                }
                else
                {
                    Rectangle rectScreen = Screen.FromControl(this).WorkingArea;
                    int maxDisplayedRows = (int) (rectScreen.Height / DataGridViewBand.minBandThickness);
 
                    // Make sure all displayed scrolling rows have the Displayed state.
                    int rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                    if (rowIndexTmp != -1)
                    {
                        int numDisplayedScrollingRows = this.displayedBandsInfo.NumDisplayedScrollingRows;
                        Debug.Assert(numDisplayedScrollingRows > 0);
                        while (numDisplayedScrollingRows > 0)
                        {
                            Debug.Assert(rowIndexTmp != -1);
                            if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0)
                            {
                                this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true);
                            }
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                            numDisplayedScrollingRows--;
                        }
 
                        int rowIndexTmp2 = rowIndexTmp;
 
                        // Make sure all scrolling rows before FirstDisplayedScrollingRow have their Displayed state set to false
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow != -1);
                        rowIndexTmp = this.Rows.GetPreviousRow(this.displayedBandsInfo.FirstDisplayedScrollingRow, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                        while (rowIndexTmp != -1 && (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0)
                        {
                            this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false);
                            rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                        }
 
                        // Make sure all rows below last displayed scrolling row have Displayed state set to false (next loop)
                        rowIndexTmp = rowIndexTmp2;
                    }
                    else
                    {
                        // No displayed scrolling rows. Make sure all non-frozen rows have their Displayed state set to false (next loop)
                        rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                    }
                    while (rowIndexTmp != -1 && (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0)
                    {
                        this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false);
                        rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                    }
 
                    // Make sure all displayed frozen rows have their Displayed state set to true
                    int numDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedFrozenRows;                    
                    rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                    while (numDisplayedFrozenRows > 0)
                    {
                        Debug.Assert(rowIndexTmp != -1);
                        if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0)
                        {
                            this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true);
                        }
                        rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        numDisplayedFrozenRows--;
                    }
 
                    // Make sure all non-displayed frozen rows have their Displayed state set to false
                    while (rowIndexTmp != -1 && (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0)
                    {
                        this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false);
                        rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                    }
 
                    // Treat the cases where the old displayed rows are completely disjoint from the new displayed rows
                    int lastDisplayedFrozenRowIndex = -1;
                    int lastDisplayedScrollingRowIndex = -1;
 
                    if (this.displayedBandsInfo.NumDisplayedFrozenRows > 0) 
                    {
                        int firstDisplayedFrozenRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        Debug.Assert(firstDisplayedFrozenRowIndex != -1);
                        if (this.displayedBandsInfo.NumDisplayedFrozenRows > 1)
                        {
                            lastDisplayedFrozenRowIndex = this.Rows.GetNextRow(firstDisplayedFrozenRowIndex, DataGridViewElementStates.Visible, this.displayedBandsInfo.NumDisplayedFrozenRows-2 /*skipRows*/);
                        }
                        else
                        {
                            lastDisplayedFrozenRowIndex = firstDisplayedFrozenRowIndex;
                        }
                    }
 
                    if (this.displayedBandsInfo.FirstDisplayedScrollingRow != -1)
                    {
                        if (this.displayedBandsInfo.NumDisplayedScrollingRows > 1)
                        {
                            lastDisplayedScrollingRowIndex = this.Rows.GetNextRow(this.displayedBandsInfo.FirstDisplayedScrollingRow, DataGridViewElementStates.Visible, this.displayedBandsInfo.NumDisplayedScrollingRows - 2 /*skipRows*/);
                        }
                        else
                        {
                            lastDisplayedScrollingRowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                        }
                    }
 
                    rowIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingRow;
                    while (rowIndexTmp != -1 &&
                        rowIndexTmp < this.displayedBandsInfo.FirstDisplayedScrollingRow &&
                        !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex))
                    {
                        if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0)
                        {
                            break;
                        }
                        else
                        {
                            this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false);
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                        }
                    }
 
                    rowIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingRow;
                    if (rowIndexTmp != -1 &&
                        rowIndexTmp < this.Rows.Count &&
                        (this.displayedBandsInfo.FirstDisplayedScrollingRow == -1 || this.displayedBandsInfo.FirstDisplayedScrollingRow < rowIndexTmp) &&
                        !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex))
                    {
                        while (rowIndexTmp != -1)
                        {
                            if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0)
                            {
                                break;
                            }
                            else
                            {
                                this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false);
                                rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                            }
                        }
                    }
 
                    if (this.displayedBandsInfo.RowInsertionOccurred)
                    {
                        // Adjust the scrolling rows that were pushed down by the rows insertion
                        rowIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingRow;
                        if (rowIndexTmp != -1)
                        {
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible, this.displayedBandsInfo.OldNumDisplayedScrollingRows - 1);
                            if (rowIndexTmp == -1)
                            {
                                rowIndexTmp = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                            }
                            int rowCount = 0;
                            while (rowIndexTmp != -1 &&
                                   rowCount <= maxDisplayedRows &&
                                   !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex))
                            {
                                if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0)
                                {
                                    this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false);
                                }
                                rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp, DataGridViewElementStates.Visible);
                                rowCount++;
                            }
                        }
 
                        // Adjust the frozen rows that were pushed down by the rows insertion
                        rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                        if (rowIndexTmp != -1)
                        {
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, this.displayedBandsInfo.OldNumDisplayedFrozenRows - 1);
                            if (rowIndexTmp == -1)
                            {
                                rowIndexTmp = this.Rows.GetLastRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                            }
                            int rowCount = 0;
                            while (rowIndexTmp != -1 &&
                                   rowCount <= maxDisplayedRows &&
                                   !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex))
                            {
                                if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0)
                                {
                                    this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false);
                                }
                                rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp, DataGridViewElementStates.Visible);
                                rowCount++;
                            }
                        }
                    }
 
#if DEBUG
                    for (rowIndexTmp = 0; rowIndexTmp < this.Rows.Count; rowIndexTmp++)
                    {
                        DataGridViewElementStates rowStateDbg = this.Rows.GetRowState(rowIndexTmp);
                        bool rowNeedsDisplayedState = RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex);
                        if (((rowStateDbg & DataGridViewElementStates.Displayed) != 0) != rowNeedsDisplayedState)
                        {
                            Debug.Fail("Unexpected Displayed state for row");
                        }
                    }
#endif
                }
 
                // Handle the columns
 
                if (!this.ColumnHeadersVisible && this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 0)
                {
                    // All columns are hidden
                    UpdateColumnsDisplayedState(false /*displayed*/);
                }
                else
                {
                    // Make sure all displayed scrolling columns have the Displayed state.
                    DataGridViewColumn dataGridViewColumnTmp;
                    int columnIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingCol;
                    if (columnIndexTmp != -1)
                    {
                        int numDisplayedScrollingCols = this.displayedBandsInfo.NumDisplayedScrollingCols;
                        Debug.Assert(numDisplayedScrollingCols > 0);
                        dataGridViewColumnTmp = this.Columns[columnIndexTmp];
                        while (numDisplayedScrollingCols > 0)
                        {
                            Debug.Assert(dataGridViewColumnTmp != null);
                            if (!dataGridViewColumnTmp.Displayed)
                            {
                                dataGridViewColumnTmp.DisplayedInternal = true;
                            }
                            dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                            numDisplayedScrollingCols--;
                        }
 
                        DataGridViewColumn dataGridViewColumnTmp2 = dataGridViewColumnTmp;
 
                        // Make sure all scrolling columns before FirstDisplayedScrollingCol have their Displayed state set to false
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol != -1);
                        dataGridViewColumnTmp = this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                        while (dataGridViewColumnTmp != null && dataGridViewColumnTmp.Displayed)
                        {
                            dataGridViewColumnTmp.DisplayedInternal = false;
                            dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                        }
 
                        // Make sure all columns after last displayed scrolling column have Displayed state set to false (next loop)
                        dataGridViewColumnTmp = dataGridViewColumnTmp2;
                    }
                    else
                    {
                        // No displayed scrolling columns. Make sure all non-frozen columns have their Displayed state set to false (next loop)
                        dataGridViewColumnTmp = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                    }
                    while (dataGridViewColumnTmp != null && dataGridViewColumnTmp.Displayed)
                    {
                        dataGridViewColumnTmp.DisplayedInternal = false;
                        dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    }
 
                    // Make sure all displayed frozen columns have their Displayed state set to true
                    int numDisplayedFrozenCols = this.displayedBandsInfo.NumDisplayedFrozenCols;
                    dataGridViewColumnTmp = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                    while (numDisplayedFrozenCols > 0)
                    {
                        Debug.Assert(dataGridViewColumnTmp != null);
                        if (!dataGridViewColumnTmp.Displayed)
                        {
                            dataGridViewColumnTmp.DisplayedInternal = true;
                        }
                        dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None);
                        numDisplayedFrozenCols--;
                    }
 
                    // Make sure all non-displayed frozen columns have their Displayed state set to false
                    while (dataGridViewColumnTmp != null && dataGridViewColumnTmp.Displayed)
                    {
                        dataGridViewColumnTmp.DisplayedInternal = false;
                        dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None);
                    }
 
                    // Treat the cases where the old displayed columns are completely disjoint from the new displayed columns
 
                    columnIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingCol;
                    while (columnIndexTmp != -1 &&
                        columnIndexTmp < this.Columns.Count &&
                        this.displayedBandsInfo.FirstDisplayedScrollingCol != -1 &&
                        columnIndexTmp != this.displayedBandsInfo.FirstDisplayedScrollingCol &&
                        this.Columns.DisplayInOrder(columnIndexTmp, this.displayedBandsInfo.FirstDisplayedScrollingCol) &&
                        !ColumnNeedsDisplayedState(this.Columns[columnIndexTmp]))
                    {
                        dataGridViewColumnTmp = this.Columns[columnIndexTmp];
                        if (!dataGridViewColumnTmp.Displayed)
                        {
                            break;
                        }
                        else
                        {
                            dataGridViewColumnTmp.DisplayedInternal = false;
                            dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                            columnIndexTmp = (dataGridViewColumnTmp == null) ? -1 : dataGridViewColumnTmp.Index;
                        }
                    }
 
                    columnIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingCol;
                    if (columnIndexTmp != -1 &&
                        columnIndexTmp < this.Columns.Count &&
                        (this.displayedBandsInfo.FirstDisplayedScrollingCol == -1 || (this.displayedBandsInfo.FirstDisplayedScrollingCol != columnIndexTmp && this.Columns.DisplayInOrder(this.displayedBandsInfo.FirstDisplayedScrollingCol, columnIndexTmp))) &&
                        !ColumnNeedsDisplayedState(this.Columns[columnIndexTmp]))
                    {
                        dataGridViewColumnTmp = this.Columns[columnIndexTmp];
                        while (dataGridViewColumnTmp != null)
                        {
                            if (!dataGridViewColumnTmp.Displayed)
                            {
                                break;
                            }
                            else
                            {
                                dataGridViewColumnTmp.DisplayedInternal = false;
                                dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                            }
                        }
                    }
 
                    if (this.displayedBandsInfo.ColumnInsertionOccurred)
                    {
                        dataGridViewColumnTmp = this.Columns[this.Columns.Count - 1];
                        while (dataGridViewColumnTmp != null && !ColumnNeedsDisplayedState(dataGridViewColumnTmp))
                        {
                            if (dataGridViewColumnTmp.Displayed)
                            {
                                dataGridViewColumnTmp.DisplayedInternal = false;
                            }
                            dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                        }
                    }
 
#if DEBUG
                    for (columnIndexTmp = 0; columnIndexTmp < this.Columns.Count; columnIndexTmp++)
                    {
                        DataGridViewElementStates colStateDbg = this.Columns[columnIndexTmp].State;
                        bool columnNeedsDisplayedState = ColumnNeedsDisplayedState(this.Columns[columnIndexTmp]);
                        if (((colStateDbg & DataGridViewElementStates.Displayed) != 0) != columnNeedsDisplayedState)
                        {
                            Debug.Fail("Unexpected Displayed state for column");
                        }
                    }
#endif
                }
 
                this.displayedBandsInfo.Dirty = false;
            }
        }
 
        private void FlushDisplayIndexChanged(bool raiseEvent)
        {
            foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
            {
                if (dataGridViewColumn.DisplayIndexHasChanged)
                {
                    dataGridViewColumn.DisplayIndexHasChanged = false;
                    if (raiseEvent)
                    {
                        OnColumnDisplayIndexChanged(dataGridViewColumn);
                    }
                }
            }
        }
 
        private void FlushSelectionChanged()
        {
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged])
            {
                OnSelectionChanged(EventArgs.Empty);
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.GetAccessibilityObjectById"]/*' />
        protected override AccessibleObject GetAccessibilityObjectById(int objectId)
        {
            // decrement the objectId because in our implementation of AccessibilityClient notitification objectId's are 1 - based.
            // 0 == NativeMethods.CHILDID_SELF corresponds to the AccessibleObject itself
            return this.AccessibilityObject.GetChild(objectId - 1);
        }
 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        internal SolidBrush GetCachedBrush(Color color)
        {
            SolidBrush brush = (SolidBrush) this.brushes[color];
            if (brush == null)
            {
                brush = new SolidBrush(color);
                this.brushes.Add(color, brush);
            }
            return brush;
        }
 
#if DGV_GDI
        internal WindowsSolidBrush GetCachedWindowsBrush(Color color)
        {
            WindowsSolidBrush brush = (WindowsSolidBrush)this.brushes[color];
            if (brush == null)
            {
                brush = new WindowsSolidBrush(color);
                this.brushes.Add(color, brush);
            }
            return brush;
        }
#endif // DGV_GDI
 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        internal Pen GetCachedPen(Color color)
        {
            Pen pen = (Pen) this.pens[color];
            if (pen == null)
            {
                pen = new Pen(color);
                this.pens.Add(color, pen);
            }
            return pen;
        }
 
#if DGV_GDI
        internal WindowsPen GetCachedWindowsPen(Color color)
        {
            WindowsPen pen = (WindowsPen)this.pens[color];
            if (pen == null)
            {
                pen = new WindowsPen(color);
                this.pens.Add(color, pen);
            }
            return pen;
        }
#endif // DGV_GDI
 
        internal TypeConverter GetCachedTypeConverter(Type type)
        {
            if (this.converters.ContainsKey(type))
            {
                return (TypeConverter)this.converters[type];
            }
 
            TypeConverter converter = TypeDescriptor.GetConverter(type);
            this.converters.Add(type, converter);
            return converter;
        }
 
        internal Rectangle GetCellAdjustedDisplayRectangle(int columnIndex, int rowIndex, bool cutOverflow)
        {
            Rectangle rect = GetCellDisplayRectangle(columnIndex, rowIndex, cutOverflow);
            if (!rect.IsEmpty)
            {
                if (this.SingleVerticalBorderAdded && columnIndex == this.FirstDisplayedColumnIndex)
                {
                    if (!this.RightToLeftInternal)
                    {
                        rect.X--;
                    }
                    rect.Width++;
                }
                if (this.SingleHorizontalBorderAdded && rowIndex == this.FirstDisplayedRowIndex)
                {
                    rect.Y--;
                    rect.Height++;
                }
            }
            return rect;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.GetCellCount"]/*' />
        [
            SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes"), // using specialized DataGridViewCellLinkedList class instead of generics
        ]
        public int GetCellCount(DataGridViewElementStates includeFilter)
        {
            if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable |
                                   DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter"));
            }
 
            int cellCount = 0;
            bool displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired;
 
            if ((includeFilter & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected)
            {
                if (includeFilter == DataGridViewElementStates.Selected)
                {
                    cellCount = this.individualSelectedCells.Count;
                    switch (this.SelectionMode)
                    {
                        case DataGridViewSelectionMode.CellSelect:
                        {
                            // If we change the design and decide that SelectAll() should use band selection, 
                            // we need to take the bands into account.
                            return cellCount;
                        }
                        case DataGridViewSelectionMode.FullColumnSelect:
                        case DataGridViewSelectionMode.ColumnHeaderSelect:
                        {
                            return cellCount + this.selectedBandIndexes.Count * this.Rows.Count;
                        }
                        case DataGridViewSelectionMode.FullRowSelect:
                        case DataGridViewSelectionMode.RowHeaderSelect:
                        {
                            return cellCount + this.selectedBandIndexes.Count * this.Columns.Count;
                        }
                    }
                }
 
                displayedRequired = (includeFilter & DataGridViewElementStates.Displayed) == DataGridViewElementStates.Displayed;
                frozenRequired = (includeFilter & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen;
                resizableRequired = (includeFilter & DataGridViewElementStates.Resizable) == DataGridViewElementStates.Resizable;
                readOnlyRequired = (includeFilter & DataGridViewElementStates.ReadOnly) == DataGridViewElementStates.ReadOnly;
                visibleRequired = (includeFilter & DataGridViewElementStates.Visible) == DataGridViewElementStates.Visible;
                
                foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells)
                {
                    if (GetCellCount_CellIncluded(dataGridViewCell, dataGridViewCell.RowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired))
                    {
                        cellCount++;
                    }
                }
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                    {
                        // If we change the design and decide that SelectAll() should use band selection, 
                        // we need to take the bands into account.
                        return cellCount;
                    }
                    case DataGridViewSelectionMode.FullColumnSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                    {
                        for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
                        {
                            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                            foreach (int columnIndex in this.selectedBandIndexes)
                            {
                                DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex];
                                if (GetCellCount_CellIncluded(dataGridViewCell, rowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired))
                                {
                                    cellCount++;
                                }
                            }
                        }
                        return cellCount;
                    }
                    case DataGridViewSelectionMode.FullRowSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    {
                        foreach (int rowIndex in this.selectedBandIndexes)
                        {
                            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                            foreach (DataGridViewCell dataGridViewCell in dataGridViewRow.Cells)
                            {
                                if (GetCellCount_CellIncluded(dataGridViewCell, rowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired))
                                {
                                    cellCount++;
                                }
                            }
                        }
                        return cellCount;
                    }
                }
            }
 
            if ((includeFilter == DataGridViewElementStates.ReadOnly && this.ReadOnly) ||
                includeFilter == DataGridViewElementStates.None)
            {
                return this.Rows.Count * this.Columns.Count;
            }
 
            displayedRequired = (includeFilter & DataGridViewElementStates.Displayed) == DataGridViewElementStates.Displayed;
            frozenRequired = (includeFilter & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen;
            resizableRequired = (includeFilter & DataGridViewElementStates.Resizable) == DataGridViewElementStates.Resizable;
            readOnlyRequired = (includeFilter & DataGridViewElementStates.ReadOnly) == DataGridViewElementStates.ReadOnly;
            visibleRequired = (includeFilter & DataGridViewElementStates.Visible) == DataGridViewElementStates.Visible;
 
            for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                if (!visibleRequired || (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0)
                {
                    foreach (DataGridViewCell dataGridViewCell in dataGridViewRow.Cells)
                    {
                        if (GetCellCount_CellIncluded(dataGridViewCell, rowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired))
                        {
                            cellCount++;
                        }
                    }
                }
            }
            return cellCount;
        }
 
        private bool GetCellCount_CellIncluded(DataGridViewCell dataGridViewCell, 
                                               int rowIndex,
                                               bool displayedRequired,
                                               bool frozenRequired, 
                                               bool resizableRequired, 
                                               bool readOnlyRequired, 
                                               bool visibleRequired)
        {
            Debug.Assert(dataGridViewCell != null);
            Debug.Assert(rowIndex >= 0);
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
            if (displayedRequired)
            {
                bool cellDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0 &&
                                     dataGridViewCell.OwningColumn.Displayed;
                if (!cellDisplayed)
                {
                    return false;
                }
            }
            if (frozenRequired)
            {
                bool cellFrozen = (rowState & DataGridViewElementStates.Frozen) != 0 ||
                                  dataGridViewCell.OwningColumn.Frozen ||
                                  dataGridViewCell.StateIncludes(DataGridViewElementStates.Frozen);
                if (!cellFrozen)
                {
                    return false;
                }
            }
            if (resizableRequired)
            {
                if (!RowIsResizable(rowIndex) && dataGridViewCell.OwningColumn.Resizable != DataGridViewTriState.True)
                {
                    return false;
                }
            }
            if (readOnlyRequired)
            {
                bool cellReadOnly = this.ReadOnly ||
                                    (rowState & DataGridViewElementStates.ReadOnly) != 0 ||
                                    dataGridViewCell.OwningColumn.ReadOnly ||
                                    dataGridViewCell.StateIncludes(DataGridViewElementStates.ReadOnly);
                if (!cellReadOnly)
                {
                    return false;
                }
            }
            if (visibleRequired)
            {
                bool cellVisible = (rowState & DataGridViewElementStates.Visible) != 0 &&
                                   dataGridViewCell.OwningColumn.Visible;
                if (!cellVisible)
                {
                    return false;
                }
            }
            return true;
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.GetCellDisplayRectangle"]/*' />
        public Rectangle GetCellDisplayRectangle(int columnIndex, int rowIndex, bool cutOverflow)
        {
            Rectangle rowRect;
            Rectangle columnRect;
 
            if (columnIndex >= 0)
            {
                if (columnIndex >= this.Columns.Count)
                {
                    throw new ArgumentOutOfRangeException("columnIndex");
                }
                columnRect = GetColumnDisplayRectanglePrivate(columnIndex, cutOverflow);
            }
            else
            {
                if (columnIndex != -1)
                {
                    throw new ArgumentOutOfRangeException("columnIndex");
                }
                if (rowIndex >= 0)
                {
                    columnRect = this.layout.RowHeaders;
                }
                else
                {
                    columnRect = this.layout.TopLeftHeader;
                }
            }
 
            if (rowIndex >= 0)
            {
                if (rowIndex >= this.Rows.Count)
                {
                    throw new ArgumentOutOfRangeException("rowIndex");
                }
                rowRect = GetRowDisplayRectanglePrivate(rowIndex, cutOverflow);
            }
            else
            {
                if (rowIndex != -1)
                {
                    throw new ArgumentOutOfRangeException("rowIndex");
                }
                if (columnIndex >= 0)
                {
                    rowRect = this.layout.ColumnHeaders;
                }
                else
                {
                    rowRect = this.layout.TopLeftHeader;
                }
            }
 
            if (!cutOverflow)
            {
                int height = rowRect.Bottom - columnRect.Bottom;
                if (height > 0)
                {
                    columnRect.Height += height;
                }
                int width;
                if (this.RightToLeftInternal)
                {
                    width = rowRect.X - columnRect.X;
                    if (width > 0)
                    {
                        rowRect.Width += width;
                        rowRect.X -= width;
                    }
                }
                else
                {
                    width = columnRect.Right - rowRect.Right;
                    if (width > 0)
                    {
                        rowRect.Width += width;
                    }
                }
            }
 
            rowRect.Intersect(columnRect);
 
            return rowRect;
        }
 
        internal DataGridViewCell GetCellInternal(int columnIndex, int rowIndex)
        {
            Debug.Assert(columnIndex >= -1 && columnIndex < this.Columns.Count);
            Debug.Assert(rowIndex >= -1 && rowIndex < this.Rows.Count);
            if (rowIndex >= 0)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                Debug.Assert(dataGridViewRow != null);
                if (columnIndex >= 0)
                {
                    return dataGridViewRow.Cells[columnIndex];
                }
                else
                {
                    return dataGridViewRow.HeaderCell;
                }
            }
            else
            {
                if (columnIndex >= 0)
                {
                    return this.Columns[columnIndex].HeaderCell;
                }
                else
                {
                    return this.TopLeftHeaderCell;
                }
            }
        }
 
        /// <include file='doc\DataGridView.uex' path='docs/doc[@for="DataGridView.GetClipboardContent"]/*' />
        [
            SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes"), // using specialized DataGridViewCellLinkedList class instead of generics
        ]
        public virtual DataObject GetClipboardContent()
        {
            if (this.ClipboardCopyMode == DataGridViewClipboardCopyMode.Disable)
            {
                throw new NotSupportedException(SR.GetString(SR.DataGridView_DisabledClipboardCopy));
            }
 
            if (this.CurrentCellIsEditedAndOnlySelectedCell)
            {
                return null;
            }
 
            string[] formats = new string[] { DataFormats.Html, DataFormats.Text, DataFormats.UnicodeText, DataFormats.CommaSeparatedValue };
            DataObject dataObject = new DataObject();
            bool includeColumnHeaders = false, includeRowHeaders = false;
            string cellContent = null;
            StringBuilder sbContent = null;
            DataGridViewColumn dataGridViewColumn, prevDataGridViewColumn, nextDataGridViewColumn;
 
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.FullRowSelect:
                    if (this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) == 0)
                    {
                        return null;
                    }
 
                    if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText)
                    {
                        includeColumnHeaders = (this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Selected) == -1);
                        includeRowHeaders = true;
                    }
                    else
                    {
                        includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText);
                    }
 
                    includeColumnHeaders &= this.ColumnHeadersVisible;
                    includeRowHeaders &= this.RowHeadersVisible;
 
                    foreach (string format in formats)
                    {
                        /* if (!String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase) &&
                            !String.Equals(format, DataFormats.Text, StringComparison.OrdinalIgnoreCase) &&
                            !String.Equals(format, DataFormats.UnicodeText, StringComparison.OrdinalIgnoreCase) &&
                            !String.Equals(format, DataFormats.CommaSeparatedValue, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }*/
 
                        if (sbContent == null)
                        {
                            sbContent = new StringBuilder(1024);
                        }
                        else
                        {
                            sbContent.Length = 0;
                        }
 
                        if (includeColumnHeaders)
                        {
                            if (this.RightToLeftInternal)
                            {
                                // Cycle through the visible columns in their reverse display order
                                dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                if (dataGridViewColumn != null)
                                {
                                    prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            true /*firstCell*/,
                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,