DataGridViewMethods.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / WinForms / Managed / System / WinForms / DataGridViewMethods.cs / 1 / DataGridViewMethods.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

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; 

    /// 
    public partial class DataGridView
    { 
        /// 
        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);
            } 
            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);
            }
        } 

        ///  
        [ 
            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, 
                                           DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal,
                                           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--; 
            }
 
            //VSWhidbey 538300: Assertion is wrong when multiple rows are added/inserted. Bug was postponed for Whidbey.
            Debug.Assert(dataGridViewColumn.Width == dataGridViewColumn.GetPreferredWidth((DataGridViewAutoSizeColumnMode)autoSizeColumnCriteriaInternal, true /*fixedHeight*/));

            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, inheritedAutoSizeColumnCriteria, 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); 
                } 
            }
        } 

        /// 
        // 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;
        } 
 
        /// 
        ///    Assigns a new parent control to the DataGridView. 
        /// 
        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;
        } 

        ///  
        public void AutoResizeColumn(int columnIndex) 
        {
            AutoResizeColumn(columnIndex, DataGridViewAutoSizeColumnMode.AllCells); 
        }

        /// 
        public void AutoResizeColumn(int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode) 
        {
            AutoResizeColumn(columnIndex, autoSizeColumnMode, true); 
        } 

        ///  
        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);
        } 

        /// 
        public void AutoResizeColumnHeadersHeight()
        { 
            AutoResizeColumnHeadersHeight(true, true);
        } 
 
        /// 
        public void AutoResizeColumnHeadersHeight(int columnIndex) 
        {
            AutoResizeColumnHeadersHeight(columnIndex, true, true);
        }
 
        /// 
        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--; 
            } 
        }
 
        /// 
        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;
        }

        ///  
        public void AutoResizeColumns()
        { 
            AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); 
        }
 
        /// 
        public void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode)
        {
            AutoResizeColumns(autoSizeColumnsMode, true); 
        }
 
        ///  
        protected void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode, bool fixedHeight)
        { 
            for (int columnIndex = 0; columnIndex < this.Columns.Count; columnIndex++)
            {
                AutoResizeColumn(columnIndex, (DataGridViewAutoSizeColumnMode)autoSizeColumnsMode, fixedHeight);
            } 
        }
 
        ///  
        public void AutoResizeRow(int rowIndex)
        { 
            AutoResizeRow(rowIndex, DataGridViewAutoSizeRowMode.AllCells);
        }

        ///  
        public void AutoResizeRow(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode)
        { 
            AutoResizeRow(rowIndex, autoSizeRowMode, true /*fixedWidth*/); 
        }
 
        /// 
        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*/);
        } 

        /// 
        // 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*/);
        } 

        /// 
        // 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--; 
            }
        }

        ///  
        public void AutoResizeRowHeadersWidth(int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode)
        { 
            AutoResizeRowHeadersWidth(rowIndex, 
                                      rowHeadersWidthSizeMode,
                                      true /*fixedColumnHeadersHeight*/, 
                                      true /*fixedRowHeight*/);
        }

        ///  
        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--;
            } 
        }

        /// 
        public void AutoResizeRows() 
        {
            AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCells); 
        } 

        ///  
        public void AutoResizeRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode)
        {
            AutoResizeRows(autoSizeRowsMode, true /*fixedWidth*/);
        } 

        ///  
        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*/); 
        }
 
        /// 
        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)
        {
            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)
        {
            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 mouseX, int mouseBarOffset, int index) 
        {
            Rectangle clip = Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data); 
            int leftEdge = GetColumnXFromIndex(index); 
            if (this.RightToLeftInternal)
            { 
                clip.X = this.layout.Data.X - mouseBarOffset - 1;
                clip.Width = leftEdge - this.Columns[index].MinimumThickness - this.layout.Data.X + 3;
                int overflowWidth = leftEdge - mouseBarOffset - clip.Left - DataGridViewBand.maxBandThickness + 1;
                if (overflowWidth > 0) 
                {
                    clip.X += overflowWidth; 
                    clip.Width -= overflowWidth; 
                }
            } 
            else
            {
                clip.X = leftEdge + this.Columns[index].MinimumThickness - mouseBarOffset - 1;
                clip.Width = this.layout.Data.Right - leftEdge - 1; 
                int overflowWidth = clip.Right + mouseBarOffset - leftEdge - DataGridViewBand.maxBandThickness;
                if (overflowWidth > 0) 
                { 
                    clip.Width -= overflowWidth;
                } 
            }
            CaptureMouse(clip);

            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] = true; 
            this.trackColAnchor = mouseX;
            this.trackColumn = index; 
 
            this.mouseBarOffset = mouseBarOffset;
            Debug.Assert(this.lastColSplitBar == -1); 
            this.currentColSplitBar = mouseX;
            Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar));
        }
 
        /// 
        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 = this.CurrentCellInternal;
                }
                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)
        { 
            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) 
        {
            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;
        }
 
        /// 
        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; 
            }
        }

        // 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; 
        }

        /// 
        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); 
                        }
                        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);
                } 
            }
        } 
 
        /// 
        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); 
        } 

        ///  
        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);
 
                    // [....]: 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); 
            }
        } 
 
        /// 
        ///      Determines which column is the first visible scrolling 
        ///      column given the object's horizontalOffset.
        /// 
        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)
                    { 
                        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;
            }
        }
 
        /// 
        protected override AccessibleObject CreateAccessibilityInstance() 
        { 
            return new DataGridViewAccessibleObject(this);
        } 

        /// 
        protected override Control.ControlCollection CreateControlsInstance()
        { 
            return new DataGridViewControlCollection(this);
        } 
 
        /// 
        ///  
        ///     Constructs the new instance of the Columns collection objects. Subclasses
        ///     should not call base.CreateColumnsInstance.
        /// 
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected virtual DataGridViewColumnCollection CreateColumnsInstance()
        { 
            return new DataGridViewColumnCollection(this); 
        }
 
        /// 
        /// 
        ///     Constructs the new instance of the Rows collection objects. Subclasses
        ///     should not call base.CreateRowsInstance. 
        /// 
        [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; 
            }
        }

        ///  
        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;
        }
 
        /// 
        public int DisplayedRowCount(bool includePartialRow) 
        { 
            return includePartialRow ? (this.displayedBandsInfo.NumDisplayedFrozenRows + this.displayedBandsInfo.NumDisplayedScrollingRows) :
                (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows + this.displayedBandsInfo.NumTotallyDisplayedScrollingRows); 
        }

        /// 
        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;
                    }
 
                    DisposeCachedGraphics();
 
                    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;
                    } 
                    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 DisposeCachedGraphics()
        {
            if (this.cachedGraphics != null) 
            {
                this.cachedGraphics.Dispose(); 
                this.cachedGraphics = null; 
            }
        } 

        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);
                } 
            }
        } 
 
        /// 
        ///      Draws an XOR region to give UI feedback for Column Resizing. 
        ///      This looks just like the Splitter control's UI when resizing.
        /// 
        private void DrawColSplitBar(int mouseX)
        { 
            Rectangle r = CalcColResizeFeedbackRect(mouseX);
            DrawSplitBar(r); 
        } 

        ///  
        ///      Draws an XOR region to give UI feedback for Row Resizing.
        ///      This looks just like the Splitter control's UI when resizing.
        /// 
        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));
        } 

        /// 
        ///      Draws an XOR region to give UI feedback for Column/Row Resizing.
        ///      This looks just like the Splitter control's UI when resizing. 
        /// 
        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
            { 
                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.X); 
                    delta = GetColumnXFromIndex(this.trackColumn) - this.Columns[this.trackColumn].Thickness - x + 1;
                } 
                else
                {
                    x = Math.Min(e.X + this.mouseBarOffset, this.layout.Data.Right - 1);
                    delta = x - (GetColumnXFromIndex(this.trackColumn) + this.Columns[this.trackColumn].Thickness) + 1; 
                }
 
                if (this.trackColAnchor != x && 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;
                } 
            }
            finally 
            { 
                RealeaseMouse();
            } 
        }

        /// 
        public bool EndEdit() 
        {
            return EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit); 
        } 

        ///  
        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); 
            }
        } 
 
        /// 
        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); 
        }
 
        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

        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 (this.SingleVerticalBorderAdded && columnIndex == this.FirstDisplayedColumnIndex) 
            {
                if (!this.RightToLeftInternal) 
                {
                    rect.X--;
                }
                rect.Width++; 
            }
            if (this.SingleHorizontalBorderAdded && rowIndex == this.FirstDisplayedRowIndex) 
            { 
                rect.Y--;
                rect.Width++; 
            }
            return rect;
        }
 
        /// 
        [ 
            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; 
        }

        /// 
        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; 
                } 
            }
        } 

        /// 
        [
            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*/, 
                                                                                                            true /*inFirstRow*/,
                                                                                                            false /*inLastRow*/, 
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    while (prevDataGridViewColumn != null)
                                    { 
                                        dataGridViewColumn = prevDataGridViewColumn;
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/,
                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                true /*inFirstRow*/,
                                                                                                                false /*inLastRow*/,
                                                                                                                format) as string;
                                        if (cellContent != null) 
                                        {
                                            sbContent.Append(cellContent); 
                                        } 
                                    }
                                } 
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*firstCell*/, 
                                                                                                     true /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/, 
                                                                                                     format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                            }
                            else 
                            { 
                                if (includeRowHeaders)
                                { 
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     true /*firstCell*/,
                                                                                                     this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/,
                                                                                                     format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                }
                                // Cycle through the visible columns in their display order
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
                                if (dataGridViewColumn != null)
                                { 
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            !includeRowHeaders /*firstCell*/, 
                                                                                                            nextDataGridViewColumn == null /*lastCell*/,
                                                                                                            true /*inFirstRow*/,
                                                                                                            false /*inLastRow*/,
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = nextDataGridViewColumn;
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/,
                                                                                                                nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                true /*inFirstRow*/, 
                                                                                                                false /*inLastRow*/,
                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        {
                                            sbContent.Append(cellContent);
                                        } 
                                    }
                                } 
                            } 
                        }
                        // Cycle through the visible selected rows. 
                        bool firstRowIndex = true;
                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);
                        Debug.Assert(rowIndex != -1);
                        int nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected); 
                        while (rowIndex != -1)
                        { 
                            if (this.RightToLeftInternal) 
                            {
                                dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None); 

                                // Cycle through the visible columns in their reverse display order
                                if (dataGridViewColumn != null)
                                { 
                                    prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, 
                                                                                                                                            true /*firstCell*/, 
                                                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                            format) as string;
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                    while (prevDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = prevDataGridViewColumn; 
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                                false /*firstCell*/,
                                                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        { 
                                            sbContent.Append(cellContent);
                                        }
                                    }
                                } 

                                // Get the row header clipboard content 
                                if (includeRowHeaders) 
                                {
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, 
                                                                                                                       this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*firstCell*/,
                                                                                                                       true /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                       nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                       format) as string;
                                    if (cellContent != null) 
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                }
                            }
                            else
                            { 
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
 
                                // Get the row header clipboard content 
                                if (includeRowHeaders)
                                { 
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex,
                                                                                                                       true /*firstCell*/,
                                                                                                                       dataGridViewColumn == null /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                       nextRowIndex == -1 /*inLastRow*/,
                                                                                                                       format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                }

                                // Cycle through the visible columns in their display order 
                                if (dataGridViewColumn != null)
                                { 
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            !includeRowHeaders /*firstCell*/, 
                                                                                                                                            nextDataGridViewColumn == null /*lastCell*/,
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = nextDataGridViewColumn;
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, 
                                                                                                                                                false /*firstCell*/,
                                                                                                                                                nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        {
                                            sbContent.Append(cellContent);
                                        } 
                                    }
                                } 
                            } 
                            rowIndex = nextRowIndex;
                            if (rowIndex != -1) 
                            {
                                nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);
                            }
                            firstRowIndex = false; 
                        }
                        if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase)) 
                        { 
                            GetClipboardContentForHtml(sbContent);
                        } 
                        dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString());
                    }
                    break;
 
                case DataGridViewSelectionMode.FullColumnSelect:
                    if (this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) == 0) 
                    { 
                        return null;
                    } 

                    if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText)
                    {
                        includeColumnHeaders = true; 
                        includeRowHeaders = (this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Selected) == null);
                    } 
                    else 
                    {
                        includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText); 
                    }

                    includeColumnHeaders &= this.ColumnHeadersVisible;
                    includeRowHeaders &= this.RowHeadersVisible; 

                    int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
 
                    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 & selected columns in their display order 
                                DataGridViewColumn lastDataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                dataGridViewColumn = lastDataGridViewColumn; 
                                Debug.Assert(dataGridViewColumn != null); 
                                if (dataGridViewColumn != null)
                                { 
                                    prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            true /*firstCell*/,
                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                            true /*inFirstRow*/,
                                                                                                            firstVisibleRowIndex == -1 /*inLastRow*/, 
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    while (prevDataGridViewColumn != null)
                                    { 
                                        dataGridViewColumn = prevDataGridViewColumn;
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/,
                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                true /*inFirstRow*/,
                                                                                                                firstVisibleRowIndex == -1 /*inLastRow*/,
                                                                                                                format) as string;
                                        if (cellContent != null) 
                                        {
                                            sbContent.Append(cellContent); 
                                        } 
                                    }
                                } 
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     lastDataGridViewColumn == null /*firstCell*/, 
                                                                                                     true /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     firstVisibleRowIndex == -1 /*inLastRow*/, 
                                                                                                     format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                            }
                            else 
                            { 
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);
 
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     true /*firstCell*/, 
                                                                                                     dataGridViewColumn == null /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     firstVisibleRowIndex == -1 /*inLastRow*/, 
                                                                                                     format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                                // Cycle through the visible & selected columns in their display order
                                Debug.Assert(dataGridViewColumn != null); 
                                if (dataGridViewColumn != null) 
                                {
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            !includeRowHeaders /*firstCell*/,
                                                                                                            nextDataGridViewColumn == null /*lastCell*/,
                                                                                                            true /*inFirstRow*/, 
                                                                                                            firstVisibleRowIndex == -1 /*inLastRow*/,
                                                                                                            format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null)
                                    {
                                        dataGridViewColumn = nextDataGridViewColumn; 
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/, 
                                                                                                                nextDataGridViewColumn == null /*lastCell*/,
                                                                                                                true /*inFirstRow*/, 
                                                                                                                firstVisibleRowIndex == -1 /*inLastRow*/,
                                                                                                                format) as string;
                                        if (cellContent != null)
                                        { 
                                            sbContent.Append(cellContent);
                                        } 
                                    } 
                                }
                            } 
                        }
                        // Cycle through the visible rows.
                        bool firstRowIndex = true;
                        int rowIndex = firstVisibleRowIndex; 
                        int nextRowIndex = -1;
                        if (rowIndex != -1) 
                        { 
                            nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                        } 
                        while (rowIndex != -1)
                        {
                            if (this.RightToLeftInternal)
                            { 
                                DataGridViewColumn lastDataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
 
                                // Cycle through the visible & selected columns in their reverse display order 
                                dataGridViewColumn = lastDataGridViewColumn;
                                if (dataGridViewColumn != null) 
                                {
                                    prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            true /*firstCell*/, 
                                                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                    while (prevDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = prevDataGridViewColumn; 
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                                false /*firstCell*/, 
                                                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        { 
                                            sbContent.Append(cellContent); 
                                        }
                                    } 
                                }

                                // Get the row header clipboard content
                                if (includeRowHeaders) 
                                {
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, 
                                                                                                                       lastDataGridViewColumn == null /*firstCell*/, 
                                                                                                                       true /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                       nextRowIndex == -1 /*inLastRow*/,
                                                                                                                       format) as string;
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                } 
                            }
                            else 
                            {
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);

                                // Get the row header clipboard content 
                                if (includeRowHeaders)
                                { 
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, 
                                                                                                                       true /*firstCell*/,
                                                                                                                       dataGridViewColumn == null /*lastCell*/, 
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                       nextRowIndex == -1 /*inLastRow*/,
                                                                                                                       format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    } 
                                }
 
                                // Cycle through the visible & selected columns in their display order
                                if (dataGridViewColumn != null)
                                {
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            !includeRowHeaders /*firstCell*/, 
                                                                                                                                            nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string;
                                    if (cellContent != null)
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null) 
                                    { 
                                        dataGridViewColumn = nextDataGridViewColumn;
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                                false /*firstCell*/,
                                                                                                                                                nextDataGridViewColumn == null /*lastCell*/,
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                                format) as string; 
                                        if (cellContent != null) 
                                        {
                                            sbContent.Append(cellContent); 
                                        }
                                    }
                                }
                            } 
                            rowIndex = nextRowIndex;
                            if (rowIndex != -1) 
                            { 
                                nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                            } 
                            firstRowIndex = false;
                        }
                        if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase))
                        { 
                            GetClipboardContentForHtml(sbContent);
                        } 
                        dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString()); 
                    }
                    break; 

                case DataGridViewSelectionMode.CellSelect:
                case DataGridViewSelectionMode.RowHeaderSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    bool selectedVisibleCellExists = false;
                    bool selectedVisibleColumnExists = false; 
                    bool selectedVisibleRowExists = false; 
                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                    { 
                        selectedVisibleRowExists = this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) != 0;
                        selectedVisibleCellExists = selectedVisibleRowExists && this.Columns.GetColumnCount(DataGridViewElementStates.Visible) != 0;
                    }
                    else if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) 
                    {
                        selectedVisibleColumnExists = this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) != 0; 
                        selectedVisibleCellExists = selectedVisibleColumnExists && this.Rows.GetRowCount(DataGridViewElementStates.Visible) != 0; 
                    }
                    if (!selectedVisibleCellExists && this.individualSelectedCells.Count > 0) 
                    {
                        foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells)
                        {
                            if (dataGridViewCell.Visible) 
                            {
                                selectedVisibleCellExists = true; 
                                break; 
                            }
                        } 
                    }
                    if (!selectedVisibleCellExists)
                    {
                        return null; 
                    }
 
                    // There is at least one selected visible cell. 
                    if (this.SelectionMode == DataGridViewSelectionMode.CellSelect)
                    { 
                        includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText);
                        includeColumnHeaders &= this.ColumnHeadersVisible;
                        includeRowHeaders &= this.RowHeadersVisible;
                    } 
                    else
                    { 
                        includeColumnHeaders = includeRowHeaders = false; 
                        if (this.ColumnHeadersVisible)
                        { 
                            if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText)
                            {
                                if (selectedVisibleColumnExists)
                                { 
                                    includeColumnHeaders = true;
                                } 
                                /* Use this code if column headers should be included when all cells are selected in a visible column. 
                                else
                                { 
                                    // Include column headers if there is a column where all visible cells are selected
                                    DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                                    Debug.Assert(dataGridViewColumn != null);
                                    while (dataGridViewColumn != null) 
                                    {
                                        // Cycle through the visible rows, see if the cell in that column is selected 
                                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                                        while (rowIndex != -1)
                                        { 
                                            if (!this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].Selected)
                                            {
                                                break;
                                            } 
                                            rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                                        } 
                                        if (rowIndex == -1) 
                                        {
                                            // All visible cells in column are selected 
                                            includeColumnHeaders = true;
                                            break;
                                        }
                                        dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    }
                                } 
                                */ 
                            }
                            else 
                            {
                                includeColumnHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText);
                            }
                        } 

                        if (this.RowHeadersVisible) 
                        { 
                            if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText)
                            { 
                                if (selectedVisibleRowExists)
                                {
                                    includeRowHeaders = true;
                                } 
                                /* Use this code if row headers should be included when all cells are selected in a visible row.
                                else 
                                { 
                                    // Include row headers if there is a row where all visible cells are selected
                                    int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                                    Debug.Assert(rowIndex != -1);
                                    while (rowIndex != -1)
                                    {
                                        // Cycle through the visible columns, see if the cell in that row is selected 
                                        DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                                        Debug.Assert(dataGridViewColumn != null); 
                                        while (dataGridViewColumn != null) 
                                        {
                                            if (!this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].Selected) 
                                            {
                                                break;
                                            }
                                            dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        }
                                        if (dataGridViewColumn == null) 
                                        { 
                                            // All visible cells in row are selected
                                            includeRowHeaders = true; 
                                            break;
                                        }
                                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                                    } 
                                }
                                */ 
                            } 
                            else
                            { 
                                includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText);
                            }
                        }
                    } 

                    // Get the four corners of the 'selected table' 
                    int lRowIndex = int.MaxValue; 
                    int uRowIndex = -1;
                    DataGridViewColumn lColumn = null, uColumn = null; 

                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                    {
                        DataGridViewColumn firstVisibleColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
                        DataGridViewColumn lastVisibleColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None);
 
                        Debug.Assert(firstVisibleColumn != null); 
                        Debug.Assert(lastVisibleColumn != null);
                        foreach (int rowIndex in this.selectedBandIndexes) 
                        {
                            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0)
                            {
                                if (rowIndex < lRowIndex) 
                                {
                                    lRowIndex = rowIndex; 
                                } 
                                if (rowIndex > uRowIndex)
                                { 
                                    uRowIndex = rowIndex;
                                }
                                lColumn = firstVisibleColumn;
                                uColumn = lastVisibleColumn; 
                            }
                        } 
                    } 
                    else if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)
                    { 
                        firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                        int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                        Debug.Assert(firstVisibleRowIndex != -1);
                        Debug.Assert(lastVisibleRowIndex != -1); 
                        foreach (int columnIndex in this.selectedBandIndexes)
                        { 
                            if (this.Columns[columnIndex].Visible) 
                            {
                                if (lColumn == null || this.Columns.DisplayInOrder(columnIndex, lColumn.Index)) 
                                {
                                    lColumn = this.Columns[columnIndex];
                                }
                                if (uColumn == null || this.Columns.DisplayInOrder(uColumn.Index, columnIndex)) 
                                {
                                    uColumn = this.Columns[columnIndex]; 
                                } 
                                lRowIndex = firstVisibleRowIndex;
                                uRowIndex = lastVisibleRowIndex; 
                            }
                        }
                    }
 
                    // Go through the individually selected cells to potentially stretch the current 'selected table'.
                    foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells) 
                    { 
                        if (dataGridViewCell.Visible)
                        { 
                            if (dataGridViewCell.RowIndex < lRowIndex)
                            {
                                lRowIndex = dataGridViewCell.RowIndex;
                            } 
                            if (dataGridViewCell.RowIndex > uRowIndex)
                            { 
                                uRowIndex = dataGridViewCell.RowIndex; 
                            }
                            if (lColumn == null || this.Columns.DisplayInOrder(dataGridViewCell.ColumnIndex, lColumn.Index)) 
                            {
                                lColumn = dataGridViewCell.OwningColumn;
                            }
                            if (uColumn == null || this.Columns.DisplayInOrder(uColumn.Index, dataGridViewCell.ColumnIndex)) 
                            {
                                uColumn = dataGridViewCell.OwningColumn; 
                            } 
                        }
                    } 

                    Debug.Assert(lRowIndex != -1);
                    Debug.Assert(uRowIndex != -1);
                    Debug.Assert(lColumn != null); 
                    Debug.Assert(uColumn != null);
                    Debug.Assert(lColumn.Index == uColumn.Index || this.Columns.DisplayInOrder(lColumn.Index, uColumn.Index)); 
                    Debug.Assert(lRowIndex <= uRowIndex); 

                    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 from uColumn to lColumn
                                dataGridViewColumn = uColumn; 
                                Debug.Assert(dataGridViewColumn != null); 
                                while (dataGridViewColumn != null)
                                { 
                                    if (dataGridViewColumn != lColumn)
                                    {
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        Debug.Assert(prevDataGridViewColumn != null); 
                                    }
                                    else 
                                    { 
                                        prevDataGridViewColumn = null;
                                    } 
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            dataGridViewColumn == uColumn /*firstCell*/,
                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                            true /*inFirstRow*/, 
                                                                                                            false /*inLastRow*/,
                                                                                                            format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    dataGridViewColumn = prevDataGridViewColumn;
                                }
                                if (includeRowHeaders) 
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, 
                                                                                                     false /*firstCell*/, 
                                                                                                     true /*lastCell*/,
                                                                                                     true  /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/,
                                                                                                     format) as string;
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                } 
                            }
                            else 
                            {
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, 
                                                                                                     true  /*firstCell*/,
                                                                                                     false /*lastCell*/, 
                                                                                                     true  /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/,
                                                                                                     format) as string; 
                                    if (cellContent != null)
                                    {
                                        sbContent.Append(cellContent);
                                    } 
                                }
                                // Cycle through the visible columns from lColumn to uColumn 
                                dataGridViewColumn = lColumn; 
                                Debug.Assert(dataGridViewColumn != null);
                                while (dataGridViewColumn != null) 
                                {
                                    if (dataGridViewColumn != uColumn)
                                    {
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        Debug.Assert(nextDataGridViewColumn != null);
                                    } 
                                    else 
                                    {
                                        nextDataGridViewColumn = null; 
                                    }
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            !includeRowHeaders && dataGridViewColumn == lColumn /*firstCell*/,
                                                                                                            nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                            true /*inFirstRow*/,
                                                                                                            false /*inLastRow*/, 
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    dataGridViewColumn = nextDataGridViewColumn;
                                } 
                            }
                        } 
                        // Cycle through the visible rows from lRowIndex to uRowIndex. 
                        bool firstRowIndex = true;
                        int rowIndex = lRowIndex; 
                        int nextRowIndex = -1;
                        Debug.Assert(rowIndex != -1);
                        while (rowIndex != -1)
                        { 
                            if (rowIndex != uRowIndex)
                            { 
                                nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); 
                                Debug.Assert(nextRowIndex != -1);
                            } 
                            else
                            {
                                nextRowIndex = -1;
                            } 

                            if (this.RightToLeftInternal) 
                            { 
                                // Cycle through the visible columns from uColumn to lColumn
                                dataGridViewColumn = uColumn; 
                                Debug.Assert(dataGridViewColumn != null);
                                while (dataGridViewColumn != null)
                                {
                                    if (dataGridViewColumn != lColumn) 
                                    {
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        Debug.Assert(prevDataGridViewColumn != null); 
                                    }
                                    else 
                                    {
                                        prevDataGridViewColumn = null;
                                    }
 
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            dataGridViewColumn == uColumn /*firstCell*/, 
                                                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string;
                                    if (cellContent != null)
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    dataGridViewColumn = prevDataGridViewColumn; 
                                } 

                                if (includeRowHeaders) 
                                {
                                    // Get the row header clipboard content
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex,
                                                                                                                       false /*firstCell*/, 
                                                                                                                       true /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                       nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                       format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                            }
                            else 
                            { 
                                if (includeRowHeaders)
                                { 
                                    // Get the row header clipboard content
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex,
                                                                                                                       true /*firstCell*/,
                                                                                                                       false /*lastCell*/, 
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                       nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                       format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                }
 
                                // Cycle through the visible columns from lColumn to uColumn
                                dataGridViewColumn = lColumn; 
                                Debug.Assert(dataGridViewColumn != null); 
                                while (dataGridViewColumn != null)
                                { 
                                    if (dataGridViewColumn != uColumn)
                                    {
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        Debug.Assert(nextDataGridViewColumn != null); 
                                    }
                                    else 
                                    { 
                                        nextDataGridViewColumn = null;
                                    } 

                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            !includeRowHeaders && dataGridViewColumn == lColumn /*firstCell*/,
                                                                                                                                            nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    dataGridViewColumn = nextDataGridViewColumn;
                                } 
                            }
                            rowIndex = nextRowIndex; 
                            firstRowIndex = false; 
                        }
                        if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase)) 
                        {
                            GetClipboardContentForHtml(sbContent);
                        }
                        dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString()); 
                    }
                    break; 
            } 
            return dataObject;
        } 

        private static void GetClipboardContentForHtml(StringBuilder sbContent)
        {
            // Marshal.SystemDefaultCharSize is 2 on WinXP Pro - so the offsets seem to be in character counts instead of bytes. 
            // Test on JPN and Win9x machines.
            int bytecountEndOfFragment = 135 + sbContent.Length; 
            int bytecountEndOfHtml = bytecountEndOfFragment + 36; 
            string prefix = string.Format(CultureInfo.InvariantCulture, DATAGRIDVIEW_htmlPrefix, bytecountEndOfHtml.ToString("00000000", CultureInfo.InvariantCulture), bytecountEndOfFragment.ToString("00000000", CultureInfo.InvariantCulture)) + DATAGRIDVIEW_htmlStartFragment;
            sbContent.Insert(0, prefix); 
            sbContent.Append(DATAGRIDVIEW_htmlEndFragment);
            #if DEBUG
            string strContent = sbContent.ToString();
            Debug.Assert(strContent[97] == '<'); 
            Debug.Assert(strContent[bytecountEndOfHtml-1] == '>');
            Debug.Assert(strContent[133] == '<'); 
            Debug.Assert(strContent[bytecountEndOfFragment] == '<'); 
            #endif
        } 

        /// 
        // Rectangle returned includes the potential column header
        public Rectangle GetColumnDisplayRectangle(int columnIndex, bool cutOverflow) 
        {
            if (columnIndex < 0 || columnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("columnIndex");
            } 
            return GetColumnDisplayRectanglePrivate(columnIndex, cutOverflow);
        }

        private Rectangle GetColumnDisplayRectanglePrivate(int columnIndex, bool cutOverflow) 
        {
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 
 
            if (!this.Columns[columnIndex].Displayed)
            { 
                return Rectangle.Empty;
            }

            Rectangle data = this.layout.Data; 
            int cx;
            bool columnFound = false; 
            DataGridViewColumn dataGridViewColumn; 
            if (this.RightToLeftInternal)
            { 
                cx = data.Right;
            }
            else
            { 
                cx = data.X;
            } 
            for (dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                dataGridViewColumn != null && !columnFound;
                ) 
            {
                if ((this.RightToLeftInternal && cx < data.X) ||
                    (!this.RightToLeftInternal && cx > data.Right))
                { 
                    break;
                } 
                if (dataGridViewColumn.Index == columnIndex) 
                {
                    columnFound = true; 
                }
                else
                {
                    if (this.RightToLeftInternal) 
                    {
                        cx -= dataGridViewColumn.Thickness; 
                    } 
                    else
                    { 
                        cx += dataGridViewColumn.Thickness;
                    }
                    dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, 
                        DataGridViewElementStates.None);
                } 
            } 

            if (!columnFound && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) 
            {
                for (dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                    dataGridViewColumn != null && !columnFound;
                    ) 
                {
                    if ((this.RightToLeftInternal && cx < data.X) || 
                        (!this.RightToLeftInternal && cx > data.Right)) 
                    {
                        break; 
                    }
                    if (dataGridViewColumn.Index == columnIndex)
                    {
                        columnFound = true; 
                    }
                    else 
                    { 
                        if (this.RightToLeftInternal)
                        { 
                            cx -= dataGridViewColumn.Thickness;
                        }
                        else
                        { 
                            cx += dataGridViewColumn.Thickness;
                        } 
                        if (dataGridViewColumn.Index == this.displayedBandsInfo.FirstDisplayedScrollingCol) 
                        {
                            if (this.RightToLeftInternal) 
                            {
                                cx += this.negOffset;
                            }
                            else 
                            {
                                cx -= this.negOffset; 
                            } 
                        }
                        dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None);
                    }
                } 
            }
 
            if (columnFound) 
            {
                Debug.Assert(dataGridViewColumn != null); 
                int displayWidth, viewedColumnWidth = dataGridViewColumn.Thickness;
                if (dataGridViewColumn.Index == this.displayedBandsInfo.FirstDisplayedScrollingCol)
                {
                    viewedColumnWidth -= this.negOffset; 
                }
                if (cutOverflow && 
                    ((!this.RightToLeftInternal && cx + viewedColumnWidth > data.Right) || 
                     (this.RightToLeftInternal && cx - viewedColumnWidth < data.X)))
                { 
                    if (this.RightToLeftInternal)
                    {
                        displayWidth = cx - data.X;
                    } 
                    else
                    { 
                        displayWidth = data.Right - cx; 
                    }
                } 
                else
                {
                    displayWidth = viewedColumnWidth;
                } 

                Rectangle columnRect; 
                if (this.RightToLeftInternal) 
                {
                    columnRect = new Rectangle(cx - displayWidth, data.Y, displayWidth, data.Height); 
                }
                else
                {
                    columnRect = new Rectangle(cx, data.Y, displayWidth, data.Height); 
                }
                if (this.layout.ColumnHeadersVisible) 
                { 
                    columnRect.Height += this.layout.ColumnHeaders.Height;
                    columnRect.Y      -= this.layout.ColumnHeaders.Height; 
                }
                return columnRect;
            }
 
            return Rectangle.Empty;
        } 
 
        // xColumnLeftEdge returns the left edge of the column when RightToLeft is false.
        // xColumnLeftEdge returns the right edge of the column when RightToLeft is true. 
        private int GetColumnIndexFromX(int x, out int xColumnLeftEdge)
        {
            Rectangle data = this.layout.Data;
            Debug.Assert(this.RightToLeftInternal || (x >= data.X - 1 && x < data.Right), "x must be inside the horizontal bounds of this.layout.Data"); 
            Debug.Assert(!this.RightToLeftInternal || (x >= data.X && x <= data.Right), "x must be inside the horizontal bounds of this.layout.Data");
 
            if (!this.RightToLeftInternal && x == data.X - 1) 
            {
                x++; 
            }
            else if (this.RightToLeftInternal && x == data.Right)
            {
                x--; 
            }
 
            int cx; 
            if (this.RightToLeftInternal)
            { 
                cx = data.Right-1;
            }
            else
            { 
                cx = data.X;
            } 
 
            // first try to match x against a frozen column
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            while (dataGridViewColumn != null &&
                   ((!this.RightToLeftInternal && cx < data.Right) || (this.RightToLeftInternal && cx >= data.X)))
            {
                if (this.RightToLeftInternal) 
                {
                    cx -= dataGridViewColumn.Thickness; 
                } 
                else
                { 
                    cx += dataGridViewColumn.Thickness;
                }
                if (!this.RightToLeftInternal && cx > x)
                { 
                    xColumnLeftEdge = cx - dataGridViewColumn.Thickness;
                    return dataGridViewColumn.Index; 
                } 
                else if (this.RightToLeftInternal && cx < x)
                { 
                    xColumnLeftEdge = cx + dataGridViewColumn.Thickness;
                    return dataGridViewColumn.Index;
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                    DataGridViewElementStates.None); 
            } 

            if (this.RightToLeftInternal) 
            {
                cx += this.negOffset;
            }
            else 
            {
                cx -= this.negOffset; 
            } 

            // second try to match x against a scrolling column 
            if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0)
            {
                dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                while (dataGridViewColumn != null && 
                       ((!this.RightToLeftInternal && cx < data.Right) || (this.RightToLeftInternal && cx >= data.X)))
                { 
                    Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); 
                    if (this.RightToLeftInternal)
                    { 
                        cx -= dataGridViewColumn.Thickness;
                    }
                    else
                    { 
                        cx += dataGridViewColumn.Thickness;
                    } 
                    if (!this.RightToLeftInternal && cx > x) 
                    {
                        xColumnLeftEdge = cx - dataGridViewColumn.Thickness; 
                        return dataGridViewColumn.Index;
                    }
                    else if (this.RightToLeftInternal && cx < x)
                    { 
                        xColumnLeftEdge = cx + dataGridViewColumn.Thickness;
                        return dataGridViewColumn.Index; 
                    } 
                    dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.None);
                }
            }
 
            xColumnLeftEdge = -1;
            return -1; 
        } 

        private static int GetColumnScrollRate(int xOffset) 
        {
            Debug.Assert(xOffset > 0);
            // Counting 20ms for executing the actual column scrolling
            if (xOffset <= 10) 
            {
                return 480;     // Two columns per second 
            } 
            if (xOffset <= 15)
            { 
                return 313;     // Three columns per second
            }
            if (xOffset <= 25)
            { 
                return 180;     // Five columns per second
            } 
            if (xOffset <= 35) 
            {
                return 123;     // Seven columns per second 
            }
            return Math.Max(1, 4000 / xOffset);
        }
 
        /// 
        ///      Returns the coordinate of the left edge of the given column. Note that 
        ///      the column does not need to be completely visible on the display area. 
        ///      Value returned is not necessarily within layout.Data because of the
        ///      this.negOffset value, or because the column may start to the right of 
        ///      data area, or behind the frozen area, or completely on the left of the control.
        ///      The right edge is returned in RightToLeft mode.
        /// 
        internal int GetColumnXFromIndex(int index) 
        {
            Debug.Assert(index < this.Columns.Count); 
            Debug.Assert(this.Columns[index].Visible); 

            int x; 
            if (this.RightToLeftInternal)
            {
                x = this.layout.Data.Right-1;
            } 
            else
            { 
                x = this.layout.Data.X; 
            }
 
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            while (dataGridViewColumn != null)
            {
                if (index == dataGridViewColumn.Index) 
                {
                    return x; 
                } 
                if (this.RightToLeftInternal)
                { 
                    x -= dataGridViewColumn.Thickness;
                }
                else
                { 
                    x += dataGridViewColumn.Thickness;
                } 
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                    DataGridViewElementStates.None); 
            }

            if (this.RightToLeftInternal)
            { 
                x += this.negOffset;
            } 
            else 
            {
                x -= this.negOffset; 
            }

            int xFirstVisibleScrollingCol = x;
 
            if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0)
            { 
                dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
            }
            else 
            {
                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
            }
            Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); 

            while (dataGridViewColumn != null) 
            { 
                if (index == dataGridViewColumn.Index)
                { 
                    return x;
                }
                if (this.RightToLeftInternal)
                { 
                    x -= dataGridViewColumn.Thickness;
                } 
                else 
                {
                    x += dataGridViewColumn.Thickness; 
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None); 
            }
 
            // The column is completely hidden on the left/right of the dataGridView 
            x = xFirstVisibleScrollingCol;
            dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
            dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn,
                DataGridViewElementStates.Visible,
                DataGridViewElementStates.Frozen);
            while (dataGridViewColumn != null) 
            {
                if (this.RightToLeftInternal) 
                { 
                    x += dataGridViewColumn.Thickness;
                } 
                else
                {
                    x -= dataGridViewColumn.Thickness;
                } 
                if (index == dataGridViewColumn.Index)
                { 
                    return x; 
                }
                dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
            }
 
            Debug.Fail("Could not find column in GetColumnXFromIndex");
            return 0; 
        } 

        private int GetNegOffsetFromHorizontalOffset(int horizontalOffset) 
        {
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
            while (dataGridViewColumn != null && dataGridViewColumn.Thickness <= horizontalOffset)
            { 
                horizontalOffset -= dataGridViewColumn.Thickness;
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
            } 
            return horizontalOffset;
        } 

        private bool GetOutOfBoundCorrectedHitTestInfo(ref HitTestInfo hti, ref int mouseX, ref int mouseY, out int xOffset, out int yOffset)
        {
            xOffset = yOffset = 0; 
            Rectangle rectScrollingArea = this.layout.Data;
            int visibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); 
            int frozenVisibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            int fittingTrailingScrollingRowsHeight = ComputeHeightOfFittingTrailingScrollingRows(frozenVisibleRowsHeight);
            int trailingScrollingRowsHeight = ComputeHeightOfTrailingScrollingRows(); 
            int emptyBackgroundWidth = Math.Max(0, this.layout.Data.Width - this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible));
            int emptyBackgroundHeight = Math.Max(0, this.layout.Data.Height - frozenVisibleRowsHeight - trailingScrollingRowsHeight);

            Debug.Assert(!this.vertScrollBar.Enabled || 
                         !this.vertScrollBar.Visible ||
                         this.vertScrollBar.Maximum == visibleRowsHeight - frozenVisibleRowsHeight); 
            //VSWhidbey 525671 
            //Debug.Assert(!this.vertScrollBar.Enabled ||
            //             !this.vertScrollBar.Visible || 
            //             this.vertScrollBar.Value >= this.verticalOffset);

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect])
            { 
                if (this.layout.RowHeadersVisible)
                { 
                    // Include row headers 
                    rectScrollingArea = Rectangle.Union(rectScrollingArea, this.layout.RowHeaders);
                } 
                // Discard frozen rows
                DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight,
                                            false /*discardFrozenColumns*/, true /*discardFrozenRows*/);
 
                if (mouseY >= rectScrollingArea.Top && mouseY <= rectScrollingArea.Bottom)
                { 
                    // Mouse's Y is in-bound -- correct X value 
                    hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right-1 : rectScrollingArea.Left, mouseY);
                    if (this.ptAnchorCell.Y != -1 && 
                        (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) != 0 &&
                        this.trackRowEdge != -1 &&
                        (this.Rows.GetRowState(this.trackRowEdge) & DataGridViewElementStates.Frozen) != 0 &&
                        hti.row >= 0 && 
                        (this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Frozen) == 0)
                    { 
                        // Anchor cell is in frozen row and target cell is in unfrozen row. Make sure no row is scrolled off. 
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                        int firstUnfrozenRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                        int firstColumnIndex;
                        if (hti.col >= 0)
                        {
                            firstColumnIndex = hti.col; 
                        }
                        else 
                        { 
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                            firstColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
                        }
                        if (firstColumnIndex >= 0 && firstUnfrozenRowIndex >= 0)
                        {
                            if (!ScrollIntoView(firstColumnIndex, firstUnfrozenRowIndex, false /*forCurrentCellChange*/)) 
                            {
                                return false; 
                            } 
                            hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right : rectScrollingArea.Left, mouseY);
                        } 
                    }
                    return true;
                }
 
                // Mouse's Y is outside of scrolling bands
                if (mouseY < rectScrollingArea.Top) 
                { 
                    if (this.ptAnchorCell.Y != -1 &&
                        ((this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) == 0 || 
                         (this.trackRowEdge != -1 && (this.Rows.GetRowState(this.trackRowEdge) & DataGridViewElementStates.Frozen) == 0)) &&
                        this.verticalOffset != 0)
                    {
                        // Up scrolling is required because the anchor's row is unfrozen 
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                        yOffset = mouseY - rectScrollingArea.Top;   // yOffset strictly negative 
                        if (this.RightToLeftInternal) 
                        {
                            mouseX = rectScrollingArea.Right-1; 
                        }
                        else
                        {
                            mouseX = rectScrollingArea.Left+1; 
                        }
                    } 
                    else 
                    {
                        hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right : rectScrollingArea.Left, mouseY); 
                    }
                }
                else
                { 
                    Debug.Assert(mouseY > rectScrollingArea.Bottom);
                    if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
                    { 
                        if (this.verticalOffset + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <=
                            visibleRowsHeight - frozenVisibleRowsHeight - fittingTrailingScrollingRowsHeight) 
                        {
                            // Down scrolling is required
                            yOffset = mouseY - rectScrollingArea.Bottom;   // yOffset strictly positive
                            if (this.RightToLeftInternal) 
                            {
                                mouseX = rectScrollingArea.Right-1; 
                            } 
                            else
                            { 
                                mouseX = rectScrollingArea.Left+1;
                            }
                        }
                    } 
                }
                return true; 
            } 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect]) 
            {
                if (this.layout.ColumnHeadersVisible)
                {
                    // Include column headers 
                    rectScrollingArea = Rectangle.Union(rectScrollingArea, this.layout.ColumnHeaders);
                } 
 
                // Discard frozen columns
                DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight, 
                                            true /*discardFrozenColumns*/, false /*discardFrozenRows*/);

                if (mouseX >= rectScrollingArea.Left && mouseX <= rectScrollingArea.Right)
                { 
                    // Mouse's X is in-bound -- correct Y value
                    hti = HitTest(mouseX, rectScrollingArea.Top); 
                    if (this.ptAnchorCell.X != -1 && 
                        this.Columns[this.ptAnchorCell.X].Frozen &&
                        this.trackColumnEdge != -1 && 
                        this.Columns[this.trackColumnEdge].Frozen &&
                        hti.col >= 0 &&
                        !this.Columns[hti.col].Frozen)
                    { 
                        // Anchor cell is in frozen column and target cell is in unfrozen column. Make sure no column is scrolled off.
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0); 
                        int firstUnfrozenColumnIndex = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen).Index; 
                        int firstRowIndex;
                        if (hti.row >= 0) 
                        {
                            firstRowIndex = hti.row;
                        }
                        else 
                        {
                            firstRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                        } 
                        if (firstRowIndex >= 0 && firstUnfrozenColumnIndex >= 0)
                        { 
                            if (!ScrollIntoView(firstUnfrozenColumnIndex, firstRowIndex, false /*forCurrentCellChange*/))
                            {
                                return false;
                            } 
                            hti = HitTest(mouseX, rectScrollingArea.Top);
                        } 
                    } 
                    return true;
                } 

                // Mouse's X is outside of scrolling bands
                if ((!this.RightToLeftInternal && mouseX < rectScrollingArea.Left) ||
                    (this.RightToLeftInternal && mouseX > rectScrollingArea.Right)) 
                {
                    if (this.ptAnchorCell.X != -1 && 
                        (!this.Columns[this.ptAnchorCell.X].Frozen || 
                         (this.trackColumnEdge != -1 && !this.Columns[this.trackColumnEdge].Frozen)) &&
                        this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && 
                        (this.negOffset > 0 ||
                         this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) != null))
                    {
                        // xOffset strictly negative 
                        if (this.RightToLeftInternal)
                        { 
                            // Right scrolling is required 
                            xOffset = rectScrollingArea.Right - mouseX;
                        } 
                        else
                        {
                            // Left scrolling is required
                            xOffset = mouseX - rectScrollingArea.Left; 
                        }
                        mouseY = rectScrollingArea.Top+1; 
                    } 
                    else
                    { 
                        hti = HitTest(mouseX, rectScrollingArea.Top);
                    }
                }
                else 
                {
                    Debug.Assert((!this.RightToLeftInternal && mouseX > rectScrollingArea.Right) || (this.RightToLeftInternal && mouseX < rectScrollingArea.Left)); 
                    if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) 
                    {
                        if (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol != -1 && 
                            this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None) == null)
                        {
                            // No more columns to scroll
                            return true; 
                        }
 
                        DataGridViewColumn newFirstVisibleScrollingCol = this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], 
                                                                                                             DataGridViewElementStates.Visible,
                                                                                                             DataGridViewElementStates.None); 
                        int newColOffset = 0;
                        for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible,
                                                                                                          DataGridViewElementStates.Frozen);
                            dataGridViewColumn != newFirstVisibleScrollingCol; 
                            dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                            DataGridViewElementStates.Visible, 
                            DataGridViewElementStates.None)) 
                        {
                            newColOffset += dataGridViewColumn.Thickness; 
                        }

                        if (this.HorizontalOffset != newColOffset)
                        { 
                            // xOffset strictly positive
                            if (this.RightToLeftInternal) 
                            { 
                                // Left scrolling is required
                                xOffset = rectScrollingArea.Left - mouseX; 
                            }
                            else
                            {
                                // Right scrolling is required 
                                xOffset = mouseX - rectScrollingArea.Right;
                            } 
                            mouseY = rectScrollingArea.Top+1; 
                        }
                    } 
                }
                return true;
            }
 
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])
            { 
                bool recomputeHitTestInfo = false; 

                // Discard frozen columns and rows 
                DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight,
                                            true /*discardFrozenColumns*/, true /*discardFrozenRows*/);

                if (mouseY < rectScrollingArea.Top) 
                {
                    // Mouse's Y is above scrolling bands 
                    if ( 
                        (
                         (this.ptAnchorCell.Y != -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) == 0) 
                         ||
                         (this.ptCurrentCell.Y != -1 && (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Frozen) == 0)
                        )
                        && 
                        this.verticalOffset != 0
                       ) 
                    { 
                        // Up scrolling is required - the anchor's row is unfrozen
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
                        yOffset = mouseY - rectScrollingArea.Top;   // yOffset strictly negative
                    }
                    else
                    { 
                        // Correct mouse's Y - no scrolling can be performed
                        if (mouseY < this.layout.Data.Top) 
                        { 
                            mouseY = this.layout.Data.Top+1;
                            recomputeHitTestInfo = true; 
                        }
                    }
                }
                else if (mouseY > rectScrollingArea.Bottom) 
                {
                    // Mouse's Y is below scrolling bands 
                    if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
                    {
                        if (this.verticalOffset + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <= 
                            visibleRowsHeight - frozenVisibleRowsHeight - fittingTrailingScrollingRowsHeight)
                        {
                            // Down scrolling is required
                            yOffset = mouseY - rectScrollingArea.Bottom;   // yOffset strictly positive 
                        }
                        else 
                        { 
                            // Correct mouse's Y - no scrolling can be performed
                            mouseY = rectScrollingArea.Bottom-1; 
                            recomputeHitTestInfo = true;
                        }
                    }
                    else 
                    {
                        // Correct mouse's Y - no scrolling can be performed 
                        mouseY = rectScrollingArea.Bottom-1; 
                        recomputeHitTestInfo = true;
                    } 
                }
#if DEBUG
                else
                { 
                    // Mouse's Y is in-bound
                    Debug.Assert(mouseY >= rectScrollingArea.Top && mouseY <= rectScrollingArea.Bottom); 
                } 
#endif
                if ((!this.RightToLeftInternal && mouseX < rectScrollingArea.Left) || 
                    (this.RightToLeftInternal && mouseX > rectScrollingArea.Right))
                {
                    // Mouse's X is on the left of scrolling bands (LTR)
                    if ( 
                        (
                         (this.ptAnchorCell.X != -1 && !this.Columns[this.ptAnchorCell.X].Frozen) 
                         || 
                         (this.ptCurrentCell.X != -1 && !this.Columns[this.ptCurrentCell.X].Frozen)
                        ) 
                        &&
                        this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 &&
                        (this.negOffset > 0 ||
                         this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) != null) 
                       )
                    { 
                        // xOffset strictly negative 
                        if (this.RightToLeftInternal)
                        { 
                            // Right scrolling is required - anchor's column is unfrozen
                            xOffset = rectScrollingArea.Right - mouseX;
                        }
                        else 
                        {
                            // Left scrolling is required - anchor's column is unfrozen 
                            xOffset = mouseX - rectScrollingArea.Left; 
                        }
                    } 
                    else
                    {
                        // Correct mouse's X - no scrolling can be performed
                        if (!this.RightToLeftInternal && mouseX < this.layout.Data.Left) 
                        {
                            mouseX = this.layout.Data.Left+1; 
                            recomputeHitTestInfo = true; 
                        }
                        else if (this.RightToLeftInternal && mouseX > this.layout.Data.Right) 
                        {
                            mouseX = this.layout.Data.Right-1;
                            recomputeHitTestInfo = true;
                        } 
                    }
                } 
                else if ((!this.RightToLeftInternal && mouseX > rectScrollingArea.Right) || 
                         (this.RightToLeftInternal && mouseX < rectScrollingArea.Left))
                { 
                    // Mouse's X is on the right of scrolling bands (LTR)
                    if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 &&
                        (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol == -1 ||
                         this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None) != null)) 
                    {
                        DataGridViewColumn newFirstVisibleScrollingCol = this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], 
                                                                                                            DataGridViewElementStates.Visible, 
                                                                                                            DataGridViewElementStates.None);
                        int newColOffset = 0; 
                        for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible,
                                                                                                          DataGridViewElementStates.Frozen);
                            dataGridViewColumn != newFirstVisibleScrollingCol;
                            dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None)) 
                        { 
                            newColOffset += dataGridViewColumn.Thickness;
                        } 
                        if (this.HorizontalOffset != newColOffset)
                        {
                            // xOffset strictly positive
                            if (this.RightToLeftInternal) 
                            {
                                // Left scrolling is required 
                                xOffset = rectScrollingArea.Left - mouseX; 
                            }
                            else 
                            {
                                // Right scrolling is required
                                xOffset = mouseX - rectScrollingArea.Right;
                            } 
                        }
                        else 
                        { 
                            // Correct mouse's X - no scrolling can be performed
                            if (this.RightToLeftInternal) 
                            {
                                mouseX = rectScrollingArea.Left+1;
                            }
                            else 
                            {
                                mouseX = rectScrollingArea.Right-1; 
                            } 
                            recomputeHitTestInfo = true;
                        } 
                    }
                    else
                    {
                        // Correct mouse's X - no scrolling can be performed 
                        if (this.RightToLeftInternal)
                        { 
                            mouseX = rectScrollingArea.Left+1; 
                        }
                        else 
                        {
                            mouseX = rectScrollingArea.Right-1;
                        }
                        recomputeHitTestInfo = true; 
                    }
                } 
#if DEBUG 
                else
                { 
                    // Mouse's X is in-bound
                    Debug.Assert(mouseX >= rectScrollingArea.Left && mouseX <= rectScrollingArea.Right);
                }
#endif 
                if (recomputeHitTestInfo)
                { 
                    hti = HitTest(mouseX, mouseY); 
                }
            } 
            return true;
        }

        internal override Size GetPreferredSizeCore(Size proposedConstraints) 
        {
            int bordersAndPaddingWidth = 2*(this.BorderWidth + this.Padding.Size.Width); 
            int bordersAndPaddingHeight = 2*(this.BorderWidth + this.Padding.Size.Height); 

            bool allowHorizScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Horizontal); 
            bool allowVertScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Vertical);

            int minimumWidth = 16 + bordersAndPaddingWidth;
            if (allowVertScrollbar) 
            {
                minimumWidth += this.vertScrollBar.Width; 
            } 
            if (this.RowHeadersVisible)
            { 
                minimumWidth += this.RowHeadersWidth;
            }
            int preferredWidth = Math.Min(minimumWidth + this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible), proposedConstraints.Width);
            if (preferredWidth < minimumWidth) 
            {
                preferredWidth = minimumWidth; 
            } 

            int minimumHeight = 16 + bordersAndPaddingHeight; 
            if (allowHorizScrollbar)
            {
                minimumHeight += this.horizScrollBar.Height;
            } 
            if (this.ColumnHeadersVisible)
            { 
                minimumHeight += this.ColumnHeadersHeight; 
            }
            int preferredHeight = Math.Min(minimumHeight + this.Rows.GetRowsHeight(DataGridViewElementStates.Visible), proposedConstraints.Height); 
            if (preferredHeight < minimumHeight)
            {
                preferredHeight = minimumHeight;
            } 

            return new Size(preferredWidth, preferredHeight); 
        } 

        ///  
        // Rectangle returned includes the potential row header
        public Rectangle GetRowDisplayRectangle(int rowIndex, bool cutOverflow)
        {
            if (rowIndex < 0 || rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            } 
            return GetRowDisplayRectanglePrivate(rowIndex, cutOverflow);
        } 

        private Rectangle GetRowDisplayRectanglePrivate(int rowIndex, bool cutOverflow)
        {
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); 

            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) == 0) 
            { 
                return Rectangle.Empty;
            } 

            Rectangle data = this.layout.Data;
            int cy = data.Y;
            bool rowFound = false; 
            int indexTmp;
            for (indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                indexTmp != -1 && !rowFound; 
                )
            { 
                if (cy > data.Bottom)
                {
                    break;
                } 
                if (indexTmp == rowIndex)
                { 
                    rowFound = true; 
                }
                else 
                {
                    cy += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                    indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                } 
            }
 
            if (!rowFound && this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
            {
                for (indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                    indexTmp != -1 && !rowFound;
                    )
                {
                    if (cy > data.Bottom) 
                    {
                        break; 
                    } 
                    if (indexTmp == rowIndex)
                    { 
                        rowFound = true;
                    }
                    else
                    { 
                        cy += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                        indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); 
                    } 
                }
            } 

            if (rowFound)
            {
                int displayHeight; 
                if (cutOverflow && cy + this.Rows.SharedRow(indexTmp).GetHeight(indexTmp) > data.Bottom)
                { 
                    displayHeight = data.Bottom - cy; 
                }
                else 
                {
                    displayHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                }
 
                Rectangle rowRect = new Rectangle(data.X,
                    cy, 
                    data.Width, 
                    displayHeight);
                if (this.layout.RowHeadersVisible) 
                {
                    rowRect.Width += this.layout.RowHeaders.Width;
                    if (!this.RightToLeftInternal)
                    { 
                        rowRect.X -= this.layout.RowHeaders.Width;
                    } 
                } 
                return rowRect;
            } 

            return Rectangle.Empty;
        }
 
        private int GetRowIndexFromY(int y, out int yRowTopEdge)
        { 
            Rectangle data = this.layout.Data; 
            Debug.Assert(y >= data.Y-1 && y < data.Bottom, "y must be inside the vertical bounds of the data area.");
 
            if (y == data.Y-1)
            {
                y++;
            } 

            int rowHeight; 
            int cy = data.Y; 

            // first try to match y against a frozen rows 
            int indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            while (indexTmp != -1 && cy < data.Bottom)
            {
                rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                cy += rowHeight;
                if (cy > y) 
                { 
                    yRowTopEdge = cy - rowHeight;
                    return indexTmp; 
                }
                indexTmp = this.Rows.GetNextRow(indexTmp,
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            } 

            // second try to match y against a scrolling row 
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
            {
                indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0 &&
                    (this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0);

                while (indexTmp != -1 && cy < data.Bottom) 
                {
                    rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                    cy += rowHeight; 
                    if (cy > y)
                    { 
                        yRowTopEdge = cy - rowHeight;
                        return indexTmp;
                    }
                    indexTmp = this.Rows.GetNextRow(indexTmp, 
                        DataGridViewElementStates.Visible);
                } 
            } 

            yRowTopEdge = -1; 
            return -1;
        }

        private static int GetRowScrollRate(int yOffset) 
        {
            Debug.Assert(yOffset > 0); 
            // Counting 10ms for executing the actual row scrolling 
            if (yOffset <= 10)
            { 
                return 90;      // Ten rows per second
            }
            if (yOffset <= 15)
            { 
                return 57;     // Fifteen rows per second
            } 
            if (yOffset <= 25) 
            {
                return 30;     // Twenty-five rows per second 
            }
            if (yOffset <= 35)
            {
                return 18;     // Thirty-five rows per second 
            }
            return Math.Max(1, 600 / yOffset); 
        } 

        ///  
        ///      Returns the coordinate of the upper edge of the given row. Note that
        ///      the row does not need to be completely visible on the display area.
        ///      Value returned is not necessarily within layout.Data because the row
        ///      may start below the data area. 
        /// 
        internal int GetRowYFromIndex(int index) 
        { 
            Debug.Assert(index >= 0 && index < this.Rows.Count);
            Debug.Assert((this.Rows.GetRowState(index) & DataGridViewElementStates.Visible) != 0); 

            int y = this.layout.Data.Y;

            int indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            while (indexTmp != -1)
            { 
                if (index == indexTmp) 
                {
                    return y; 
                }
                y += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                indexTmp = this.Rows.GetNextRow(indexTmp,
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            }
 
            int yFirstVisibleScrollingRow = y; 

            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
            {
                if (index >= this.displayedBandsInfo.FirstDisplayedScrollingRow)
                {
                    // index is part of the scrolling rows below the frozen rows 
                    indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                } 
                else 
                {
                    // index is part of the rows hidden behind the frozen rows or on top of the control 
                    indexTmp = -1;
                }
            }
            else 
            {
                // frozen rows cover all the rows real-estate. Look for index starting at the first visible non-frozen row. 
                indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                Debug.Assert(indexTmp != -1);
            } 

            if (indexTmp != -1)
            {
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0 && 
                    (this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0);
 
                while (indexTmp != -1) 
                {
                    if (index == indexTmp) 
                    {
                        return y;
                    }
                    y += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                    indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible);
                } 
            } 

            // Row is completely hidden behind frozen rows or on top of control 
            y = yFirstVisibleScrollingRow;
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow != -1);
            indexTmp = this.Rows.GetPreviousRow(this.displayedBandsInfo.FirstDisplayedScrollingRow,
                DataGridViewElementStates.Visible, 
                DataGridViewElementStates.Frozen);
            while (indexTmp != -1) 
            { 
                y -= this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                if (index == indexTmp) 
                {
                    return y;
                }
                indexTmp = this.Rows.GetPreviousRow(indexTmp, 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen); 
            } 

            Debug.Fail("Could not find row in GetRowYFromIndex"); 
            return 0;
        }

        private bool GetTabKeyEffective(bool shift, bool ctrl) 
        {
            if (this.StandardTab) 
            { 
                return ctrl &&
                       !((!shift && (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell)) || 
                         (shift && (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell)));
            }
            else
            { 
                return !ctrl &&
                       !((!shift && (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell)) || 
                         (shift && (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell))); 
            }
        } 

        /// 
        public HitTestInfo HitTest(int x, int y)
        { 
            HitTestInfo hti = new HitTestInfo();
 
            if (!this.layout.Inside.Contains(x, y)) 
            {
                return hti; 
            }

            if (this.horizScrollBar != null && this.horizScrollBar.Visible && this.horizScrollBar.Bounds.Contains(x, y))
            { 
                hti.type = DataGridViewHitTestType.HorizontalScrollBar;
                return hti; 
            } 

            if (this.vertScrollBar != null && this.vertScrollBar.Visible && this.vertScrollBar.Bounds.Contains(x, y)) 
            {
                hti.type = DataGridViewHitTestType.VerticalScrollBar;
                return hti;
            } 

            if (this.layout.TopLeftHeader.Contains(x, y)) 
            { 
                hti.type = DataGridViewHitTestType.TopLeftHeader;
                hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeader; 
                if (this.RightToLeftInternal)
                {
                    hti.colStart = this.layout.TopLeftHeader.Right-1;
                } 
                else
                { 
                    hti.colStart = this.layout.TopLeftHeader.Left; 
                }
                hti.rowStart = this.layout.TopLeftHeader.Top; 
                if ((!this.RightToLeftInternal && this.layout.TopLeftHeader.Right - x < DATAGRIDVIEW_columnSizingHotZone) ||
                    (this.RightToLeftInternal && x - this.layout.TopLeftHeader.Left < DATAGRIDVIEW_columnSizingHotZone))
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Right; 
                    if (this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft; 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = this.layout.TopLeftHeader.Left - x - 1;
                        }
                        else
                        { 
                            hti.mouseBarOffset = this.layout.TopLeftHeader.Right - x - 1;
                        } 
                    } 
                }
                else if (this.layout.TopLeftHeader.Top + this.layout.TopLeftHeader.Height - y < DATAGRIDVIEW_rowSizingHotZone) 
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom;
                    if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop;
                        hti.mouseBarOffset = this.layout.TopLeftHeader.Top + this.layout.TopLeftHeader.Height - y - 1; 
                    } 
                }
                return hti; 
            }

            // check for column resize / insertion
            if (this.layout.ColumnHeaders.Contains(x, y)) 
            {
                int xColumnLeftEdge; // this is actually the right edge in RTL mode 
                hti.col = GetColumnIndexFromX(x, out xColumnLeftEdge); 
                if (hti.col < 0)
                { 
                    return HitTestInfo.Nowhere;
                }
                Debug.Assert(xColumnLeftEdge == GetColumnXFromIndex(hti.col));
                hti.type = DataGridViewHitTestType.ColumnHeader; 
                hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeader;
                hti.rowStart = this.layout.ColumnHeaders.Top; 
                hti.colStart = xColumnLeftEdge; 
                int columnWidth = this.Columns[hti.col].Thickness;
                if ((!this.RightToLeftInternal && xColumnLeftEdge + columnWidth - x < DATAGRIDVIEW_columnSizingHotZone) || 
                    (this.RightToLeftInternal && x - xColumnLeftEdge + columnWidth < DATAGRIDVIEW_columnSizingHotZone))
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Right;
                    if (this.RightToLeftInternal) 
                    {
                        hti.mouseBarOffset = xColumnLeftEdge - columnWidth - x + 1; 
                    } 
                    else
                    { 
                        hti.mouseBarOffset = xColumnLeftEdge + columnWidth - x - 1;
                    }
                    DataGridViewColumn dataGridViewColumn = this.Columns[hti.col];
                    if (dataGridViewColumn.Resizable == DataGridViewTriState.True && 
                        (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill))
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeRight; 
                    }
                    else 
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeaderRight;
                    }
                } 
                else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) ||
                         (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone)) 
                { 
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Left;
                    DataGridViewColumn dataGridViewColumn = null; 
                    // VS Whidbey bug 317105 - Condition unnecessary
                    //if (hti.col != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0)
                    //{
                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], 
                                                                                 DataGridViewElementStates.Visible,
                                                                                 DataGridViewElementStates.None); 
                    //} 
                    if (dataGridViewColumn != null)
                    { 
                        hti.adjacentCol = dataGridViewColumn.Index;
                        if (this.RightToLeftInternal)
                        {
                            hti.mouseBarOffset = xColumnLeftEdge - x + 1; 
                        }
                        else 
                        { 
                            hti.mouseBarOffset = xColumnLeftEdge - x - 1;
                        } 
                        if (dataGridViewColumn.Resizable == DataGridViewTriState.True &&
                            (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill))
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeLeft; 
                        }
                        else 
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeaderLeft;
                        } 
                    }
                    else
                    {
                        if (this.RowHeadersVisible && this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) 
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight; 
                            if (this.RightToLeftInternal) 
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x; 
                            }
                            else
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x - 1; 
                            }
                        } 
                        else 
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft; 
                        }
                    }
                }
                else if (this.layout.ColumnHeaders.Bottom - y < DATAGRIDVIEW_rowSizingHotZone) 
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom; 
                    if (/*!this.RowHeadersVisible &&*/ this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) 
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom; 
                        hti.mouseBarOffset = this.layout.ColumnHeaders.Bottom - y - 1;
                    }
                }
            } 

            // check for row resize 
            if (this.layout.RowHeaders.Contains(x, y)) 
            {
                int yRowTopEdge; 
                hti.row = GetRowIndexFromY(y, out yRowTopEdge);
                if (hti.row < 0)
                {
                    return HitTestInfo.Nowhere; 
                }
                Debug.Assert(yRowTopEdge == GetRowYFromIndex(hti.row)); 
                hti.type = DataGridViewHitTestType.RowHeader; 
                hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeader;
                hti.rowStart = yRowTopEdge; 
                if (this.RightToLeftInternal)
                {
                    hti.colStart = this.layout.RowHeaders.Right-1;
                } 
                else
                { 
                    hti.colStart = this.layout.RowHeaders.Left; 
                }
                int rowHeight = this.Rows.SharedRow(hti.row).GetHeight(hti.row); 
                if (yRowTopEdge + rowHeight - y < DATAGRIDVIEW_rowSizingHotZone)
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom;
 
                    if (RowIsResizable(hti.row) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeBottom; 
                        hti.mouseBarOffset = yRowTopEdge + rowHeight - y - 1;
                    } 
                }
                else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone)
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Top; 
                    int indexTmp = -1;
                    if (hti.row != this.displayedBandsInfo.FirstDisplayedScrollingRow || this.displayedBandsInfo.NumDisplayedFrozenRows > 0) 
                    { 
                        indexTmp = this.Rows.GetPreviousRow(hti.row, DataGridViewElementStates.Visible);
                    } 
                    if (indexTmp != -1)
                    {
                        if (RowIsResizable(indexTmp) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeTop;
                            hti.adjacentRow = indexTmp; 
                            hti.mouseBarOffset = yRowTopEdge - y - 1; 
                        }
                    } 
                    else
                    {
                        if (this.ColumnHeadersVisible && this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing)
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom;
                            hti.mouseBarOffset = yRowTopEdge - y - 1; 
                        } 
                    }
                } 
                else if ((!this.RightToLeftInternal && this.layout.RowHeaders.Right - x < DATAGRIDVIEW_columnSizingHotZone) ||
                         (this.RightToLeftInternal && x - this.layout.RowHeaders.Left < DATAGRIDVIEW_columnSizingHotZone))
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Right; 
                    if (this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeRight; 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = this.layout.RowHeaders.Left - x - 1;
                        }
                        else
                        { 
                            hti.mouseBarOffset = this.layout.RowHeaders.Right - x - 1;
                        } 
                    } 
                }
            } 

            if (this.layout.Data.Contains(x, y))
            {
                int xColumnLeftEdge, yRowTopEdge; 
                hti.col = GetColumnIndexFromX(x, out xColumnLeftEdge);
                hti.row = GetRowIndexFromY(y, out yRowTopEdge); 
                if (hti.col < 0 || hti.row < 0) 
                {
                    return HitTestInfo.Nowhere; 
                }
                Debug.Assert(xColumnLeftEdge == GetColumnXFromIndex(hti.col));
                Debug.Assert(yRowTopEdge == GetRowYFromIndex(hti.row));
                hti.type = DataGridViewHitTestType.Cell; 
                hti.typeInternal = DataGridViewHitTestTypeInternal.Cell;
                hti.rowStart = yRowTopEdge; 
                hti.colStart = xColumnLeftEdge; 
                if (!this.ColumnHeadersVisible)
                { 
                    int columnWidth = this.Columns[hti.col].Thickness;
                    if ((!this.RightToLeftInternal && xColumnLeftEdge + columnWidth - x < DATAGRIDVIEW_columnSizingHotZone) ||
                        (this.RightToLeftInternal && x - xColumnLeftEdge + columnWidth < DATAGRIDVIEW_columnSizingHotZone))
                    { 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = xColumnLeftEdge - columnWidth - x + 1; 
                        }
                        else 
                        {
                            hti.mouseBarOffset = xColumnLeftEdge + columnWidth - x - 1;
                        }
                        DataGridViewColumn dataGridViewColumn = this.Columns[hti.col]; 
                        if (dataGridViewColumn.Resizable == DataGridViewTriState.True &&
                            (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) 
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeRight;
                        } 
                        return hti;
                    }
                    else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) ||
                             (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone)) 
                    {
                        DataGridViewColumn dataGridViewColumn = null; 
                        if (hti.col != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0) 
                        {
                            dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], 
                                DataGridViewElementStates.Visible,
                                DataGridViewElementStates.None);
                        }
                        if (dataGridViewColumn != null) 
                        {
                            hti.adjacentCol = dataGridViewColumn.Index; 
                            if (this.RightToLeftInternal) 
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x + 1; 
                            }
                            else
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x - 1; 
                            }
                            if (dataGridViewColumn.Resizable == DataGridViewTriState.True && 
                                (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) 
                            {
                                hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeLeft; 
                            }
                            return hti;
                        }
                        else 
                        {
                            if (this.RowHeadersVisible && this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) 
                            { 
                                hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeLeft;
                                if (this.RightToLeftInternal) 
                                {
                                    hti.mouseBarOffset = xColumnLeftEdge - x;
                                }
                                else 
                                {
                                    hti.mouseBarOffset = xColumnLeftEdge - x - 1; 
                                } 
                                return hti;
                            } 
                        }
                    }
                }
                else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) || 
                         (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone))
                { 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
                    Debug.Assert(dataGridViewColumn != null);
                    if (hti.col == dataGridViewColumn.Index && 
                        this.RowHeadersVisible &&
                        this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing)
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeLeft; 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = xColumnLeftEdge - x; 
                        }
                        else 
                        {
                            hti.mouseBarOffset = xColumnLeftEdge - x - 1;
                        }
                        return hti; 
                    }
                } 
 
                if (!this.RowHeadersVisible)
                { 
                    int rowHeight = this.Rows.SharedRow(hti.row).GetHeight(hti.row);
                    if (yRowTopEdge + rowHeight - y < DATAGRIDVIEW_rowSizingHotZone)
                    {
                        if (RowIsResizable(hti.row) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) 
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeBottom; 
                            hti.mouseBarOffset = yRowTopEdge + rowHeight - y - 1; 
                        }
                    } 
                    else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone)
                    {
                        int indexTmp = -1;
                        if (hti.row != this.displayedBandsInfo.FirstDisplayedScrollingRow || this.displayedBandsInfo.NumDisplayedFrozenRows > 0) 
                        {
                            indexTmp = this.Rows.GetPreviousRow(hti.row, 
                                DataGridViewElementStates.Visible); 
                        }
                        if (indexTmp != -1) 
                        {
                            if (RowIsResizable(indexTmp) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                            {
                                hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeTop; 
                                hti.adjacentRow = indexTmp;
                                hti.mouseBarOffset = yRowTopEdge - y - 1; 
                            } 
                        }
                        else 
                        {
                            if (this.ColumnHeadersVisible && this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing)
                            {
                                hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop; 
                                hti.mouseBarOffset = yRowTopEdge - y - 1;
                            } 
                        } 
                    }
                } 
                else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone)
                {
                    int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                    Debug.Assert(rowIndex >= 0); 
                    if (hti.row == rowIndex &&
                        this.ColumnHeadersVisible && 
                        this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) 
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop; 
                        hti.mouseBarOffset = yRowTopEdge - y - 1;
                    }
                }
            } 

            return hti; 
        } 

        private void HorizScrollTimer_Tick(object sender, System.EventArgs e) 
        {
            BeginInvoke(new MethodInvoker(HorizScrollTimerHandler));
        }
 
        private void HorizScrollTimerHandler()
        { 
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]); 

            Point ptMouse = PointToClient(Control.MousePosition); 
            HitTestInfo hti = HitTest(ptMouse.X, ptMouse.Y);
            int xOffset, yOffset, mouseX = ptMouse.X, mouseY = ptMouse.Y;
            if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset))
            { 
                if (xOffset != 0)
                { 
                    int absXOffset = Math.Abs(xOffset), normOffset = xOffset / absXOffset; 
                    ScrollColumns(normOffset);
                    this.horizScrollTimer.Interval = GetColumnScrollRate(absXOffset); 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect])
                    {
                        hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), mouseY);
                        if (hti.col >= 0) 
                        {
                            OnColumnSelectMouseMove(hti); 
                        } 
                    }
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]) 
                    {
                        if (yOffset != 0)
                        {
                            hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), ptMouse.Y-yOffset-(yOffset/Math.Abs(yOffset))); 
                        }
                        else 
                        { 
                            hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), mouseY);
                        } 
                        if (hti.col >= 0 && hti.row >= 0)
                        {
                            OnCellSelectMouseMove(hti);
                        } 
                    }
                } 
                else 
                {
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && hti.col >= 0) 
                    {
                        OnColumnSelectMouseMove(hti);
                    }
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) 
                    {
                        OnCellSelectMouseMove(hti); 
                    } 
                    this.HorizScrollTimer.Enabled = false;
                } 
            }
        }

        // Returns true for success, returns false when the OnDataError event cancels the operation. 
        private bool InitializeEditingCellValue(ref DataGridViewCellStyle dataGridViewCellStyle, ref DataGridViewCell dataGridViewCell)
        { 
            DataGridViewDataErrorEventArgs dgvdee = null; 
            // Save unedited value so we can restore it later if parsing of new value fails
            this.uneditedFormattedValue = dataGridViewCell.GetFormattedValue(this.ptCurrentCell.Y, ref dataGridViewCellStyle, DataGridViewDataErrorContexts.Formatting); 
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true;
            try
            {
                IDataGridViewEditingCell dataGridViewEditingCell = dataGridViewCell as IDataGridViewEditingCell; 
                Debug.Assert(dataGridViewEditingCell != null);
                object currentFormattedValue = dataGridViewEditingCell.GetEditingCellFormattedValue(DataGridViewDataErrorContexts.Formatting); 
                if ((currentFormattedValue == null && this.uneditedFormattedValue != null) || 
                    (currentFormattedValue != null && this.uneditedFormattedValue == null) ||
                    (currentFormattedValue != null && !this.uneditedFormattedValue.Equals(currentFormattedValue))) 
                {
                    Debug.Assert(this.ptCurrentCell.X == dataGridViewCell.ColumnIndex);
                    dataGridViewCell = this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X]; // unshare the edited cell
                    dataGridViewEditingCell = dataGridViewCell as IDataGridViewEditingCell; 
                    dataGridViewEditingCell.EditingCellFormattedValue = this.uneditedFormattedValue;
                    dataGridViewEditingCell.EditingCellValueChanged = false; 
                } 
            }
            catch (Exception exception) 
            {
                if (ClientUtils.IsCriticalException(exception))
                {
                    throw; 
                }
                dgvdee = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X, 
                    this.ptCurrentCell.Y, 
                    DataGridViewDataErrorContexts.InitialValueRestoration);
                OnDataErrorInternal(dgvdee); 
            }
            finally
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false; 
            }
            if (dgvdee != null) 
            { 
                if (dgvdee.ThrowException)
                { 
                    throw dgvdee.Exception;
                }
                return !dgvdee.Cancel;
            } 
            return true;
        } 
 
        // Returns true for success, returns false when the OnDataError event cancels the operation.
        private bool InitializeEditingControlValue(ref DataGridViewCellStyle dataGridViewCellStyle, DataGridViewCell dataGridViewCell) 
        {
            Debug.Assert(dataGridViewCell != null);
            Debug.Assert(this.editingControl != null);
 
            DataGridViewDataErrorEventArgs dgvdee = null;
            object initialFormattedValue = dataGridViewCell.GetFormattedValue(this.ptCurrentCell.Y, ref dataGridViewCellStyle, DataGridViewDataErrorContexts.Formatting); 
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true; 
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true;
            try 
            {
                dataGridViewCell.InitializeEditingControl(this.ptCurrentCell.Y, initialFormattedValue, dataGridViewCellStyle);
                ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged = false;
            } 
            catch (Exception exception)
            { 
                if (ClientUtils.IsCriticalException(exception)) 
                {
                    throw; 
                }
                dgvdee = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X,
                    this.ptCurrentCell.Y,
                    DataGridViewDataErrorContexts.InitialValueRestoration); 
                OnDataErrorInternal(dgvdee);
            } 
            finally 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = false; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false;
            }
            if (dgvdee != null)
            { 
                if (dgvdee.ThrowException)
                { 
                    throw dgvdee.Exception; 
                }
                return !dgvdee.Cancel; 
            }

            // Save unedited value so we can restore it later if parsing of new value fails
            this.uneditedFormattedValue = initialFormattedValue; 
            return true;
        } 
 
        /// 
        public void InvalidateCell(DataGridViewCell dataGridViewCell) 
        {
            if (dataGridViewCell == null)
            {
                throw new ArgumentNullException("dataGridViewCell"); 
            }
            if (dataGridViewCell.DataGridView != this) 
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_CellDoesNotBelongToDataGridView));
            } 
            InvalidateCellPrivate(dataGridViewCell);
        }

        private void InvalidateCellPrivate(DataGridViewCell dataGridViewCell) 
        {
            Debug.Assert(dataGridViewCell != null); 
            Debug.Assert(dataGridViewCell.DataGridView == this); 
            InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex);
        } 

        /// 
        public void InvalidateCell(int columnIndex, int rowIndex)
        { 
            if (columnIndex < -1 || columnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("columnIndex"); 
            }
            if (rowIndex < -1 || rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex");
            }
            InvalidateCellPrivate(columnIndex, rowIndex); 
        }
 
        private void InvalidateCellPrivate(int columnIndex, int rowIndex) 
        {
            if (this.IsHandleCreated) 
            {
                Rectangle cellDisplayRect = GetCellAdjustedDisplayRectangle(columnIndex, rowIndex, true);
                if (!cellDisplayRect.IsEmpty)
                { 
                    Invalidate(cellDisplayRect);
                } 
            } 
        }
 
        /// 
        /// 
        ///      Invalidate the painting region for the column specified.
        ///  
        public void InvalidateColumn(int columnIndex)
        { 
            if (columnIndex < 0 || columnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("columnIndex"); 
            }
            InvalidateColumnInternal(columnIndex);
        }
 
        internal void InvalidateColumnInternal(int columnIndex)
        { 
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 

            if (this.IsHandleCreated) 
            {
                Rectangle columnDisplayRect = GetColumnDisplayRectanglePrivate(columnIndex, true);
                if (!columnDisplayRect.IsEmpty)
                { 
                    Invalidate(columnDisplayRect);
                } 
            } 
        }
 
        private void InvalidateData()
        {
            if (this.IsHandleCreated)
            { 
                Invalidate(this.layout.Data);
            } 
        } 

        ///  
        ///      Invalidates the scrollable area of the DataGridView.
        /// 
        private void InvalidateInside()
        { 
            if (this.IsHandleCreated)
            { 
                Invalidate(this.layout.Inside); 
            }
        } 

        /// 
        /// 
        ///      Invalidate the painting region for the row specified. 
        /// 
        public void InvalidateRow(int rowIndex) 
        { 
            if (rowIndex < 0 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex");
            }
            InvalidateRowPrivate(rowIndex);
        } 

        private void InvalidateRowPrivate(int rowIndex) 
        { 
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
 
            if (this.IsHandleCreated)
            {
                Rectangle rowDisplayRect = GetRowDisplayRectanglePrivate(rowIndex, true);
                if (!rowDisplayRect.IsEmpty) 
                {
                    Invalidate(rowDisplayRect); 
                } 
            }
        } 

        private void InvalidateRowHeights()
        {
            this.Rows.InvalidateCachedRowsHeights(); 
            if (this.IsHandleCreated)
            { 
                PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
                Invalidate();
            } 
        }

        private void InvalidateRows(int lo, int hi)
        { 
            Debug.Assert(lo <= hi);
            Debug.Assert(lo < this.Rows.Count); 
            Debug.Assert(hi < this.Rows.Count); 

            if (this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 0) 
            {
                return;
            }
 
            Rectangle rowDisplayRect, data;
            int top, bottom; 
 
            data = this.layout.Data;
 
            // If "lo" is not visible, then get the next visible row
            if ((this.Rows.GetRowState(lo) & DataGridViewElementStates.Visible) == 0)
            {
                lo = this.Rows.GetNextRow(lo, DataGridViewElementStates.Visible); 
            }
 
            if (lo == -1) 
            {
                // there are no visible rows below "lo" so there is nothing to invalidate. 
                return;
            }

            // If "hi" is not visible, then get the previous visible row 
            if ((this.Rows.GetRowState(hi) & DataGridViewElementStates.Visible) == 0)
            { 
                hi = this.Rows.GetPreviousRow(hi, DataGridViewElementStates.Visible); 
            }
 
            Debug.Assert(lo <= hi);
            Debug.Assert(lo > -1);

            rowDisplayRect = this.GetRowDisplayRectangle(lo, true /*cutOverflow*/); 

            if (rowDisplayRect.IsEmpty) 
            { 
                // The top row is offscreen
                if ((this.Rows.GetRowState(lo) & DataGridViewElementStates.Frozen) != 0) 
                {
                    // "lo" is a frozen row which is offscreen.
                    // This means that "lo" and any other row below it are offscreen.
                    return; 
                }
                else if (this.displayedBandsInfo.NumDisplayedScrollingRows == 0) 
                { 
                    // "lo" and all the rows below are scrolling rows but no scrolling rows are displayed.
                    return; 
                }
                else if (lo >= this.displayedBandsInfo.FirstDisplayedScrollingRow &&
                    this.Rows.GetRowCount(DataGridViewElementStates.Visible,
                                          this.displayedBandsInfo.FirstDisplayedScrollingRow, 
                                          lo) >= this.displayedBandsInfo.NumDisplayedScrollingRows)
                { 
                    // "lo" is a scrolling row whose coordinates are below the last visible row. 
                    return;
                } 
                else
                {
                    // "lo" is a scrolling row "behind" frozen rows.
                    // Start invalidating at the top of the first displayed scrolling row. 
                    top = this.GetRowDisplayRectangle(this.displayedBandsInfo.FirstDisplayedScrollingRow, true /*cutOverflow*/).Top;
                } 
            } 
            else
            { 
                top = rowDisplayRect.Top;
            }

            rowDisplayRect = this.GetRowDisplayRectangle(hi, true /*cutOverflow*/); 

            if (rowDisplayRect.IsEmpty) 
            { 
                // The bottom row is offscreen.
                if ((this.Rows.GetRowState(hi) & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen) 
                {
                    // "hi" is a frozen row offscreen and "lo" is a frozen row on screen.
                    // Invalidate all the way to the bottom
                    bottom = data.Bottom; 
                }
                else if (hi > this.displayedBandsInfo.FirstDisplayedScrollingRow) 
                { 
                    // "hi" is a scrolling row offscreen which is beyond the firstDisplayedScrollingRow
                    // Invalidate all the way to the bottom again. 
                    bottom = data.Bottom;
                }
                else if (this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) == 0)
                { 
                    // "hi" is a scrolling row above the first displayed scrolling row and there are no frozen rows.
                    // There is nothing to invalidate. 
                    return; 
                }
                else 
                {
                    // "hi" is a scrolling row which is "behind" the frozen rows.
                    // Invalidate all the way to the bottom of the frozen rows
                    // Compute the bottom of the last displayed frozen row. 
                    // There may be invisible rows between the frozen rows.
                    bottom = 0; 
                    for (int i = 0; i < this.displayedBandsInfo.NumDisplayedFrozenRows;) 
                    {
                        if ((this.Rows.GetRowState(i) & DataGridViewElementStates.Visible) == 0) 
                        {
                            continue;
                        }
 
                        if (i == this.displayedBandsInfo.NumDisplayedFrozenRows - 1)
                        { 
                            bottom = this.GetRowDisplayRectangle(i, true /*cutOverflow*/).Bottom; 
                            break;
                        } 

                        i ++;
                    }
 
                    if (bottom <= top)
                    { 
                        // In this case both "lo" and "hi" are two scrolling rows behind the frozen rows. 
                        // Nothing to invalidate.
                        return; 
                    }
                }
            }
            else 
            {
                bottom = rowDisplayRect.Bottom; 
            } 

            Invalidate(new Rectangle(data.X, top, data.Width, bottom - top)); 
        }

        private void InvalidateScrollBars()
        { 
            // invalidate the horizontal and the vertical scrollbars
            // note that the scrollbars can be null - this happens when 
            // the control has been disposed. 
            if (this.horizScrollBar != null && this.horizScrollBar.Visible)
            { 
                this.horizScrollBar.Invalidate();
            }
            if (this.vertScrollBar != null && this.vertScrollBar.Visible)
            { 
                this.vertScrollBar.Invalidate();
            } 
        } 

        private bool IsColumnOutOfBounds(int columnIndex) 
        {
            return columnIndex >= this.Columns.Count || columnIndex == -1;
        }
 
        private bool IsInnerCellOutOfBounds(int columnIndex, int rowIndex)
        { 
            return columnIndex >= this.Columns.Count || rowIndex >= this.Rows.Count || columnIndex == -1 || rowIndex == -1; 
        }
 
        private bool IsRowOutOfBounds(int rowIndex)
        {
            return rowIndex >= this.Rows.Count || rowIndex == -1;
        } 

        ///  
        protected override bool IsInputChar(char charCode) 
        {
            if (this.editingControl != null && 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage])
            {
                // Do not process key press in ProcessDialogChar.
                return true; 
            }
            else 
            { 
                return base.IsInputChar(charCode);
            } 
        }

        /// 
        protected override bool IsInputKey(Keys keyData) 
        {
            if ((keyData & Keys.Alt) == Keys.Alt) 
            { 
                return false;
            } 
            switch (keyData & Keys.KeyCode)
            {
                case Keys.Escape:
                { 
                    return this.IsEscapeKeyEffective;
                } 
 
                case Keys.Tab:
                { 
                    return GetTabKeyEffective((keyData & Keys.Shift) == Keys.Shift, (keyData & Keys.Control) == Keys.Control);
                }

                case Keys.A: 
                {
                    if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Control) 
                    { 
                        return true;
                    } 
                    break;
                }

                case Keys.C: 
                case Keys.Insert:
                { 
                    if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Control) 
                    {
                        return true; 
                    }
                    break;
                }
 
                case Keys.Space:
                { 
                    if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Shift && 
                        (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect ||
                         this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) && 
                        this.ptCurrentCell.X != -1)
                    {
                        return true;
                    } 
                    break;
                } 
 
                case Keys.Up:
                case Keys.Down: 
                case Keys.Left:
                case Keys.Right:
                case Keys.Home:
                case Keys.End: 
                case Keys.Next:
                case Keys.Prior: 
                case Keys.Enter: 
                case Keys.Delete:
                case Keys.D0: 
                case Keys.NumPad0:
                case Keys.F2:
                {
                    return true; 
                }
            } 
            return base.IsInputKey(keyData); 
        }
 
        /// 
        ///      Determines if Scrollbars should be visible,
        ///      updates their bounds and the bounds of all
        ///      other regions in the dataGridView's Layout. 
        /// 
        private void LayoutScrollBars() 
        { 
            SuspendLayout();
            try 
            {
                // Scrollbars are a tricky issue.
                // We need to see if we can cram our columns and rows
                // in without scrollbars and if they don't fit, we make 
                // scrollbars visible and then fixup our regions for the
                // data. 
                bool allowHorizScrollbar = ((this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Horizontal)) && 
                                           this.dataGridViewState2[DATAGRIDVIEWSTATE2_allowHorizontalScrollbar];
                bool allowVertScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Vertical); 
                bool needHorizScrollbarWithoutVertScrollbar = false;
                bool needHorizScrollbar = false;
                bool needVertScrollbar = false;
                bool rightToLeftInternal = this.RightToLeftInternal; 
                int oldfirstDisplayedScrollingRow;
 
                int totalVisibleColCount = this.Columns.GetColumnCount(DataGridViewElementStates.Visible); 
                int totalVisibleRowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible);
                int totalVisibleWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible); 
                int totalVisibleFrozenWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);

                // Expensive call - dataGridView could have a mode where no row is resizable which would result in better perfs
                int totalVisibleHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); 
                int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
 
                int horizScrollBarHeight = this.horizScrollBar.Height = SystemInformation.HorizontalScrollBarHeight; 
                int vertScrollBarWidth = this.vertScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
 
                if (allowHorizScrollbar &&
                    totalVisibleWidth > this.layout.Data.Width && totalVisibleFrozenWidth < this.layout.Data.Width &&
                    horizScrollBarHeight <= this.layout.Data.Height)
                { 
                    int oldDataHeight = this.layout.Data.Height;
                    this.layout.Data.Height -= horizScrollBarHeight; 
                    Debug.Assert(this.layout.Data.Height >= 0); 
                    needHorizScrollbarWithoutVertScrollbar = needHorizScrollbar = true;
                    if (totalVisibleWidth - this.layout.Data.Width <= vertScrollBarWidth || 
                        this.layout.Data.Width - totalVisibleFrozenWidth <= vertScrollBarWidth)
                    {
                        // Would we still need a horizontal scrollbar if there were a vertical one?
                        oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                        ComputeVisibleRows();
                        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)))
                        { 
                            needHorizScrollbar = (totalVisibleFrozenWidth < this.layout.Data.Width - vertScrollBarWidth);
                        }
                        this.displayedBandsInfo.FirstDisplayedScrollingRow = oldfirstDisplayedScrollingRow;
                    } 

                    if (needHorizScrollbar) 
                    { 
                        if (this.layout.RowHeadersVisible)
                        { 
                            this.layout.RowHeaders.Height -= horizScrollBarHeight;
                            Debug.Assert(this.layout.RowHeaders.Height >= 0);
                        }
                    } 
                    else
                    { 
                        // Restore old data height because turns out a horizontal scroll bar wouldn't make sense 
                        this.layout.Data.Height = oldDataHeight;
                    } 
                }

                oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
 
                ComputeVisibleRows();
                if (allowVertScrollbar && 
                    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 &&
                    vertScrollBarWidth <= this.layout.Data.Width)
                {
                    this.layout.Data.Width -= vertScrollBarWidth; 
                    Debug.Assert(this.layout.Data.Width >= 0);
                    if (rightToLeftInternal) 
                    { 
                        this.layout.Data.X += vertScrollBarWidth;
                    } 
                    if (this.layout.ColumnHeadersVisible)
                    {
                        this.layout.ColumnHeaders.Width -= vertScrollBarWidth;
                        Debug.Assert(this.layout.ColumnHeaders.Width >= 0); 
                        if (rightToLeftInternal)
                        { 
                            this.layout.ColumnHeaders.X += vertScrollBarWidth; 
                        }
                    } 
                    needVertScrollbar = true;
                }

                this.displayedBandsInfo.FirstDisplayedScrollingCol = ComputeFirstVisibleScrollingColumn(); 
                // we compute the number of visible columns only after we set up the vertical scroll bar.
                ComputeVisibleColumns(); 
 
                if (allowHorizScrollbar &&
                    needVertScrollbar && !needHorizScrollbar && 
                    totalVisibleWidth > this.layout.Data.Width && totalVisibleFrozenWidth < this.layout.Data.Width &&
                    horizScrollBarHeight <= this.layout.Data.Height)
                {
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = oldfirstDisplayedScrollingRow; 
                    if (this.layout.ColumnHeadersVisible)
                    { 
                        this.layout.ColumnHeaders.Width += vertScrollBarWidth; 
                        if (rightToLeftInternal)
                        { 
                            this.layout.ColumnHeaders.X -= vertScrollBarWidth;
                        }
                    }
                    this.layout.Data.Width += vertScrollBarWidth; 
                    if (rightToLeftInternal)
                    { 
                        this.layout.Data.X -= vertScrollBarWidth; 
                    }
                    this.layout.Data.Height -= horizScrollBarHeight; 
                    Debug.Assert(this.layout.Data.Height >= 0);
                    needVertScrollbar = false;

                    ComputeVisibleRows(); 
                    if (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) &&
                        this.displayedBandsInfo.NumTotallyDisplayedScrollingRows != totalVisibleRowCount && 
                        (totalVisibleHeight - totalVisibleFrozenHeight != ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) && 
                        this.layout.Data.Height > totalVisibleFrozenHeight &&
                        vertScrollBarWidth <= this.layout.Data.Width) 
                    {
                        this.layout.Data.Width -= vertScrollBarWidth;
                        Debug.Assert(this.layout.Data.Width >= 0);
                        if (rightToLeftInternal) 
                        {
                            this.layout.Data.X += vertScrollBarWidth; 
                        } 
                        if (this.layout.ColumnHeadersVisible)
                        { 
                            this.layout.ColumnHeaders.Width -= vertScrollBarWidth;
                            Debug.Assert(this.layout.ColumnHeaders.Width >= 0);
                            if (rightToLeftInternal)
                            { 
                                this.layout.ColumnHeaders.X += vertScrollBarWidth;
                            } 
                        } 
                        needVertScrollbar = true;
                    } 
                    if (needVertScrollbar)
                    {
                        needHorizScrollbar = true;
                    } 
                    else
                    { 
                        needHorizScrollbar = needHorizScrollbarWithoutVertScrollbar; 
                    }
                } 

                this.layout.ResizeBoxRect = new Rectangle();
                if (needVertScrollbar && needHorizScrollbar)
                { 
                    this.layout.ResizeBoxRect = new Rectangle(
                        rightToLeftInternal ? this.layout.Data.X - this.vertScrollBar.Width : this.layout.Data.Right, 
                        this.layout.Data.Bottom, 
                        this.vertScrollBar.Width,
                        this.horizScrollBar.Height); 
                }

                if (needHorizScrollbar && totalVisibleColCount > 0)
                { 
                    int widthNotVisible = totalVisibleWidth - this.layout.Data.Width;
 
                    this.horizScrollBar.Minimum = 0; 
                    this.horizScrollBar.Maximum = totalVisibleWidth - totalVisibleFrozenWidth;
                    Debug.Assert(this.horizScrollBar.Maximum > 0); 
                    this.horizScrollBar.SmallChange = 1;
                    this.horizScrollBar.LargeChange = Math.Max(totalVisibleWidth - totalVisibleFrozenWidth - widthNotVisible, 0);
                    this.horizScrollBar.Enabled = this.Enabled;
                    this.horizScrollBar.Bounds = new Rectangle( 
                        rightToLeftInternal ? this.layout.Inside.X + this.layout.ResizeBoxRect.Width : this.layout.Inside.X,
                        this.layout.Data.Bottom, 
                        this.layout.Inside.Width - this.layout.ResizeBoxRect.Width, 
                        this.horizScrollBar.Height);
                    this.horizScrollBar.Visible = true; 
                    this.horizScrollBar.Invalidate();
                }
                else
                { 
                    this.horizScrollBar.Visible = false;
                    this.HorizontalOffset = 0; 
 
                    this.horizScrollBar.Enabled = false;
                    this.horizScrollBar.Minimum = 0; 
                    this.horizScrollBar.Maximum = 1;
                    this.horizScrollBar.SmallChange = 1;
                    this.horizScrollBar.LargeChange = 1;
                    this.horizScrollBar.Value = 0; 
                }
 
                if (needVertScrollbar) 
                {
                    int vertScrollBarTop = this.layout.Data.Y; 
                    int vertScrollBarHeight = this.layout.Data.Height;
                    if (this.layout.ColumnHeadersVisible)
                    {
                        vertScrollBarTop = this.layout.ColumnHeaders.Y; 
                        vertScrollBarHeight += this.layout.ColumnHeaders.Height;
                    } 
                    else if (this.SingleHorizontalBorderAdded) 
                    {
                        vertScrollBarTop--; 
                        vertScrollBarHeight++;
                    }

                    this.vertScrollBar.Minimum = 0; 
                    this.vertScrollBar.Maximum = totalVisibleHeight - totalVisibleFrozenHeight;
                    Debug.Assert(this.vertScrollBar.Maximum > 0); 
                    this.vertScrollBar.Value = ComputeHeightOfScrolledOffRows(); 
                    this.vertScrollBar.LargeChange = this.layout.Data.Height - totalVisibleFrozenHeight;
                    this.vertScrollBar.Bounds = new Rectangle( 
                        rightToLeftInternal ? this.layout.Data.X - this.vertScrollBar.Width : this.layout.Data.Right,
                        vertScrollBarTop,
                        this.vertScrollBar.Width,
                        vertScrollBarHeight); 
                    this.vertScrollBar.Enabled = this.Enabled;
                    this.vertScrollBar.Visible = true; 
                    this.vertScrollBar.Invalidate(); 

                    this.verticalOffset = this.vertScrollBar.Value; 
                }
                else
                {
                    this.vertScrollBar.Visible = false; 
                    this.verticalOffset = 0;
 
                    this.vertScrollBar.Enabled = false; 
                    this.vertScrollBar.Minimum = 0;
                    this.vertScrollBar.Maximum = 1; 
                    this.vertScrollBar.LargeChange = 1;
                    this.vertScrollBar.Value = 0;
                }
            } 
            finally
            { 
                ResumeLayout(false); 
            }
        } 

        private void MakeFirstDisplayedCellCurrentCell(bool includeNewRow)
        {
            // No current cell - try to set the first displayed cell to be the current one. 
            Point firstDisplayedCellAddress = this.FirstDisplayedCellAddress;
            if (firstDisplayedCellAddress.X != -1 && 
                (includeNewRow || 
                 !this.AllowUserToAddRowsInternal ||
                 firstDisplayedCellAddress.Y != this.Rows.Count - 1)) 
            {
                bool success = SetAndSelectCurrentCellAddress(firstDisplayedCellAddress.X,
                                                              firstDisplayedCellAddress.Y,
                                                              true /*setAnchorCellAddress*/, 
                                                              false /*validateCurrentCell*/,
                                                              false /*throughMouseClick*/, 
                                                              true /*clearSelection*/, 
                                                              false /*forceCurrentCellSelection (unused)*/);
                Debug.Assert(success); 
            }
        }

        private static DataGridViewAutoSizeRowMode MapAutoSizeRowsModeToRowMode(DataGridViewAutoSizeRowsMode autoSizeRowsMode) 
        {
            switch (autoSizeRowsMode) 
            { 
                case DataGridViewAutoSizeRowsMode.AllHeaders:
                    return DataGridViewAutoSizeRowMode.RowHeader; 
                case DataGridViewAutoSizeRowsMode.DisplayedHeaders:
                    return DataGridViewAutoSizeRowMode.RowHeader;
                case DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders:
                    return DataGridViewAutoSizeRowMode.AllCellsExceptHeader; 
                case DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders:
                    return DataGridViewAutoSizeRowMode.AllCellsExceptHeader; 
                case DataGridViewAutoSizeRowsMode.AllCells: 
                    return DataGridViewAutoSizeRowMode.AllCells;
                case DataGridViewAutoSizeRowsMode.DisplayedCells: 
                    return DataGridViewAutoSizeRowMode.AllCells;
                default:
                    Debug.Fail("Unexpected autoSizeRowsMode value in MapAutoSizeRowsModeToRowMode");
                    return DataGridViewAutoSizeRowMode.RowHeader; 
            }
        } 
 
        private void MoveColumnHeadersOrRowResize(MouseEventArgs e)
        { 
            this.lastRowSplitBar = this.currentRowSplitBar;
            this.currentRowSplitBar = e.Y;
            Rectangle lastSplitBarRect = CalcRowResizeFeedbackRect(this.lastRowSplitBar);
            if (this.editingControl != null && 
                !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] &&
                this.editingPanel.Bounds.IntersectsWith(lastSplitBarRect)) 
            { 
                this.editingPanel.Invalidate();
                this.editingPanel.Update(); 
                this.editingControl.Invalidate();
                this.editingControl.Update();
            }
            Invalidate(lastSplitBarRect); 
            Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar));
        } 
 
        private void MapDataGridViewColumnToDataBoundField(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(this.DataSource != null, "this method should only be called when we have a data connection");
            Debug.Assert(dataGridViewColumn.DataPropertyName.Length != 0, "this method should be called only for columns which have DataPropertyName set");
            DataGridViewDataConnection conn = this.DataConnection;
 
            int boundColumnIndex = ((conn == null) ? -1 : conn.BoundColumnIndex(dataGridViewColumn.DataPropertyName));
            if (boundColumnIndex != -1) 
            { 
                dataGridViewColumn.IsDataBoundInternal = true;
                dataGridViewColumn.BoundColumnIndex = boundColumnIndex; 
                dataGridViewColumn.BoundColumnConverter = conn.BoundColumnConverter(boundColumnIndex);
                dataGridViewColumn.ValueType = conn.BoundColumnValueType(boundColumnIndex);
                dataGridViewColumn.ReadOnly = conn.DataFieldIsReadOnly(dataGridViewColumn.BoundColumnIndex) || dataGridViewColumn.ReadOnly;
                InvalidateColumnInternal(dataGridViewColumn.Index); 

                // Set the Sorting information on the data grid view according to the new DataPropertyName. 
                // RefreshColumns() has its own routine for setting the Sorting information so don't do this step 
                // if we are in RefreshColumns();
                if (dataGridViewColumn.SortMode != DataGridViewColumnSortMode.NotSortable && 
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns])
                {
                    dataGridViewColumn.HeaderCell.SortGlyphDirection = conn.BoundColumnSortOrder(boundColumnIndex);
                    if (this.sortedColumn == null && dataGridViewColumn.HeaderCell.SortGlyphDirection != SortOrder.None) 
                    {
                        this.sortedColumn = dataGridViewColumn; 
                        this.sortOrder = dataGridViewColumn.HeaderCell.SortGlyphDirection; 
                        // no need to sort because the back end is already sorted....
                    } 
                }
            }
            else
            { 
                dataGridViewColumn.IsDataBoundInternal = false;
                dataGridViewColumn.BoundColumnIndex = -1; 
                dataGridViewColumn.BoundColumnConverter = null; 
                InvalidateColumnInternal(dataGridViewColumn.Index);
            } 
        }

        private void MoveColumnRelocation(MouseEventArgs e, HitTestInfo hti)
        { 
            this.lastHeaderShadow = e.X;
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = ColumnRelocationTarget(e, hti, out this.trackColumnEdge); 
            Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders)); 
        }
 
        private void MoveRowHeadersOrColumnResize(MouseEventArgs e)
        {
            this.lastColSplitBar = this.currentColSplitBar;
            this.currentColSplitBar = e.X; 
            Rectangle lastSplitBarRect = CalcColResizeFeedbackRect(this.lastColSplitBar);
            if (this.editingControl != null && 
                !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] && 
                this.editingPanel.Bounds.IntersectsWith(lastSplitBarRect))
            { 
                this.editingPanel.Invalidate();
                this.editingPanel.Update();
                this.editingControl.Invalidate();
                this.editingControl.Update(); 
            }
            Invalidate(lastSplitBarRect); 
            Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar)); 
        }
 
        /// 
        public virtual void NotifyCurrentCellDirty(bool dirty)
        {
            Debug.Assert(this.ptCurrentCell.X >= 0 && this.ptCurrentCell.X < this.Columns.Count); 
            Debug.Assert(this.ptCurrentCell.Y >= 0 && this.ptCurrentCell.Y < this.Rows.Count);
 
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] == false) 
            {
                // autosizing has no effect since edited value hasn't been committed 
                // and autosizing code only looks at committed values.

                this.IsCurrentCellDirtyInternal = dirty;
                if (dirty && this.editingControl != null && ((IDataGridViewEditingControl) this.editingControl).RepositionEditingControlOnValueChange) 
                {
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); 
                } 
            }
        } 

        internal void OnAddedColumn(DataGridViewColumn dataGridViewColumn)
        {
            Debug.Assert(dataGridViewColumn.Index >= 0); 
            Debug.Assert(dataGridViewColumn.Index < this.Columns.Count);
            Debug.Assert(dataGridViewColumn.DataGridView == this); 
 
            if (dataGridViewColumn.DisplayIndex == -1 || dataGridViewColumn.DisplayIndex >= this.Columns.Count)
            { 
                // Developer did not assign a DisplayIndex or picked a large number.
                // Choose the Index as the DisplayIndex.
                dataGridViewColumn.DisplayIndexInternal = dataGridViewColumn.Index;
            } 

            CorrectColumnDisplayIndexesAfterInsertion(dataGridViewColumn); 
 
            if (dataGridViewColumn.HasHeaderCell)
            { 
                dataGridViewColumn.HeaderCell.DataGridViewInternal = this;
            }

            AdjustExpandingRows(dataGridViewColumn.Index, false /*fixedWidth*/); 
            DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode;
            Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); 
            bool fixedColumnWidth = autoSizeColumnMode == DataGridViewAutoSizeColumnMode.None || 
                                    autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill;
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth);
            }
 
            if (!fixedColumnWidth)
            { 
                // This is the first time the column autosizes. Save current column width for later reuse. 
                dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness;
                AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/); 

                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                {
                    // Second round of column headers autosizing 
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
                } 
            } 

            // Raise the ColumnAdded event 
            OnColumnAdded(new DataGridViewColumnEventArgs(dataGridViewColumn));
        }

        internal void OnAddedRow_PreNotification(int rowIndex) 
        {
            Debug.Assert(rowIndex >= 0); 
 
            if (this.AllowUserToAddRowsInternal && this.newRowIndex == -1)
            { 
                // The added row is necessarily the 'new row'
                // Set the this.newRowIndex variable as early as possible.
                Debug.Assert(rowIndex == this.Rows.Count - 1);
                this.newRowIndex = rowIndex; 
            }
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 

#if DEBUG 
            DataGridViewRow dataGridViewRowDebug = this.Rows.SharedRow(rowIndex);
            foreach (DataGridViewCell dataGridViewCell in dataGridViewRowDebug.Cells)
            {
                Debug.Assert(!dataGridViewCell.Selected); 
                Debug.Assert(dataGridViewRowDebug.Index != -1 || !dataGridViewCell.HasValue);
            } 
#endif 

            // Update this.individualReadOnlyCells 
            if ((rowState & DataGridViewElementStates.ReadOnly) == 0 &&
                !this.ReadOnly)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); 
                foreach (DataGridViewCell dataGridViewCell in dataGridViewRow.Cells)
                { 
                    if (!dataGridViewCell.OwningColumn.ReadOnly && IsSharedCellReadOnly(dataGridViewCell, rowIndex)) 
                    {
                        this.individualReadOnlyCells.Add(dataGridViewCell); 
                    }
                }
            }
        } 

        internal void OnAddedRow_PostNotification(int rowIndex) 
        { 
            Debug.Assert(rowIndex >= 0);
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);

            if ((rowState & DataGridViewElementStates.Visible) != 0)
            { 
                bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0;
 
                DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode; 

                bool autoSizeRow = false; 
                // Auto size row if needed
                if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None &&
                    !((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed))
                { 
                    // this call may unshare the row.
                    int rowHeight = this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); 
                    this.Rows.SharedRow(rowIndex).CachedThickness = rowHeight; 
                    AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/);
                    autoSizeRow = true; 
                }

                // Auto size columms also if needed
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; 
                if (rowDisplayed)
                { 
                    autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; 
                }
                bool columnAutoSized; 
                if (this.Rows.GetRowCount(DataGridViewElementStates.Visible) > 1)
                {
                    // Columns can only expand, and not collapse.
                    columnAutoSized = AdjustExpandingColumns(autoSizeColumnCriteriaFilter, rowIndex); 
                }
                else 
                { 
                    columnAutoSized = AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/);
                } 
                bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize;
                bool rowHeadersAutoSize = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                                          this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing;
 
                if (!rowHeadersAutoSize && !columnAutoSized)
                { 
                    // No need to autosize the column headers when the row headers and columns don't change. 
                    fixedColumnHeadersHeight = true;
                } 

                // Auto size row headers
                if (rowHeadersAutoSize)
                { 
                    AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, fixedColumnHeadersHeight, true /*fixedRowsHeight*/);
                } 
 
                // Auto size column headers
                if (!fixedColumnHeadersHeight) 
                {
                    AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
                }
 
                if (autoSizeRow)
                { 
                    // Second round of row autosizing 
                    AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/);
                } 

                if (rowHeadersAutoSize && !fixedColumnHeadersHeight)
                {
                    // Second round of row headers autosizing 
                    AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
                } 
            } 
        }
 
        internal void OnAddedRows_PreNotification(DataGridViewRow[] dataGridViewRows)
        {
            // Note: no row can be added that breaks the frozen row packing on the top
 
            foreach(DataGridViewRow dataGridViewRow in dataGridViewRows)
            { 
                OnAddedRow_PreNotification(dataGridViewRow.Index); 
            }
        } 

        internal void OnAddedRows_PostNotification(DataGridViewRow[] dataGridViewRows)
        {
            foreach (DataGridViewRow dataGridViewRow in dataGridViewRows) 
            {
                OnAddedRow_PostNotification(dataGridViewRow.Index); 
            } 
        }
 
        internal void OnAddingColumn(DataGridViewColumn dataGridViewColumn)
        {
            // throw an exception if the column to be added breaks the rules
            if (dataGridViewColumn == null) 
            {
                throw new ArgumentNullException("dataGridViewColumn"); 
            } 
            if (dataGridViewColumn.DataGridView != null)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView));
            }

            if (!this.InInitialization && 
                dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic &&
                (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || 
                 this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString())); 
            }

            if (dataGridViewColumn.Visible)
            { 
                // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used
 
                // Make sure the column does not autosize based only on header while column headers are invisible 
                if (!this.ColumnHeadersVisible &&
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader))) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn));
                }
 
                // Make sure the column is not frozen and auto fills
                if (dataGridViewColumn.Frozen && 
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill))) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn)); 
                }

                // UsedFillWeight values need to be updated
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; 
            }
 
            // Make sure the sum of the column weights does not exceed ushort.MaxValue 
            float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) + dataGridViewColumn.FillWeight;
            if (weightSum > (float)ushort.MaxValue) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture)));
            }
 
            // check for correctness of frozen state - throws exception if state is incorrect.
            CorrectColumnFrozenState(dataGridViewColumn, this.Columns.Count); 
 
            // prepare the existing rows by appending cells of correct type
            if (this.Rows.Count > 0) 
            {
                // Only require a default cell type when there are rows to fill
                if (dataGridViewColumn.CellType == null)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn));
                } 
 
                if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1)
                { 
                    // New row needs to be unshared before addition of new cell with a Value != null
                    DataGridViewRow newRow = this.Rows[this.newRowIndex];
                }
 
                int newColumnCount = this.Columns.Count + 1;
 
                try 
                {
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) 
                    {
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        if (dataGridViewRow.Cells.Count < newColumnCount)
                        { 
                            DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone();
                            dataGridViewRow.Cells.AddInternal(dataGridViewCellNew); 
                            if (rowIndex == this.newRowIndex) 
                            {
                                dataGridViewCellNew.SetValueInternal(rowIndex, dataGridViewCellNew.DefaultNewRowValue); 
                            }
                            dataGridViewCellNew.DataGridViewInternal = this;
                            dataGridViewCellNew.OwningRowInternal = dataGridViewRow;
                            dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn; 
                        }
                    } 
                } 
                catch
                { 
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
                    {
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        if (dataGridViewRow.Cells.Count == newColumnCount) 
                        {
                            dataGridViewRow.Cells.RemoveAtInternal(newColumnCount - 1); 
                        } 
                        else
                        { 
                            Debug.Assert(dataGridViewRow.Cells.Count < newColumnCount);
                            break;
                        }
                    } 
                    throw;
                } 
            } 
        }
 
        [
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // not legitimate
        ]
        internal void OnAddingColumns(DataGridViewColumn[] dataGridViewColumns) 
        {
            // Make sure the sum of the column weights does not exceed ushort.MaxValue 
            float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None); 
            Debug.Assert(weightSum <= (float)ushort.MaxValue);
 
            // throw an exception if any of the columns to be added breaks the rules
            Debug.Assert(dataGridViewColumns != null);
            foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns)
            { 
                if (dataGridViewColumn == null)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_AtLeastOneColumnIsNull)); 
                }
                if (dataGridViewColumn.DataGridView != null) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView));
                }
                // Only require a default cell type when there are rows to fill 
                if (this.Rows.Count > 0 && dataGridViewColumn.CellType == null)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn)); 
                }
 
                if (!this.InInitialization &&
                    dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic &&
                    (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect ||
                     this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString())); 
                } 

                if (dataGridViewColumn.Visible) 
                {
                    // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used

                    // Make sure the column does not autosize based only on header while column headers are invisible 
                    if (!this.ColumnHeadersVisible &&
                        (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader))) 
                    { 
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn));
                    } 

                    // Make sure the column is not frozen and auto fills
                    if (dataGridViewColumn.Frozen &&
                        (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill))) 
                    {
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn)); 
                    } 

                    // UsedFillWeight values need to be updated 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
                }

                weightSum += dataGridViewColumn.FillWeight; 
                if (weightSum > (float)ushort.MaxValue)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); 
                }
            } 

            Debug.Assert(weightSum <= (float)ushort.MaxValue);

            // make sure no two columns are identical 
            int columnCount = dataGridViewColumns.Length;
            for (int column1 = 0; column1 < columnCount - 1; column1++) 
            { 
                for (int column2 = column1 + 1; column2 < columnCount; column2++)
                { 
                    if (dataGridViewColumns[column1] == dataGridViewColumns[column2])
                    {
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddIdenticalColumns));
                    } 
                }
            } 
 
            // check for correctness of frozen states - throws exception if any state is incorrect.
            CorrectColumnFrozenStates(dataGridViewColumns); 

            // prepare the existing rows by appending cells of correct type
            if (this.Rows.Count > 0)
            { 
                foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns)
                { 
                    Debug.Assert(dataGridViewColumn.CellType != null); 
                    if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1)
                    { 
                        // New row needs to be unshared before addition of new cell with a Value != null
                        DataGridViewRow newRow = this.Rows[this.newRowIndex];
                        break;
                    } 
                }
 
                int previousColumnCount = this.Columns.Count; 
                int addedColumnCount = 0;
 
                try
                {
                    foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns)
                    { 
                        addedColumnCount++;
                        Debug.Assert(dataGridViewColumn.CellType != null); 
                        for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) 
                        {
                            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); 
                            if (dataGridViewRow.Cells.Count < previousColumnCount + addedColumnCount)
                            {
                                DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone();
                                int indexCell = dataGridViewRow.Cells.AddInternal(dataGridViewCellNew); 
                                if (rowIndex == this.newRowIndex)
                                { 
                                    dataGridViewCellNew.Value = dataGridViewCellNew.DefaultNewRowValue; 
                                }
                                dataGridViewCellNew.DataGridViewInternal = this; 
                                dataGridViewCellNew.OwningRowInternal = dataGridViewRow;
                                dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn;
                            }
                        } 
                    }
                } 
                catch 
                {
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) 
                    {
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        while (dataGridViewRow.Cells.Count > previousColumnCount)
                        { 
                            dataGridViewRow.Cells.RemoveAtInternal(dataGridViewRow.Cells.Count - 1);
                        } 
                    } 
                    throw;
                } 
            }
        }

        internal void OnAddingRow(DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, bool checkFrozenState) 
        {
            // Note dataGridViewRow.DataGridView != null for duplication of shared rows. 
 
            // throw an exception if the row to be added breaks the rules
            if (dataGridViewRow == null) 
            {
                throw new ArgumentNullException("dataGridViewRow");
            }
 
            // !Do not check for dataGridViewRow.Selected flag. Caller does it instead!
            // !Do not check for dataGridViewRow.DataGridView != null. Caller does it instead! 
 
            if (checkFrozenState)
            { 
                // check for correctness of frozen state - throws exception if state is incorrect.
                CorrectRowFrozenState(dataGridViewRow, rowState, this.Rows.Count);
            }
 
            if (this.ReadOnly && dataGridViewRow.DataGridView == null && dataGridViewRow.ReadOnly)
            { 
                // Clear the superfluous flag since the whole dataGridView is read-only 
                dataGridViewRow.ReadOnly = false;
            } 

            int columnIndex = 0;
            foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
            { 
                DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex];
                if ((this.ReadOnly || dataGridViewColumn.ReadOnly) && dataGridViewCell.StateIncludes(DataGridViewElementStates.ReadOnly)) 
                { 
                    // Clear superfluous flag since the whole dataGridView or column is ReadOnly
                    dataGridViewCell.ReadOnlyInternal = false; 
                }
                columnIndex++;
            }
        } 

        internal void OnAddingRows(DataGridViewRow[] dataGridViewRows, bool checkFrozenStates) 
        { 
            // throw an exception if any of the rows to be added breaks the rules
            Debug.Assert(dataGridViewRows != null); 

            foreach (DataGridViewRow dataGridViewRow in dataGridViewRows)
            {
                if (dataGridViewRow == null) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_AtLeastOneRowIsNull)); 
                } 

                if (dataGridViewRow.DataGridView != null) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_RowAlreadyBelongsToDataGridView));
                }
 
                if (dataGridViewRow.Selected)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridViewRowCollection_CannotAddOrInsertSelectedRow)); 
                }
 
                if (dataGridViewRow.Cells.Count > this.Columns.Count)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridViewRowCollection_TooManyCells));
                } 
            }
 
            // make sure no two rows are identical 
            int rowCount = dataGridViewRows.Length;
            for (int row1 = 0; row1 < rowCount - 1; row1++) 
            {
                for (int row2 = row1 + 1; row2 < rowCount; row2++)
                {
                    if (dataGridViewRows[row1] == dataGridViewRows[row2]) 
                    {
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddIdenticalRows)); 
                    } 
                }
            } 

            if (checkFrozenStates)
            {
                Debug.Assert(!this.AllowUserToAddRowsInternal); 
                CorrectRowFrozenStates(dataGridViewRows, this.Rows.Count /*rowIndexInserted*/);
            } 
 
            foreach (DataGridViewRow dataGridViewRow in dataGridViewRows)
            { 
                CompleteCellsCollection(dataGridViewRow);
                OnAddingRow(dataGridViewRow, dataGridViewRow.State, false /*checkFrozenState*/);
            }
        } 

        internal void OnAdvancedBorderStyleChanged(DataGridViewAdvancedBorderStyle dgvabs) 
        { 
            if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inBorderStyleChange])
            { 
                if (dgvabs == this.advancedCellBorderStyle)
                {
                    OnCellBorderStyleChanged(EventArgs.Empty);
                } 
                else if (dgvabs == this.advancedColumnHeadersBorderStyle)
                { 
                    OnColumnHeadersBorderStyleChanged(EventArgs.Empty); 
                }
                else if (dgvabs == this.advancedRowHeadersBorderStyle) 
                {
                    OnRowHeadersBorderStyleChanged(EventArgs.Empty);
                }
            } 
        }
 
        ///  
        protected virtual void OnAllowUserToAddRowsChanged(EventArgs e)
        { 
            PushAllowUserToAddRows();

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTOADDROWSCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnAllowUserToDeleteRowsChanged(EventArgs e)
        {
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTODELETEROWSCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnAllowUserToOrderColumnsChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTOORDERCOLUMNSCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnAllowUserToResizeColumnsChanged(EventArgs e) 
        {
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTORESIZECOLUMNSCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnAllowUserToResizeRowsChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTORESIZEROWSCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        /// 
        protected virtual void OnAlternatingRowsDefaultCellStyleChanged(EventArgs e) 
        { 
            DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
            if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize) 
            {
                InvalidateData();
            }
            else 
            {
                OnRowsGlobalAutoSize(); 
                if (this.editingControl != null) 
                {
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); 
                }
            }

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALTERNATINGROWSDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnAutoGenerateColumnsChanged(EventArgs e)
        { 
            if (this.AutoGenerateColumns && this.DataSource != null)
            { 
                // refresh the list of columns and the rows 
                RefreshColumnsAndRows();
            } 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOGENERATECOLUMNSCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        internal void OnAutoSizeColumnModeChanged(DataGridViewColumn dataGridViewColumn, DataGridViewAutoSizeColumnMode previousInheritedMode)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewAutoSizeColumnModeEventArgs dgvascme = new DataGridViewAutoSizeColumnModeEventArgs(dataGridViewColumn, previousInheritedMode);
            OnAutoSizeColumnModeChanged(dgvascme);
        } 

        ///  
        protected virtual void OnAutoSizeColumnModeChanged(DataGridViewAutoSizeColumnModeEventArgs e) 
        {
            DataGridViewColumn dataGridViewColumn = e.Column; 
            if (e.Column == null)
            {
                throw new InvalidOperationException(SR.GetString(SR.InvalidNullArgument, "e.Column"));
            } 
            DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode;
            Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); 
 
            DataGridViewAutoSizeColumnMode previousInheritedMode = e.PreviousMode;
            bool previousInheritedModeAutoSized = previousInheritedMode != DataGridViewAutoSizeColumnMode.Fill && 
                                                  previousInheritedMode != DataGridViewAutoSizeColumnMode.None &&
                                                  previousInheritedMode != DataGridViewAutoSizeColumnMode.NotSet;

            if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill || 
                previousInheritedMode == DataGridViewAutoSizeColumnMode.Fill)
            { 
                // UsedFillWeight values need to be updated 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
            } 

            bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0;

            if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None) 
            {
                if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                { 
                    if (!previousInheritedModeAutoSized)
                    { 
                        // Save current column width for later reuse
                        dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness;
                    }
                    AutoResizeColumnInternal(dataGridViewColumn.Index, 
                                             (DataGridViewAutoSizeColumnCriteriaInternal) autoSizeColumnMode,
                                             fixedHeight); 
                } 
            }
            else if (dataGridViewColumn.Thickness != dataGridViewColumn.CachedThickness && previousInheritedModeAutoSized) 
            {
                // Restoring cached column width
                dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness);
            } 

            // Auto fill columns if needed 
            PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 

            // Autosize rows and column headers if needed 
            if (!fixedHeight)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                {
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                } 

                // Column gets autosized with 1 degree of freedom this time. 
                if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill)
                {
                    AutoResizeColumnInternal(dataGridViewColumn.Index,
                                             (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, 
                                             true /*fixedHeight*/);
                } 
            } 

            DataGridViewAutoSizeColumnModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZECOLUMNMODECHANGED] as DataGridViewAutoSizeColumnModeEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.PreviousModes is more precise than just e
        protected virtual void OnAutoSizeColumnsModeChanged(DataGridViewAutoSizeColumnsModeEventArgs e) 
        {
            DataGridViewAutoSizeColumnMode[] previousModes = e.PreviousModes;
            if (previousModes == null)
            { 
                throw new ArgumentNullException("e.PreviousModes");
            } 
            if (previousModes.Length != this.Columns.Count) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_PreviousModesHasWrongLength)); 
            }

            foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
            { 
                if (dataGridViewColumn.Visible)
                { 
                    DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; 
                    Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet);
                    DataGridViewAutoSizeColumnMode previousInheritedMode = previousModes[dataGridViewColumn.Index]; 
                    bool previousInheritedModeAutoSized = previousInheritedMode != DataGridViewAutoSizeColumnMode.Fill &&
                                                          previousInheritedMode != DataGridViewAutoSizeColumnMode.None &&
                                                          previousInheritedMode != DataGridViewAutoSizeColumnMode.NotSet;
                    if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill || 
                        previousInheritedMode == DataGridViewAutoSizeColumnMode.Fill)
                    { 
                        // UsedFillWeight values need to be updated 
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
                    } 

                    if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None)
                    {
                        if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                        {
                            if (!previousInheritedModeAutoSized) 
                            { 
                                // Save current column width for later reuse
                                dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness; 
                            }
                            AutoResizeColumnInternal(dataGridViewColumn.Index,
                                                     (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode,
                                                     (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0 /*fixedHeight*/); 
                        }
                    } 
                    else if (dataGridViewColumn.Thickness != dataGridViewColumn.CachedThickness && previousInheritedModeAutoSized) 
                    {
                        // Restoring cached column width 
                        dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness);
                    }
                }
            } 

            // Auto fill columns if needed 
            PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 

            // Autosize rows and column headers if needed 
            if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                {
                    AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                } 

                // Second pass of column autosizing with 1 degree of freedom 
                foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
                {
                    DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode;
                    Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); 

                    if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                    { 
                        AutoResizeColumnInternal(dataGridViewColumn.Index,
                                                 (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, 
                                                 true /*fixedHeight*/);
                    }
                }
            } 

            DataGridViewAutoSizeColumnsModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZECOLUMNSMODECHANGED] as DataGridViewAutoSizeColumnsModeEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnAutoSizeRowsModeChanged(DataGridViewAutoSizeModeEventArgs e)
        { 
            if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) 
            {
                // restore cached rows thickness 
                RestoreRowsCachedThickness();
            }
            else
            { 
                if (!e.PreviousModeAutoSized)
                { 
                    // Save the rows thickness for later reuse 
                    // Note that only visible rows are affected, contrary to columns in OnAutoSizeColumnsModeChanged where all columns are affected.
                    for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                        rowIndex != -1;
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                    {
                        // this call may unshare the row. 
                        int rowHeight = this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                        this.Rows.SharedRow(rowIndex).CachedThickness = rowHeight; 
                    } 
                }
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }

            DataGridViewAutoSizeModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZEROWSMODECHANGED] as DataGridViewAutoSizeModeEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnBackgroundColorChanged(EventArgs e)
        {
            InvalidateInside(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWBACKGROUNDCOLORCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnBandContextMenuStripChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnContextMenuStripChanged(dgvce);
            }
            else
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowContextMenuStripChanged(dgvre); 
            } 
        }
 
        internal void OnBandDefaultCellStyleChanged(DataGridViewBand dataGridViewBand)
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn;
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnDefaultCellStyleChanged(dgvce); 
            }
            else 
            {
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowDefaultCellStyleChanged(dgvre);
            } 
        }
 
        internal void OnBandDividerThicknessChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null)
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn);
                OnColumnDividerWidthChanged(dgvce); 
            }
            else 
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowDividerHeightChanged(dgvre); 
            }
        }

        internal void OnBandHeaderCellChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnHeaderCellChanged(dgvce);
            }
            else
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowHeaderCellChanged(dgvre); 
            } 
        }
 
        internal void OnBandMinimumThicknessChanged(DataGridViewBand dataGridViewBand)
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn;
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnMinimumWidthChanged(dgvce); 
            }
            else 
            {
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowMinimumHeightChanged(dgvre);
            } 
        }
 
        internal void OnBandThicknessChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null)
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn);
                OnColumnWidthChanged(dgvce); 
            }
            else 
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowHeightChanged(dgvre); 
            }
        }

        internal void OnBandThicknessChanging() 
        {
            if (this.InAdjustFillingColumns) 
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter));
            } 
        }

        /// 
        protected override void OnBindingContextChanged(EventArgs e) 
        {
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged]) 
            { 
                return;
            } 

            this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged] = true;
            try
            { 
                if (this.dataConnection != null)
                { 
                    this.CurrentCell = null; 
                    try
                    { 
                        this.dataConnection.SetDataConnection(this.DataSource, this.DataMember);
                    }
                    catch (ArgumentException)
                    { 
                        if (this.DesignMode)
                        { 
                            // This is the minimal fix for vsw 527646. 
                            // If the DataMember became invalid at DesignTime then set it to String.Empty,
                            // regenerate the column collection and DO NOT send BindingContextChanged event. 
                            this.DataMember = String.Empty;
                            RefreshColumnsAndRows();
                            return;
                        } 
                        else
                        { 
                            throw; 
                        }
                    } 
                    RefreshColumnsAndRows();
                    base.OnBindingContextChanged(e);
                    if (this.dataConnection.CurrencyManager != null)
                    { 
                        OnDataBindingComplete(ListChangedType.Reset);
                    } 
                } 
                else
                { 
                    base.OnBindingContextChanged(e);
                }
            }
            finally 
            {
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged] = false; 
            } 
        }
 
        /// 
        protected virtual void OnBorderStyleChanged(EventArgs e)
        {
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWBORDERSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnCancelRowEdit(QuestionEventArgs e)
        { 
            QuestionEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCANCELROWEDIT] as QuestionEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
                CorrectFocus(true /*onlyIfGridHasFocus*/); 
            }
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellBeginEdit(DataGridViewCellCancelEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLBEGINEDIT] as DataGridViewCellCancelEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        /// 
        protected virtual void OnCellBorderStyleChanged(EventArgs e) 
        { 
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            Invalidate(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLBORDERSTYLECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        internal void OnCellClickInternal(DataGridViewCellEventArgs e) 
        {
            OnCellClick(e);
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellClick(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            } 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null); 
            if (e.RowIndex >= 0 && dataGridViewCell.ClickUnsharesRowInternal(e))
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnClickInternal(e); 
            }
            else 
            { 
                dataGridViewCell.OnClickInternal(e);
            } 

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCLICK] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        internal void OnCellCommonChange(int columnIndex, int rowIndex) 
        {
            if (columnIndex == -1)
            {
                // row or topleft header characteristic has changed 
                OnRowHeaderGlobalAutoSize(rowIndex);
            } 
            else 
            {
                if (rowIndex == -1) 
                {
                    // column header characteristic has changed
                    OnColumnHeaderGlobalAutoSize(columnIndex);
                } 
                else
                { 
                    // regular cell characteristic changed 
                    InvalidateCellPrivate(columnIndex, rowIndex);
 
                    bool rowDisplayed = false;
                    if (rowIndex != -1)
                    {
                        rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0; 
                    }
 
                    DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode; 
                    bool autoSizeColumn = (autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.AllRows) != 0;
                    if (rowDisplayed) 
                    {
                        autoSizeColumn |= (autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows) != 0;
                    }
 
                    bool autoSizeRow = (((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0;
                    if (autoSizeRow) 
                    { 
                        AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), !autoSizeColumn /*fixedWidth*/, true /*internalAutosizing*/);
                    } 
                    if (autoSizeColumn)
                    {
                        AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/);
                        if (autoSizeRow) 
                        {
                            // Second round of row autosizing with 1 degree of freedom. 
                            AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
                        }
                    } 
                }
            }
        }
 
        internal void OnCellContentClickInternal(DataGridViewCellEventArgs e)
        { 
            OnCellContentClick(e); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContentClick(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.ContentClickUnsharesRowInternal(e)) 
            { 
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnContentClickInternal(e); 
            }
            else
            {
                dataGridViewCell.OnContentClickInternal(e); 
            }
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTENTCLICK] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnCellContentDoubleClickInternal(DataGridViewCellEventArgs e)
        { 
            OnCellContentDoubleClick(e); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContentDoubleClick(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.ContentDoubleClickUnsharesRowInternal(e)) 
            { 
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnContentDoubleClickInternal(e); 
            }
            else
            {
                dataGridViewCell.OnContentDoubleClickInternal(e); 
            }
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTENTDOUBLECLICK] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnCellContextMenuStripChanged(DataGridViewCell dataGridViewCell)
        { 
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); 
            OnCellContextMenuStripChanged(dgvce);
        } 

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContextMenuStripChanged(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTEXTMENUSTRIPCHANGED] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        internal ContextMenuStrip OnCellContextMenuStripNeeded(int columnIndex, int rowIndex, ContextMenuStrip contextMenuStrip)
        { 
            DataGridViewCellContextMenuStripNeededEventArgs dgvccmsne = new DataGridViewCellContextMenuStripNeededEventArgs(columnIndex, rowIndex, contextMenuStrip);
            OnCellContextMenuStripNeeded(dgvccmsne); 
            return dgvccmsne.ContextMenuStrip; 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContextMenuStripNeeded(DataGridViewCellContextMenuStripNeededEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellContextMenuStripNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTEXTMENUSTRIPNEEDED] as DataGridViewCellContextMenuStripNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellDoubleClick(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null); 
            if (e.RowIndex >= 0 && dataGridViewCell.DoubleClickUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnDoubleClickInternal(e);
            }
            else
            { 
                dataGridViewCell.OnDoubleClickInternal(e);
            } 
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLDOUBLECLICK] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellEndEdit(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLENDEDIT] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnCellEnter(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) 
        {
            OnCellEnter(new DataGridViewCellEventArgs(columnIndex, rowIndex)); 
            if (dataGridViewCell != null)
            {
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    dataGridViewCell = null;
                } 
                else 
                {
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); 
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                }
            }
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellEnter(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            try 
            {
                this.noDimensionChangeCount++;

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLENTER] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e); 
                }
            } 
            finally
            {
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0); 
            }
        } 
 
        internal void OnCellErrorTextChanged(DataGridViewCell dataGridViewCell)
        { 
            Debug.Assert(dataGridViewCell.RowIndex >= -1);
            Debug.Assert(dataGridViewCell.ColumnIndex >= -1);
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell);
            OnCellErrorTextChanged(dgvce); 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellErrorTextChanged(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            UpdateCellErrorText(e.ColumnIndex, e.RowIndex);

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLERRORTEXTCHANGED] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        internal string OnCellErrorTextNeeded(int columnIndex, int rowIndex, string errorText)
        {
            Debug.Assert(columnIndex >= 0);
            Debug.Assert(rowIndex >= 0); 
            DataGridViewCellErrorTextNeededEventArgs dgvcetne = new DataGridViewCellErrorTextNeededEventArgs(columnIndex, rowIndex, errorText);
            OnCellErrorTextNeeded(dgvcetne); 
            return dgvcetne.ErrorText; 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellErrorTextNeeded(DataGridViewCellErrorTextNeededEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellErrorTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLERRORTEXTNEEDED] as DataGridViewCellErrorTextNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        internal DataGridViewCellFormattingEventArgs OnCellFormatting(int columnIndex, int rowIndex, object val, Type formattedValueType, DataGridViewCellStyle cellStyle)
        {
            DataGridViewCellFormattingEventArgs dgvcfe = new DataGridViewCellFormattingEventArgs(columnIndex, 
                                                                                                 rowIndex,
                                                                                                 val, 
                                                                                                 formattedValueType, 
                                                                                                 cellStyle);
            OnCellFormatting(dgvcfe); 
            return dgvcfe;
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellFormatting(DataGridViewCellFormattingEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellFormattingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLFORMATTING] as DataGridViewCellFormattingEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnCellLeave(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        { 
            OnCellLeave(new DataGridViewCellEventArgs(columnIndex, rowIndex)); 
            if (dataGridViewCell != null)
            { 
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                {
                    dataGridViewCell = null;
                } 
                else
                { 
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); 
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                } 
            }
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellLeave(DataGridViewCellEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            try 
            {
                this.noDimensionChangeCount++; 

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLLEAVE] as DataGridViewCellEventHandler;
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e);
                } 
            } 
            finally
            { 
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0);
            }
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseClick(DataGridViewCellMouseEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseClickUnsharesRowInternal(e))
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseClickInternal(e);
            } 
            else 
            {
                dataGridViewCell.OnMouseClickInternal(e); 
            }
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble] = false;

            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellMouseDoubleClick(DataGridViewCellMouseEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null); 
            if (e.RowIndex >= 0 && dataGridViewCell.MouseDoubleClickUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseDoubleClickInternal(e);
            }
            else
            { 
                dataGridViewCell.OnMouseDoubleClickInternal(e);
            } 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble] = true; 

            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellMouseDown(DataGridViewCellMouseEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 

            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null);
 
            // Only left clicks for now
            Keys nModifier = ModifierKeys; 
            bool isControlDown = (nModifier & Keys.Control) == Keys.Control && (nModifier & Keys.Alt) == 0; 
            bool isShiftDown = (nModifier & Keys.Shift) == Keys.Shift;
            bool isAltDown = (nModifier & Keys.Alt) == Keys.Alt; 

            Point ptGridCoord = ConvertCellToGridCoord(e.ColumnIndex, e.RowIndex, e.X, e.Y);

            HitTestInfo hti = HitTest(ptGridCoord.X, ptGridCoord.Y); 

            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && e.Button == MouseButtons.Left) 
            { 
                Debug.Assert(hti.Type != DataGridViewHitTestType.None &&
                             hti.Type != DataGridViewHitTestType.HorizontalScrollBar && 
                             hti.Type != DataGridViewHitTestType.VerticalScrollBar);
                Debug.Assert(this.ptMouseDownCell.X == hti.col);
                Debug.Assert(this.ptMouseDownCell.Y == hti.row);
 
                switch (hti.typeInternal)
                { 
                    // Check for column/row (headers) resize 
                    case DataGridViewHitTestTypeInternal.ColumnResizeLeft:
                    case DataGridViewHitTestTypeInternal.ColumnResizeRight: 
                    case DataGridViewHitTestTypeInternal.RowResizeBottom:
                    case DataGridViewHitTestTypeInternal.RowResizeTop:
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft:
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight: 
                    case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft:
                    case DataGridViewHitTestTypeInternal.RowHeadersResizeRight: 
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop: 
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom:
                    case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: 
                    case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom:
                    {
                        this.dataGridViewOper[DATAGRIDVIEWOPER_resizingOperationAboutToStart] = (e.Clicks == 1);
                        break; 
                    }
                } 
            } 

            try 
            {
                if (e.RowIndex >= 0 && dataGridViewCell.MouseDownUnsharesRowInternal(e))
                {
                    DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                    GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseDownInternal(e);
                } 
                else 
                {
                    dataGridViewCell.OnMouseDownInternal(e); 
                }

                DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEDOWN] as DataGridViewCellMouseEventHandler;
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
                {
                    eh(this, e); 
                } 

                if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && e.Button == MouseButtons.Left) 
                {
                    switch (hti.typeInternal)
                    {
                        // Check column resize 
                        case DataGridViewHitTestTypeInternal.ColumnResizeLeft:
                        case DataGridViewHitTestTypeInternal.ColumnResizeRight: 
                        { 
                            int columnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight) ? hti.col : hti.adjacentCol;
                            Debug.Assert(this.Columns[columnIndex].Resizable == DataGridViewTriState.True); 
                            if (e.Clicks == 1)
                            {
                                BeginColumnResize(ptGridCoord.X, hti.mouseBarOffset, columnIndex);
                            } 
                            break;
                        } 
 
                        // Check row resize
                        case DataGridViewHitTestTypeInternal.RowResizeBottom: 
                        case DataGridViewHitTestTypeInternal.RowResizeTop:
                        {
                            int rowIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom) ? hti.row : hti.adjacentRow;
                            if (e.Clicks == 1) 
                            {
                                BeginRowResize(ptGridCoord.Y, hti.mouseBarOffset, rowIndex); 
                            } 
                            break;
                        } 

                        // Check for column header mouse down
                        case DataGridViewHitTestTypeInternal.ColumnHeader:
                        case DataGridViewHitTestTypeInternal.ColumnHeaderLeft: 
                        case DataGridViewHitTestTypeInternal.ColumnHeaderRight:
                        case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft: 
                        { 
                            if (isAltDown && this.AllowUserToOrderColumns &&
                                (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || 
                                 this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect))
                            {
                                BeginColumnRelocation(ptGridCoord.X, hti.col);
                            } 
                            else
                            { 
                                OnColumnHeaderMouseDown(hti, isShiftDown, isControlDown); 
                            }
                            break; 
                        }

                        // Check for row header mouse down
                        case DataGridViewHitTestTypeInternal.RowHeader: 
                        {
                            OnRowHeaderMouseDown(hti, isShiftDown, isControlDown); 
                            break; 
                        }
 
                        // Check for cell mouse down
                        case DataGridViewHitTestTypeInternal.Cell:
                        {
                            OnCellMouseDown(hti, isShiftDown, isControlDown); 
                            break;
                        } 
 
                        // Check for top/left header mouse down
                        case DataGridViewHitTestTypeInternal.TopLeftHeader: 
                        {
                            OnTopLeftHeaderMouseDown();
                            break;
                        } 

                        // Check for row headers resize 
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft: 
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight:
                        case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft: 
                        case DataGridViewHitTestTypeInternal.RowHeadersResizeRight:
                        {
                            if (e.Clicks == 1)
                            { 
                                BeginRowHeadersResize(ptGridCoord.X, hti.mouseBarOffset);
                            } 
                            break; 
                        }
 
                        // Check for column headers resize
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop:
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom:
                        case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: 
                        case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom:
                        { 
                            if (e.Clicks == 1) 
                            {
                                BeginColumnHeadersResize(ptGridCoord.Y, hti.mouseBarOffset); 
                            }
                            break;
                        }
                    } 
                    // Make sure that there is a current cell after this mouse down event.
                    if (this.ptCurrentCell.X == -1) 
                    { 
                        MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/);
                    } 
                }
            }
            finally
            { 
                this.dataGridViewOper[DATAGRIDVIEWOPER_resizingOperationAboutToStart] = false;
            } 
        } 

        private void OnCellMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown) 
        {
            Debug.Assert(hti.Type == DataGridViewHitTestType.Cell);
            // Only commit cell if the target cell is different from the current one.
            if (this.ptCurrentCell.X >= 0 && 
                (this.ptCurrentCell.X != hti.col || this.ptCurrentCell.Y != hti.row))
            { 
                Point ptOriginalCurrentCell = this.ptCurrentCell; 
                if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit,
                    this.ptCurrentCell.X != hti.col || this.ptCurrentCell.Y != hti.row /*forCurrentCellChange*/, 
                    this.ptCurrentCell.Y != hti.row /*forCurrentRowChange*/))
                {
                    // Return silently if validating/commit/abort failed
                    return; 
                }
                if (this.ptCurrentCell != ptOriginalCurrentCell) 
                { 
                    // VSWhidbey 492203. Somehow the fact that the current cell was committed altered the current cell value.
                    // To avoid unintentional multi-selections, we act as if Shift and Control keys were up. 
                    isShiftDown = isControlDown = false;
                }
            }
 
            if (hti.col >= this.Columns.Count)
            { 
                DataGridViewColumn dataGridViewLastVisibleColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, 
                                                                                              DataGridViewElementStates.None);
                if (this.ptCurrentCell.X == -1 && dataGridViewLastVisibleColumn != null) 
                {
                    // CurrentCell was reset because CommitEdit deleted column(s).
                    // Since the user clicked on a cell, we don't want to end up
                    // with no CurrentCell. We pick the last visible column in the grid. 
                    hti.col = dataGridViewLastVisibleColumn.Index;
                } 
                else 
                {
                    return; 
                }
            }
            if (hti.row >= this.Rows.Count)
            { 
                int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                if (this.ptCurrentCell.X == -1 && lastVisibleRowIndex != -1) 
                { 
                    // CurrentCell was reset because CommitEdit deleted row(s).
                    // Since the user clicked on a 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'.
                    hti.row = lastVisibleRowIndex;
                } 
                else
                { 
                    return; 
                }
            } 

            bool select = true;
            this.noSelectionChangeCount++;
            try 
            {
                switch (this.SelectionMode) 
                { 
                    case DataGridViewSelectionMode.CellSelect:
                    { 
                        if (isControlDown &&
                            IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row) &&
                            (!isShiftDown || !this.MultiSelect))
                        { 
                            select = false;
                        } 
                        if (select) 
                        {
                            if ((!this.MultiSelect || !isControlDown) && !(this.MultiSelect && isShiftDown)) 
                            {
                                Debug.Assert(this.MultiSelect || this.individualSelectedCells.Count <= 1);
                                RemoveIndividuallySelectedCells(hti.col, hti.row);
                            } 
                            if (this.MultiSelect)
                            { 
                                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) 
                                {
                                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true; 
                                }
                                if (isShiftDown)
                                {
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    if (this.ptAnchorCell.X == -1) 
                                    { 
                                        return;
                                    } 
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col,
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row);
                                }
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, true); 
                                } 
                            }
                            else 
                            {
                                SetSelectedCellCore(hti.col, hti.row, true);
                            }
                        } 
                        else
                        { 
                            SetSelectedCellCore(hti.col, hti.row, false); 
                        }
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); 
                        Debug.Assert(success);
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                    { 
                        if (isControlDown && this.Columns[hti.col].Selected) 
                        {
                            select = false; 
                        }
                        if (select)
                        {
                            bool selectColumnRange = false; 
                            this.trackColumn = hti.col;
                            this.trackColumnEdge = -1; 
                            if (this.MultiSelect && 
                                isShiftDown &&
                                this.ptAnchorCell.X > -1 && 
                                this.Columns[this.ptAnchorCell.X].Selected)
                            {
                                selectColumnRange = true;
                            } 
                            if (!this.MultiSelect || !isControlDown || isShiftDown)
                            { 
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                                {
                                    this.inBulkPaintCount++;
                                    switchedToBulkPaint = true; 
                                }
                                try 
                                { 
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.col)
                                        {
                                            // deselect currently selected column
                                            SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false); 
                                        }
                                        else 
                                        { 
                                            bandIndex++;
                                        } 
                                    }
                                }
                                finally
                                { 
                                    if (switchedToBulkPaint)
                                    { 
                                        ExitBulkPaint(-1, -1); 
                                    }
                                } 
                            }
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                            {
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = true; 
                            }
                            if (selectColumnRange) 
                            { 
                                if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, hti.col))
                                { 
                                    SelectColumnRange(this.ptAnchorCell.X, hti.col, true);
                                }
                                else
                                { 
                                    SelectColumnRange(hti.col, this.ptAnchorCell.X, true);
                                } 
                            } 
                            else if (!this.selectedBandIndexes.Contains(hti.col))
                            { 
                                SetSelectedColumnCore(hti.col, true);
                            }
                        }
                        else 
                        {
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.col)); 
                            SetSelectedColumnCore(hti.col, false); 
                        }
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); 
                        Debug.Assert(success);
                        break;
                    }
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                    { 
                        if (isControlDown && 
                            (this.Columns[hti.col].Selected || IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row)) &&
                            (!isShiftDown || !this.MultiSelect)) 
                        {
                            select = false;
                        }
                        if (select) 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    RemoveIndividuallySelectedCells(); 
                                } 
                                SetSelectedCellCore(hti.col, hti.row, true);
                            } 
                            else
                            {
                                // this.MultiSelect == true
                                if (!isControlDown && !isShiftDown) 
                                {
                                    bool switchedToBulkPaint = false; 
                                    if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) 
                                    {
                                        this.inBulkPaintCount++; 
                                        switchedToBulkPaint = true;
                                    }
                                    try
                                    { 
                                        while (this.selectedBandIndexes.Count > 0)
                                        { 
                                            SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); 
                                        }
                                        RemoveIndividuallySelectedCells(hti.col, hti.row); 
                                    }
                                    finally
                                    {
                                        if (switchedToBulkPaint) 
                                        {
                                            ExitBulkPaint(-1, -1); 
                                        } 
                                    }
                                } 
                                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                                {
                                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true;
                                } 
                                if (isShiftDown)
                                { 
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return;
                                    }
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row);
                                } 
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, true); 
                                }
                            }
                        }
                        else 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, false); 
                                } 
                            }
                            else 
                            {
                                SetSelectedCellCore(hti.col, hti.row, false);
                            }
                        } 
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true);
                        Debug.Assert(success); 
                        break; 
                    }
 
                    case DataGridViewSelectionMode.FullRowSelect:
                    {
                        if (isControlDown &&
                            ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)) 
                        {
                            select = false; 
                        } 
                        if (select)
                        { 
                            bool selectRowRange = false;
                            this.trackRow = hti.row;
                            this.trackRowEdge = -1;
                            if (this.MultiSelect && 
                                isShiftDown &&
                                this.ptAnchorCell.Y > -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Selected) != 0) 
                            { 
                                selectRowRange = true;
                            } 

                            if (!this.MultiSelect || !isControlDown || isShiftDown)
                            {
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) 
                                {
                                    this.inBulkPaintCount++; 
                                    switchedToBulkPaint = true;
                                }
                                try
                                { 
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.row) 
                                        {
                                            // deselect currently selected row 
                                            SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false);
                                        }
                                        else
                                        { 
                                            bandIndex++;
                                        } 
                                    } 
                                }
                                finally 
                                {
                                    if (switchedToBulkPaint)
                                    {
                                        ExitBulkPaint(-1, -1); 
                                    }
                                } 
                            } 
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                            { 
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = true;
                            }
                            if (selectRowRange)
                            { 
                                if (hti.row >= this.ptAnchorCell.Y)
                                { 
                                    SelectRowRange(this.ptAnchorCell.Y, hti.row, true); 
                                }
                                else 
                                {
                                    SelectRowRange(hti.row, this.ptAnchorCell.Y, true);
                                }
                            } 
                            else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) == 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(hti.row) == 
                                             ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0));
                                SetSelectedRowCore(hti.row, true); 
                            }
                        }
                        else
                        { 
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.row));
                            SetSelectedRowCore(hti.row, false); 
                        } 
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true);
                        Debug.Assert(success); 
                        break;
                    }

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                    {
                        if (isControlDown && 
                            (((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0) || 
                            IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row)) &&
                            (!isShiftDown || !this.MultiSelect)) 
                        {
                            select = false;
                        }
                        if (select) 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    RemoveIndividuallySelectedCells(); 
                                } 
                                SetSelectedCellCore(hti.col, hti.row, true);
                            } 
                            else
                            {
                                // this.MultiSelect == true
                                if (!isControlDown && !isShiftDown) 
                                {
                                    bool switchedToBulkPaint = false; 
                                    if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) 
                                    {
                                        this.inBulkPaintCount++; 
                                        switchedToBulkPaint = true;
                                    }
                                    try
                                    { 
                                        while (this.selectedBandIndexes.Count > 0)
                                        { 
                                            SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); 
                                        }
                                        RemoveIndividuallySelectedCells(hti.col, hti.row); 
                                    }
                                    finally
                                    {
                                        if (switchedToBulkPaint) 
                                        {
                                            ExitBulkPaint(-1, -1); 
                                        } 
                                    }
                                } 
                                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                                {
                                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true;
                                } 
                                if (isShiftDown)
                                { 
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return;
                                    }
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row);
                                } 
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, true); 
                                }
                            }
                        }
                        else 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, false); 
                                } 
                            }
                            else 
                            {
                                SetSelectedCellCore(hti.col, hti.row, false);
                            }
                        } 
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true);
 
                        // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                        // DataGridView changes.
                        // See vsWhidbey: 325296. 
                        // Debug.Assert(success);
                        break;
                    }
                } 
            }
            finally 
            { 
                this.NoSelectionChangeCount--;
            } 
        }

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseEnter(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            this.ptMouseEnteredCell.X = e.ColumnIndex; 
            this.ptMouseEnteredCell.Y = e.RowIndex; 

            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseEnterUnsharesRowInternal(e.RowIndex))
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseEnterInternal(e.RowIndex);
            } 
            else 
            {
                dataGridViewCell.OnMouseEnterInternal(e.RowIndex); 
            }

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEENTER] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellMouseLeave(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            this.ptMouseEnteredCell.X = -2; 
            this.ptMouseEnteredCell.Y = -2;
 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseLeaveUnsharesRowInternal(e.RowIndex)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseLeaveInternal(e.RowIndex);
            } 
            else
            { 
                dataGridViewCell.OnMouseLeaveInternal(e.RowIndex); 
            }
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSELEAVE] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseMove(DataGridViewCellMouseEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseMoveUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseMoveInternal(e); 
            }
            else 
            {
                dataGridViewCell.OnMouseMoveInternal(e);
            }
 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEMOVE] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 

            if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] && 
                this.AllowUserToOrderColumns &&
                this.SelectionMode != DataGridViewSelectionMode.FullColumnSelect && 
                this.SelectionMode != DataGridViewSelectionMode.ColumnHeaderSelect &&
                e.Button == MouseButtons.Left &&
                this.ptMouseDownCell.Y == -1 &&
                this.ptMouseDownCell.X >= 0 && 
                this.ptMouseDownCell.X < this.Columns.Count)
            { 
                Point ptGridCoord = ConvertCellToGridCoord(e.ColumnIndex, e.RowIndex, e.X, e.Y); 

                HitTestInfo hti = HitTest(ptGridCoord.X, ptGridCoord.Y); 

                Debug.Assert(hti.Type != DataGridViewHitTestType.None &&
                             hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                             hti.Type != DataGridViewHitTestType.VerticalScrollBar); 

                switch (hti.typeInternal) 
                { 
                    // Check for column header mouse down
                    case DataGridViewHitTestTypeInternal.ColumnHeader: 
                    case DataGridViewHitTestTypeInternal.ColumnHeaderLeft:
                    case DataGridViewHitTestTypeInternal.ColumnHeaderRight:
                    case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft:
                    { 
                        Debug.Assert(!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]);
                        if (Math.Abs(this.ptMouseDownGridCoord.X - ptGridCoord.X) >= DataGridView.DragSize.Width || 
                            Math.Abs(this.ptMouseDownGridCoord.Y - ptGridCoord.Y) >= DataGridView.DragSize.Height) 
                        {
                            BeginColumnRelocation(this.ptMouseDownGridCoord.X, this.ptMouseDownCell.X); 
                        }
                        break;
                    }
                } 
            }
        } 
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseUp(DataGridViewCellMouseEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseUpUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseUpInternal(e); 
            }
            else 
            {
                dataGridViewCell.OnMouseUpInternal(e);
            }
 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEUP] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected internal virtual void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCellPaintingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLPAINTING] as DataGridViewCellPaintingEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal DataGridViewCellParsingEventArgs OnCellParsing(int rowIndex, int columnIndex, object formattedValue, Type valueType, DataGridViewCellStyle cellStyle) 
        {
            DataGridViewCellParsingEventArgs dgvcpe = new DataGridViewCellParsingEventArgs(rowIndex, columnIndex, 
                                                                                           formattedValue, 
                                                                                           valueType,
                                                                                           cellStyle); 
            OnCellParsing(dgvcpe);
            return dgvcpe;
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellParsing(DataGridViewCellParsingEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            } 
            DataGridViewCellParsingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLPARSING] as DataGridViewCellParsingEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
        } 

        private void OnCellSelectMouseMove(HitTestInfo hti) 
        { 
            Debug.Assert(this.MultiSelect);
            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
            int oldEdgeRowIndex = this.ptCurrentCell.Y;
            if ((hti.col != this.ptCurrentCell.X || hti.row != this.ptCurrentCell.Y) &&
                !CommitEditForOperation(hti.col, hti.row, true))
            { 
                // Return silently if validating/commit/abort failed
                return; 
            } 
            this.noSelectionChangeCount++;
            try 
            {
                if (this.ptAnchorCell.X == -1 || IsInnerCellOutOfBounds(hti.col, hti.row))
                {
                    return; 
                }
                UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, 
                    this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row); 
                if (hti.col != this.ptCurrentCell.X || hti.row != this.ptCurrentCell.Y)
                { 
                    bool success = SetCurrentCellAddressCore(hti.col, hti.row, false, false, false);
                    Debug.Assert(success);
                }
            } 
            finally
            { 
                this.NoSelectionChangeCount--; 
            }
        } 

        /// 
        protected virtual void OnCellStateChanged(DataGridViewCellStateChangedEventArgs e)
        { 
            // At this point we assume that only the Selected state has an influence on the rendering of the cell.
            // If there is a scenario where another state has an effect, then the dev will have to invalidate the cell by hand. 
            DataGridViewCell dataGridViewCell = e.Cell; 
            if (e.StateChanged == DataGridViewElementStates.Selected)
            { 
                Debug.Assert(dataGridViewCell.RowIndex >= 0);
                if (this.inBulkPaintCount == 0)
                {
                    InvalidateCellPrivate(dataGridViewCell); 
                }
            } 
 
            DataGridViewCellStateChangedEventHandler eh = Events[EVENT_DATAGRIDVIEWCELLSTATECHANGED] as DataGridViewCellStateChangedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
 
            if (e.StateChanged == DataGridViewElementStates.ReadOnly &&
                this.ptCurrentCell.X == dataGridViewCell.ColumnIndex && 
                this.ptCurrentCell.Y == dataGridViewCell.RowIndex && 
                dataGridViewCell.RowIndex > -1 &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
            {
                VerifyImeRestrictedModeChanged();

                if (!dataGridViewCell.ReadOnly && 
                    ColumnEditable(this.ptCurrentCell.X) &&
                    !this.IsCurrentCellInEditMode && 
                    (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                    (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)))
                { 
                    // Current cell becomes read/write. Enter editing mode.
                    BeginEditInternal(true /*selectAll*/);
                }
            } 
        }
 
        internal void OnCellStyleChanged(DataGridViewCell dataGridViewCell) 
        {
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); 
            OnCellStyleChanged(dgvce);
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellStyleChanged(DataGridViewCellEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            OnCellCommonChange(e.ColumnIndex, e.RowIndex); 

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLSTYLECHANGED] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnCellStyleContentChanged(DataGridViewCellStyle dataGridViewCellStyle, DataGridViewCellStyle.DataGridViewCellStylePropertyInternal property) 
        {
            Debug.Assert(dataGridViewCellStyle != null); 
            switch (property)
            {
                case DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.Font:
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.DataGridView) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont]) 
                    {
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] = false; 
                    } 
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.ColumnHeaders) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont])
                    { 
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] = false;
                    }
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.RowHeaders) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont])
                    { 
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] = false;
                    } 
                    break; 

                case DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.ForeColor: 
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.DataGridView) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor])
                    {
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] = false;
                    } 
                    break;
            } 
 
            DataGridViewCellStyleContentChangedEventArgs dgvcscce = new DataGridViewCellStyleContentChangedEventArgs(dataGridViewCellStyle,
                property != DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.Color && 
                property != DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.ForeColor /*changeAffectsPreferredSize*/);
            OnCellStyleContentChanged(dgvcscce);
        }
 
        /// 
        protected virtual void OnCellStyleContentChanged(DataGridViewCellStyleContentChangedEventArgs e) 
        { 
            // We assume that when a color changes, it has no effect on the autosize of elements
            bool repositionEditingControl = false; 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Cell) == DataGridViewCellStyleScopes.Cell && (e.CellStyleScope & DataGridViewCellStyleScopes.DataGridView) == 0)
            {
                // Same processing as in OnDefaultCellStyleChanged 
                if (e.ChangeAffectsPreferredSize)
                { 
                    repositionEditingControl = true; 
                    OnGlobalAutoSize();
                } 
                else
                {
                    Invalidate();
                } 
            }
 
            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Column) == DataGridViewCellStyleScopes.Column) 
            {
                if (e.ChangeAffectsPreferredSize) 
                {
                    repositionEditingControl = true;
                    OnColumnsGlobalAutoSize();
                } 
                else
                { 
                    InvalidateData(); 
                }
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Row) == DataGridViewCellStyleScopes.Row && (e.CellStyleScope & DataGridViewCellStyleScopes.Rows) == 0 && (e.CellStyleScope & DataGridViewCellStyleScopes.AlternatingRows) == 0)
            {
                // Same processing as in OnRowsDefaultCellStyleChanged 
                InvalidateData();
                if (e.ChangeAffectsPreferredSize) 
                { 
                    repositionEditingControl = true;
                    // Autosize rows if needed 
                    if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/);
                    } 
                    // Auto size columms also if needed
                    // Impossible to figure out if DisplayedRows filter should be added or not. Adding it to be on the conservative side. 
                    AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | 
                                                        DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows,
                                                        true /*fixedHeight*/); 
                    // Second round of rows autosizing
                    if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                    }
                } 
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.DataGridView) == DataGridViewCellStyleScopes.DataGridView) 
            {
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize;
                if (e.ChangeAffectsPreferredSize)
                { 
                    repositionEditingControl = false;
                    // OnDefaultCellStyleChanged will reposition the editing control. 
                } 
                OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.ColumnHeaders) == DataGridViewCellStyleScopes.ColumnHeaders)
            {
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; 
                if (e.ChangeAffectsPreferredSize)
                { 
                    repositionEditingControl = false; 
                    // OnColumnHeadersDefaultCellStyleChanged will reposition the editing control.
                } 
                OnColumnHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            }

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.RowHeaders) == DataGridViewCellStyleScopes.RowHeaders) 
            {
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; 
                if (e.ChangeAffectsPreferredSize) 
                {
                    repositionEditingControl = false; 
                    // OnRowHeadersDefaultCellStyleChanged will reposition the editing control.
                }
                OnRowHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Rows) == DataGridViewCellStyleScopes.Rows) 
            { 
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize;
                if (e.ChangeAffectsPreferredSize) 
                {
                    repositionEditingControl = false;
                    // OnRowsDefaultCellStyleChanged will reposition the editing control.
                } 
                OnRowsDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 
 
            if ((e.CellStyleScope & DataGridViewCellStyleScopes.AlternatingRows) == DataGridViewCellStyleScopes.AlternatingRows)
            { 
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize;
                if (e.ChangeAffectsPreferredSize)
                {
                    repositionEditingControl = false; 
                    // OnAlternatingRowsDefaultCellStyleChanged will reposition the editing control.
                } 
                OnAlternatingRowsDefaultCellStyleChanged(this.CellStyleChangedEventArgs); 
            }
 
            if (repositionEditingControl && this.editingControl != null)
            {
                PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
            } 

            DataGridViewCellStyleContentChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLSTYLECONTENTCHANGED] as DataGridViewCellStyleContentChangedEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnCellToolTipTextChanged(DataGridViewCell dataGridViewCell) 
        {
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); 
            OnCellToolTipTextChanged(dgvce); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellToolTipTextChanged(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLTOOLTIPTEXTCHANGED] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        internal string OnCellToolTipTextNeeded(int columnIndex, int rowIndex, string toolTipText)
        {
            DataGridViewCellToolTipTextNeededEventArgs dgvctttne = new DataGridViewCellToolTipTextNeededEventArgs(columnIndex, rowIndex, toolTipText); 
            OnCellToolTipTextNeeded(dgvctttne);
            return dgvctttne.ToolTipText; 
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellToolTipTextNeeded(DataGridViewCellToolTipTextNeededEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellToolTipTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLTOOLTIPTEXTNEEDED] as DataGridViewCellToolTipTextNeededEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        internal void OnCellValidated(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        {
            OnCellValidated(new DataGridViewCellEventArgs(columnIndex, rowIndex));
            if (dataGridViewCell != null) 
            {
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                { 
                    dataGridViewCell = null;
                } 
                else
                {
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; 
                }
            } 
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellValidated(DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            try
            { 
                this.noDimensionChangeCount++;
 
                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALIDATED] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e);
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                }
            } 
            finally
            { 
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
            } 
        }

        internal bool OnCellValidating(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, DataGridViewDataErrorContexts context)
        { 
            DataGridViewCell currentCell = (dataGridViewCell == null) ? this.CurrentCellInternal : dataGridViewCell;
            DataGridViewCellStyle dataGridViewCellStyle = currentCell.GetInheritedStyle(null, rowIndex, false); 
            object val = currentCell.GetValueInternal(rowIndex); 
            object editedFormattedValue = currentCell.GetEditedFormattedValue(val, rowIndex, ref dataGridViewCellStyle, context);
            DataGridViewCellValidatingEventArgs dgvcfvce = new DataGridViewCellValidatingEventArgs(columnIndex, rowIndex, editedFormattedValue); 
            OnCellValidating(dgvcfvce);
            if (dataGridViewCell != null)
            {
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                {
                    dataGridViewCell = null; 
                } 
                else
                { 
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                }
            } 
            return dgvcfvce.Cancel;
        } 
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellValidating(DataGridViewCellValidatingEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            try
            {
                this.noDimensionChangeCount++; 
                this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating] = true;
 
                DataGridViewCellValidatingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALIDATING] as DataGridViewCellValidatingEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e);
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                }
            } 
            finally
            { 
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
                this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating] = false; 
            }
        }

        internal void OnCellValueChangedInternal(DataGridViewCellEventArgs e) 
        {
            // For now, same effect as if the cell style had changed. 
            OnCellValueChanged(e); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellValueChanged(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            OnCellCommonChange(e.ColumnIndex, e.RowIndex); 

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUECHANGED] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal object OnCellValueNeeded(int columnIndex, int rowIndex) 
        {
            DataGridViewCellValueEventArgs dgvcve = this.CellValueEventArgs; 
            dgvcve.SetProperties(columnIndex, rowIndex, null); 
            OnCellValueNeeded(dgvcve);
            return dgvcve.Value; 
        }

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellValueNeeded(DataGridViewCellValueEventArgs e)
        { 
            if (e.ColumnIndex < 0 || e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex < 0 || e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
//#if DEBUG 
            // Some customer scenarios may result in accessing cell values while this.dataStoreAccessAllowed is false. This is bad practice, 
            // but since we're late in Whidbey, throwing an exception would be destabilizing our internal customers.
            // Debug.Assert(this.dataStoreAccessAllowed); 
//#endif
            DataGridViewCellValueEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUENEEDED] as DataGridViewCellValueEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        internal void OnCellValuePushed(int columnIndex, int rowIndex, object value) 
        {
            DataGridViewCellValueEventArgs dgvcve = this.CellValueEventArgs;
            dgvcve.SetProperties(columnIndex, rowIndex, value);
            OnCellValuePushed(dgvcve); 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellValuePushed(DataGridViewCellValueEventArgs e) 
        {
            if (e.ColumnIndex < 0 || e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex < 0 || e.RowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellValueEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUEPUSHED] as DataGridViewCellValueEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        internal void OnClearedRows()
        { 
            // Raise the RowStateChanged(Displayed->false) events
            foreach (DataGridViewRow dataGridViewRow in this.lstRows)
            {
                if (dataGridViewRow.Displayed) 
                {
                    dataGridViewRow.DisplayedInternal = false; 
                    DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, DataGridViewElementStates.Displayed); 
                    OnRowStateChanged(-1 /*rowIndex*/, dgvrsce);
                } 
            }
            this.lstRows.Clear();
        }
 
        internal void OnClearingColumns()
        { 
            this.CurrentCell = null; 

            // Rows need to be cleared first. There cannot be rows without also having columns. 
            this.Rows.ClearInternal(false /*recreateNewRow*/);

            // Reset sort related variables.
            this.sortedColumn = null; 
            this.sortOrder = SortOrder.None;
 
            // selectedBandIndexes, individualSelectedCells & individualReadOnlyCells cleared in OnClearingRows. 
        }
 
        [
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ]
        internal void OnClearingRows() 
        {
            // Build a list of displayed rows in order to be able to raise their RowStateChanged(Displayed->false) events later on 
            this.lstRows.Clear(); 
            int numDisplayedRows = this.displayedBandsInfo.NumDisplayedFrozenRows + this.displayedBandsInfo.NumDisplayedScrollingRows;
            if (numDisplayedRows > 0) 
            {
                this.lstRows.Capacity = numDisplayedRows;
                int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Displayed);
                while (numDisplayedRows > 0 && rowIndex != -1) 
                {
                    this.lstRows.Add(this.Rows[rowIndex]); 
                    numDisplayedRows--; 
                    if (numDisplayedRows > 0)
                    { 
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Displayed);
                    }
                }
            } 

            this.CurrentCell = null; 
 
            this.newRowIndex = -1;
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = this.selectedBandIndexes.Count > 0 || 
                                                                                this.individualSelectedCells.Count > 0;
            this.selectedBandIndexes.Clear();
            if (this.selectedBandSnapshotIndexes != null)
            { 
                this.selectedBandSnapshotIndexes.Clear();
            } 
            this.individualSelectedCells.Clear(); 
            this.individualReadOnlyCells.Clear();
        } 

        /// 
        protected virtual void OnColumnAdded(DataGridViewColumnEventArgs e)
        { 
            if (e.Column.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            }
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNADDED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnColumnCollectionChanged_PreNotification(CollectionChangeEventArgs ccea) 
        {
            // we need to map columns w/ DataPropertyName to bound columns 
            if (this.DataSource != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns])
            {
                if (ccea.Action == CollectionChangeAction.Add)
                { 
                    DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)ccea.Element;
                    if (dataGridViewColumn.DataPropertyName.Length != 0) 
                    { 
                        MapDataGridViewColumnToDataBoundField(dataGridViewColumn);
                    } 
                }
                else if (ccea.Action == CollectionChangeAction.Refresh)
                {
                    for (int i = 0; i < this.Columns.Count; i++) 
                    {
                        if (this.Columns[i].DataPropertyName.Length != 0) 
                        { 
                            MapDataGridViewColumnToDataBoundField(this.Columns[i]);
                        } 
                    }
                }
            }
 
            ResetUIState(false /*useRowShortcut*/, false /*computeVisibleRows*/);
        } 
 
        internal void OnColumnCollectionChanged_PostNotification(DataGridViewColumn dataGridViewColumn)
        { 
            if (this.Columns.Count != 0 && this.Rows.Count == 0)
            {
                if (this.DataSource != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns])
                { 
                    // this will create the 'add new row' when AllowUserToAddRowsInternal == true
                    RefreshRows(true /*scrollIntoView*/); 
                } 
                else if (this.AllowUserToAddRowsInternal)
                { 
                    AddNewRow(false);
                }
            }
            if (this.AutoSize && (dataGridViewColumn == null || dataGridViewColumn.Visible)) 
            {
                LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Columns); 
            } 
        }
 
        internal void OnColumnCommonChange(int columnIndex)
        {
            OnColumnGlobalAutoSize(columnIndex);
        } 

        ///  
        protected virtual void OnColumnContextMenuStripChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNCONTEXTMENUSTRIPCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        internal void OnColumnDataPropertyNameChanged(DataGridViewColumn dataGridViewColumn)
        {
            OnColumnDataPropertyNameChanged(new DataGridViewColumnEventArgs(dataGridViewColumn)); 
        }
 
        ///  
        protected virtual void OnColumnDataPropertyNameChanged(DataGridViewColumnEventArgs e)
        { 
            if (e.Column.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            } 
            // map the dataGridView column to some data field
            if (this.DataSource != null && e.Column.DataPropertyName.Length != 0 && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns]) 
            { 
                MapDataGridViewColumnToDataBoundField(e.Column);
            } 
            else if (this.DataSource != null && e.Column.DataPropertyName.Length == 0)
            {
                if (e.Column.IsDataBound)
                { 
                    e.Column.IsDataBoundInternal = false;
                    e.Column.BoundColumnIndex = -1; 
                    e.Column.BoundColumnConverter = null; 
                    InvalidateColumnInternal(e.Column.Index);
                } 
            }

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDATAPROPERTYNAMECHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnColumnDefaultCellStyleChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            OnColumnGlobalAutoSize(e.Column.Index);
 
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDEFAULTCELLSTYLECHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        internal void OnColumnDisplayIndexChanged(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn);
            OnColumnDisplayIndexChanged(dgvce);
        } 

        internal void OnColumnDisplayIndexChanging(DataGridViewColumn dataGridViewColumn, int newDisplayIndex) 
        { 
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(newDisplayIndex != dataGridViewColumn.DisplayIndex); 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments])
            {
                // We are within columns display indexes adjustments. We do not allow changing display indexes while adjusting them. 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterDisplayIndexWithinAdjustments));
            } 
 
            // Throws an exception if the requested move is illegal
            CorrectColumnFrozenStatesForMove(dataGridViewColumn, newDisplayIndex); 

            try
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = true; 

                // Move is legal - let's adjust the affected display indexes. 
                if (newDisplayIndex < dataGridViewColumn.DisplayIndex) 
                {
                    // DisplayIndex decreases. All columns with newDisplayIndex <= DisplayIndex < dataGridViewColumn.DisplayIndex 
                    // get their DisplayIndex incremented.
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (newDisplayIndex <= dataGridViewColumnTmp.DisplayIndex && dataGridViewColumnTmp.DisplayIndex < dataGridViewColumn.DisplayIndex) 
                        {
                            dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex + 1; 
                            dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on 
                        }
                    } 
                }
                else
                {
                    // DisplayIndex increases. All columns with dataGridViewColumn.DisplayIndex < DisplayIndex <= newDisplayIndex 
                    // get their DisplayIndex incremented.
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) 
                    { 
                        if (dataGridViewColumn.DisplayIndex < dataGridViewColumnTmp.DisplayIndex && dataGridViewColumnTmp.DisplayIndex <= newDisplayIndex)
                        { 
                            dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex - 1;
                            dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on
                        }
                    } 
                }
            } 
            finally 
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = false; 
            }

            // Note that displayIndex of moved column is updated by caller.
        } 

        ///  
        protected virtual void OnColumnDisplayIndexChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
 
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]);
#if DEBUG 
            Debug.Assert(this.Columns.VerifyColumnDisplayIndexes()); 
#endif
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDISPLAYINDEXCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnColumnDisplayIndexChanged_PreNotification() 
        {
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]); 

            // column.DisplayIndex changed - this may require a complete re-layout of the control
            this.Columns.InvalidateCachedColumnsOrder();
 
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            if (this.editingControl != null) 
            { 
                PositionEditingControl(true, true, false);
            } 
            Invalidate(Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data));
        }

        internal void OnColumnDisplayIndexChanged_PostNotification() 
        {
            // Notifications for adjusted display indexes. 
            FlushDisplayIndexChanged(true /*raiseEvent*/); 
        }
 
        /// 
        protected virtual void OnColumnDividerDoubleClick(DataGridViewColumnDividerDoubleClickEventArgs e)
        {
            DataGridViewColumnDividerDoubleClickEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDIVIDERDOUBLECLICK] as DataGridViewColumnDividerDoubleClickEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
 
            if (!e.Handled && e.Button == MouseButtons.Left && e.ColumnIndex < this.Columns.Count)
            {
                if (e.ColumnIndex == -1)
                { 
                    AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders,
                                              true /*fixedColumnHeadersHeight*/, 
                                              true /*fixedRowsHeight*/); 
                }
                else 
                {
                    DataGridViewAutoSizeColumnMode inheritedAutoSizeMode = this.Columns[e.ColumnIndex].InheritedAutoSizeMode;
                    if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                    { 
                        AutoResizeColumnInternal(e.ColumnIndex, DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows, true /*fixedHeight*/);
                    } 
                    else 
                    {
                        AutoResizeColumnInternal(e.ColumnIndex, (DataGridViewAutoSizeColumnCriteriaInternal)inheritedAutoSizeMode, true /*fixedHeight*/); 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnColumnDividerWidthChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
            OnColumnGlobalAutoSize(e.Column.Index); 

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDIVIDERWIDTHCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnColumnFillWeightChanged(DataGridViewColumn dataGridViewColumn) 
        {
            if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) 
            { 
                // UsedFillWeight properties need to be re-evaluated
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; 
                // Adjust filling columns based on new weight of this column
                PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            }
        } 

        internal void OnColumnFillWeightChanging(DataGridViewColumn dataGridViewColumn, float fillWeight) 
        { 
            if (this.InAdjustFillingColumns)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter));
            }

            // Make sure the sum of the column weights does not exceed ushort.MaxValue 
            float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) - dataGridViewColumn.FillWeight + fillWeight;
            if (weightSum > (float)ushort.MaxValue) 
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture)));
            } 
        }

        private void OnColumnGlobalAutoSize(int columnIndex)
        { 
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count);
 
            if (!this.Columns[columnIndex].Visible) 
            {
                return; 
            }

            InvalidateColumnInternal(columnIndex);
 
            if (this.noAutoSizeCount > 0)
            { 
                return; 
            }
 
            bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0;

            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode;
            if (autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None && 
                autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill)
            { 
                AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, fixedHeight); 
            }
 
            // Autosize rows and column headers if needed
            if (!fixedHeight)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            { 
                AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
            } 
            if (!fixedHeight &&
                autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None &&
                autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill)
            { 
                // Second round of column autosizing with 1 degree of freedom
                AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); 
            } 
        }
 
        /// 
        protected virtual void OnColumnHeaderCellChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 

            OnColumnHeaderGlobalAutoSize(e.Column.Index); 

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERCELLCHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        private void OnColumnHeaderGlobalAutoSize(int columnIndex) 
        {
            if (!this.ColumnHeadersVisible)
            {
                return; 
            }
 
            InvalidateCellPrivate(columnIndex, -1); 

            if (this.noAutoSizeCount > 0) 
            {
                return;
            }
 
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode;
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header; 
            bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0; 

            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, fixedColumnWidth);
            }
 
            if (!fixedColumnWidth)
            { 
                Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None); 
                Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill);
                bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; 
                AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, fixedHeight);
                if (!fixedHeight)
                {
                    AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                    // Second round of column autosizing with 1 degree of freedom
                    AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); 
                } 
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                { 
                    // Second round of column headers autosizing with 1 degree of freedom
                    AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
                }
            } 
        }
 
        ///  
        protected virtual void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
        { 
            if (e.Button == MouseButtons.Left &&
                this.SelectionMode != DataGridViewSelectionMode.FullColumnSelect &&
                this.SelectionMode != DataGridViewSelectionMode.ColumnHeaderSelect)
            { 
                DataGridViewColumn dataGridViewColumn = this.Columns[e.ColumnIndex];
 
                if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && (!this.VirtualMode || dataGridViewColumn.IsDataBound)) 
                {
                    ListSortDirection direction = ListSortDirection.Ascending; 

                    if (this.sortedColumn == dataGridViewColumn)
                    {
                        Debug.Assert(this.sortOrder != SortOrder.None); 
                        if (this.sortOrder == SortOrder.Ascending)
                        { 
                            direction = ListSortDirection.Descending; 
                        }
                    } 

                    if ((this.DataSource == null) ||
                        (this.DataSource != null &&
                         (this.dataConnection.List is IBindingList) && 
                         ((IBindingList) this.dataConnection.List).SupportsSorting &&
                         dataGridViewColumn.IsDataBound)) 
                    { 
                        Sort(dataGridViewColumn, direction);
                    } 
                }
            }

            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERMOUSECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnColumnHeaderMouseDoubleClick(DataGridViewCellMouseEventArgs e)
        { 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        private void OnColumnHeaderMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown)
        { 
            Debug.Assert(hti.Type == DataGridViewHitTestType.ColumnHeader);
            this.noSelectionChangeCount++; 
            try 
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.FullRowSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        break;
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                    { 
                        bool select = true;
                        if (isControlDown && this.Columns[hti.col].Selected)
                        {
                            select = false; 
                        }
                        if (select) 
                        { 
                            int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                            if (rowIndex > -1 && hti.col != this.ptCurrentCell.X) 
                            {
                                // Make sure we will be able to scroll into view
                                int oldCurrentCellX = this.ptCurrentCell.X;
                                int oldCurrentCellY = this.ptCurrentCell.Y; 
                                if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange,
                                            DataGridViewValidateCellInternal.Always /*validateCell*/, 
                                            true /*fireCellLeave*/, 
                                            true /*fireCellEnter*/,
                                            rowIndex != this.ptCurrentCell.Y /*fireRowLeave*/, 
                                            rowIndex != this.ptCurrentCell.Y /*fireRowEnter*/,
                                            false /*fireLeave*/,
                                            this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/,
                                            true /*resetCurrentCell*/, 
                                            false /*resetAnchorCell*/))
                                { 
                                    // Just cancel operation silently instead of throwing InvalidOperationException 
                                    return;
                                } 
                                if (rowIndex != oldCurrentCellY && oldCurrentCellY != -1)
                                {
                                    DataGridViewCell dataGridViewCellTmp = null;
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        return; 
                                    } 
                                    if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY))
                                    { 
                                        // Row validation was cancelled
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                        {
                                            return; 
                                        }
                                        OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); 
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                        {
                                            return; 
                                        }
                                        OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);
                                        return;
                                    } 
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                    { 
                                        return; 
                                    }
                                    OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                }
                            }
                            if (IsColumnOutOfBounds(hti.col))
                            { 
                                return;
                            } 
 
                            bool selectColumnRange = false;
                            this.trackColumn = hti.col; 
                            this.trackColumnEdge = -1;
                            if (this.MultiSelect &&
                                isShiftDown &&
                                this.ptAnchorCell.X > -1 && 
                                this.Columns[this.ptAnchorCell.X].Selected)
                            { 
                                selectColumnRange = true; 
                            }
                            if (!this.MultiSelect || !isControlDown || isShiftDown) 
                            {
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1);
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                                { 
                                    this.inBulkPaintCount++; 
                                    switchedToBulkPaint = true;
                                } 
                                try
                                {
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.col)
                                        { 
                                            // deselect currently selected column 
                                            SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false);
                                        } 
                                        else
                                        {
                                            bandIndex++;
                                        } 
                                    }
                                    if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) 
                                    { 
                                        RemoveIndividuallySelectedCells();
                                    } 
                                    else
                                    {
                                        Debug.Assert(this.individualSelectedCells.Count == 0);
                                    } 
                                }
                                finally 
                                { 
                                    if (switchedToBulkPaint)
                                    { 
                                        ExitBulkPaint(-1, -1);
                                    }
                                }
                            } 
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                            { 
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = true; 
                            }
                            if (selectColumnRange) 
                            {
                                if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, hti.col))
                                {
                                    SelectColumnRange(this.ptAnchorCell.X, hti.col, true); 
                                }
                                else 
                                { 
                                    SelectColumnRange(hti.col, this.ptAnchorCell.X, true);
                                } 
                            }
                            else if (!this.selectedBandIndexes.Contains(hti.col))
                            {
                                SetSelectedColumnCore(hti.col, true); 
                            }
                            // set current cell to the top most visible cell in the column 
                            if (rowIndex != -1) 
                            {
                                if (hti.col != this.ptCurrentCell.X) 
                                {
                                    if (IsInnerCellOutOfBounds(hti.col, rowIndex))
                                    {
                                        return; 
                                    }
                                    bool success = ScrollIntoView(hti.col, rowIndex, false); 
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(hti.col, rowIndex))
                                    { 
                                        return;
                                    }
                                    success = SetCurrentCellAddressCore(hti.col, rowIndex, !isShiftDown, false, true);
                                    Debug.Assert(success); 
                                }
                                else if (-1 != this.ptCurrentCell.X) 
                                { 
                                    // Potentially have to give focus back to the current edited cell.
                                    bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); 
                                    Debug.Assert(success);
                                }
                            }
                            else 
                            {
                                Debug.Assert(this.CurrentCellAddress == new Point(-1, -1)); 
                            } 
                        }
                        else 
                        {
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.col));
                            SetSelectedColumnCore(hti.col, false);
                        } 
                        break;
                    } 
                } 
            }
            finally 
            {
                this.NoSelectionChangeCount--;
            }
        } 

        ///  
        protected virtual void OnColumnHeadersBorderStyleChanged(EventArgs e) 
        {
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
            Invalidate();

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSBORDERSTYLECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnColumnHeadersDefaultCellStyleChanged(EventArgs e)
        {
            if (this.ColumnHeadersVisible) 
            {
                Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders)); 
 
                DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
                if (dgvcsce == null || dgvcsce.ChangeAffectsPreferredSize) 
                {
                    OnColumnHeadersGlobalAutoSize();
                    if (this.editingControl != null)
                    { 
                        PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                    } 
                } 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSDEFAULTCELLSTYLECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        private void OnColumnHeadersGlobalAutoSize()
        { 
            if (this.noAutoSizeCount > 0)
            {
                return;
            } 

            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || 
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize;
 
            if (!fixedColumnHeadersHeight)
            {
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, false /*fixedColumnsWidth*/);
            } 

            if (!fixedRowHeadersWidth) 
            { 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, false /*fixedRowsHeight*/);
            } 

            // Autosize columns
            bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header, false /*fixedHeight*/);
 
            if (!fixedRowHeadersWidth || columnAutoSized)
            { 
                // Autosize rows 
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
            } 

            if (!fixedColumnHeadersHeight)
            {
                // Second round of column headers autosizing 
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            } 
 
            if (!fixedRowHeadersWidth)
            { 
                // Second round of row headers autosizing
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            }
 
            // Second round of columns autosizing
            AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header, true /*fixedHeight*/); 
        } 

        ///  
        protected virtual void OnColumnHeadersHeightChanged(EventArgs e)
        {
            if (this.editingControl != null)
            { 
                PositionEditingControl(true, false, false);
            } 
 
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
 
            OnColumnHeadersGlobalAutoSize();

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSHEIGHTCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnColumnHeadersHeightSizeModeChanged(DataGridViewAutoSizeModeEventArgs e)
        {
            if (this.columnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                if (!e.PreviousModeAutoSized) 
                { 
                    // Save current column headers height for later reuse
                    this.cachedColumnHeadersHeight = this.ColumnHeadersHeight; 
                }
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            }
            else if (e.PreviousModeAutoSized) 
            {
                this.ColumnHeadersHeight = this.cachedColumnHeadersHeight; 
            } 

            DataGridViewAutoSizeModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSHEIGHTSIZEMODECHANGED] as DataGridViewAutoSizeModeEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnColumnHidden(DataGridViewColumn dataGridViewColumn) 
        {
            Debug.Assert(dataGridViewColumn != null); 
            if (dataGridViewColumn.Displayed)
            {
                dataGridViewColumn.DisplayedInternal = false;
                DataGridViewColumnStateChangedEventArgs dgvrsce = new DataGridViewColumnStateChangedEventArgs(dataGridViewColumn, DataGridViewElementStates.Displayed); 
                OnColumnStateChanged(dgvrsce);
            } 
        } 

        internal void OnColumnMinimumWidthChanging(DataGridViewColumn dataGridViewColumn, int minimumWidth) 
        {
            if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && dataGridViewColumn.Width < minimumWidth)
            {
                // Force the filled column's width to be minimumWidth 
                try
                { 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; 
                    dataGridViewColumn.DesiredMinimumWidth = minimumWidth;
                    PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
                }
                finally
                {
                    dataGridViewColumn.DesiredMinimumWidth = 0; 
                }
                Debug.Assert(dataGridViewColumn.Width == minimumWidth); 
            } 
        }
 
        /// 
        protected virtual void OnColumnMinimumWidthChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            if (e.Column.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
            { 
                // Column's width may adjust smaller
                PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            }
 
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNMINIMUMWIDTHCHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        internal void OnColumnNameChanged(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
            OnColumnNameChanged(dgvce); 
        }
 
        /// 
        protected virtual void OnColumnNameChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            // Check if the column name is used as is in the column header
            DataGridViewColumn dataGridViewColumn = e.Column; 

            if (dataGridViewColumn.HasHeaderCell && dataGridViewColumn.HeaderCell.Value is string &&
                String.Compare((string)dataGridViewColumn.HeaderCell.Value, dataGridViewColumn.Name, false, CultureInfo.InvariantCulture) == 0)
            { 
                InvalidateCellPrivate(dataGridViewColumn.Index, -1);
 
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode; 
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header;
                bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0 || !this.ColumnHeadersVisible; 
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                {
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth);
                } 
                if (!fixedColumnWidth)
                { 
                    bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; 
                    AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, fixedHeight);
                    if (!fixedHeight) 
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                        // Second round of column autosizing
                        AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); 
                    }
                    if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                    { 
                        // Second round of column headers autosizing
                        AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                    }
                }
            }
 
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNNAMECHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        internal void OnColumnRemoved(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(dataGridViewColumn.DataGridView == null); 
            OnColumnRemoved(new DataGridViewColumnEventArgs(dataGridViewColumn)); 
        }
 
        /// 
        protected virtual void OnColumnRemoved(DataGridViewColumnEventArgs e)
        {
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNREMOVED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        private void OnColumnSelectMouseMove(HitTestInfo hti)
        {
            Debug.Assert(hti.col >= 0); 
            Debug.Assert(this.MultiSelect);
 
            if (this.ptCurrentCell.X != -1 && 
                hti.col != this.ptCurrentCell.X &&
                !CommitEditForOperation(hti.col, this.ptCurrentCell.Y, true)) 
            {
                // Return silently if validating/commit/abort failed
                return;
            } 
            if (IsColumnOutOfBounds(hti.col))
            { 
                return; 
            }
 
            this.noSelectionChangeCount++;
            try
            {
                if (this.trackColumnEdge >= 0 && (this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) || this.trackColumnEdge == this.trackColumn) && this.Columns.DisplayInOrder(this.trackColumnEdge, hti.col)) 
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(dataGridViewColumn.Index, hti.col, true);
                    this.trackColumnEdge = hti.col; 
                }
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) && this.Columns.DisplayInOrder(hti.col, this.trackColumnEdge) && (this.Columns.DisplayInOrder(this.trackColumn, hti.col) || hti.col == this.trackColumn))
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(dataGridViewColumn.Index, this.trackColumnEdge, false); 
                    this.trackColumnEdge = hti.col; 
                }
                else if (this.trackColumnEdge == -1 && this.Columns.DisplayInOrder(this.trackColumn, hti.col)) 
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(dataGridViewColumn.Index, hti.col, true); 
                    this.trackColumnEdge = hti.col;
                } 
                else if (this.trackColumnEdge >= 0 && (this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn) || this.trackColumnEdge == this.trackColumn) && this.Columns.DisplayInOrder(hti.col, this.trackColumnEdge)) 
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(hti.col, dataGridViewColumn.Index, true);
                    this.trackColumnEdge = hti.col;
                } 
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn) && this.Columns.DisplayInOrder(this.trackColumnEdge, hti.col) && (this.Columns.DisplayInOrder(hti.col, this.trackColumn) || hti.col == this.trackColumn))
                { 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(this.trackColumnEdge, dataGridViewColumn.Index, false); 
                    this.trackColumnEdge = hti.col;
                }
                else if (this.trackColumnEdge == -1 && this.Columns.DisplayInOrder(hti.col, this.trackColumn))
                { 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(hti.col, dataGridViewColumn.Index, true); 
                    this.trackColumnEdge = hti.col;
                } 
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) && this.Columns.DisplayInOrder(hti.col, this.trackColumn))
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(dataGridViewColumn.Index, this.trackColumnEdge, false);
                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(hti.col, dataGridViewColumn.Index, true);
                    this.trackColumnEdge = hti.col; 
                }
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, hti.col) && this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn))
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(this.trackColumnEdge, dataGridViewColumn.Index, false); 
                    dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(dataGridViewColumn.Index, hti.col, true); 
                    this.trackColumnEdge = hti.col;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 

            if (this.ptCurrentCell.X != -1 && hti.col != this.ptCurrentCell.X) 
            {
                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(hti.col))
                {
                    return; 
                }
                bool success = SetCurrentCellAddressCore(hti.col, 
                    this.ptCurrentCell.Y, 
                    false /*setAnchorCellAddress*/,
                    false /*validateCurrentCell*/, 
                    false /*throughMouseClick*/);
                Debug.Assert(success);
            }
        } 

        private void OnColumnsGlobalAutoSize() 
        { 
            InvalidateData();
 
            if (this.noAutoSizeCount > 0)
            {
                return;
            } 

            // Auto-size columms if needed 
            bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; 
            bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, fixedHeight);
            // Autosize rows if needed 
            if (!fixedHeight)
            {
                if (columnAutoSized)
                { 
                    AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                } 
                // Second round of columns autosizing 
                AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/);
            } 
        }

        internal void OnColumnSortModeChanged(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
            OnColumnSortModeChanged(dgvce); 
        }
 
        /// 
        protected virtual void OnColumnSortModeChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            DataGridViewColumn dataGridViewColumn = e.Column;
 
            if (dataGridViewColumn.HasHeaderCell)
            {
                if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.NotSortable ||
                    (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Programmatic && this.SortedColumn == dataGridViewColumn)) 
                {
                    dataGridViewColumn.HeaderCell.SortGlyphDirection = SortOrder.None; 
                    // This call will trigger OnSortGlyphDirectionChanged which in turn does 
                    // this.sortedColumn = null; and InvalidateCellPrivate(e.Column.Index, -1);
                } 
                // Potential resizing of the column headers and/or affected column.
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode;
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header;
                bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0 || !this.ColumnHeadersVisible; 
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                { 
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth); 
                }
                if (!fixedColumnWidth) 
                {
                    bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0;
                    AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, fixedHeight);
                    if (!fixedHeight) 
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                        // Second round of column autosizing 
                        AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, true /*fixedHeight*/);
                    } 
                    if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                    {
                        // Second round of column headers autosizing
                        AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                    }
                } 
            } 

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNSORTMODECHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        protected virtual void OnColumnStateChanged(DataGridViewColumnStateChangedEventArgs e)
        { 
            // column.Frozen | .Visible changed - this may require a complete re-layout of the control
            DataGridViewColumn dataGridViewColumn = e.Column;
            switch (e.StateChanged)
            { 
                // At this point we assume that only the Selected state has an influence on the rendering of the column.
                // If there is a customer scenario where another state has an influence, the dev must invalidate the column by hand. 
                // case DataGridViewElementStates.ReadOnly: 
                // case DataGridViewElementStates.Resizable:
 
                case DataGridViewElementStates.Selected:
                    if (dataGridViewColumn.Visible && this.inBulkPaintCount == 0)
                    {
                        InvalidateColumnInternal(dataGridViewColumn.Index); 
                    }
                    break; 
 
                case DataGridViewElementStates.Frozen:
                    if (dataGridViewColumn.Visible) 
                    {
                        if (dataGridViewColumn.Frozen)
                        {
                            // visible column became frozen 
                            if (this.horizontalOffset >= dataGridViewColumn.Thickness)
                            { 
                                Debug.Assert(this.Columns.DisplayInOrder(dataGridViewColumn.Index, this.displayedBandsInfo.FirstDisplayedScrollingCol)); 
                                this.horizontalOffset -= dataGridViewColumn.Thickness;
                            } 
                            else
                            {
                                this.horizontalOffset = this.negOffset = 0;
                            } 
                        }
                        else 
                        { 
                            // column was unfrozen - make it the first visible scrolling column if there is room
                            this.horizontalOffset = this.negOffset = 0; 
                        }
                        if (this.horizScrollBar.Enabled)
                        {
                            this.horizScrollBar.Value = this.horizontalOffset; 
                        }
 
                        // UsedFillWeight values need to be updated 
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
 
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/);
                        Invalidate();
                    }
                    break; 

                case DataGridViewElementStates.Visible: 
                    if (!dataGridViewColumn.Visible && dataGridViewColumn.Displayed) 
                    {
                        // Displayed column becomes invisible. Turns off the Displayed state. 
                        dataGridViewColumn.DisplayedInternal = false;
                    }

                    // UsedFillWeight values need to be updated 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
 
                    PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); 

                    bool autoSizeRows = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0 || 
                                        ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0 &&
                                        this.RowHeadersVisible);
                    bool autoSizeColumn = false;
                    DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; 
                    Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet);
                    if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && 
                        autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                    {
                        // Column autosizes 
                        int width = dataGridViewColumn.ThicknessInternal;
                        if (dataGridViewColumn.Visible)
                        {
                            // Cache column's width before potential autosizing occurs 
                            dataGridViewColumn.CachedThickness = width;
                            AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, !autoSizeRows /*fixedHeight*/); 
                            autoSizeColumn = true; 
                        }
                        else if (width != dataGridViewColumn.CachedThickness) 
                        {
                            // Columns that are made invisible in the collection take their non-autosized width
                            dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness);
                        } 
                    }
 
                    if (autoSizeRows) 
                    {
                        if (dataGridViewColumn.Visible) 
                        {
                            AdjustExpandingRows(dataGridViewColumn.Index, true /*fixedWidth*/);
                        }
                        else 
                        {
                            AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                        } 
                        if (autoSizeColumn)
                        { 
                            // Second round of column autosizing
                            AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/);
                        }
                    } 
                    else
                    { 
                        Invalidate(); 
                    }
                    break; 
            }

            DataGridViewColumnStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNSTATECHANGED] as DataGridViewColumnStateChangedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 

            if (e.StateChanged == DataGridViewElementStates.ReadOnly && 
                dataGridViewColumn.Index == this.ptCurrentCell.X &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange])
            {
                VerifyImeRestrictedModeChanged(); 

                if (!dataGridViewColumn.ReadOnly && 
                    ColumnEditable(this.ptCurrentCell.X) && 
                    (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.ReadOnly) == 0 &&
                     !this.IsCurrentCellInEditMode && 
                     (this.EditMode == DataGridViewEditMode.EditOnEnter ||
                      (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)))
                {
                    // Current column becomes read/write. Enter editing mode. 
                    BeginEditInternal(true /*selectAll*/);
                } 
            } 
        }
 
        internal void OnColumnToolTipTextChanged(DataGridViewColumn dataGridViewColumn)
        {
            OnColumnToolTipTextChanged(new DataGridViewColumnEventArgs(dataGridViewColumn));
        } 

        ///  
        protected virtual void OnColumnToolTipTextChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNTOOLTIPTEXTCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
        { 
            if (e.Column.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            }
            this.Columns.InvalidateCachedColumnsWidths(); 

            // don't do any layout logic if the handle was not created already
            if (e.Column.Visible && this.IsHandleCreated)
            { 
                PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
 
                Rectangle rightArea = this.layout.Data; 
                if (this.layout.ColumnHeadersVisible)
                { 
                    rightArea = Rectangle.Union(rightArea, this.layout.ColumnHeaders);
                }
                else if (this.SingleHorizontalBorderAdded)
                { 
                    rightArea.Y--;
                    rightArea.Height++; 
                } 
                if (rightArea.Width > 0 && rightArea.Height > 0)
                { 
                    int leftEdge = GetColumnXFromIndex(e.Column.Index);
                    if (this.RightToLeftInternal)
                    {
                        rightArea.Width -= rightArea.Right - leftEdge; 
                    }
                    else 
                    { 
                        rightArea.Width -= leftEdge - rightArea.X;
                        rightArea.X = leftEdge; 
                    }
                    if (rightArea.Width > 0 && rightArea.Height > 0)
                    {
                        Invalidate(rightArea); 
                    }
                } 
 
                if (this.editingControl != null)
                { 
                    PositionEditingControl(this.ptCurrentCell.X != e.Column.Index, true, false);
                }

                UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 

                if (this.AutoSize) 
                { 
                    LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Columns);
                } 
            }

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNWIDTHCHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 

            if (!this.InAdjustFillingColumns) 
            {
                // Autosize rows and column headers if needed
                OnColumnGlobalAutoSize(e.Column.Index);
            } 
        }
 
        internal void OnCommonCellContentClick(int columnIndex, int rowIndex, bool doubleClick) 
        {
            if (this.ptMouseDownCell.X == -2 || 
                (this.dataGridViewState2[DATAGRIDVIEWSTATE2_cellMouseDownInContentBounds] &&
                 this.ptMouseDownCell.X == columnIndex && this.ptMouseDownCell.Y == rowIndex &&
                 (this.ptMouseDownCell.X == -1 || this.ptMouseDownCell.Y == -1 ||
                  (columnIndex == this.ptCurrentCell.X && rowIndex == this.ptCurrentCell.Y)))) 
            {
                DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); 
                if (doubleClick) 
                {
                    OnCellContentDoubleClick(dgvce); 
                }
                else
                {
                    OnCellContentClick(dgvce); 
                }
            } 
        } 

        ///  
        protected virtual void OnCurrentCellChanged(EventArgs e)
        {
            VerifyImeRestrictedModeChanged();
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCURRENTCELLCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnCurrentCellDirtyStateChanged(EventArgs e)
        { 
            if (this.RowHeadersVisible && this.ShowEditingIcon)
            { 
                // Force the pencil to appear in the row header 
                Debug.Assert(this.ptCurrentCell.Y >= 0);
                InvalidateCellPrivate(-1, this.ptCurrentCell.Y); 
            }
            if (this.IsCurrentCellDirty && this.newRowIndex == this.ptCurrentCell.Y)
            {
                Debug.Assert(this.newRowIndex != -1); 
                Debug.Assert(this.AllowUserToAddRowsInternal);
                // First time the 'new' row gets edited. 
                // It becomes a regular row and a new 'new' row is appened. 
                this.newRowIndex = -1;
                AddNewRow(true /*createdByEditing*/); 
            }

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCURRENTCELLDIRTYSTATECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected override void OnCursorChanged(EventArgs e)
        {
            base.OnCursorChanged(e); 
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_ignoreCursorChange])
            { 
                this.oldCursor = this.Cursor; 
            }
        } 

        internal void OnDataBindingComplete(ListChangedType listChangedType)
        {
            OnDataBindingComplete(new DataGridViewBindingCompleteEventArgs(listChangedType)); 
        }
 
        ///  
        protected virtual void OnDataBindingComplete(DataGridViewBindingCompleteEventArgs e)
        { 
            DataGridViewBindingCompleteEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATABINDINGCOMPLETE] as DataGridViewBindingCompleteEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        [ 
            SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions") // Not using options when RightToLeft == false
        ]
        protected virtual void OnDataError(bool displayErrorDialogIfNoHandler, DataGridViewDataErrorEventArgs e)
        { 
            DataGridViewDataErrorEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATAERROR] as DataGridViewDataErrorEventHandler;
            if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                if (eh == null)
                { 
                    if (displayErrorDialogIfNoHandler)
                    {
                        string errorText;
                        if (e.Exception == null) 
                        {
                            errorText = SR.GetString(SR.DataGridView_ErrorMessageText_NoException); 
                        } 
                        else
                        { 
                            errorText = SR.GetString(SR.DataGridView_ErrorMessageText_WithException, e.Exception);
                        }
                        if (this.RightToLeftInternal)
                        { 
                            MessageBox.Show(errorText, SR.GetString(SR.DataGridView_ErrorMessageCaption), MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading);
                        } 
                        else 
                        {
                            MessageBox.Show(errorText, SR.GetString(SR.DataGridView_ErrorMessageCaption), MessageBoxButtons.OK, MessageBoxIcon.Error); 
                        }
                        CorrectFocus(true /*onlyIfGridHasFocus*/);
                    }
                } 
                else
                { 
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            }
        }

        internal void OnDataErrorInternal(DataGridViewDataErrorEventArgs e) 
        {
            OnDataError(!this.DesignMode /*displayErrorDialogIfNoHandler*/, e); 
        } 

        internal void OnDataGridViewElementStateChanged(DataGridViewElement element, int index, DataGridViewElementStates elementState) 
        {
            DataGridViewColumn dataGridViewColumn = element as DataGridViewColumn;
            if (dataGridViewColumn != null)
            { 
                DataGridViewColumnStateChangedEventArgs dgvcsce = new DataGridViewColumnStateChangedEventArgs(dataGridViewColumn, elementState);
 
                OnColumnStateChanged(dgvcsce); 
            }
            else 
            {
                DataGridViewRow dataGridViewRow = element as DataGridViewRow;
                if (dataGridViewRow != null)
                { 
                    DataGridViewRowStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSTATECHANGED] as DataGridViewRowStateChangedEventHandler;
 
                    if (eh != null && dataGridViewRow.DataGridView != null && dataGridViewRow.Index == -1) 
                    {
                        dataGridViewRow = this.Rows[index]; 
                    }

                    DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, elementState);
 
                    OnRowStateChanged(dataGridViewRow.Index == -1 ? index : dataGridViewRow.Index, dgvrsce);
                } 
                else 
                {
                    DataGridViewCell dataGridViewCell = element as DataGridViewCell; 
                    if (dataGridViewCell != null)
                    {
                        DataGridViewCellStateChangedEventArgs dgvcsce = new DataGridViewCellStateChangedEventArgs(dataGridViewCell, elementState);
 
                        OnCellStateChanged(dgvcsce);
                    } 
                } 
            }
 
            if ((elementState & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected)
            {
                if (this.noSelectionChangeCount > 0)
                { 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = true;
                } 
                else 
                {
                    OnSelectionChanged(EventArgs.Empty); 
                }
            }
        }
 
        internal void OnDataGridViewElementStateChanging(DataGridViewElement element, int index, DataGridViewElementStates elementState)
        { 
            DataGridViewColumn dataGridViewColumn = element as DataGridViewColumn; 
            if (dataGridViewColumn != null)
            { 
                // column.Frozen | .Visible | .ReadOnly changing
                switch (elementState)
                {
                    case DataGridViewElementStates.Frozen: 
                    case DataGridViewElementStates.Visible:
                        if (elementState == DataGridViewElementStates.Visible) 
                        { 
                            if (!dataGridViewColumn.Visible &&
                                dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader && 
                                !this.ColumnHeadersVisible)
                            {
                                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMakeAutoSizedColumnVisible));
                            } 
                            else if (!dataGridViewColumn.Visible &&
                                dataGridViewColumn.Frozen && 
                                dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) 
                            {
                                // alternative: throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMakeAutoFillColumnVisible)); 
                                //              DataGridView_CannotMakeAutoFillColumnVisible=The column cannot be made visible because its autosizing mode is Fill and it is frozen.
                                // Removing the Fill auto size mode when frozen column becomes visible (instead of throwing an exception)
                                dataGridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                            } 
                            else if (dataGridViewColumn.Visible && this.ptCurrentCell.X == dataGridViewColumn.Index)
                            { 
                                // Column of the current cell is made invisible. Trying to reset the current cell. May throw an exception. 
                                ResetCurrentCell();
                                // [....]: Should the current cell be set to some cell after the operation? 
                            }
                        }
                        if (elementState == DataGridViewElementStates.Frozen &&
                            !dataGridViewColumn.Frozen && 
                            dataGridViewColumn.Visible &&
                            dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) 
                        { 
                            // Removing the Fill auto size mode when visible column becomes frozen (instead of throwing an exception)
                            dataGridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; 
                        }
                        CorrectColumnFrozenStates(dataGridViewColumn, elementState == DataGridViewElementStates.Frozen);
                        break;
 
                    case DataGridViewElementStates.ReadOnly:
                        if (this.ptCurrentCell.X == dataGridViewColumn.Index && 
                            this.IsCurrentCellInEditMode && 
                            !dataGridViewColumn.ReadOnly &&
                            !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
                        {
                            Debug.Assert(!this.ReadOnly);
                            // Column becomes read-only. Exit editing mode.
                            if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, 
                                        DataGridViewValidateCellInternal.Always /*validateCell*/,
                                        false /*fireCellLeave*/, 
                                        false /*fireCellEnter*/, 
                                        false /*fireRowLeave*/,
                                        false /*fireRowEnter*/, 
                                        false /*fireLeave*/,
                                        true /*keepFocus*/,
                                        false /*resetCurrentCell*/,
                                        false /*resetAnchorCell*/)) 
                            {
                                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation)); 
                            } 
                        }
                        break; 

                    default:
                        Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging");
                        break; 
                }
            } 
            else 
            {
                DataGridViewRow dataGridViewRow = element as DataGridViewRow; 
                if (dataGridViewRow != null)
                {
                    // row.Frozen | .Visible | .ReadOnly changing
                    int rowIndex = ((dataGridViewRow.Index > -1) ? dataGridViewRow.Index : index); 
                    switch (elementState)
                    { 
                        case DataGridViewElementStates.Frozen: 
                        case DataGridViewElementStates.Visible:
                            if (elementState == DataGridViewElementStates.Visible && this.ptCurrentCell.Y == rowIndex) 
                            {
                                Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0);
                                // Row of the current cell is made invisible.
                                if (this.DataSource != null) 
                                {
                                    Debug.Assert(this.dataConnection != null); 
                                    Debug.Assert(this.dataConnection.CurrencyManager != null); 
                                    Debug.Assert(this.dataConnection.CurrencyManager.Position == this.ptCurrentCell.Y);
                                    // the row associated with the currency manager's position cannot be made invisble. 
                                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CurrencyManagerRowCannotBeInvisible));
                                }
                                // Trying to reset the current cell. May throw an exception.
                                ResetCurrentCell(); 
                                // [....]: Should the current cell be set to some cell after the operation?
                            } 
                            CorrectRowFrozenStates(dataGridViewRow, rowIndex, elementState == DataGridViewElementStates.Frozen); 
                            break;
 
                        case DataGridViewElementStates.ReadOnly:
                            if (this.ptCurrentCell.Y == rowIndex &&
                                (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.ReadOnly) == 0 &&
                                !this.ReadOnly && 
                                this.IsCurrentCellInEditMode &&
                                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
                            { 
                                // Row becomes read-only. Exit editing mode.
                                if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, 
                                            DataGridViewValidateCellInternal.Always /*validateCell*/,
                                            false /*fireCellLeave*/,
                                            false /*fireCellEnter*/,
                                            false /*fireRowLeave*/, 
                                            false /*fireRowEnter*/,
                                            false /*fireLeave*/, 
                                            true /*keepFocus*/, 
                                            false /*resetCurrentCell*/,
                                            false /*resetAnchorCell*/)) 
                                {
                                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation));
                                }
                            } 
                            break;
 
                        default: 
                            Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging");
                            break; 
                    }
                }
                else
                { 
                    DataGridViewCell dataGridViewCell = element as DataGridViewCell;
                    if (dataGridViewCell != null) 
                    { 
                        // cell.ReadOnly changing
                        switch (elementState) 
                        {
                            case DataGridViewElementStates.ReadOnly:
                                if (this.ptCurrentCell.X == dataGridViewCell.ColumnIndex &&
                                    this.ptCurrentCell.Y == dataGridViewCell.RowIndex && 
                                    this.IsCurrentCellInEditMode &&
                                    !dataGridViewCell.ReadOnly && 
                                    !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
                                {
                                    Debug.Assert(!this.Columns[dataGridViewCell.ColumnIndex].ReadOnly); 
                                    Debug.Assert(!this.Rows[dataGridViewCell.RowIndex].ReadOnly);
                                    Debug.Assert(!this.ReadOnly);
                                    // Current cell becomes read-only. Exit editing mode.
                                    if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, 
                                                DataGridViewValidateCellInternal.Always /*validateCell*/,
                                                false /*fireCellLeave*/, 
                                                false /*fireCellEnter*/, 
                                                false /*fireRowLeave*/,
                                                false /*fireRowEnter*/, 
                                                false /*fireLeave*/,
                                                true /*keepFocus*/,
                                                false /*resetCurrentCell*/,
                                                false /*resetAnchorCell*/)) 
                                    {
                                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation)); 
                                    } 
                                }
                                break; 

                            default:
                                Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging");
                                break; 
                        }
                    } 
                    else 
                    {
                        Debug.Fail("Unexpected DataGridViewElement type in DataGridView.OnDataGridViewElementStateChanging"); 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnDataMemberChanged(EventArgs e) 
        {
            RefreshColumnsAndRows(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATAMEMBERCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
 
            if (this.dataConnection != null && this.dataConnection.CurrencyManager != null)
            { 
                OnDataBindingComplete(ListChangedType.Reset);
            }
        }
 
        /// 
        protected virtual void OnDataSourceChanged(EventArgs e) 
        { 
            RefreshColumnsAndRows();
            InvalidateRowHeights(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATASOURCECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
 
            if (this.dataConnection != null && this.dataConnection.CurrencyManager != null)
            { 
                OnDataBindingComplete(ListChangedType.Reset);
            }
        }
 
        /// 
        protected virtual void OnDefaultCellStyleChanged(EventArgs e) 
        { 
            DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
            if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize) 
            {
                Invalidate();
            }
            else 
            {
                OnGlobalAutoSize(); 
                if (this.editingControl != null) 
                {
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); 
                }
            }

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnDefaultValuesNeeded(DataGridViewRowEventArgs e)
        { 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDEFAULTVALUESNEEDED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected override void OnDoubleClick(EventArgs e) 
        {
            base.OnDoubleClick(e); 
 
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                MouseEventArgs me = e as MouseEventArgs;
                if (me != null)
                {
                    HitTestInfo hti = HitTest(me.X, me.Y); 
                    if (hti.Type != DataGridViewHitTestType.None &&
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar && 
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar && 
                        me.Button == MouseButtons.Left)
                    { 
                        OnCellDoubleClick(new DataGridViewCellEventArgs(hti.col, hti.row));
                    }
                }
            } 
        }
 
        ///  
        protected virtual void OnEditingControlShowing(DataGridViewEditingControlShowingEventArgs e)
        { 
            DataGridViewEditingControlShowingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWEDITINGCONTROLSHOWING] as DataGridViewEditingControlShowingEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnEditModeChanged(EventArgs e) 
        {
            if (this.Focused &&
                this.EditMode == DataGridViewEditMode.EditOnEnter &&
                this.ptCurrentCell.X > -1 && 
                !this.IsCurrentCellInEditMode)
            { 
                // New edit mode is EditOnEnter and there is an editable current cell, try to go to edit mode. 
                BeginEditInternal(true /*selectAll*/);
            } 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWEDITMODECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        ///  
        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);
            if (GetAnyDisposingInHierarchy()) 
            {
                return; 
            } 

            if (this.IsHandleCreated && this.Enabled) 
            {
                if (this.vertScrollBar != null && this.vertScrollBar.Visible)
                {
                    this.vertScrollBar.Enabled = true; 
                }
                if (this.horizScrollBar != null && this.horizScrollBar.Visible) 
                { 
                    this.horizScrollBar.Enabled = true;
                } 
            }
        }

        ///  
        protected override void OnEnter(EventArgs e)
        { 
            if (this.editingControl != null && this.editingControl.ContainsFocus) 
            {
                return; 
            }

            base.OnEnter(e);
 
            // vsw 453314: there are cases when a control is on the designer and it still receives the OnEnter event.
            // Guard against this. 
            if (this.DesignMode) 
            {
                return; 
            }

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey] = false;
 
            if (this.ptCurrentCell.X > -1)
            { 
                DataGridViewCell dataGridViewCell = null; 
                // We're re-entering a row we already entered earlier. The first time we entered the row,
                // the DataGridView didn't have focus. This time it does. We don't want to recreate the new row a second time. 
                OnRowEnter(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*canCreateNewRow*/, false /*validationFailureOccurred*/);
                if (this.ptCurrentCell.X == -1)
                {
                    return; 
                }
                OnCellEnter(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); 
            } 
            else if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown])
            { 
                // Focus is given to the DataGridView control via a the TAB key.
                MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/);
            }
 
            if (this.ptCurrentCell.X > -1 &&
                !this.IsCurrentCellInEditMode) 
            { 
                if (this.EditMode == DataGridViewEditMode.EditOnEnter ||
                   (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)) 
                {
                    BeginEditInternal(true /*selectAll*/);
                    if (this.ptCurrentCell.X > -1 && this.CurrentCellInternal.EditType == null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown])
                    { 
                        // The current cell does not have an edit type so the data grid view did not put an edit control on top.
                        // We should invalidate the current cell so that the dataGridView repaints the focus around the current cell. 
                        // But do that only if the dataGridView did not get the focus via mouse. 
                        InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/);
                    } 
                }
                else if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown])
                {
                    // When the focus is given to the DataGridView control via mouse 
                    // the dataGridView changes selection so it invalidates the current cell anyway
                    // 
                    // In any other case Invalidate the current cell so the dataGridView repaints the focus around the current cell 
                    InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/);
                } 
            }
        }

        ///  
        protected override void OnFontChanged(EventArgs e)
        { 
            base.OnFontChanged(e); 

            if (GetAnyDisposingInHierarchy ()) 
            {
                return;
            }
 
            // Change may be due to an ambient font change.
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] && 
                this.ColumnHeadersDefaultCellStyle.Font != base.Font) 
            {
                this.ColumnHeadersDefaultCellStyle.Font = base.Font; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true;
                OnColumnHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] && 
                this.RowHeadersDefaultCellStyle.Font != base.Font) 
            {
                this.RowHeadersDefaultCellStyle.Font = base.Font; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true;
                OnRowHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] && 
                this.DefaultCellStyle.Font != base.Font) 
            {
                this.DefaultCellStyle.Font = base.Font; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true;
                OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 
        }
 
        ///  
        protected override void OnForeColorChanged(EventArgs e)
        { 
            base.OnForeColorChanged(e);
            if (GetAnyDisposingInHierarchy())
            {
                return; 
            }
 
            // Change may be due to an ambient forecolor change. 
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] && this.DefaultCellStyle.ForeColor != base.ForeColor)
            { 
                this.DefaultCellStyle.ForeColor = base.ForeColor;
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = false;
                OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs); 
            }
        } 
 
        private void OnGlobalAutoSize()
        { 
            Invalidate();

            if (this.noAutoSizeCount > 0)
            { 
                return;
            } 
 
            bool autoSizeRowHeaders = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                                      this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            if (autoSizeRowHeaders)
            {
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode,
                                          this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize /*fixedColumnHeadersHeight*/, 
                                          this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None /*fixedRowsHeight*/);
            } 
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, false /*fixedColumnsWidth*/); 
            }
            if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/); 
            }
            AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/); 
 
            if (autoSizeRowHeaders &&
                (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize || this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)) 
            {
                // Second round of row headers autosizing
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            } 
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
            { 
                // Second round of column headers autosizing 
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            } 
            if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)
            {
                // Second round of rows autosizing
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
        } 
 
        /// 
        protected override void OnGotFocus(EventArgs e) 
        {
            base.OnGotFocus(e);
            if (this.ptCurrentCell.X != -1)
            { 
                InvalidateCell(this.ptCurrentCell.X, this.ptCurrentCell.Y);
            } 
 
            // Inform Accessibility that our current cell contains the focus.
            if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] && 
                (!this.dataGridViewOper[DATAGRIDVIEWOPER_inEndEdit] || this.EditMode != DataGridViewEditMode.EditOnEnter) &&
                (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] || this.EditMode != DataGridViewEditMode.EditOnEnter) &&
                this.ptCurrentCell.X > -1)
            { 
                // The name is misleading ( the current cell did not change ).
                // However, AccessibilityNotifyCurrentCellChanged is now a public method so we can't change its name 
                // to better reflect its purpose. 
                AccessibilityNotifyCurrentCellChanged(this.ptCurrentCell);
            } 
        }

        /// 
        protected virtual void OnGridColorChanged(EventArgs e) 
        {
            InvalidateInside(); 
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWGRIDCOLORCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
        } 

        ///  
        protected override void OnHandleCreated(EventArgs e) 
        {
            base.OnHandleCreated(e); 
            DisposeCachedGraphics();

            if (this.layout.dirty)
            { 
                PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            } 
            if (this.ptCurrentCell.X == -1) 
            {
                MakeFirstDisplayedCellCurrentCell(false /*includeNewRow*/); 
            }
            else
            {
                ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*forCurrentCellChange*/); 
            }
 
            // do the AutoSize work that was skipped during initialization 
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle])
            { 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = false;
                OnGlobalAutoSize();
            }
            SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(this.OnUserPreferenceChanged); 
        }
 
        ///  
        protected override void OnHandleDestroyed(EventArgs e)
        { 
            SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(this.OnUserPreferenceChanged);
            base.OnHandleDestroyed(e);
        }
 
        internal void OnInsertedColumn_PreNotification(DataGridViewColumn dataGridViewColumn)
        { 
            // Fix the OldFirstDisplayedScrollingCol 
            this.displayedBandsInfo.CorrectColumnIndexAfterInsertion(dataGridViewColumn.Index, 1);
 
            // Fix the Index of all following columns
            CorrectColumnIndexesAfterInsertion(dataGridViewColumn, 1);

            // Same effect as appending a column 
            OnAddedColumn(dataGridViewColumn);
        } 
 
        internal void OnInsertedColumn_PostNotification(Point newCurrentCell)
        { 
            // Update current cell if needed
            if (newCurrentCell.X != -1)
            {
                Debug.Assert(this.ptCurrentCell.X == -1); 
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X,
                                                              newCurrentCell.Y, 
                                                              true, 
                                                              false,
                                                              false, 
                                                              false /*clearSelection*/,
                                                              this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 1 /*forceCurrentCellSelection*/);
                Debug.Assert(success);
            } 
        }
 
        internal void OnInsertedRow_PreNotification(int rowIndex, int insertionCount) 
        {
            Debug.Assert(rowIndex >= 0); 
            Debug.Assert(insertionCount > 0);

            // Fix the OldFirstDisplayedScrollingRow
            this.displayedBandsInfo.CorrectRowIndexAfterInsertion(rowIndex, insertionCount); 

            // Fix the Index of all following rows 
            CorrectRowIndexesAfterInsertion(rowIndex, insertionCount); 

            // Next, same effect as adding a row 
            OnAddedRow_PreNotification(rowIndex);
        }

        internal void OnInsertedRow_PostNotification(int rowIndex, Point newCurrentCell, bool lastInsertion) 
        {
            Debug.Assert(rowIndex >= 0); 
 
            // Same effect as adding a row
            OnAddedRow_PostNotification(rowIndex); 

            // Update current cell if needed
            if (lastInsertion && newCurrentCell.Y != -1)
            { 
                Debug.Assert(this.ptCurrentCell.X == -1);
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, 
                                                              newCurrentCell.Y, 
                                                              true,
                                                              false, 
                                                              false,
                                                              false /*clearSelection*/,
                                                              this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 1 /*forceCurrentCellSelection*/);
                Debug.Assert(success); 
            }
        } 
 
        internal void OnInsertedRows_PreNotification(int rowIndex, DataGridViewRow[] dataGridViewRows)
        { 
            Debug.Assert(rowIndex >= 0);
            Debug.Assert(dataGridViewRows != null);
            Debug.Assert(dataGridViewRows.Length > 0);
 
            // Fix the OldFirstDisplayedScrollingRow
            this.displayedBandsInfo.CorrectRowIndexAfterInsertion(rowIndex, dataGridViewRows.Length); 
 
            // Fix the Index of all following rows
            CorrectRowIndexesAfterInsertion(rowIndex, dataGridViewRows.Length); 

            // Next, same effect as adding the rows
            OnAddedRows_PreNotification(dataGridViewRows);
        } 

        internal void OnInsertedRows_PostNotification(DataGridViewRow[] dataGridViewRows, Point newCurrentCell) 
        { 
            Debug.Assert(dataGridViewRows != null);
            Debug.Assert(dataGridViewRows.Length > 0); 

            // Same effect as adding the rows
            OnAddedRows_PostNotification(dataGridViewRows);
 
            // Update current cell if needed
            if (newCurrentCell.Y != -1) 
            { 
                Debug.Assert(this.ptCurrentCell.X == -1);
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, newCurrentCell.Y, true, false, false, false /*clearSelection*/, false /*forceCurrentCellSelection*/); 
                Debug.Assert(success);
            }
        }
 
        internal void OnInsertingColumn(int columnIndexInserted, DataGridViewColumn dataGridViewColumn, out Point newCurrentCell)
        { 
            Debug.Assert(dataGridViewColumn != null); 

            if (dataGridViewColumn.DataGridView != null) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView));
            }
 
            if (!this.InInitialization &&
                dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && 
                (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || 
                 this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect))
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString()));
            }

            if (dataGridViewColumn.Visible) 
            {
                // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used 
 
                // Make sure the column does not autosize based only on header while column headers are invisible
                if (!this.ColumnHeadersVisible && 
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader)))
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn));
                } 

                // Make sure the column is not frozen and auto fills 
                if (dataGridViewColumn.Frozen && 
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill)))
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn));
                }
            }
 
            // check for correctness of frozen state - throws exception if state is incorrect.
            CorrectColumnFrozenState(dataGridViewColumn, columnIndexInserted); 
 
            // Reset current cell if there is one, no matter the relative position of the columns involved
            if (this.ptCurrentCell.X != -1) 
            {
                newCurrentCell = new Point(columnIndexInserted <= this.ptCurrentCell.X ? this.ptCurrentCell.X + 1 : this.ptCurrentCell.X,
                     this.ptCurrentCell.Y);
                ResetCurrentCell(); 
            }
            else 
            { 
                newCurrentCell = new Point(-1, -1);
            } 

            // prepare the existing rows by inserting cells of correct type
            if (this.Rows.Count > 0)
            { 
                // Only require a default cell type when there are rows to fill
                if (dataGridViewColumn.CellType == null) 
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn));
                } 

                if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1)
                {
                    // New row needs to be unshared before addition of new cell with a Value != null 
                    DataGridViewRow newRow = this.Rows[this.newRowIndex];
                } 
 
                int newColumnCount = this.Columns.Count + 1;
 
                try
                {
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
                    { 
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        if (dataGridViewRow.Cells.Count < newColumnCount) 
                        { 
                            DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone();
                            dataGridViewRow.Cells.InsertInternal(columnIndexInserted, dataGridViewCellNew); 
                            if (rowIndex == this.newRowIndex)
                            {
                                dataGridViewCellNew.Value = dataGridViewCellNew.DefaultNewRowValue;
                            } 
                            dataGridViewCellNew.DataGridViewInternal = this;
                            dataGridViewCellNew.OwningRowInternal = dataGridViewRow; 
                            dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn; 
                        }
                    } 
                }
                catch
                {
                    // An error occurred while inserting the cells. Revert all the insertions. 
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
                    { 
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); 
                        if (dataGridViewRow.Cells.Count == newColumnCount)
                        { 
                            dataGridViewRow.Cells.RemoveAtInternal(columnIndexInserted);
                        }
                        else
                        { 
                            Debug.Assert(dataGridViewRow.Cells.Count < newColumnCount);
                            break; 
                        } 
                    }
                    throw; 
                }
            }

            // Update the indexes of selected columns to compensate for the insertion of this column 
            switch (this.SelectionMode)
            { 
                case DataGridViewSelectionMode.FullColumnSelect: 
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                    int columnEntries = this.selectedBandIndexes.Count; 
                    int columnEntry = 0;
                    while (columnEntry < columnEntries)
                    {
                        int columnIndex = this.selectedBandIndexes[columnEntry]; 
                        if (columnIndexInserted <= columnIndex)
                        { 
                            this.selectedBandIndexes[columnEntry] = columnIndex + 1; 
                        }
                        columnEntry++; 
                    }
                    if (this.selectedBandSnapshotIndexes != null)
                    {
                        columnEntries = this.selectedBandSnapshotIndexes.Count; 
                        columnEntry = 0;
                        while (columnEntry < columnEntries) 
                        { 
                            int columnIndex = this.selectedBandSnapshotIndexes[columnEntry];
                            if (columnIndexInserted <= columnIndex) 
                            {
                                this.selectedBandSnapshotIndexes[columnEntry] = columnIndex + 1;
                            }
                            columnEntry++; 
                        }
                    } 
                    break; 
            }
        } 

        internal void OnInsertingRow(int rowIndexInserted,
                                     DataGridViewRow dataGridViewRow,
                                     DataGridViewElementStates rowState, 
                                     ref Point newCurrentCell,
                                     bool firstInsertion, 
                                     int insertionCount, 
                                     bool force)
        { 
            // Reset the current cell's address if it's after the inserted row.
            if (firstInsertion)
            {
                if (this.ptCurrentCell.Y != -1 && rowIndexInserted <= this.ptCurrentCell.Y) 
                {
                    newCurrentCell = new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y + insertionCount); 
                    if (force) 
                    {
                        // When force is true, the underlying data was already added, therefore we need to avoid accessing any back-end data 
                        // since we might be off by 1 row.
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true;
                        bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false);
                        Debug.Assert(success); 
                    }
                    else 
                    { 
                        ResetCurrentCell();
                    } 
                }
                else
                {
                    newCurrentCell = new Point(-1, -1); 
                }
            } 
            else 
            {
                if (newCurrentCell.Y != -1) 
                {
                    newCurrentCell.Y += insertionCount;
                }
            } 

            // For now same checks as for OnAddingRow 
            OnAddingRow(dataGridViewRow, rowState, false /*checkFrozenState*/); 

            // check for correctness of frozen state - throws exception if state is incorrect. 
            CorrectRowFrozenState(dataGridViewRow, rowState, rowIndexInserted);

            // Update the indexes of selected rows to compensate for the insertion of this row
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.FullRowSelect: 
                case DataGridViewSelectionMode.RowHeaderSelect: 
                    int rowEntries = this.selectedBandIndexes.Count;
                    int rowEntry = 0; 
                    while (rowEntry < rowEntries)
                    {
                        int rowIndex = this.selectedBandIndexes[rowEntry];
                        if (rowIndexInserted <= rowIndex) 
                        {
                            this.selectedBandIndexes[rowEntry] = rowIndex + insertionCount; 
                        } 
                        rowEntry++;
                    } 
                    if (this.selectedBandSnapshotIndexes != null)
                    {
                        rowEntries = this.selectedBandSnapshotIndexes.Count;
                        rowEntry = 0; 
                        while (rowEntry < rowEntries)
                        { 
                            int rowIndex = this.selectedBandSnapshotIndexes[rowEntry]; 
                            if (rowIndexInserted <= rowIndex)
                            { 
                                this.selectedBandSnapshotIndexes[rowEntry] = rowIndex + insertionCount;
                            }
                            rowEntry++;
                        } 
                    }
                    break; 
            } 
        }
 
        internal void OnInsertingRows(int rowIndexInserted, DataGridViewRow[] dataGridViewRows, ref Point newCurrentCell)
        {
            Debug.Assert(dataGridViewRows != null);
 
            // Reset the current cell's address if it's after the inserted row.
            if (this.ptCurrentCell.Y != -1 && rowIndexInserted <= this.ptCurrentCell.Y) 
            { 
                newCurrentCell = new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y + dataGridViewRows.Length);
                ResetCurrentCell(); 
            }
            else
            {
                newCurrentCell = new Point(-1, -1); 
            }
 
            // For now almost same checks as for OnAddingRows 
            // OnAddingRows checks for Selected status of rows.
            OnAddingRows(dataGridViewRows, false /*checkFrozenStates*/); 

            // Check for Frozen state correctness
            CorrectRowFrozenStates(dataGridViewRows, rowIndexInserted);
 
            // Update the indexes of selected rows to compensate for the insertion of this row
            switch (this.SelectionMode) 
            { 
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect: 
                    int rowEntries = this.selectedBandIndexes.Count;
                    int rowEntry = 0;
                    while (rowEntry < rowEntries)
                    { 
                        int rowIndex = this.selectedBandIndexes[rowEntry];
                        if (rowIndexInserted <= rowIndex) 
                        { 
                            this.selectedBandIndexes[rowEntry] = rowIndex + dataGridViewRows.Length;
                        } 
                        rowEntry++;
                    }
                    if (this.selectedBandSnapshotIndexes != null)
                    { 
                        rowEntries = this.selectedBandSnapshotIndexes.Count;
                        rowEntry = 0; 
                        while (rowEntry < rowEntries) 
                        {
                            int rowIndex = this.selectedBandSnapshotIndexes[rowEntry]; 
                            if (rowIndexInserted <= rowIndex)
                            {
                                this.selectedBandSnapshotIndexes[rowEntry] = rowIndex + dataGridViewRows.Length;
                            } 
                            rowEntry++;
                        } 
                    } 
                    break;
            } 
        }

        /// 
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override void OnKeyDown(KeyEventArgs e)
        { 
            base.OnKeyDown(e); 
            if (e.Handled)
            { 
                return;
            }

            // Forward key down to current cell if any 
            if (this.ptCurrentCell.X != -1)
            { 
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal; 
                Debug.Assert(dataGridViewCell != null);
                if (dataGridViewCell.KeyDownUnsharesRowInternal(e, this.ptCurrentCell.Y)) 
                {
                    DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y];
                    this.CurrentCellInternal.OnKeyDownInternal(e, this.ptCurrentCell.Y);
                } 
                else
                { 
                    dataGridViewCell.OnKeyDownInternal(e, this.ptCurrentCell.Y); 
                }
            } 

            if (!e.Handled)
            {
                switch (e.KeyData & Keys.KeyCode) 
                {
                    case Keys.A: 
                    case Keys.C: 
                    case Keys.D0:
                    case Keys.NumPad0: 
                    case Keys.Delete:
                    case Keys.Down:
                    case Keys.F2:
                    case Keys.End: 
                    case Keys.Enter:
                    case Keys.Escape: 
                    case Keys.Home: 
                    case Keys.Insert:
                    case Keys.Left: 
                    case Keys.Next:
                    case Keys.Prior:
                    case Keys.Right:
                    case Keys.Space: 
                    case Keys.Tab:
                    case Keys.Up: 
                    { 
                        e.Handled = ProcessDataGridViewKey(e);
                        break; 
                    }
                }
            }
        } 

        ///  
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override void OnKeyPress(KeyPressEventArgs e)
        { 
            base.OnKeyPress(e);
            if (e.Handled)
            {
                return; 
            }
 
            // Forward key press to current cell if any 
            if (this.ptCurrentCell.X != -1)
            { 
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                Debug.Assert(dataGridViewCell != null);
                if (dataGridViewCell.KeyPressUnsharesRowInternal(e, this.ptCurrentCell.Y))
                { 
                    DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y];
                    this.CurrentCellInternal.OnKeyPressInternal(e, this.ptCurrentCell.Y); 
                } 
                else
                { 
                    dataGridViewCell.OnKeyPressInternal(e, this.ptCurrentCell.Y);
                }
            }
        } 

        ///  
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override void OnKeyUp(KeyEventArgs e)
        { 
            base.OnKeyUp(e);
            if (e.Handled)
            {
                return; 
            }
 
            // Forward key up to current cell if any 
            if (this.ptCurrentCell.X != -1)
            { 
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                Debug.Assert(dataGridViewCell != null);
                if (dataGridViewCell.KeyUpUnsharesRowInternal(e, this.ptCurrentCell.Y))
                { 
                    DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y];
                    this.CurrentCellInternal.OnKeyUpInternal(e, this.ptCurrentCell.Y); 
                } 
                else
                { 
                    dataGridViewCell.OnKeyUpInternal(e, this.ptCurrentCell.Y);
                }
            }
        } 

        ///  
        protected override void OnLayout(LayoutEventArgs e) 
        {
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging]) 
            {
                return;
            }
 
            base.OnLayout(e);
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
            if (this.RightToLeftInternal) 
            {
                Invalidate(); 
            }
            if (this.editingControl != null)
            {
                PositionEditingControl(true, true, false); 
            }
        } 
 
        /// 
        protected override void OnLeave(EventArgs e) 
        {
            if (this.ptCurrentCell.X > -1 && !this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey])
            {
                DataGridViewCell dataGridViewCell = null; 
                OnCellLeave(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                if (this.ptCurrentCell.X == -1) 
                { 
                    return;
                } 
                OnRowLeave(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
            }

            if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey]) 
            {
                base.OnLeave(e); 
 
                // 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*/);
                }
            } 
        }
 
        ///  
        protected override void OnLostFocus(EventArgs e)
        { 
            base.OnLostFocus(e);
            if (this.ptCurrentCell.X != -1)
            {
                InvalidateCell(this.ptCurrentCell.X, this.ptCurrentCell.Y); 
            }
        } 
 
        /// 
        protected override void OnMouseClick(MouseEventArgs e) 
        {
            bool mouseClickRaised = false;

            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
            {
                HitTestInfo hti = HitTest(e.X, e.Y);

                if (this.ptMouseDownCell.X == hti.col && 
                    this.ptMouseDownCell.Y == hti.row &&
                    (e.Button != MouseButtons.Left || 
                     this.ptMouseDownCell.X == -1 || 
                     this.ptMouseDownCell.Y == -1 ||
                     (this.ptMouseDownCell.X == this.ptCurrentCell.X && 
                      this.ptMouseDownCell.Y == this.ptCurrentCell.Y)))
                {
                    DataGridViewCellMouseEventArgs dgvcme = null;
                    if (hti.Type != DataGridViewHitTestType.None && 
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
                    { 
                        int mouseX = e.X - hti.ColumnX;
                        if (this.RightToLeftInternal) 
                        {
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness);
                        }
                        dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e); 
                        RecordCellMouseClick(dgvcme);
                        if (e.Button == MouseButtons.Left) 
                        { 
                            OnCellClick(new DataGridViewCellEventArgs(hti.col, hti.row));
                        } 
                        base.OnMouseClick(e);
                        mouseClickRaised = true;
                        if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                        { 
                            OnCellMouseClick(dgvcme);
                        } 
                    } 
                    else
                    { 
                        base.OnMouseClick(e);
                        mouseClickRaised = true;
                    }
 
                    if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation])
                    { 
                        switch (hti.typeInternal) 
                        {
                            case DataGridViewHitTestTypeInternal.ColumnHeader: 
                            case DataGridViewHitTestTypeInternal.ColumnHeaderLeft:
                            case DataGridViewHitTestTypeInternal.ColumnHeaderRight:
                            case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft:
                            { 
                                Debug.Assert(dgvcme != null);
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) 
                                { 
                                    OnColumnHeaderMouseClick(dgvcme);
                                } 
                                break;
                            }

                            case DataGridViewHitTestTypeInternal.RowHeader: 
                            {
                                Debug.Assert(dgvcme != null); 
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) 
                                {
                                    OnRowHeaderMouseClick(dgvcme); 
                                }
                                break;
                            }
                        } 
                    }
                } 
            } 
            if (!mouseClickRaised)
            { 
                base.OnMouseClick(e);
            }
        }
 
        /// 
        protected override void OnMouseDoubleClick(MouseEventArgs e) 
        { 
            base.OnMouseDoubleClick(e);
 
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize])
            { 
                HitTestInfo hti = HitTest(e.X, e.Y); 

                if (this.ptMouseDownCell.X == hti.col && this.ptMouseDownCell.Y == hti.row) 
                {
                    DataGridViewCellMouseEventArgs dgvcme = null;
                    if (hti.Type != DataGridViewHitTestType.None &&
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar && 
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar)
                    { 
                        int mouseX = e.X - hti.ColumnX; 
                        if (this.RightToLeftInternal)
                        { 
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness);
                        }
                        dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e);
                        OnCellMouseDoubleClick(dgvcme); 
                    }
 
                    if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) 
                    {
                        switch (hti.typeInternal) 
                        {
                            case DataGridViewHitTestTypeInternal.ColumnHeader:
                            case DataGridViewHitTestTypeInternal.ColumnHeaderLeft:
                            case DataGridViewHitTestTypeInternal.ColumnHeaderRight: 
                            case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft:
                            { 
                                Debug.Assert(dgvcme != null); 
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                                { 
                                    OnColumnHeaderMouseDoubleClick(dgvcme);
                                }
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.ColumnResizeLeft: 
                            case DataGridViewHitTestTypeInternal.ColumnResizeRight: 
                            {
                                int columnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight) ? hti.col : hti.adjacentCol; 
                                if (columnIndex < this.Columns.Count)
                                {
                                    HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/);
                                    DataGridViewColumnDividerDoubleClickEventArgs dgvcddce = new DataGridViewColumnDividerDoubleClickEventArgs(columnIndex, hme); 
                                    Debug.Assert(this.Columns[columnIndex].Resizable == DataGridViewTriState.True);
                                    OnColumnDividerDoubleClick(dgvcddce); 
                                } 
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop:
                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom:
                            case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: 
                            case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom:
                            { 
                                HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); 
                                DataGridViewRowDividerDoubleClickEventArgs dgvrddce = new DataGridViewRowDividerDoubleClickEventArgs(-1, hme);
                                Debug.Assert(this.columnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing); 
                                OnRowDividerDoubleClick(dgvrddce);
                                break;
                            }
 
                            case DataGridViewHitTestTypeInternal.RowHeader:
                            { 
                                Debug.Assert(dgvcme != null); 
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                                { 
                                    OnRowHeaderMouseDoubleClick(dgvcme);
                                }
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.RowResizeBottom: 
                            case DataGridViewHitTestTypeInternal.RowResizeTop: 
                            {
                                int rowIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom) ? hti.row : hti.adjacentRow; 
                                if (rowIndex < this.Rows.Count)
                                {
                                    HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/);
                                    DataGridViewRowDividerDoubleClickEventArgs dgvrddce = new DataGridViewRowDividerDoubleClickEventArgs(rowIndex, hme); 
                                    Debug.Assert(this.Rows[rowIndex].Resizable == DataGridViewTriState.True);
                                    OnRowDividerDoubleClick(dgvrddce); 
                                } 
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft:
                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight:
                            case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft: 
                            case DataGridViewHitTestTypeInternal.RowHeadersResizeRight:
                            { 
                                HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); 
                                DataGridViewColumnDividerDoubleClickEventArgs dgvcddce = new DataGridViewColumnDividerDoubleClickEventArgs(-1, hme);
                                Debug.Assert(this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing); 
                                OnColumnDividerDoubleClick(dgvcddce);
                                break;
                            }
                        } 
                    }
                } 
            } 
        }
 
        /// 
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]) 
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves] = true; 
            } 

            base.OnMouseDown(e); 

            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls])
            {
                return; 
            }
 
            if (this.ptMouseDownCell.X != -2) 
            {
                // Happens when user pushes the mouse wheel down while the left mouse button is already down 
                Debug.Assert(this.ptMouseDownCell.Y != -2);
                return;
            }
 
            HitTestInfo hti = HitTest(e.X, e.Y);
 
            if (hti.Type != DataGridViewHitTestType.None && 
                hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
            {
                this.ptMouseDownCell.X = hti.col;
                this.ptMouseDownCell.Y = hti.row;
                this.ptMouseDownGridCoord = new Point(e.X, e.Y); 
                int mouseX = e.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, e.Y - hti.RowY, e);
                OnCellMouseDown(dgvcme);
            }
        } 

        ///  
        protected override void OnMouseEnter(EventArgs e) 
        {
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] && 
                !this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] &&
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] &&
                !this.toolTipControl.Activated)
            { 
                base.OnMouseEnter(e);
            } 
 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] = false;
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] = false; 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] = false;
        }

        ///  
        protected override void OnMouseLeave(EventArgs e)
        { 
            // when the mouse leaves the dataGridView control, reset the cursor to the previously cached one 
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet])
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false;
                this.CursorInternal = this.oldCursor;
            }
 
            bool mouseOverEditingControl = this.MouseOverEditingControl;
            bool mouseOverEditingPanel = this.MouseOverEditingPanel; 
            bool mouseOverToolTipControl = this.toolTipControl.Activated && this.ClientRectangle.Contains(PointToClient(Control.MousePosition)); 

            if (!mouseOverEditingPanel && !mouseOverEditingControl && !mouseOverToolTipControl && this.ptMouseEnteredCell.X != -2) 
            {
                if (this.ptMouseEnteredCell.X >= -1 && this.ptMouseEnteredCell.X < this.Columns.Count &&
                    this.ptMouseEnteredCell.Y >= -1 && this.ptMouseEnteredCell.Y < this.Rows.Count)
                { 
                    DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(this.ptMouseEnteredCell.X, this.ptMouseEnteredCell.Y);
                    OnCellMouseLeave(dgvce); 
                } 
                else
                { 
                    this.ptMouseEnteredCell.X = this.ptMouseEnteredCell.Y = -2;
                }
            }
 
            ResetTrackingState();
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves] = false; 
 
            if (!mouseOverEditingPanel && !mouseOverEditingControl && !mouseOverToolTipControl && !this.MouseOverScrollBar)
            { 
                this.toolTipControl.Activate(false /*activate*/);
                base.OnMouseLeave(e);
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] = true;
            } 
        }
 
        ///  
        protected override void OnMouseMove(MouseEventArgs e)
        { 
            base.OnMouseMove(e);

            HitTestInfo hti = HitTest(e.X, e.Y);
 
            UpdateMouseEnteredCell(hti, e);
 
            // We need to give UI feedback when the user is resizing a column 
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize])
            { 
                MoveRowHeadersOrColumnResize(e);
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize])
            { 
                MoveColumnHeadersOrRowResize(e);
            } 
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) 
            {
                MoveColumnRelocation(e, hti); 
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize])
            {
                MoveColumnHeadersOrRowResize(e); 
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
            { 
                MoveRowHeadersOrColumnResize(e);
            } 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] ||
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] ||
                ((hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.RowHeadersResizeLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.RowHeadersResizeRight) && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]))
            { 
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) 
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; 
                    this.oldCursor = this.Cursor;
                }
                this.CursorInternal = Cursors.SizeWE;
                return; 
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] || 
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || 
                ((hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeTop ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom) && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])) 
            {
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet])
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; 
                    this.oldCursor = this.Cursor;
                } 
                this.CursorInternal = Cursors.SizeNS; 
                return;
            } 
            /* Whidbey bug 156884 - no longer show hand cursor
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight))
            { 
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet])
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true;
                    this.oldCursor = this.Cursor; 
                }
                this.CursorInternal = Cursors.Hand; 
                return; 
            }*/
            else if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false;
                this.CursorInternal = this.oldCursor;
            } 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] || 
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] || 
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])
            { 
                int xOffset, yOffset, mouseX = e.X, mouseY = e.Y;
                if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset))
                {
                    if (xOffset == 0) 
                    {
                        if (this.horizScrollTimer != null && this.horizScrollTimer.Enabled) 
                        { 
                            // Mouse's X came in-bound - need to stop the horizontal scroll timer
                            this.horizScrollTimer.Enabled = false; 
                        }
                    }
                    else if (this.horizScrollTimer == null || !this.horizScrollTimer.Enabled)
                    { 
                        // Need to start delayed horizontal scroll
                        this.HorizScrollTimer.Interval = GetColumnScrollRate(Math.Abs(xOffset)); 
                        this.HorizScrollTimer.Enabled = true; 
                    }
 
                    if (yOffset == 0)
                    {
                        if (this.vertScrollTimer != null && this.vertScrollTimer.Enabled)
                        { 
                            // Mouse's Y came in-bound - need to stop the vertical scroll timer
                            this.vertScrollTimer.Enabled = false; 
                        } 
                    }
                    else if (this.vertScrollTimer == null || !this.vertScrollTimer.Enabled) 
                    {
                        // Need to start delayed vertical scroll
                        this.VertScrollTimer.Interval = GetRowScrollRate(Math.Abs(yOffset));
                        this.VertScrollTimer.Enabled = true; 
                    }
 
                    if (this.HorizScrollTimer.Enabled || this.VertScrollTimer.Enabled) 
                    {
                        return; 
                    }

                    if (/*!this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] && */
                        hti.Type != DataGridViewHitTestType.None && 
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
                    { 
                        if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && hti.col >= 0)
                        { 
                            OnColumnSelectMouseMove(hti);
                        }
                        else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && hti.row >= 0)
                        { 
                            OnRowSelectMouseMove(hti);
                        } 
                        else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) 
                        {
                            OnCellSelectMouseMove(hti); 
                        }
                    }
                }
            } 
#if DEBUG
            else 
            { 
                Debug.Assert(this.vertScrollTimer == null || !this.vertScrollTimer.Enabled);
                Debug.Assert(this.horizScrollTimer == null || !this.horizScrollTimer.Enabled); 
            }
#endif
            if (!this.toolTipControl.Activated)
            { 
                //
                // After processing the MouseMove event, the tool tip is still not activated. 
                // Reset the tool tip cell. 
                this.ptToolTipCell = new Point(-1, -1);
            } 
        }

        /// 
        protected override void OnMouseUp(MouseEventArgs e) 
        {
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]) 
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] = false;
 
                HitTestInfo hti = HitTest(e.X, e.Y);

                if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] &&
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && 
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && 
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
                {
                    if (hti.Type != DataGridViewHitTestType.None && 
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar)
                    {
                        int mouseX = e.X - hti.ColumnX; 
                        if (this.RightToLeftInternal)
                        { 
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); 
                        }
                        DataGridViewCellMouseEventArgs dgvcme; 
                        if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble])
                        {
                            MouseEventArgs meTmp = new MouseEventArgs(e.Button, 2, e.X, e.Y, e.Delta);
                            dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, meTmp); 
                        }
                        else 
                        { 
                            dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e);
                        } 
                        if (hti.col >= 0 && this.ptMouseDownCell.X == hti.col &&
                            hti.row >= 0 && this.ptMouseDownCell.Y == hti.row &&
                            this.EditMode == DataGridViewEditMode.EditOnEnter &&
                            this.editingControl != null) 
                        {
                            OnClick(e); 
                            OnMouseClick(e); 
                        }
 
                        CorrectFocus(true /*onlyIfGridHasFocus*/);

                        if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                        { 
                            OnCellMouseUp(dgvcme);
                        } 
                    } 
                    else if (hti.Type == DataGridViewHitTestType.None)
                    { 
                        // VS Whidbey bug 469429
                        CorrectFocus(true /*onlyIfGridHasFocus*/);
                    }
                } 
                else
                { 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize]) 
                    {
                        EndColumnResize(e); 
                    }

                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize])
                    { 
                        EndRowResize(e);
                    } 
 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation])
                    { 
                        EndColumnRelocation(e, hti);
                    }

                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize]) 
                    {
                        EndColumnHeadersResize(e); 
                    } 

                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
                    {
                        EndRowHeadersResize(e);
                    }
 
                    // VS Whidbey bug 256893
                    CorrectFocus(true /*onlyIfGridHasFocus*/); 
 
                    // Updating the hit test info since the EndXXX operation above may have invalidated the previously
                    // determined hti. 
                    hti = HitTest(e.X, e.Y);
                    if (hti.Type != DataGridViewHitTestType.None &&
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
                    {
                        int mouseX = e.X - hti.ColumnX; 
                        if (this.RightToLeftInternal) 
                        {
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); 
                        }
                        OnCellMouseUp(new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e));
                    }
                } 

                ResetTrackingState(); 
            } 
            base.OnMouseUp(e);
        } 

        /// 
        protected override void OnMouseWheel(MouseEventArgs e)
        { 
            base.OnMouseWheel(e);
 
            HandledMouseEventArgs hme = e as HandledMouseEventArgs; 
            if (hme != null && hme.Handled)
            { 
                // The application event handler handled the scrolling - don't do anything more.
                return;
            }
 
            if ((ModifierKeys & (Keys.Shift | Keys.Alt)) != 0 || MouseButtons != MouseButtons.None)
            { 
                return; // Do not scroll when Shift or Alt key is down, or when a mouse button is down. 
            }
 
            bool verticalScroll = ((ModifierKeys & Keys.Control) == 0);

            ScrollBar sb = (verticalScroll ? (ScrollBar) this.vertScrollBar : (ScrollBar) this.horizScrollBar);
 
            if (!sb.Visible || !sb.Enabled)
            { 
                return; // Do not scroll when the corresponding scrollbar is invisible or disabled 
            }
 
            if (hme != null)
            {
                hme.Handled = true;
            } 

            int wheelScrollLines = SystemInformation.MouseWheelScrollLines; 
            if (wheelScrollLines == 0) 
            {
                return; // Do not scroll when the user system setting is 0 lines per notch 
            }

            Debug.Assert(this.cumulativeVerticalWheelDelta > -NativeMethods.WHEEL_DELTA);
            Debug.Assert(this.cumulativeVerticalWheelDelta < NativeMethods.WHEEL_DELTA); 
            Debug.Assert(this.cumulativeHorizontalWheelDelta > -NativeMethods.WHEEL_DELTA);
            Debug.Assert(this.cumulativeHorizontalWheelDelta < NativeMethods.WHEEL_DELTA); 
 
            float partialNotches;
 
            if (verticalScroll)
            {
                this.cumulativeVerticalWheelDelta += e.Delta;
                partialNotches = (float) this.cumulativeVerticalWheelDelta / (float) NativeMethods.WHEEL_DELTA; 
            }
            else 
            { 
                this.cumulativeHorizontalWheelDelta += e.Delta;
                partialNotches = (float) this.cumulativeHorizontalWheelDelta / (float) NativeMethods.WHEEL_DELTA; 
            }

            int fullNotches = (int) partialNotches;
 
            if (wheelScrollLines == -1)
            { 
                // Equivalent to large change scrolls 
                if (fullNotches != 0)
                { 
                    if (this.ptCurrentCell.X >= 0 &&
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    false /*forCurrentCellChange*/, false /*forCurrentRowChange*/))
                    { 
                        // Could not commit edited cell value
                        return; 
                    } 
                    if (verticalScroll)
                    { 
                        int originalVerticalOffset = this.VerticalOffset;
                        this.VerticalOffset -= fullNotches * this.vertScrollBar.LargeChange;
                        if (Math.Abs(this.VerticalOffset - originalVerticalOffset) >= Math.Abs(fullNotches * this.vertScrollBar.LargeChange))
                        { 
                            this.cumulativeVerticalWheelDelta -= fullNotches * NativeMethods.WHEEL_DELTA;
                        } 
                        else 
                        {
                            this.cumulativeVerticalWheelDelta = 0; 
                        }
                    }
                    else
                    { 
                        int originalHorizontalOffset = this.HorizontalOffset;
                        this.HorizontalOffset -= fullNotches * this.horizScrollBar.LargeChange; 
                        if (Math.Abs(this.HorizontalOffset - originalHorizontalOffset) >= Math.Abs(fullNotches * this.horizScrollBar.LargeChange)) 
                        {
                            this.cumulativeHorizontalWheelDelta -= fullNotches * NativeMethods.WHEEL_DELTA; 
                        }
                        else
                        {
                            this.cumulativeHorizontalWheelDelta = 0; 
                        }
                    } 
                } 
            }
            else 
            {
                // Evaluate number of bands to scroll
                int scrollBands = (int) ((float) wheelScrollLines * partialNotches);
                if (scrollBands != 0) 
                {
                    if (this.ptCurrentCell.X >= 0 && 
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                    false /*forCurrentCellChange*/, false /*forCurrentRowChange*/))
                    { 
                        // Could not commit edited cell value
                        return;
                    }
                    int absScrollBands; 
                    if (verticalScroll)
                    { 
                        if (scrollBands > 0) 
                        {
                            absScrollBands = scrollBands; 
                            while (this.vertScrollBar.Value != this.vertScrollBar.Minimum && absScrollBands > 0)
                            {
                                ScrollRowsByCount(-1, ScrollEventType.SmallDecrement);
                                absScrollBands--; 
                            }
                            if (this.vertScrollBar.Value == this.vertScrollBar.Minimum) 
                            { 
                                this.cumulativeVerticalWheelDelta = 0;
                            } 
                            else
                            {
                                this.cumulativeVerticalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines));
                            } 
                        }
                        else 
                        { 
                            absScrollBands = -scrollBands;
                            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
                            int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                            while (absScrollBands > 0 &&
                                   this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <=
                                   this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) 
                            {
                                ScrollRowsByCount(1, ScrollEventType.SmallIncrement); 
                                // Assuming totalVisibleFrozenHeight is unchanged by scrolling operation 
                                Debug.Assert(totalVisibleFrozenHeight == this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen));
                                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
                                absScrollBands--;
                            }
                            if (this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) >
                                this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) 
                            {
                                this.cumulativeVerticalWheelDelta = 0; 
                            } 
                            else
                            { 
                                this.cumulativeVerticalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines));
                            }
                        }
                    } 
                    else
                    { 
                        int extremeScrollBarValue, scrollBand; 
                        if (scrollBands > 0)
                        { 
                            extremeScrollBarValue = this.horizScrollBar.Minimum;
                            scrollBand = -1;
                        }
                        else 
                        {
                            extremeScrollBarValue = this.horizScrollBar.Maximum; 
                            scrollBand = 1; 
                        }
                        absScrollBands = Math.Abs(scrollBands); 
                        while (this.horizScrollBar.Value != extremeScrollBarValue && absScrollBands > 0)
                        {
                            ScrollColumns(scrollBand);
                            absScrollBands--; 
                        }
                        if (this.horizScrollBar.Value == extremeScrollBarValue) 
                        { 
                            this.cumulativeHorizontalWheelDelta = 0;
                        } 
                        else
                        {
                            this.cumulativeHorizontalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines));
                        } 
                    }
                } 
            } 
        }
 
        internal void OnMouseWheelInternal(MouseEventArgs e)
        {
            // Notification forwarded from editing control
            OnMouseWheel(e); 
        }
 
        ///  
        protected virtual void OnMultiSelectChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWMULTISELECTCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnNewRowNeeded(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            }
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWNEWROWNEEDED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected override void OnPaint(PaintEventArgs e)
        { 
            try 
            {
                if (this.layout.dirty) 
                {
                    PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
                }
 
                Graphics g = e.Graphics;
                bool singleVerticalBorderAdded = false, singleHorizontalBorderAdded = false; 
                Rectangle clipRect = e.ClipRectangle; 
                Rectangle gridRect = this.layout.Data;
                if (this.layout.RowHeadersVisible) 
                {
                    gridRect = Rectangle.Union(gridRect, this.layout.RowHeaders);
                }
                else if (this.SingleVerticalBorderAdded) 
                {
                    singleVerticalBorderAdded = true; 
                    if (!this.RightToLeftInternal) 
                    {
                        gridRect.X--; 
                    }
                    gridRect.Width++;
                }
 
                if (this.layout.ColumnHeadersVisible)
                { 
                    gridRect = Rectangle.Union(gridRect, this.layout.ColumnHeaders); 
                }
                else if (this.SingleHorizontalBorderAdded) 
                {
                    singleHorizontalBorderAdded = true;
                    if (gridRect.Y == this.layout.Data.Y)
                    { 
                        gridRect.Y--;
                        gridRect.Height++; 
                    } 
                }
 
                if (this.currentRowSplitBar != -1)
                {
                    clipRect = Rectangle.Union(clipRect, CalcRowResizeFeedbackRect(this.currentRowSplitBar));
                } 
                else if (this.currentColSplitBar != -1)
                { 
                    clipRect = Rectangle.Union(clipRect, CalcColResizeFeedbackRect(this.currentColSplitBar)); 
                }
 
                if (clipRect.IntersectsWith(gridRect))
                {
                    using (Region clipRegion = g.Clip)
                    { 
                        g.SetClip(gridRect);
                        PaintBackground(g, clipRect, gridRect); 
                        PaintGrid(g, gridRect, clipRect, singleVerticalBorderAdded, singleHorizontalBorderAdded); 
                        g.Clip = clipRegion;
                    } 
                }

                PaintBorder(g, clipRect, this.layout.ClientRectangle);
                if (clipRect.IntersectsWith(this.layout.ResizeBoxRect)) 
                {
                    g.FillRectangle(SystemBrushes.Control, this.layout.ResizeBoxRect); 
                } 

                base.OnPaint(e); // raise paint event 
            }
            catch (Exception ex)
            {
                #if DEBUG 
                    Debug.Fail("DataGridView.OnPaint exception: " + ex.Message + " stack trace " + ex.StackTrace);
                #endif 
                if (ClientUtils.IsCriticalException(ex)) 
                {
                    throw; 
                }
            }
        }
 
        // See VSWhidbey 527459 & 526373.
        internal override void OnParentBecameInvisible() 
        { 
            base.OnParentBecameInvisible();
            if (GetState(STATE_VISIBLE)) 
            {
                // This control became invisible too - Update the Displayed properties of the bands.
                OnVisibleChangedPrivate();
            } 
        }
 
        ///  
        protected virtual void OnReadOnlyChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWREADONLYCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
 
            VerifyImeRestrictedModeChanged(); 

            if (!this.ReadOnly && 
                this.ptCurrentCell.X != -1 &&
                ColumnEditable(this.ptCurrentCell.X) &&
                !this.IsCurrentCellInEditMode &&
                (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                 (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)) &&
                !this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X].ReadOnly) // Unshares the row 
            { 
                // Current cell becomes read/write. Enter editing mode.
                BeginEditInternal(true /*selectAll*/); 
            }
        }

        internal void OnRemovedColumn_PreNotification(DataGridViewColumn dataGridViewColumn) 
        {
            Debug.Assert(dataGridViewColumn.Index >= 0); 
            Debug.Assert(dataGridViewColumn.DataGridView == null); 

            // Clear the potential header sort glyph 
            if (dataGridViewColumn.HasHeaderCell)
            {
                dataGridViewColumn.HeaderCell.SortGlyphDirectionInternal = SortOrder.None;
            } 
            // Intentionally keep the DisplayIndex intact after detaching the column.
            CorrectColumnIndexesAfterDeletion(dataGridViewColumn); 
 
            CorrectColumnDisplayIndexesAfterDeletion(dataGridViewColumn);
 
            // Fix the OldFirstDisplayedScrollingCol
            this.displayedBandsInfo.CorrectRowIndexAfterDeletion(dataGridViewColumn.Index);

            // Raise the ColumnRemoved event 
            OnColumnRemoved(dataGridViewColumn);
        } 
 
        internal void OnRemovedColumn_PostNotification(DataGridViewColumn dataGridViewColumn, Point newCurrentCell)
        { 
            // Update current cell if needed
            if (newCurrentCell.X != -1)
            {
                Debug.Assert(this.ptCurrentCell.X == -1); 
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X,
                                                              newCurrentCell.Y, 
                                                              true, 
                                                              false,
                                                              false, 
                                                              false /*clearSelection*/,
                                                              false /*forceCurrentCellSelection*/);
                Debug.Assert(success);
            } 

            // Raise SelectionChanged event if needed 
            FlushSelectionChanged(); 

            // Raise ColumnStateChanged event for Displayed state of deleted column 
            OnColumnHidden(dataGridViewColumn);

            // Columns that are removed from the collection take their non-autosized width
            // Note that in some edge cases, the dev could have changed: 
            //     - the grid's AutoSizeColumnsMode
            //     - the column's Width or AutoSizeMode 
            // in a ColumnRemoved event handler for example, in which case using the CachedThickness may be wrong. 
            // At least we make sure the column is not sized smaller than its minimum width.
            DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.GetInheritedAutoSizeMode(this); 
            Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet);
            if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None &&
                autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill &&
                dataGridViewColumn.ThicknessInternal != dataGridViewColumn.CachedThickness) 
            {
                dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness); 
            } 

            // Autosize rows if needed 
            AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
        }

        internal void OnRemovedRow_PreNotification(int rowIndexDeleted) 
        {
            // Fix the OldFirstDisplayedScrollingRow 
            this.displayedBandsInfo.CorrectRowIndexAfterDeletion(rowIndexDeleted); 

            CorrectRowIndexesAfterDeletion(rowIndexDeleted); 
            ComputeVisibleRows();
        }

        internal void OnRemovedRow_PostNotification(DataGridViewRow dataGridViewRow, Point newCurrentCell) 
        {
            // Update current cell if needed 
            if (newCurrentCell.Y != -1) 
            {
                Debug.Assert(this.ptCurrentCell.X == -1); 
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X,
                                                              newCurrentCell.Y,
                                                              true /*setAnchorCellAddress*/,
                                                              false /*validateCurrentCell*/, 
                                                              false /*throughMouseClick*/,
                                                              false /*clearSelection*/, 
                                                              false /*forceCurrentCellSelection*/); 
                Debug.Assert(success);
            } 

            // Raise SelectionChange event if needed
            FlushSelectionChanged();
 
            bool rowDisplayed = dataGridViewRow.DataGridView == null && dataGridViewRow.Displayed;
 
            // Raise RowStateChanged event for Displayed state of deleted row 
            if (rowDisplayed)
            { 
                dataGridViewRow.DisplayedInternal = false;
                DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, DataGridViewElementStates.Displayed);
                OnRowStateChanged(-1 /*rowIndex*/, dgvrsce);
            } 

            // Rows that are removed from the collection take their non-autosized height 
            // Note that in some edge cases, the dev could have changed: 
            //     - the grid's AutoSizeRowsMode
            //     - the row's Height 
            // in a RowsRemoved event handler for example, in which case using the CachedThickness may be wrong.
            // At least we make sure the row is not sized smaller than its minimum height.
            if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None && dataGridViewRow.ThicknessInternal != dataGridViewRow.CachedThickness)
            { 
                dataGridViewRow.ThicknessInternal = Math.Max(dataGridViewRow.MinimumHeight, dataGridViewRow.CachedThickness);
            } 
 
            // Auto size columms also if needed
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; 
            if (rowDisplayed)
            {
                autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows;
            } 
            bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/);
            bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize; 
            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || 
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing;
 
            if (fixedRowHeadersWidth && !columnAutoSized)
            {
                // No need to autosize the column headers when the row headers and columns don't change.
                fixedColumnHeadersHeight = true; 
            }
 
            // Auto size column headers 
            if (!fixedColumnHeadersHeight)
            { 
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/);
            }

            // Auto size row headers 
            if (!fixedRowHeadersWidth)
            { 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); 
            }
 
            if (!fixedColumnHeadersHeight && !fixedRowHeadersWidth)
            {
                // Second round of column headers autosizing
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); 
            }
        } 
 
        internal void OnRemovingColumn(DataGridViewColumn dataGridViewColumn, out Point newCurrentCell, bool force)
        { 
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(dataGridViewColumn.Index >= 0 && dataGridViewColumn.Index < this.Columns.Count);

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false; 
            int columnIndex = dataGridViewColumn.Index;
 
            // Reset the current cell's address if there is one. 
            if (this.ptCurrentCell.X != -1)
            { 
                int newX = this.ptCurrentCell.X;
                if (columnIndex == this.ptCurrentCell.X)
                {
                    DataGridViewColumn dataGridViewColumnNext = this.Columns.GetNextColumn( 
                        this.Columns[columnIndex],
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.None); 
                    if (dataGridViewColumnNext != null)
                    { 
                        if (dataGridViewColumnNext.Index > columnIndex)
                        {
                            newX = dataGridViewColumnNext.Index - 1;
                        } 
                        else
                        { 
                            newX = dataGridViewColumnNext.Index; 
                        }
                    } 
                    else
                    {
                        DataGridViewColumn dataGridViewColumnPrevious = this.Columns.GetPreviousColumn(
                            this.Columns[columnIndex], 
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None); 
                        if (dataGridViewColumnPrevious != null) 
                        {
                            if (dataGridViewColumnPrevious.Index > columnIndex) 
                            {
                                newX = dataGridViewColumnPrevious.Index - 1;
                            }
                            else 
                            {
                                newX = dataGridViewColumnPrevious.Index; 
                            } 
                        }
                        else 
                        {
                            newX = -1;
                        }
                    } 
                }
                else if (columnIndex < this.ptCurrentCell.X) 
                { 
                    newX = this.ptCurrentCell.X - 1;
                } 
                newCurrentCell = new Point(newX, (newX == -1) ? -1 : this.ptCurrentCell.Y);
                if (columnIndex == this.ptCurrentCell.X)
                {
                    // Left cell is not validated since cancelling validation wouldn't have any effect anyways. 
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false);
                    Debug.Assert(success); 
                } 
                else if (force)
                { 
                    // Underlying data of deleted column is gone. It cannot be accessed anymore.
                    // Do not end editing mode so that CellValidation doesn't get raised, since that event needs the current formatted value.
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true;
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); 
                    Debug.Assert(success);
                } 
                else 
                {
                    // Quit editing mode and set the current cell to its new location once everything is in [....] again. 
                    ResetCurrentCell();
                }
            }
            else 
            {
                newCurrentCell = new Point(-1, -1); 
            } 

            // If the last column is removed, delete all the rows first. 
            if (this.Columns.Count == 1)
            {
                Debug.Assert(columnIndex == 0);
                this.Rows.ClearInternal(false /*recreateNewRow*/); 
            }
 
            // Prepare the existing rows by removing cells at correct index 
            int newColumnCount = this.Columns.Count - 1;
 
            for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                if (dataGridViewRow.Cells.Count > newColumnCount) 
                {
                    dataGridViewRow.Cells.RemoveAtInternal(columnIndex); 
                } 
            }
 
            // Detach column header cell
            if (dataGridViewColumn.HasHeaderCell)
            {
                dataGridViewColumn.HeaderCell.DataGridViewInternal = null; 
            }
 
            // Reset sort related variables. 
            if (dataGridViewColumn == this.sortedColumn)
            { 
                this.sortedColumn = null;
                this.sortOrder = SortOrder.None;

                if (dataGridViewColumn.IsDataBound) 
                {
                    // If the column being removed is the sorted column and it is also the dataBound column 
                    // then see if there is another dataBound column which has the same property name as the sorted column. 
                    // If so, then make that dataGridViewColumn the sorted column in the data grid view.
                    for (int i = 0; i < this.Columns.Count; i ++) 
                    {
                        if (dataGridViewColumn != this.Columns[i] &&
                            this.Columns[i].SortMode != DataGridViewColumnSortMode.NotSortable &&
                            String.Compare(dataGridViewColumn.DataPropertyName, 
                                           this.Columns[i].DataPropertyName,
                                           true /*ignoreCase*/, 
                                           CultureInfo.InvariantCulture) == 0) 
                        {
                            Debug.Assert(this.Columns[i].IsDataBound, "two columns w/ the same DataPropertyName should be DataBound at the same time"); 
                            Debug.Assert(this.Columns[i].HeaderCell.SortGlyphDirection == dataGridViewColumn.HeaderCell.SortGlyphDirection, "DataBound columns should have the same SortGlyphDirection as the one on the DataGridView");
                            this.sortedColumn = this.Columns[i];
                            this.sortOrder = this.Columns[i].HeaderCell.SortGlyphDirection;
                            break; 
                        }
                    } 
                } 
            }
 
            // Is deleted column scrolled off screen?
            if (dataGridViewColumn.Visible &&
                !dataGridViewColumn.Frozen &&
                this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) 
            {
                // Deleted column is part of scrolling columns. 
                if (this.displayedBandsInfo.FirstDisplayedScrollingCol == dataGridViewColumn.Index) 
                {
                    // Deleted column is first scrolling column 
                    this.horizontalOffset -= this.negOffset;
                    this.negOffset = 0;
                }
                else if (this.Columns.DisplayInOrder(this.displayedBandsInfo.FirstDisplayedScrollingCol, dataGridViewColumn.Index)) 
                {
                    // Deleted column is displayed after first scrolling column 
                    if (this.horizScrollBar.Enabled) 
                    {
                        int newHorizontalOffset = this.horizScrollBar.Maximum - this.horizScrollBar.LargeChange - dataGridViewColumn.Thickness; 
                        if (newHorizontalOffset >= 0 && newHorizontalOffset < this.horizScrollBar.Value)
                        {
                            this.horizontalOffset = newHorizontalOffset;
                            this.negOffset = GetNegOffsetFromHorizontalOffset(this.horizontalOffset); 
                        }
                    } 
                    else 
                    {
                        this.horizontalOffset = this.negOffset = 0; 
                    }
                }
                else
                { 
                    // Deleted column is displayed before first scrolling column
                    Debug.Assert(this.horizontalOffset >= dataGridViewColumn.Thickness); 
                    this.horizontalOffset -= dataGridViewColumn.Thickness; 
                }
 
                if (this.horizScrollBar.Enabled)
                {
                    this.horizScrollBar.Value = this.horizontalOffset;
                } 
            }
 
            bool raiseSelectionChanged = false; 

            // Update the indexes of selected columns or individual cells to compensate for the removal of this column 
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.FullColumnSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    int columnEntries = this.selectedBandIndexes.Count;
                    int columnEntry = 0; 
                    while (columnEntry < columnEntries) 
                    {
                        int columnIndexSelected = this.selectedBandIndexes[columnEntry]; 
                        if (columnIndex == columnIndexSelected)
                        {
                            this.selectedBandIndexes.RemoveAt(columnEntry);
                            columnEntries--; 
                            raiseSelectionChanged = true;
                        } 
                        else 
                        {
                            if (columnIndex < columnIndexSelected) 
                            {
                                this.selectedBandIndexes[columnEntry] = columnIndexSelected - 1;
                            }
                            columnEntry++; 
                        }
                    } 
                    break; 
            }
 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] |= this.individualSelectedCells.RemoveAllCellsAtBand(true /*column*/, columnIndex) > 0 ||
                                                                                 raiseSelectionChanged;
            this.individualReadOnlyCells.RemoveAllCellsAtBand(true /*column*/, columnIndex);
        } 

        internal void OnRemovingRow(int rowIndexDeleted, out Point newCurrentCell, bool force) 
        { 
            // if force is true, the row needs to be deleted no matter what. The underlying data row was already deleted.
 
            Debug.Assert(rowIndexDeleted >= 0 && rowIndexDeleted < this.Rows.Count);

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false;
            newCurrentCell = new Point(-1, -1); 

            // Reset the current cell's address if it's on the deleted row, or after it. 
            if (this.ptCurrentCell.Y != -1 && rowIndexDeleted <= this.ptCurrentCell.Y) 
            {
                int newY; 
                if (rowIndexDeleted == this.ptCurrentCell.Y)
                {
                    int rowIndexPrevious = this.Rows.GetPreviousRow(rowIndexDeleted, DataGridViewElementStates.Visible);
                    int rowIndexNext = this.Rows.GetNextRow(rowIndexDeleted, DataGridViewElementStates.Visible); 
                    if (rowIndexPrevious > -1 && this.AllowUserToAddRowsInternal)
                    { 
                        Debug.Assert(this.newRowIndex != -1); 
                        Debug.Assert(this.newRowIndex == this.Rows.Count-1);
                        if (rowIndexNext > -1 && rowIndexNext < this.Rows.Count - 1) 
                        {
                            newY = rowIndexNext - 1;
                        }
                        else 
                        {
                            newY = rowIndexPrevious; 
                        } 
                    }
                    else 
                    {
                        if (rowIndexNext > -1)
                        {
                            newY = rowIndexNext - 1; 
                        }
                        else 
                        { 
                            newY = rowIndexPrevious;
                        } 
                    }
                    // Since the current row is deleted, the dirty states need to be reset
                    this.IsCurrentCellDirtyInternal = false;
                    this.IsCurrentRowDirtyInternal = false; 
                }
                else 
                { 
                    Debug.Assert(rowIndexDeleted < this.ptCurrentCell.Y);
                    newY = this.ptCurrentCell.Y - 1; 
                }
                newCurrentCell = new Point(this.ptCurrentCell.X, newY);
                if (rowIndexDeleted == this.ptCurrentCell.Y)
                { 
                    // Left cell is not validated since cancelling validation wouldn't have any effect anyways.
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); 
                    Debug.Assert(success); 
                }
                else if (force) 
                {
                    // Underlying data of deleted row is gone. It cannot be accessed anymore.
                    // Do not end editing mode so that CellValidation doesn't get raised, since that event needs the current formatted value.
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true; 
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false);
                    Debug.Assert(success); 
                } 
                else
                { 
                    // Quit editing mode and set the current cell to its new location once everything is in [....] again.
                    ResetCurrentCell();
                }
            } 

            bool raiseSelectionChanged = false; 
 
            // Update the indexes of selected rows to compensate for the removal of this row
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect:
                    int rowEntries = this.selectedBandIndexes.Count; 
                    int rowEntry = 0;
                    while (rowEntry < rowEntries) 
                    { 
                        int rowIndex = this.selectedBandIndexes[rowEntry];
                        if (rowIndexDeleted == rowIndex) 
                        {
                            raiseSelectionChanged = true;
                            this.selectedBandIndexes.RemoveAt(rowEntry);
                            rowEntries--; 
                        }
                        else 
                        { 
                            if (rowIndexDeleted < rowIndex)
                            { 
                                this.selectedBandIndexes[rowEntry] = rowIndex - 1;
                            }
                            rowEntry++;
                        } 
                    }
                    if (this.selectedBandSnapshotIndexes != null) 
                    { 
                        rowEntries = this.selectedBandSnapshotIndexes.Count;
                        rowEntry = 0; 
                        while (rowEntry < rowEntries)
                        {
                            int rowIndex = this.selectedBandSnapshotIndexes[rowEntry];
                            if (rowIndexDeleted == rowIndex) 
                            {
                                this.selectedBandSnapshotIndexes.RemoveAt(rowEntry); 
                                rowEntries--; 
                            }
                            else 
                            {
                                if (rowIndexDeleted < rowIndex)
                                {
                                    this.selectedBandSnapshotIndexes[rowEntry] = rowIndex - 1; 
                                }
                                rowEntry++; 
                            } 
                        }
                    } 
                    break;
            }

            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] |= this.individualSelectedCells.RemoveAllCellsAtBand(false /*column*/, rowIndexDeleted) > 0 || 
                                                                                 raiseSelectionChanged;
            this.individualReadOnlyCells.RemoveAllCellsAtBand(false /*column*/, rowIndexDeleted); 
        } 

        internal void OnReplacedCell(DataGridViewRow dataGridViewRow, int columnIndex) 
        {
            DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex];
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected])
            { 
                this.individualSelectedCells.Add(dataGridViewCell);
            } 
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly]) 
            {
                this.individualReadOnlyCells.Add(dataGridViewCell); 
            }

            // AutoSize column and row if needed
            OnCellCommonChange(columnIndex, dataGridViewRow.Index); 

            if (this.ptCurrentCellCache.X != -1) 
            { 
                if (!IsInnerCellOutOfBounds(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y))
                { 
                    SetCurrentCellAddressCore(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y, false, false, false);
                }
                this.ptCurrentCellCache.X = -1;
                this.ptCurrentCellCache.Y = -1; 
            }
        } 
 
        internal void OnReplacingCell(DataGridViewRow dataGridViewRow, int columnIndex)
        { 
            if (this.ptCurrentCell.X == dataGridViewRow.Index &&
                this.ptCurrentCell.Y == columnIndex)
            {
                // Trying to replace the current cell. Exiting editing mode first (if needed). 
                // Remember to reset the current cell in OnReplacedCell notification
                this.ptCurrentCellCache.X = this.ptCurrentCell.X; 
                this.ptCurrentCellCache.Y = this.ptCurrentCell.Y; 
                // This may fail and throw an exception
                ResetCurrentCell(); 
            }
            else
            {
                this.ptCurrentCellCache.X = -1; 
                this.ptCurrentCellCache.Y = -1;
            } 
            DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex]; 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected] = this.individualSelectedCells.Contains(dataGridViewCell);
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected]) 
            {
                this.individualSelectedCells.Remove(dataGridViewCell);
            }
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly] = this.individualReadOnlyCells.Contains(dataGridViewCell); 
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly])
            { 
                this.individualReadOnlyCells.Remove(dataGridViewCell); 
            }
        } 

        /// 
        protected override void OnResize(EventArgs e)
        { 
            int borderWidth = this.BorderWidth;
            Rectangle right; 
            Rectangle bottom; 
            Rectangle oldClientRectangle = this.layout.ClientRectangle;
 
            right = new Rectangle(oldClientRectangle.X + oldClientRectangle.Width - borderWidth,
                oldClientRectangle.Y,
                borderWidth,
                oldClientRectangle.Height); 
            bottom = new Rectangle(oldClientRectangle.X,
                oldClientRectangle.Y + oldClientRectangle.Height - borderWidth, 
                oldClientRectangle.Width, 
                borderWidth);
 
            if (!this.IsMinimized)
            {
                // When owning form is minimized, act as if it had a normal size
                this.normalClientRectangle = this.ClientRectangle; 
            }
 
            Rectangle newClientRectangle = this.normalClientRectangle; 
            if (newClientRectangle.Width != oldClientRectangle.Width)
            { 
                Invalidate(right);
                right = new Rectangle(newClientRectangle.X + newClientRectangle.Width - borderWidth,
                    newClientRectangle.Y,
                    borderWidth, 
                    newClientRectangle.Height);
                Invalidate(right); 
            } 
            if (newClientRectangle.Height != oldClientRectangle.Height)
            { 
                Invalidate(bottom);
                bottom = new Rectangle(newClientRectangle.X,
                    newClientRectangle.Y + newClientRectangle.Height - borderWidth,
                    newClientRectangle.Width, 
                    borderWidth);
                Invalidate(bottom); 
            } 

            //also, invalidate the ResizeBoxRect 
            if (!this.layout.ResizeBoxRect.IsEmpty)
            {
                Invalidate(this.layout.ResizeBoxRect);
            } 
            this.layout.ClientRectangle = newClientRectangle;
 
            int oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
            base.OnResize(e);
            if (oldfirstDisplayedScrollingRow != this.displayedBandsInfo.FirstDisplayedScrollingRow) 
            {
                Invalidate();
            }
        } 

        ///  
        protected override void OnRightToLeftChanged(EventArgs e) 
        {
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_rightToLeftValid] = false; 
            base.OnRightToLeftChanged(e);
            CorrectFocus(true /*onlyIfGridHasFocus*/);
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
        } 

        internal void OnRowCollectionChanged_PostNotification(bool recreateNewRow, 
                                                              bool allowSettingCurrentCell, 
                                                              CollectionChangeAction cca,
                                                              DataGridViewRow dataGridViewRow, 
                                                              int rowIndex)
        {
            if (recreateNewRow &&
                cca == CollectionChangeAction.Refresh && 
                this.Columns.Count != 0 &&
                this.Rows.Count == 0 && 
                this.AllowUserToAddRowsInternal) 
            {
                AddNewRow(false); 
            }

            if (cca == CollectionChangeAction.Refresh)
            { 
                FlushSelectionChanged();
            } 
 
            if ((cca == CollectionChangeAction.Refresh || cca == CollectionChangeAction.Add) &&
                this.ptCurrentCell.X == -1 && allowSettingCurrentCell && !this.InSortOperation) 
            {
                MakeFirstDisplayedCellCurrentCell(false /*includeNewRow*/);
            }
 
            if (this.AutoSize)
            { 
                bool invalidatePreferredSizeCache = true; 
                switch (cca)
                { 
                    case CollectionChangeAction.Add:
                        Debug.Assert(rowIndex >= 0);
                        DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
                        invalidatePreferredSizeCache = ((rowState & DataGridViewElementStates.Visible) != 0); 
                        break;
                    case CollectionChangeAction.Remove: 
                        invalidatePreferredSizeCache = dataGridViewRow.DataGridView == null && dataGridViewRow.Visible; 
                        break;
                    // case CollectionChangeAction.Refresh: invalidatePreferredSizeCache stays true 
                }
                if (invalidatePreferredSizeCache)
                {
                    LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows); 
                }
            } 
        } 

        ///  
        protected virtual void OnRowContextMenuStripChanged(DataGridViewRowEventArgs e)
        {
            if (e.Row.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            } 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWCONTEXTMENUSTRIPCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal ContextMenuStrip OnRowContextMenuStripNeeded(int rowIndex, ContextMenuStrip contextMenuStrip)
        { 
            DataGridViewRowContextMenuStripNeededEventArgs dgvrcmsne = new DataGridViewRowContextMenuStripNeededEventArgs(rowIndex, contextMenuStrip); 
            OnRowContextMenuStripNeeded(dgvrcmsne);
            return dgvrcmsne.ContextMenuStrip; 
        }

        /// 
        protected virtual void OnRowContextMenuStripNeeded(DataGridViewRowContextMenuStripNeededEventArgs e) 
        {
            DataGridViewRowContextMenuStripNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWCONTEXTMENUSTRIPNEEDED] as DataGridViewRowContextMenuStripNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnRowDefaultCellStyleChanged(DataGridViewRowEventArgs e)
        { 
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            }

            OnRowGlobalAutoSize(e.Row.Index);
 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDEFAULTCELLSTYLECHANGED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnRowDirtyStateNeeded(QuestionEventArgs e) 
        {
            QuestionEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIRTYSTATENEEDED] as QuestionEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnRowDividerDoubleClick(DataGridViewRowDividerDoubleClickEventArgs e)
        { 
            DataGridViewRowDividerDoubleClickEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIVIDERDOUBLECLICK] as DataGridViewRowDividerDoubleClickEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }

            if (!e.Handled && e.Button == MouseButtons.Left && e.RowIndex < this.Rows.Count) 
            {
                if (e.RowIndex == -1) 
                { 
                    AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
                } 
                else
                {
                    if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                    { 
                        AutoResizeRowInternal(e.RowIndex, DataGridViewAutoSizeRowMode.AllCells, true /*fixedWidth*/, true /*internalAutosizing*/);
                    } 
                    else 
                    {
                        AutoResizeRowInternal(e.RowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnRowDividerHeightChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            }
 
            OnRowGlobalAutoSize(e.Row.Index);
 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIVIDERHEIGHTCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        private void OnRowEnter(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, bool canCreateNewRow, bool validationFailureOccurred)
        { 
            Debug.Assert(columnIndex >= 0 && rowIndex >= 0); 

            if (!validationFailureOccurred) 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] = false;
            }
            if (rowIndex < this.Rows.Count && 
                columnIndex < this.Columns.Count)
            { 
                bool calledAddNewOnTheDataConnection = false; 
                if (!validationFailureOccurred && this.AllowUserToAddRowsInternal && this.newRowIndex == rowIndex)
                { 
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] = true;

                    if (canCreateNewRow)
                    { 
                        DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(this.Rows[this.newRowIndex]);
                        if (this.VirtualMode || this.DataSource != null) 
                        { 
                            if (this.dataConnection != null && this.dataConnection.InterestedInRowEvents)
                            { 
                                this.dataConnection.OnNewRowNeeded();
                                calledAddNewOnTheDataConnection = true;
                            }
                            if (this.VirtualMode) 
                            {
                                OnNewRowNeeded(dgvre); 
                            } 
                        }
 
                        // vsWhidbey 329429: AllowUserToAddRowsInternal can become FALSE while adding a row.
                        // NOTE: we don't need to invalidate if AllowUserToAddRowsInternal changed to FALSE.
                        //
                        if (this.AllowUserToAddRowsInternal) 
                        {
                            OnDefaultValuesNeeded(dgvre); 
                            InvalidateRowPrivate(this.newRowIndex); 
                        }
                        #if DEBUG 
                        else
                        {
                            Debug.Assert(this.newRowIndex == -1, "newRowIndex and AllowUserToAddRowsInternal became out of [....]");
                        } 
                        #endif //
                    } 
                } 

                if (calledAddNewOnTheDataConnection && rowIndex > this.Rows.Count - 1) 
                {
                    // Calling AddNew on the DataConnection can result in the entire list being wiped out.
                    //
                    rowIndex = Math.Min(rowIndex, this.Rows.Count - 1); 
                }
 
                DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); 
                OnRowEnter(dgvce);
                if (this.dataConnection != null && 
                    this.dataConnection.InterestedInRowEvents &&
                    !this.dataConnection.PositionChangingOutsideDataGridView &&
                    !this.dataConnection.ListWasReset &&
                    (!calledAddNewOnTheDataConnection || this.dataConnection.List.Count > 0)) 
                {
                    this.dataConnection.OnRowEnter(dgvce); 
                } 

                if (dataGridViewCell != null) 
                {
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                    {
                        dataGridViewCell = null; 
                    }
                    else 
                    { 
                        Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                        dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnRowEnter(DataGridViewCellEventArgs e) 
        {
            try 
            {
                this.noDimensionChangeCount++;

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWENTER] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            }
            finally
            {
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
            } 
        } 

        internal void OnRowErrorTextChanged(DataGridViewRow dataGridViewRow) 
        {
            DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
            OnRowErrorTextChanged(dgvre);
        } 

        ///  
        protected virtual void OnRowErrorTextChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            }
            UpdateRowErrorText(e.Row.Index); 

            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWERRORTEXTCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal string OnRowErrorTextNeeded(int rowIndex, string errorText) 
        {
            Debug.Assert(rowIndex >= 0); 
            DataGridViewRowErrorTextNeededEventArgs dgvretne = new DataGridViewRowErrorTextNeededEventArgs(rowIndex, errorText); 
            OnRowErrorTextNeeded(dgvretne);
            return dgvretne.ErrorText; 
        }

        /// 
        protected virtual void OnRowErrorTextNeeded(DataGridViewRowErrorTextNeededEventArgs e) 
        {
            DataGridViewRowErrorTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWERRORTEXTNEEDED] as DataGridViewRowErrorTextNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        private void OnRowGlobalAutoSize(int rowIndex) 
        {
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if ((rowState & DataGridViewElementStates.Visible) == 0) 
            {
                return; 
            }

            InvalidateRowPrivate(rowIndex);
 
            if (this.noAutoSizeCount > 0)
            { 
                return; 
            }
 
            DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode;
            bool autoSizeRow = false;
            bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0;
            if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None && 
                !((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed))
            { 
                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/); 
                autoSizeRow = true;
            } 

            // Auto size columms also if needed
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows;
            if (rowDisplayed) 
            {
                autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; 
            } 
            AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/);
 
            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing ||
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing;
            // Auto size column headers
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/); 
            } 

            // Auto size row headers 
            if (!fixedRowHeadersWidth)
            {
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            } 

            if (autoSizeRow) 
            { 
                // Second round of row autosizing
                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
            }

            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize && !fixedRowHeadersWidth)
            { 
                // Second round of column headers autosizing
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); 
            } 
        }
 
        /// 
        protected virtual void OnRowHeaderCellChanged(DataGridViewRowEventArgs e)
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            } 

            OnRowHeaderGlobalAutoSize(e.Row.Index); 

            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERCELLCHANGED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        private void OnRowHeaderGlobalAutoSize(int rowIndex) 
        {
            if (!this.RowHeadersVisible)
            {
                return; 
            }
 
            InvalidateCellPrivate(-1, rowIndex); 

            if (this.noAutoSizeCount > 0) 
            {
                return;
            }
 
            bool rowDisplayed = false;
            if (rowIndex != -1) 
            { 
                rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0;
            } 

            bool fixedColumnHeadersHeight = rowIndex != -1 || this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            bool fixedRowHeight = rowIndex == -1 ||
                                  ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) == 0) || 
                                  ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && rowIndex != -1 && !rowDisplayed);
 
            bool autoSizeRowHeaders = false; 
            if (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders ||
                (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders && rowIndex != -1 && rowDisplayed) || 
                (this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing && rowIndex == -1) ||
                (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader && rowIndex != -1 && rowIndex == this.Rows.GetFirstRow(DataGridViewElementStates.Visible)))
            {
                AutoResizeRowHeadersWidth(rowIndex, 
                                          this.rowHeadersWidthSizeMode,
                                          fixedColumnHeadersHeight, 
                                          fixedRowHeight); 
                autoSizeRowHeaders = true;
            } 
            if (!fixedColumnHeadersHeight)
            {
                AutoResizeColumnHeadersHeight(-1, true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            } 
            if (!fixedRowHeight)
            { 
                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
 
            if (autoSizeRowHeaders && (!fixedColumnHeadersHeight || !fixedRowHeight))
            {
                // Second round of row headers autosizing
                AutoResizeRowHeadersWidth(rowIndex, 
                                          this.rowHeadersWidthSizeMode,
                                          true /*fixedColumnHeadersHeight*/, 
                                          true /*fixedRowHeight*/); 
            }
        } 

        /// 
        protected virtual void OnRowHeaderMouseClick(DataGridViewCellMouseEventArgs e)
        { 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERMOUSECLICK] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnRowHeaderMouseDoubleClick(DataGridViewCellMouseEventArgs e) 
        {
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        private void OnRowHeaderMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown) 
        {
            Debug.Assert(hti.Type == DataGridViewHitTestType.RowHeader); 
            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.FullColumnSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        break; 
 
                    case DataGridViewSelectionMode.FullRowSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                    {
                        bool select = true;
                        if (isControlDown &&
                            ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)) 
                        {
                            select = false; 
                        } 
                        if (select)
                        { 
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                            if (dataGridViewColumn != null && hti.row != this.ptCurrentCell.Y)
                            {
                                int oldCurrentCellX = this.ptCurrentCell.X; 
                                int oldCurrentCellY = this.ptCurrentCell.Y;
                                // Make sure we will be able to scroll into view 
                                if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange, 
                                    DataGridViewValidateCellInternal.Always /*validateCell*/,
                                    true /*fireCellLeave*/, 
                                    true /*fireCellEnter*/,
                                    hti.row != this.ptCurrentCell.Y /*fireRowLeave*/,
                                    hti.row != this.ptCurrentCell.Y /*fireRowEnter*/,
                                    false /*fireLeave*/, 
                                    this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/,
                                    true /*resetCurrentCell*/, 
                                    false /*resetAnchorCell*/)) 
                                {
                                    // Just cancel operation silently instead of throwing InvalidOperationException 
                                    return;
                                }
                                if (oldCurrentCellY != -1)
                                { 
                                    DataGridViewCell dataGridViewCellTmp = null;
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    { 
                                        return;
                                    } 
                                    if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY))
                                    {
                                        // Row validation was cancelled
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                        {
                                            return; 
                                        } 
                                        OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/);
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                        {
                                            return;
                                        }
                                        OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                        return;
                                    } 
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        return; 
                                    }
                                    OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);

                                    // Row validation was not cancelled, but operation needs to be re-evaluated. 
                                    if (hti.row >= this.Rows.Count)
                                    { 
                                        int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); 
                                        if (this.ptCurrentCell.X == -1 && lastVisibleRowIndex != -1)
                                        { 
                                            // CurrentCell was reset because commit deleted row(s).
                                            // Since the user wants to select a row, 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'. 
                                            if (IsColumnOutOfBounds(oldCurrentCellX))
                                            { 
                                                return; 
                                            }
                                            bool success = SetAndSelectCurrentCellAddress(oldCurrentCellX, 
                                                                                          lastVisibleRowIndex,
                                                                                          true,
                                                                                          false,
                                                                                          false, 
                                                                                          false /*clearSelection*/,
                                                                                          false /*forceCurrentCellSelection*/); 
                                            Debug.Assert(success); 
                                        }
                                        return; 
                                    }
                                    else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Visible) == 0)
                                    {
                                        return; 
                                    }
                                } 
                            } 
                            bool selectRowRange = false;
                            this.trackRow = hti.row; 
                            this.trackRowEdge = -1;
                            if (this.MultiSelect &&
                                isShiftDown &&
                                this.ptAnchorCell.Y > -1 && 
                                (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Selected) != 0)
                            { 
                                selectRowRange = true; 
                            }
                            if (!this.MultiSelect || !isControlDown || isShiftDown) 
                            {
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1);
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                                { 
                                    this.inBulkPaintCount++; 
                                    switchedToBulkPaint = true;
                                } 
                                try
                                {
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.row)
                                        { 
                                            // deselect currently selected row 
                                            SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false);
                                        } 
                                        else
                                        {
                                            bandIndex++;
                                        } 
                                    }
 
                                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) 
                                    {
                                        RemoveIndividuallySelectedCells(); 
                                    }
                                    else
                                    {
                                        Debug.Assert(this.individualSelectedCells.Count == 0); 
                                    }
                                } 
                                finally 
                                {
                                    if (switchedToBulkPaint) 
                                    {
                                        ExitBulkPaint(-1, -1);
                                    }
                                } 
                            }
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) 
                            { 
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = true;
                            } 
                            if (selectRowRange)
                            {
                                if (hti.row >= this.ptAnchorCell.Y)
                                { 
                                    SelectRowRange(this.ptAnchorCell.Y, hti.row, true);
                                } 
                                else 
                                {
                                    SelectRowRange(hti.row, this.ptAnchorCell.Y, true); 
                                }
                            }
                            else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) == 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(hti.row) ==
                                             ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)); 
                                SetSelectedRowCore(hti.row, true); 
                            }
                            if (dataGridViewColumn != null) 
                            {
                                if (hti.row != this.ptCurrentCell.Y)
                                {
                                    if (IsInnerCellOutOfBounds(dataGridViewColumn.Index, hti.row)) 
                                    {
                                        return; 
                                    } 
                                    // set current cell to the left most visible cell in the row
                                    bool success = ScrollIntoView(dataGridViewColumn.Index, hti.row, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(dataGridViewColumn.Index, hti.row))
                                    {
                                        return; 
                                    }
                                    success = SetCurrentCellAddressCore(dataGridViewColumn.Index, hti.row, !selectRowRange, false, true); 
                                    Debug.Assert(success); 
                                }
                                else if (-1 != this.ptCurrentCell.Y) 
                                {
                                    // Potentially have to give focus back to the current edited cell.
                                    bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y,
                                                                            false /*setAnchorCellAddress*/, 
                                                                            false /*validateCurrentCell*/,
                                                                            false /*throughMouseClick*/); 
                                    Debug.Assert(success); 
                                }
                            } 
                            else
                            {
                                Debug.Assert(this.CurrentCellAddress == new Point(-1, -1));
                            } 
                        }
                        else 
                        { 
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.row));
                            SetSelectedRowCore(hti.row, false); 
                        }
                        break;
                    }
                } 
            }
            finally 
            { 
                this.NoSelectionChangeCount--;
            } 
        }

        /// 
        protected virtual void OnRowHeadersBorderStyleChanged(EventArgs e) 
        {
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
            Invalidate(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSBORDERSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        protected virtual void OnRowHeadersDefaultCellStyleChanged(EventArgs e)
        { 
            if (this.RowHeadersVisible)
            {
                Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.RowHeaders));
 
                DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
                if (dgvcsce == null || dgvcsce.ChangeAffectsPreferredSize) 
                { 
                    OnRowHeadersGlobalAutoSize(false /*expandingRows*/);
                    if (this.editingControl != null) 
                    {
                        PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                    }
                } 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        private void OnRowHeadersGlobalAutoSize(bool expandingRows)
        { 
            if (this.noAutoSizeCount > 0) 
            {
                return; 
            }

            bool fixedRowsHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) == 0 ||
                                   !this.RowHeadersVisible; 
            bool autoSizeRowHeaders = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                                      this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            if (autoSizeRowHeaders) 
            {
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, fixedRowsHeight); 
            }

            if (!fixedRowsHeight)
            { 
                if (expandingRows)
                { 
                    AdjustExpandingRows(-1, true /*fixedWidth*/); 
                }
                else 
                {
                    AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                }
 
                if (autoSizeRowHeaders)
                { 
                    // Second round of row headers autosizing 
                    AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
                } 
            }
        }

        ///  
        protected virtual void OnRowHeadersWidthChanged(EventArgs e)
        { 
            if (this.RowHeadersVisible) 
            {
                if (this.editingControl != null) 
                {
                    PositionEditingControl(true, false, false);
                }
 
                UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
 
                OnRowHeadersGlobalAutoSize(false /*expandingRows*/); 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSWIDTHCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnRowHeadersWidthSizeModeChanged(DataGridViewAutoSizeModeEventArgs e) 
        {
            if (this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing)
            { 
                if (!e.PreviousModeAutoSized)
                { 
                    // Save current row headers width for later reuse 
                    this.cachedRowHeadersWidth = this.RowHeadersWidth;
                } 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode,
                                          true /*fixedColumnHeadersHeight*/,
                                          true /*fixedRowsHeight*/);
            } 
            else if (e.PreviousModeAutoSized)
            { 
                this.RowHeadersWidth = this.cachedRowHeadersWidth; 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSWIDTHSIZEMODECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnRowHeightChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            }
            UpdateRowHeightInfoPrivate(e.Row.Index, false, false /*invalidInAdjustFillingColumns*/); 
 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTCHANGED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
 
            OnRowGlobalAutoSize(e.Row.Index);
        } 
 
        internal DataGridViewRowHeightInfoNeededEventArgs OnRowHeightInfoNeeded(int rowIndex, int height, int minimumHeight)
        { 
            DataGridViewRowHeightInfoNeededEventArgs dgvrhine = this.RowHeightInfoNeededEventArgs;
            dgvrhine.SetProperties(rowIndex, height, minimumHeight);
            OnRowHeightInfoNeeded(dgvrhine);
            return dgvrhine; 
        }
 
        ///  
        protected virtual void OnRowHeightInfoNeeded(DataGridViewRowHeightInfoNeededEventArgs e)
        { 
            DataGridViewRowHeightInfoNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTINFONEEDED] as DataGridViewRowHeightInfoNeededEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        private bool OnRowHeightInfoPushed(int rowIndex, int height, int minimumHeight)
        { 
            Debug.Assert(rowIndex != -1);
            Debug.Assert(this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None);
            if (this.VirtualMode || this.DataSource != null)
            { 
                DataGridViewRowHeightInfoPushedEventArgs dgvrhipe = new DataGridViewRowHeightInfoPushedEventArgs(rowIndex, height, minimumHeight);
                OnRowHeightInfoPushed(dgvrhipe); 
                if (dgvrhipe.Handled) 
                {
                    UpdateRowHeightInfoPrivate(rowIndex, false, true /*invalidInAdjustFillingColumns*/); 
                    return true;
                }
            }
            return false; 
        }
 
        ///  
        protected virtual void OnRowHeightInfoPushed(DataGridViewRowHeightInfoPushedEventArgs e)
        { 
            DataGridViewRowHeightInfoPushedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTINFOPUSHED] as DataGridViewRowHeightInfoPushedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        private void OnRowLeave(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        { 
            Debug.Assert(columnIndex >= 0 && rowIndex >= 0);
            if (rowIndex < this.Rows.Count && columnIndex < this.Columns.Count)
            {
                DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); 
                OnRowLeave(dgvce);
                if (dataGridViewCell != null) 
                { 
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                    { 
                        dataGridViewCell = null;
                    }
                    else
                    { 
                        Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                        dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; 
                    } 
                }
            } 
        }

        /// 
        protected virtual void OnRowLeave(DataGridViewCellEventArgs e) 
        {
            try 
            { 
                this.noDimensionChangeCount++;
 
                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWLEAVE] as DataGridViewCellEventHandler;
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                {
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            } 
            finally
            { 
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0);
            }
        } 

        ///  
        protected virtual void OnRowMinimumHeightChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            }
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWMINIMUMHEIGHTCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected internal virtual void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
        { 
            DataGridViewRowPostPaintEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWPOSTPAINT] as DataGridViewRowPostPaintEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected internal virtual void OnRowPrePaint(DataGridViewRowPrePaintEventArgs e) 
        {
            DataGridViewRowPrePaintEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWPREPAINT] as DataGridViewRowPrePaintEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnRowsAddedInternal(int rowIndex, int rowCount) 
        {
            OnRowsAdded(new DataGridViewRowsAddedEventArgs(rowIndex, rowCount)); 
        } 

        ///  
        protected virtual void OnRowsAdded(DataGridViewRowsAddedEventArgs e)
        {
            DataGridViewRowsAddedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSADDED] as DataGridViewRowsAddedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnRowsDefaultCellStyleChanged(EventArgs e)
        {
            DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs; 
            if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize)
            { 
                InvalidateData(); 
            }
            else 
            {
                OnRowsGlobalAutoSize();
                if (this.editingControl != null)
                { 
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                } 
            } 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        private void OnRowSelectMouseMove(HitTestInfo hti) 
        {
            Debug.Assert(hti.row >= 0); 
            Debug.Assert(this.MultiSelect);

            if (this.ptCurrentCell.Y != -1 &&
                hti.row != this.ptCurrentCell.Y && 
                !CommitEditForOperation(this.ptCurrentCell.X, hti.row, true))
            { 
                // Return silently if validating/commit/abort failed 
                return;
            } 
            if (IsRowOutOfBounds(hti.row))
            {
                return;
            } 

            this.noSelectionChangeCount++; 
            try 
            {
                if (this.trackRowEdge >= this.trackRow && hti.row > this.trackRowEdge && this.trackRowEdge >= 0) 
                {
                    SelectRowRange(this.Rows.GetNextRow(this.trackRowEdge, DataGridViewElementStates.Visible),
                        hti.row, true);
                    this.trackRowEdge = hti.row; 
                }
                else if (this.trackRowEdge > this.trackRow && hti.row < this.trackRowEdge && hti.row >= this.trackRow && this.trackRowEdge >= 0) 
                { 
                    SelectRowRange(this.Rows.GetNextRow(hti.row, DataGridViewElementStates.Visible),
                        this.trackRowEdge, false); 
                    this.trackRowEdge = hti.row;
                }
                else if (hti.row > this.trackRow && this.trackRowEdge == -1)
                { 
                    SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible),
                        hti.row, true); 
                    this.trackRowEdge = hti.row; 
                }
                else if (this.trackRowEdge <= this.trackRow && hti.row < this.trackRowEdge && this.trackRowEdge >= 0) 
                {
                    SelectRowRange(hti.row,
                        this.Rows.GetPreviousRow(this.trackRowEdge, DataGridViewElementStates.Visible),
                        true); 
                    this.trackRowEdge = hti.row;
                } 
                else if (this.trackRowEdge < this.trackRow && hti.row > this.trackRowEdge && hti.row <= this.trackRow && this.trackRowEdge >= 0) 
                {
                    SelectRowRange(this.trackRowEdge, 
                        this.Rows.GetPreviousRow(hti.row, DataGridViewElementStates.Visible),
                        false);
                    this.trackRowEdge = hti.row;
                } 
                else if (hti.row < this.trackRow && this.trackRowEdge == -1)
                { 
                    SelectRowRange(hti.row, 
                        this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible),
                        true); 
                    this.trackRowEdge = hti.row;
                }
                else if (this.trackRowEdge > this.trackRow && hti.row < this.trackRow)
                { 
                    SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible),
                        this.trackRowEdge, false); 
                    SelectRowRange(hti.row, 
                        this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible),
                        true); 
                    this.trackRowEdge = hti.row;
                }
                else if (hti.row > this.trackRow && this.trackRowEdge < this.trackRow && this.trackRowEdge >= 0)
                { 
                    SelectRowRange(this.trackRowEdge,
                        this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible), 
                        false); 
                    SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible),
                        hti.row, true); 
                    this.trackRowEdge = hti.row;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 

            if (this.ptCurrentCell.Y != -1 && hti.row != this.ptCurrentCell.Y) 
            {
                if (IsRowOutOfBounds(hti.row))
                {
                    return; 
                }
                bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, 
                    hti.row, 
                    false /*setAnchorCellAddress*/,
                    false /*validateCurrentCell*/, 
                    false /*throughMouseClick*/);
                Debug.Assert(success);
            }
        } 

        private void OnRowsGlobalAutoSize() 
        { 
            InvalidateData();
 
            if (this.noAutoSizeCount > 0)
            {
                return;
            } 

            // Autosize rows if needed 
            if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) 
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/); 
            }

            // Auto size columms also if needed
            AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | 
                                                DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows,
                                                true /*fixedHeight*/); 
 
            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing ||
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            // Auto size column headers
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
            {
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/); 
            }
 
            // Auto size row headers 
            if (!fixedRowHeadersWidth)
            { 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            }

            // Second round of rows autosizing 
            if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
            { 
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
 
            // Second round of column headers autosizing
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize && !fixedRowHeadersWidth)
            {
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); 
            }
        } 
 
        internal void OnRowsRemovedInternal(int rowIndex, int rowCount)
        { 
            OnRowsRemoved(new DataGridViewRowsRemovedEventArgs(rowIndex, rowCount));
        }

        ///  
        protected virtual void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e)
        { 
            DataGridViewRowsRemovedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSREMOVED] as DataGridViewRowsRemovedEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        /// 
        protected virtual void OnRowStateChanged(int rowIndex, DataGridViewRowStateChangedEventArgs e) 
        { 
            Debug.Assert(rowIndex >= -1);
 
            // If row.Frozen changed, we need to update the vertical scroll bar
            // A hidden row may become visible and vice-versa, we'd better repaint the whole control
            DataGridViewRow dataGridViewRow = e.Row;
            DataGridViewElementStates newState = DataGridViewElementStates.None; 
            bool rowVisible = false;
            if (rowIndex >= 0) 
            { 
                newState = this.Rows.GetRowState(rowIndex);
                rowVisible = ((newState & DataGridViewElementStates.Visible) != 0); 
            }
            switch (e.StateChanged)
            {
                // At this point we assume that only the Selected state has an influence on the rendering of the row. 
                // If there is a customer scenario where another state has an influence, the dev will have to invalidate the row by hand.
                // case DataGridViewElementStates.ReadOnly: 
                // case DataGridViewElementStates.Resizable: 

                case DataGridViewElementStates.Selected: 
                    if (rowVisible && this.inBulkPaintCount == 0)
                    {
                        InvalidateRowPrivate(rowIndex);
                    } 
                    break;
 
                case DataGridViewElementStates.Frozen: 
                    if (rowVisible)
                    { 
                        if ((newState & DataGridViewElementStates.Frozen) == 0)
                        {
                            // row was unfrozen - make it the first visible scrolling row if there is room
                            FirstVisibleScrollingRowTempted(rowIndex); 
                        }
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); 
                        Invalidate(); 
                    }
                    break; 

                case DataGridViewElementStates.Visible:
                {
                    if (!rowVisible && (newState & DataGridViewElementStates.Displayed) != 0) 
                    {
                        // Displayed row becomes invisible. Turns off the Displayed state. 
                        this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Displayed, false); 
                    }
 
                    PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/);
                    Invalidate();

                    bool rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0; 
                    DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode;
 
                    bool autoSizeRow = false; 

                    if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None) 
                    {
                        int height = dataGridViewRow.ThicknessInternal;
                        if (rowVisible)
                        { 
                            // Cache row's height before potential autosizing occurs
                            // Valid operation even for shared rows 
                            dataGridViewRow.CachedThickness = height; 
                            if (!((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed))
                            { 
                                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/);
                                autoSizeRow = true;
                            }
                        } 
                        else if (height != dataGridViewRow.CachedThickness)
                        { 
                            // Rows that are made invisible in the collection take their non-autosized height 
                            // Not calling OnRowHeightInfoPushed(...) because rows are autosized
                            // Make sure the affected row is unshared 
                            if (dataGridViewRow.Index == -1)
                            {
                                dataGridViewRow = this.Rows[rowIndex];
                            } 
                            dataGridViewRow.ThicknessInternal = Math.Max(dataGridViewRow.MinimumHeight, dataGridViewRow.CachedThickness);
                        } 
                    } 

                    // Auto size columms also if needed 
                    DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows;
                    if (rowDisplayed)
                    {
                        autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; 
                    }
                    if (rowVisible && this.Rows.GetRowCount(DataGridViewElementStates.Visible) > 1) 
                    { 
                        // Columns can only expand, and not collapse.
                        AdjustExpandingColumns(autoSizeColumnCriteriaFilter, rowIndex); 
                    }
                    else
                    {
                        AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/); 
                    }
 
                    if (autoSizeRow) 
                    {
                        // Second round of row autosizing 
                        AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/);
                    }
                    break;
                } 
            }
 
            DataGridViewRowStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSTATECHANGED] as DataGridViewRowStateChangedEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }

            if (e.StateChanged == DataGridViewElementStates.ReadOnly && 
                rowIndex == this.ptCurrentCell.Y &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
            { 
                VerifyImeRestrictedModeChanged();
 
                if ((newState & DataGridViewElementStates.ReadOnly) == 0 &&
                    !this.ReadOnly &&
                    !this.Columns[this.ptCurrentCell.X].ReadOnly &&
                    ColumnEditable(this.ptCurrentCell.X) && 
                    !this.IsCurrentCellInEditMode &&
                    (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                    (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))) 
                {
                    // Current row becomes read/write. Enter editing mode. 
                    BeginEditInternal(true /*selectAll*/);
                }
            }
        } 

        internal void OnRowUnshared(DataGridViewRow dataGridViewRow) 
        { 
            if (-1 != this.ptCurrentCell.X && dataGridViewRow.Index == this.ptCurrentCell.Y && this.editingControl != null)
            { 
                this.CurrentCellInternal.CacheEditingControl();
            }
            DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
            OnRowUnshared(dgvre); 
        }
 
        ///  
        protected virtual void OnRowUnshared(DataGridViewRowEventArgs e)
        { 
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            } 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWUNSHARED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        private bool OnRowValidating(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        { 
            DataGridViewCellCancelEventArgs dgvcce = new DataGridViewCellCancelEventArgs(columnIndex, rowIndex);
            OnRowValidating(dgvcce); 
            if (!dgvcce.Cancel) 
            {
                if (this.dataConnection != null && 
                    this.dataConnection.InterestedInRowEvents &&
                    !this.dataConnection.PositionChangingOutsideDataGridView &&
                    !this.dataConnection.ListWasReset)
                { 
                    this.dataConnection.OnRowValidating(dgvcce);
                } 
            } 
            if (dataGridViewCell != null && rowIndex < this.Rows.Count && columnIndex < this.Columns.Count)
            { 
                dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
            }
            return dgvcce.Cancel;
        } 

        ///  
        protected virtual void OnRowValidating(DataGridViewCellCancelEventArgs e) 
        {
            try 
            {
                this.noDimensionChangeCount++;

                DataGridViewCellCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWVALIDATING] as DataGridViewCellCancelEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            }
            finally
            {
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
            } 
        } 

        private void OnRowValidated(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) 
        {
            this.IsCurrentRowDirtyInternal = false;
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowCreatedByEditing] = false;
            if (rowIndex == this.newRowIndex) 
            {
                // Stop displaying the default cell values on the 'new row'. 
                InvalidateRowPrivate(rowIndex); 
            }
 
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex);
            OnRowValidated(dgvce);
            if (dataGridViewCell != null)
            { 
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    dataGridViewCell = null; 
                }
                else 
                {
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                } 
            }
        } 
 
        /// 
        protected virtual void OnRowValidated(DataGridViewCellEventArgs e) 
        {
            try
            {
                this.noDimensionChangeCount++; 

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWVALIDATED] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
                {
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                }
            }
            finally 
            {
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0); 
            }
        } 

        private void OnScroll(ScrollEventType scrollEventType, int oldValue, int newValue, ScrollOrientation orientation)
        {
            ScrollEventArgs se = new ScrollEventArgs(scrollEventType, oldValue, newValue, orientation); 
            OnScroll(se);
            if (ScrollOrientation.VerticalScroll == orientation) 
            { 
                if (se.NewValue != newValue)
                { 
                    try
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll] = true;
                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                        int rowIndexPrevious = rowIndex;
                        newValue = se.NewValue; 
                        while (rowIndex != -1 && newValue > 0) 
                        {
                            rowIndexPrevious = rowIndex; 
                            rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                            newValue--;
                        }
                        if (rowIndex != -1) 
                        {
                            rowIndexPrevious = rowIndex; 
                        } 
                        if (rowIndexPrevious != -1)
                        { 
                            this.FirstDisplayedScrollingRowIndex = rowIndexPrevious;
                        }
                    }
                    finally 
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll] = false; 
                    } 
                }
            } 
            else
            {
                if (se.NewValue != newValue)
                { 
                    try
                    { 
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingHorizontalScroll] = true; 
                        this.HorizontalOffset = se.NewValue;
                    } 
                    finally
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingHorizontalScroll] = false;
                    } 
                }
            } 
        } 

        ///  
        protected virtual void OnScroll(ScrollEventArgs e)
        {
            ScrollEventHandler eh = this.Events[EVENT_DATAGRIDVIEWSCROLL] as ScrollEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnSelectionChanged(EventArgs e)
        {
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = false; 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWSELECTIONCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal bool OnSortCompare(DataGridViewColumn dataGridViewSortedColumn, object value1, object value2, int rowIndex1, int rowIndex2, out int sortResult) 
        {
            DataGridViewSortCompareEventArgs dgvsce = new DataGridViewSortCompareEventArgs(dataGridViewSortedColumn, value1, value2, rowIndex1, rowIndex2); 
            OnSortCompare(dgvsce); 
            sortResult = dgvsce.SortResult;
            return dgvsce.Handled; 
        }

        /// 
        protected virtual void OnSortCompare(DataGridViewSortCompareEventArgs e) 
        {
            DataGridViewSortCompareEventHandler eh = this.Events[EVENT_DATAGRIDVIEWSORTCOMPARE] as DataGridViewSortCompareEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnSorted(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWSORTED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnSortGlyphDirectionChanged(DataGridViewColumnHeaderCell dataGridViewColumnHeaderCell)
        { 
            Debug.Assert(dataGridViewColumnHeaderCell != null); 

            if (dataGridViewColumnHeaderCell.OwningColumn == this.SortedColumn) 
            {
                if (dataGridViewColumnHeaderCell.SortGlyphDirection == SortOrder.None)
                {
                    this.sortedColumn = null; 
                    DataGridViewColumn dataGridViewColumn = dataGridViewColumnHeaderCell.OwningColumn;
 
                    if (dataGridViewColumn.IsDataBound) 
                    {
                        // If the column whose SortGlyphChanges is the sorted column and it is also the dataBound column 
                        // then see if there is another dataBound column which has the same property name as the sorted column.
                        // If so, then make that dataGridViewColumn the sorted column in the data grid view.
                        for (int i = 0; i < this.Columns.Count; i ++)
                        { 
                            if (dataGridViewColumn != this.Columns[i] &&
                                this.Columns[i].SortMode != DataGridViewColumnSortMode.NotSortable && 
                                String.Compare(dataGridViewColumn.DataPropertyName, 
                                               this.Columns[i].DataPropertyName,
                                               true /*ignoreCase*/, 
                                               CultureInfo.InvariantCulture) == 0)
                            {
                                Debug.Assert(this.Columns[i].IsDataBound, "two columns w/ the same DataPropertyName should be DataBound at the same time");
                                this.sortedColumn = this.Columns[i]; 
                                break;
                            } 
                        } 
                    }
                } 

                this.sortOrder = this.sortedColumn != null ? this.sortedColumn.HeaderCell.SortGlyphDirection : SortOrder.None;
            }
 
            InvalidateCellPrivate(dataGridViewColumnHeaderCell);
        } 
 
        private void OnTopLeftHeaderMouseDown()
        { 
            if (this.MultiSelect)
            {
                SelectAll();
                if (-1 != this.ptCurrentCell.X) 
                {
                    // Potentially have to give focus back to the current edited cell. 
                    bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, 
                                                             false /*setAnchorCellAddress*/,
                                                             false /*validateCurrentCell*/, 
                                                             false /*throughMouseClick*/);
                    Debug.Assert(success);
                }
            } 
        }
 
        ///  
        protected virtual void OnUserAddedRow(DataGridViewRowEventArgs e)
        { 
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            } 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERADDEDROW] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnUserDeletedRow(DataGridViewRowEventArgs e) 
        {
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERDELETEDROW] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnUserDeletingRow(DataGridViewRowCancelEventArgs e)
        { 
            DataGridViewRowCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERDELETINGROW] as DataGridViewRowCancelEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
        { 
            if (e.Category == UserPreferenceCategory.Color || 
                e.Category == UserPreferenceCategory.Locale ||
                e.Category == UserPreferenceCategory.General || 
                e.Category == UserPreferenceCategory.Window ||
                e.Category == UserPreferenceCategory.VisualStyle)
            {
                OnGlobalAutoSize(); 
                if (e.Category == UserPreferenceCategory.Window)
                { 
                    this.cachedEditingControl = null; 
                    if (this.editingControl != null)
                    { 
                        // The editing control may not adapt well to the new system rendering,
                        // so instead of caching it into the this.cachedEditingControl variable
                        // next time editing mode is exited, simply discard the control.
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_discardEditingControl] = true; 
                    }
                    PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); 
                } 
            }
        } 

        /// 
        protected override void OnValidating(CancelEventArgs e)
        { 
            // VSWhidbey 481170. Avoid Cell/Row Validation events when the grid or its editing control gets the focus
            if (!this.BecomingActiveControl && (this.editingControl == null || !this.editingControl.BecomingActiveControl)) 
            { 
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey])
                { 
                    if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.LeaveControl,
                                 DataGridViewValidateCellInternal.Always,
                                 false /*fireCellLeave*/,
                                 false /*fireCellEnter*/, 
                                 false /*fireRowLeave*/,
                                 false /*fireRowEnter*/, 
                                 false /*fireLeave*/, 
                                 false /*keepFocus*/,
                                 false /*resetCurrentCell*/, 
                                 false /*resetAnchorCell unused here*/))
                    {
                        e.Cancel = true;
                        return; 
                    }
                } 
 
                if (this.ptCurrentCell.X >= 0)
                { 
                    DataGridViewCell dataGridViewCellTmp = null;
                    if (OnRowValidating(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y))
                    {
                        // Row validation was cancelled 
                        e.Cancel = true;
                        return; 
                    } 
                    if (this.ptCurrentCell.X == -1)
                    { 
                        return;
                    }
                    OnRowValidated(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                    // Row validation was not cancelled, but does operation need to be re-evaluated. 
                    if (this.DataSource != null &&
                        this.ptCurrentCell.X >= 0 && 
                        this.AllowUserToAddRowsInternal && 
                        this.newRowIndex == this.ptCurrentCell.Y)
                    { 
                        // Current cell needs to be moved to the row just above the 'new row' if possible.
                        int rowIndex = this.Rows.GetPreviousRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
                        if (rowIndex > -1)
                        { 
                            bool success = SetAndSelectCurrentCellAddress(this.ptCurrentCell.X, rowIndex,
                                true /*setAnchorCellAddress*/, 
                                false /*validateCurrentCell*/, 
                                false /*throughMouseClick*/,
                                false /*clearSelection*/, 
                                false /*forceCurrentCellSelection*/);
                            Debug.Assert(success);
                        }
                        else 
                        {
                            bool success = SetCurrentCellAddressCore(-1, -1, 
                                true /*setAnchorCellAddress*/, 
                                false /*validateCurrentCell*/,
                                false /*throughMouseClick*/); 
                            Debug.Assert(success);
                        }
                    }
                } 
            }
            base.OnValidating(e); 
        } 

        protected override void OnVisibleChanged(EventArgs e) 
        {
            base.OnVisibleChanged(e);
            OnVisibleChangedPrivate();
        } 

        private void OnVisibleChangedPrivate() 
        { 
            // Debug.Assert(!this.displayedBandsInfo.Dirty);   Not valid because EnsureDirtyState can potentially be called
            //                                                 for example when RowHeadersVisible is changed while the control is invisible. 
            int rowIndexTmp;

            if (this.Visible)
            { 
                // Make sure all displayed bands get the Displayed state: 1 & 2 for rows
 
                // 1. Make sure all displayed frozen rows have their Displayed state set to true 
                int numDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedFrozenRows;
                if (numDisplayedFrozenRows > 0) 
                {
                    rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                    while (numDisplayedFrozenRows > 0)
                    { 
                        Debug.Assert(rowIndexTmp != -1);
                        if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) 
                        { 
#if DEBUG
                            int numDisplayedFrozenRowsDbg = numDisplayedFrozenRows; 
                            while (numDisplayedFrozenRowsDbg > 0)
                            {
                                Debug.Assert(rowIndexTmp != -1);
                                Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0); 
                                rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                                numDisplayedFrozenRowsDbg--; 
                            } 
#endif
                            return; // rows' Displayed states are already up-to-date. OnHandleCreated already did the job. 
                        }
                        else
                        {
                            this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true); 
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                            numDisplayedFrozenRows--; 
                        } 
                    }
                } 

                // 2. Make sure all displayed scrolling rows have their Displayed state set to true
                rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                if (rowIndexTmp > -1) 
                {
                    Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Visible) != 0); 
                    int numDisplayedScrollingRows = this.displayedBandsInfo.NumDisplayedScrollingRows; 
                    Debug.Assert(numDisplayedScrollingRows > 0);
                    while (numDisplayedScrollingRows > 0) 
                    {
                        Debug.Assert(rowIndexTmp != -1);
                        if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0)
                        { 
#if DEBUG
                            int numDisplayedScrollingRowsDbg = numDisplayedScrollingRows; 
                            while (numDisplayedScrollingRowsDbg > 0) 
                            {
                                Debug.Assert(rowIndexTmp != -1); 
                                Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0);
                                rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                                numDisplayedScrollingRowsDbg--;
                            } 
#endif
                            return; // rows' Displayed states are already up-to-date. OnHandleCreated already did the job. 
                        } 
                        else
                        { 
                            this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true);
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                            numDisplayedScrollingRows--;
                        } 
                    }
                } 
            } 
            else
            { 
                // Make sure all displayed bands lose the Displayed state
                UpdateRowsDisplayedState(false /*displayed*/);
            }
 
            UpdateColumnsDisplayedState(this.Visible /*displayed*/);
        } 
 
        /// 
        protected virtual void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds) 
        {
            // Paint potential block below rows
            Rectangle rcBelowRows = gridBounds;
            int visibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); 
            if (this.layout.ColumnHeadersVisible)
            { 
                rcBelowRows.Y += this.layout.ColumnHeaders.Height; 
                rcBelowRows.Height -= this.layout.ColumnHeaders.Height;
            } 
            else if (this.SingleHorizontalBorderAdded && visibleRowsHeight > 0)
            {
                rcBelowRows.Y++;
                rcBelowRows.Height--; 
            }
            int rowsHeight = visibleRowsHeight - this.verticalOffset; 
            rcBelowRows.Y += rowsHeight; 
            rcBelowRows.Height -= rowsHeight;
            if (rcBelowRows.Width > 0 && rcBelowRows.Height > 0) 
            {
                graphics.FillRectangle(this.backgroundBrush, rcBelowRows);
            }
 
            // Paint potential block next to column headers and rows
            int visibleColumnsWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible); 
            Rectangle rcNextRows = gridBounds; 
            if (this.Columns.Count > 0)
            { 
                if (this.layout.RowHeadersVisible)
                {
                    if (!this.RightToLeftInternal)
                    { 
                        rcNextRows.X += this.layout.RowHeaders.Width;
                    } 
                    rcNextRows.Width -= this.layout.RowHeaders.Width; 
                }
                else if (this.SingleVerticalBorderAdded && visibleColumnsWidth > 0) 
                {
                    if (!this.RightToLeftInternal)
                    {
                        rcNextRows.X++; 
                    }
                    rcNextRows.Width--; 
                } 
            }
            int rowsWidth = visibleColumnsWidth - this.horizontalOffset; 
            if (!this.RightToLeftInternal)
            {
                rcNextRows.X += rowsWidth;
            } 
            rcNextRows.Width -= rowsWidth;
            rcNextRows.Height = gridBounds.Height - rcBelowRows.Height; 
            if (rcNextRows.Width > 0 && rcNextRows.Height > 0) 
            {
                graphics.FillRectangle(this.backgroundBrush, rcNextRows); 
            }
        }

        private void PaintBorder(Graphics g, Rectangle clipRect, Rectangle bounds) 
        {
            Debug.Assert(bounds.Left == 0); 
            Debug.Assert(bounds.Top == 0); 
            if (this.BorderStyle == BorderStyle.None)
            { 
                return;
            }
            bool paintingNeeded = false;
            int borderWidth = this.BorderWidth; 
            // Does the clipRect intersect with the top edge?
            Rectangle edge = new Rectangle(0, 0, bounds.Width, borderWidth); 
            paintingNeeded = clipRect.IntersectsWith(edge); 
            if (!paintingNeeded)
            { 
                // Does the clipRect intersect with the bottom edge?
                edge.Y = bounds.Height - borderWidth;
                paintingNeeded = clipRect.IntersectsWith(edge);
                if (!paintingNeeded) 
                {
                    // Does the clipRect intersect with the left edge? 
                    edge.Y = 0; 
                    edge.Height = bounds.Height;
                    edge.Width = borderWidth; 
                    paintingNeeded = clipRect.IntersectsWith(edge);
                    if (!paintingNeeded)
                    {
                        // Does the clipRect intersect with the right edge? 
                        edge.X = bounds.Width - borderWidth;
                        paintingNeeded = clipRect.IntersectsWith(edge); 
                    } 
                }
            } 

            if (paintingNeeded)
            {
                if (this.BorderStyle == BorderStyle.Fixed3D) 
                {
                    if (Application.RenderWithVisualStyles) 
                    { 
                        Pen pen = GetCachedPen(VisualStyleInformation.TextControlBorder);
                        g.DrawRectangle(pen, new Rectangle(0, 0, bounds.Width - 1, bounds.Height - 1)); 
                    }
                    else
                    {
                        ControlPaint.DrawBorder3D(g, bounds, Border3DStyle.Sunken); 
                    }
                } 
                else if (this.BorderStyle == BorderStyle.FixedSingle) 
                {
                    Pen pen = GetCachedPen(SystemColors.ControlText); 
                    g.DrawRectangle(pen, new Rectangle(0, 0, bounds.Width - 1, bounds.Height - 1));
                }
                else
                { 
                    Debug.Fail("DataGridView.PaintBorder - Unexpected BorderStyle value.");
                } 
            } 
        }
 
        private void PaintColumnHeaders(Graphics g, Rectangle clipBounds, bool singleBorderAdded)
        {
            if (g.IsVisible(this.layout.ColumnHeaders))
            { 
                Rectangle bandBounds, cellBounds;
                bandBounds = cellBounds = this.layout.ColumnHeaders; 
                bandBounds.Height = cellBounds.Height = this.columnHeadersHeight; 
                int cx = 0;
                bool isFirstDisplayedColumn = true, isLastVisibleColumn = false; 
                DataGridViewCell cell;
                DataGridViewCellStyle inheritedCellStyle = new DataGridViewCellStyle();
                DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder = new DataGridViewAdvancedBorderStyle(), dgvabsEffective;
                DataGridViewColumn dataGridViewColumnNext = null; 

                // first paint the visible frozen columns 
                DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                while (dataGridViewColumn != null)
                { 
                    cell = dataGridViewColumn.HeaderCell;
                    cellBounds.Width = dataGridViewColumn.Thickness;
                    if (singleBorderAdded && isFirstDisplayedColumn)
                    { 
                        cellBounds.Width++;
                    } 
                    Debug.Assert(cellBounds.Width > 0); 
                    if (this.RightToLeftInternal)
                    { 
                        cellBounds.X = bandBounds.Right - cx - cellBounds.Width;
                    }
                    else
                    { 
                        cellBounds.X = bandBounds.X + cx;
                    } 
 
                    BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell);
 
                    dataGridViewColumnNext = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                        DataGridViewElementStates.None);
                    if (dataGridViewColumnNext == null) 
                    {
                        isLastVisibleColumn = (this.displayedBandsInfo.FirstDisplayedScrollingCol < 0); 
                    } 

                    dgvabsEffective = AdjustColumnHeaderBorderStyle(this.AdvancedColumnHeadersBorderStyle, dataGridViewAdvancedBorderStylePlaceholder, 
                                                                    isFirstDisplayedColumn, isLastVisibleColumn);

                    // [....]: should paintSelectionBackground be dev-settable?
                    cell.PaintWork(g, 
                                   clipBounds,
                                   cellBounds, 
                                   -1, 
                                   dataGridViewColumn.State,
                                   inheritedCellStyle, 
                                   dgvabsEffective,
                                   DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground);

                    cx += cellBounds.Width; 
                    if (cx >= bandBounds.Width)
                    { 
                        break; 
                    }
 
                    dataGridViewColumn = dataGridViewColumnNext;
                    isFirstDisplayedColumn = false;
                }
 
                // then paint the visible scrolling ones
                Rectangle scrollingBounds = bandBounds; 
                if (!this.RightToLeftInternal) 
                {
                    scrollingBounds.X -= this.negOffset; 
                }
                scrollingBounds.Width += this.negOffset;

                if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && cx < scrollingBounds.Width) 
                {
                    Region clipRegion = null; 
                    if (this.negOffset > 0) 
                    {
                        clipRegion = g.Clip; 
                        Rectangle rowRect = bandBounds;
                        if (!this.RightToLeftInternal)
                        {
                            rowRect.X += cx; 
                        }
                        rowRect.Width -= cx; 
                        g.SetClip(rowRect); 
                    }
 
                    dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                    while (dataGridViewColumn != null)
                    {
                        Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); 

                        cell = dataGridViewColumn.HeaderCell; 
                        cellBounds.Width = dataGridViewColumn.Thickness; 
                        if (singleBorderAdded && isFirstDisplayedColumn)
                        { 
                            cellBounds.Width++;
                        }
                        Debug.Assert(cellBounds.Width > 0);
                        if (this.RightToLeftInternal) 
                        {
                            cellBounds.X = scrollingBounds.Right - cx - cellBounds.Width; 
                        } 
                        else
                        { 
                            cellBounds.X = scrollingBounds.X + cx;
                        }

                        BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell); 

                        dataGridViewColumnNext = this.Columns.GetNextColumn(dataGridViewColumn, 
                            DataGridViewElementStates.Visible, 
                            DataGridViewElementStates.None);
                        isLastVisibleColumn = (dataGridViewColumnNext == null); 

                        dgvabsEffective = AdjustColumnHeaderBorderStyle(this.AdvancedColumnHeadersBorderStyle, dataGridViewAdvancedBorderStylePlaceholder,
                                                                        isFirstDisplayedColumn, isLastVisibleColumn);
 
                        cell.PaintWork(g,
                                       clipBounds, 
                                       cellBounds, 
                                       -1,
                                       dataGridViewColumn.State, 
                                       inheritedCellStyle,
                                       dgvabsEffective,
                                       DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground);
 
                        cx += cellBounds.Width;
                        if (cx >= scrollingBounds.Width) 
                        { 
                            break;
                        } 

                        dataGridViewColumn = dataGridViewColumnNext;
                        isFirstDisplayedColumn = false;
                    } 

                    if (this.negOffset > 0) 
                    { 
                        Debug.Assert(clipRegion != null);
                        g.Clip = clipRegion; 
                        clipRegion.Dispose();
                    }
                }
            } 
        }
 
        private void PaintGrid(Graphics g, 
            Rectangle gridBounds,
            Rectangle clipRect, 
            bool singleVerticalBorderAdded,
            bool singleHorizontalBorderAdded)
        {
            Rectangle rc = gridBounds; 

            if (this.layout.TopLeftHeader.Width > 0 && 
                (clipRect.IntersectsWith(this.layout.TopLeftHeader) || this.lastHeaderShadow != -1)) 
            {
                if (this.Columns.Count > 0 || this.Rows.Count > 0) 
                {
                    using (Region clipRegion = g.Clip)
                    {
                        g.SetClip(this.layout.TopLeftHeader); 
                        PaintTopLeftHeaderCell(g);
                        g.Clip = clipRegion; 
                    } 
                }
            } 

            if (this.layout.ColumnHeadersVisible)
            {
                Rectangle columnHeadersClip = new Rectangle(); 
                columnHeadersClip = this.layout.ColumnHeaders;
                if (singleVerticalBorderAdded) 
                { 
                    columnHeadersClip.Width++;
                } 
                if (clipRect.IntersectsWith(columnHeadersClip) || this.lastHeaderShadow != -1)
                {
                    using (Region clipRegion = g.Clip)
                    { 
                        g.SetClip(columnHeadersClip);
                        PaintColumnHeaders(g, columnHeadersClip, singleVerticalBorderAdded); 
                        g.Clip = clipRegion; 
                    }
                } 
                int columnHeadersHeight = this.layout.ColumnHeaders.Height;
                rc.Y += columnHeadersHeight;
                rc.Height -= columnHeadersHeight;
 
                if (this.lastHeaderShadow != -1)
                { 
                    DrawColHeaderShadow(g, this.lastHeaderShadow); 
                }
            } 

            if (rc.Height > 0)
            {
                PaintRows(g, rc, clipRect, /*singleVerticalBorderAdded, */ singleHorizontalBorderAdded); 
            }
 
            if (this.currentRowSplitBar != -1) 
            {
                Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize]); 
                DrawRowSplitBar(this.currentRowSplitBar);
            }
            else if (this.currentColSplitBar != -1)
            { 
                Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize]);
                DrawColSplitBar(this.currentColSplitBar); 
            } 
        }
 
        private void PaintRows(Graphics g,
            Rectangle boundingRect,
            Rectangle clipRect,
            /*bool singleVerticalBorderAdded,*/ 
            bool singleHorizontalBorderAdded)
        { 
            int cy = 0; 
            Rectangle rowBounds;
            DataGridViewRow dataGridViewRow; 
            bool isFirstDisplayedRow = true;
            int indexTmp, indexTmpNext;

            // paint visible none-scrolling rows 
            indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            while (indexTmp != -1) 
            { 
                rowBounds = boundingRect;
                rowBounds.Height = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                if (isFirstDisplayedRow && singleHorizontalBorderAdded)
                {
                    rowBounds.Height++;
                } 
                rowBounds.Y = boundingRect.Y + cy;
 
                indexTmpNext = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 

                if (clipRect.IntersectsWith(rowBounds)) 
                {
                    dataGridViewRow = this.Rows.SharedRow(indexTmp);
                    dataGridViewRow.Paint(g,
                        clipRect, 
                        rowBounds,
                        indexTmp, 
                        this.Rows.GetRowState(indexTmp), 
                        isFirstDisplayedRow,
                        (indexTmpNext == -1) && (this.displayedBandsInfo.FirstDisplayedScrollingRow == -1)); 
                }
                cy += rowBounds.Height;
                if (cy >= boundingRect.Height)
                { 
                    break;
                } 
                indexTmp = indexTmpNext; 
                isFirstDisplayedRow = false;
            } 

            // paint scrolling rows
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0 && cy < boundingRect.Height)
            { 
                indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0); 
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0); 
                while (indexTmp != -1)
                { 
                    rowBounds = boundingRect;
                    rowBounds.Height = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                    if (isFirstDisplayedRow && singleHorizontalBorderAdded)
                    { 
                        rowBounds.Height++;
                    } 
                    rowBounds.Y = boundingRect.Y + cy; 

                    indexTmpNext = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); 

                    if (clipRect.IntersectsWith(rowBounds))
                    {
                        dataGridViewRow = this.Rows.SharedRow(indexTmp); 
                        dataGridViewRow.Paint(g,
                            clipRect, 
                            rowBounds, 
                            indexTmp,
                            this.Rows.GetRowState(indexTmp), 
                            isFirstDisplayedRow,
                            indexTmpNext == -1);
                    }
                    cy += rowBounds.Height; 
                    if (cy >= boundingRect.Height)
                    { 
                        break; 
                    }
                    indexTmp = indexTmpNext; 
                    isFirstDisplayedRow = false;
                }
            }
        } 

        private void PaintTopLeftHeaderCell(Graphics g) 
        { 
            if (g.IsVisible(this.layout.TopLeftHeader))
            { 
                DataGridViewCell cell = this.TopLeftHeaderCell;
                DataGridViewCellStyle inheritedCellStyle = new DataGridViewCellStyle();
                BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell);
                Rectangle cellBounds = this.layout.TopLeftHeader; 
                cellBounds.Width = this.rowHeadersWidth;
                cellBounds.Height = this.columnHeadersHeight; 
                // [....]: Should paintSelectionBackground be dev-settable? 
                cell.PaintWork(g,
                               this.layout.TopLeftHeader, 
                               cellBounds,
                               -1,
                               cell.State,
                               inheritedCellStyle, 
                               this.AdjustedTopLeftHeaderBorderStyle,
                               DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground); 
            } 
        }
 
        private void PerformLayoutPrivate(bool useRowShortcut,
                                          bool computeVisibleRows,
                                          bool invalidInAdjustFillingColumns,
                                          bool repositionEditingControl) 
        {
            this.inPerformLayoutCount++; 
            try 
            {
                if (invalidInAdjustFillingColumns && this.InAdjustFillingColumns) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter));
                }
 
                if (this.IsHandleCreated)
                { 
                    bool columnsAdjusted = false; 
                    if (useRowShortcut)
                    { 
                        ComputeLayoutShortcut(computeVisibleRows);
                    }
                    else
                    { 
                        columnsAdjusted = ComputeLayout();
                    } 
                    FlushDisplayedChanged(); 
                    if (columnsAdjusted && this.inPerformLayoutCount < 3)
                    { 
                        // Some columns were auto-filled, the rows and column headers may need to be autosized.
                        if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
                        {
                            AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                        }
                        if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                        { 
                            AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
                        } 
                    }
                    if (repositionEditingControl && this.editingControl != null)
                    {
                        PositionEditingControl(true /*setLocation*/, false /*setSize*/, false /*setFocus*/); 
                    }
                } 
                else 
                {
                    this.displayedBandsInfo.FirstDisplayedFrozenCol = -1; 
                    this.displayedBandsInfo.FirstDisplayedFrozenRow = -1;
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = -1;
                    this.displayedBandsInfo.FirstDisplayedScrollingCol = -1;
                    this.displayedBandsInfo.NumDisplayedFrozenRows = 0; 
                    this.displayedBandsInfo.NumDisplayedFrozenCols = 0;
                    this.displayedBandsInfo.NumDisplayedScrollingRows = 0; 
                    this.displayedBandsInfo.NumDisplayedScrollingCols = 0; 
                    this.displayedBandsInfo.NumTotallyDisplayedFrozenRows = 0;
                    this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = 0; 
                    this.displayedBandsInfo.LastDisplayedScrollingRow = -1;
                    this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1;
                    if (this.layout != null)
                    { 
                        this.layout.dirty = true;
                    } 
                } 
            }
            finally 
            {
                this.inPerformLayoutCount--;
                Debug.Assert(this.inPerformLayoutCount >= 0);
            } 
        }
 
        [ 
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ] 
        private void PopulateNewRowWithDefaultValues()
        {
            if (this.newRowIndex != -1)
            { 
                DataGridViewRow newRow = this.Rows.SharedRow(this.newRowIndex);
                DataGridViewCellCollection newRowCells = newRow.Cells; 
                foreach (DataGridViewCell dataGridViewCell in newRowCells) 
                {
                    if (dataGridViewCell.DefaultNewRowValue != null) 
                    {
                        newRow = this.Rows[this.newRowIndex]; // unshare the 'new row'.
                        newRowCells = newRow.Cells;
                        break; 
                    }
                } 
                foreach (DataGridViewCell dataGridViewCell in newRowCells) 
                {
                    dataGridViewCell.SetValueInternal(this.newRowIndex, dataGridViewCell.DefaultNewRowValue); 
                }
            }
        }
 
        private void PositionEditingControl(bool setLocation, bool setSize, bool setFocus)
        { 
            Debug.Assert(this.editingControl != null); 

            if (!this.IsHandleCreated) 
            {
                return;
            }
 
            #if DEBUG
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal; 
                Debug.Assert(dataGridViewCell != null); 
                Debug.Assert(dataGridViewCell.ColumnIndex == this.ptCurrentCell.X);
                Debug.Assert(dataGridViewCell.RowIndex == this.ptCurrentCell.Y || dataGridViewCell.RowIndex == -1); 
            #endif

            Rectangle editingZone = this.layout.Data;
            if (editingZone.Width == 0 || editingZone.Height == 0) 
            {
                return; 
            } 

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true; 

            try
            {
                int leftEdge = GetColumnXFromIndex(this.ptCurrentCell.X); 
                if (this.RightToLeftInternal)
                { 
                    leftEdge -= this.Columns[this.ptCurrentCell.X].Width-1; 
                }
                Rectangle cellBounds = new Rectangle(leftEdge, GetRowYFromIndex(this.ptCurrentCell.Y), 
                                                     this.Columns[this.ptCurrentCell.X].Width, this.Rows.SharedRow(this.ptCurrentCell.Y).GetHeight(this.ptCurrentCell.Y));
                Rectangle cellClip = cellBounds;
                // Need to clip the zones of the frozen columns and rows and headers.
                if (!this.Columns[this.ptCurrentCell.X].Frozen) 
                {
                    int totalVisibleFrozenWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    if (!this.RightToLeftInternal) 
                    {
                        editingZone.X += totalVisibleFrozenWidth; 
                    }
                    editingZone.Width = Math.Max(0, editingZone.Width - totalVisibleFrozenWidth);
                }
                if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Frozen) == 0) 
                {
                    int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    editingZone.Y += totalVisibleFrozenHeight; 
                }
                cellClip.Intersect(editingZone); 

                if (cellClip.Width == 0 || cellClip.Height == 0)
                {
                    // we cannot simply make the control invisible because we want it to keep the focus. 
                    // (and Control::CanFocus returns false if the control is not visible).
                    // So we place the editing control to the right of the DataGridView. 
                    Debug.Assert(this.editingControl != null); 
                    this.editingPanel.Location = new Point(this.Width + 1, 0);
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] = true; 
                }
                else
                {
                    bool singleVerticalBorderAdded = this.SingleVerticalBorderAdded; 
                    bool singleHorizontalBorderAdded = this.SingleHorizontalBorderAdded;
                    bool isFirstDisplayedColumn = this.FirstDisplayedColumnIndex == this.ptCurrentCell.X; 
                    bool isFirstDisplayedRow = this.FirstDisplayedRowIndex == this.ptCurrentCell.Y; 

                    if (singleVerticalBorderAdded && isFirstDisplayedColumn) 
                    {
                        if (!this.RightToLeftInternal)
                        {
                            cellBounds.X--; 
                            cellClip.X--;
                        } 
                        cellBounds.Width++; 
                        cellClip.Width++;
                    } 
                    if (singleHorizontalBorderAdded && isFirstDisplayedRow)
                    {
                        cellBounds.Y--;
                        cellClip.Y--; 
                        cellBounds.Height++;
                        cellClip.Height++; 
                    } 

                    this.CurrentCellInternal.PositionEditingControl( 
                        setLocation || this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden],
                        setSize || this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden],
                        cellBounds, cellClip, this.InheritedEditingCellStyle,
                        singleVerticalBorderAdded, singleHorizontalBorderAdded, 
                        isFirstDisplayedColumn, isFirstDisplayedRow);
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] = false; 
                } 
                this.editingPanel.Visible = true;
                if (setFocus) 
                {
                    CorrectFocus(false /*onlyIfGridHasFocus*/);
                }
            } 
            finally
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = false; 
            }
        } 

        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessAKey(Keys keyData) 
        { 
            if ((keyData & (Keys.Shift | Keys.Control | Keys.Alt)) == Keys.Control &&
                this.MultiSelect) 
            {
                SelectAll();
                return true;
            } 
            return false;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
            SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters") // Derived controls may need keyData.
        ]
        protected bool ProcessDeleteKey(Keys keyData) 
        {
            if (this.AllowUserToDeleteRowsInternal) 
            { 
                if (this.editingControl != null)
                { 
                    // editing control gets a chance to handle the Delete key first
                    return false;
                }
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.FullRowSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        int remainingSelectedRows = 0;
                        try 
                        {
                            this.selectedBandSnapshotIndexes = new DataGridViewIntLinkedList(this.selectedBandIndexes);
                            while (this.selectedBandSnapshotIndexes.Count > remainingSelectedRows)
                            { 
                                int rowIndex = this.selectedBandSnapshotIndexes[remainingSelectedRows];
                                Debug.Assert(rowIndex >= 0); 
                                if (rowIndex == this.newRowIndex || rowIndex >= this.Rows.Count) 
                                {
                                    remainingSelectedRows++; 
                                }
                                else
                                {
                                    DataGridViewRowCancelEventArgs dgvrce = new DataGridViewRowCancelEventArgs(this.Rows[rowIndex]); 
                                    OnUserDeletingRow(dgvrce);
                                    if (!dgvrce.Cancel) 
                                    { 
                                        DataGridViewRow dataGridViewRow = this.Rows[rowIndex];
                                        if (this.DataSource != null) 
                                        {
                                            int rowCount = this.dataConnection.CurrencyManager.List.Count;
#if DEBUG
                                        int dataGridViewRowsCount = this.Rows.Count;           // the number of rows in the dataGridView row collection not counting the AddNewRow 
                                        if (this.AllowUserToAddRowsInternal )
                                        { 
                                            if (this.newRowIndex < rowCount) 
                                            {
                                                // the user did not type inside the 'add new row' 
                                                Debug.Assert(rowCount == dataGridViewRowsCount, "out of [....] in AddNewTransaction when the user did not type in the 'add new row'");
                                            }
                                            else
                                            { 
                                                dataGridViewRowsCount --;
                                            } 
                                        } 

                                        Debug.Assert(rowCount == dataGridViewRowsCount, "out of [....]"); 
#endif
                                            DataGridViewDataErrorEventArgs dgvdee = null;
                                            try
                                            { 
                                                this.DataConnection.DeleteRow(rowIndex);
                                            } 
                                            catch (Exception exception) 
                                            {
                                                if (ClientUtils.IsCriticalException(exception)) 
                                                {
                                                    throw;
                                                }
                                                // this is tricky. 
                                                // the back-end threw an exception. At that stage, we did not delete the dataGridView row
                                                // from our collection of dataGridView rows. 
                                                // So all we do is to throw the exception if the user wants. Otherwise we don't do anything. 
                                                dgvdee = new DataGridViewDataErrorEventArgs(exception,
                                                                                            -1, 
                                                                                            rowIndex,
                                                                                            // null,
                                                                                            // null,
                                                                                            DataGridViewDataErrorContexts.RowDeletion); 
                                                OnDataErrorInternal(dgvdee);
 
                                                if (dgvdee.ThrowException) 
                                                {
                                                    throw dgvdee.Exception; 
                                                }
                                                else
                                                {
                                                    remainingSelectedRows++; 
                                                }
                                            } 
                                            catch 
                                            {
                                                throw; 
                                            }
                                            if (rowCount != this.dataConnection.CurrencyManager.List.Count)
                                            {
                                                Debug.Assert(dataGridViewRow.Index == -1); 
                                                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
                                                OnUserDeletedRow(dgvre); 
                                            } 
                                            else if (dgvdee == null)
                                            { 
                                                remainingSelectedRows++;
                                            }
                                        }
                                        else 
                                        {
                                            this.Rows.RemoveAtInternal(rowIndex, false /*force*/); 
                                            Debug.Assert(dataGridViewRow.Index == -1); 
                                            DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
                                            OnUserDeletedRow(dgvre); 
                                        }
                                    }
                                    else
                                    { 
                                        remainingSelectedRows++;
                                    } 
                                } 
                            }
                        } 
                        finally
                        {
                            this.selectedBandSnapshotIndexes = null;
                        } 
                        return true;
                } 
            } 
            return false;
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets a value that indicates whether a key should be processed
        ///       further. 
        ///     
        /// 
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)] 
        protected override bool ProcessDialogKey(Keys keyData)
        {
            Keys key = (keyData & Keys.KeyCode);
 
            if (key == Keys.Enter)
            { 
                if (ProcessEnterKey(keyData)) 
                {
                    return true; 
                }
            }
            else if (key == Keys.Escape)
            { 
                bool keyEffective = this.IsEscapeKeyEffective;
                bool ret = base.ProcessDialogKey(keyData); 
                if (!keyEffective) 
                {
                    // This call may perform Click of Cancel button of form. 
                    if (this.Focused)
                    {
                        // Make sure the current cell is in editing mode if needed.
                        if (this.ptCurrentCell.X > -1 && 
                            !this.IsCurrentCellInEditMode &&
                            (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                            (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))) 
                        {
                            BeginEditInternal(true /*selectAll*/); 
                        }
                    }
                }
                return ret; 
            }
            else if (key == Keys.D0 || key == Keys.NumPad0) 
            { 
                if (ProcessZeroKey(keyData))
                { 
                    return true;
                }
            }
            else if (key == Keys.C || key == Keys.Insert) 
            {
                if (ProcessInsertKey(keyData)) 
                { 
                    return true;
                } 
            }
            else if (key == Keys.Tab)
            {
                IntSecurity.AllWindows.Demand(); 
                if (ProcessTabKey(keyData))
                { 
                    return true; 
                }
                else 
                {
                    if (this.editingControl != null)
                    {
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey] = true; 
                        if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.LeaveControl,
                                     DataGridViewValidateCellInternal.Always, 
                                     true /*fireCellLeave*/, 
                                     true /*fireCellEnter*/,
                                     true /*fireRowLeave*/, 
                                     true /*fireRowEnter*/,
                                     true /*fireLeave*/,
                                     false /*keepFocus*/,
                                     false /*resetCurrentCell*/, 
                                     false /*resetAnchorCell unused here*/))
                        { 
                            return true; 
                        }
                    } 

                    keyData &= ~Keys.Control;
                    bool ret = false;
 
                    // SECREVIEW : ProcessDialogKey can generate a call to ContainerControl.SetActiveControl which demands ModifyFocus permission,
                    //             we need to assert it here; the assert is safe, setting the active control does not expose any sec vulnerability 
                    //             indirectly. 
                    //
                    IntSecurity.ModifyFocus.Assert(); 
                    try
                    {
                        ret = base.ProcessDialogKey(keyData);
                    } 
                    finally
                    { 
                        CodeAccessPermission.RevertAssert(); 
                    }
 
                    if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey] && this.Focused)
                    {
                        // There was no other control to tab to. The CellLeave, RowLeave, Leave events were raised.
                        // Since the DataGridView control still has the focus, Enter, RowEnter, CellEnter events need to be raised. 
                        OnEnter(EventArgs.Empty);
                    } 
 
                    return ret;
                } 
            }
            return base.ProcessDialogKey(keyData);
        }
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessDownKey(Keys keyData) 
        {
            bool moved;
            return ProcessDownKeyInternal(keyData, out moved);
        } 

        private bool ProcessDownKeyInternal(Keys keyData, out bool moved) 
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || lastVisibleRowIndex == -1)
            { 
                moved = false;
                return false; 
            } 
            int nextVisibleRowIndex = -1;
            if (this.ptCurrentCell.Y != -1) 
            {
                nextVisibleRowIndex = this.Rows.GetNextRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
            }
            moved = true; 

            this.noSelectionChangeCount++; 
            try 
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                    { 
                                        moved = false; 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    {
                                        // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell 
                                        // the list under the DataGridView changes.
                                        // In this case set moved to false so the users that call ProcessDownKey 
                                        // will commit the data. 
                                        // See vsWhidbey: 325296.
                                        moved = false; 
                                    }
                                }
                                else
                                { 
                                    if (this.MultiSelect)
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                        {
                                            return true; 
                                        }
                                        //ClearSelection();
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        //SelectCellRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptCurrentCell.X == -1 || this.ptAnchorCell.X == -1 || 
                                            IsRowOutOfBounds(lastVisibleRowIndex))
                                        { 
                                            moved = false;
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex);
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, false, false, false); 
                                        if (!success) 
                                        {
                                            moved = false; 
                                        }
                                    }
                                    else
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                        { 
                                            return true; 
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                        {
                                            moved = false;
                                            return true;
                                        } 
                                        //SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                        if (!success) 
                                        {
                                            moved = false;
                                        }
                                    } 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                    {
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex))
                                    { 
                                        moved = false; 
                                        return true;
                                    } 
                                    ClearSelection();
                                    SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    {
                                        moved = false; 
                                    } 
                                }
                            } 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                    { 
                                        moved = false;
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    {
                                        moved = false;
                                    }
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1) 
                                    {
                                        moved = false; 
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true))
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true;
                                    }
                                    if (this.MultiSelect)
                                    { 
                                        //SelectCellUnorderedRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            moved = false;
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextVisibleRowIndex);
                                    } 
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, !this.MultiSelect, false, false);
                                    if (!success) 
                                    {
                                        moved = false; 
                                    } 
                                }
                            } 
                            else
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (nextVisibleRowIndex == -1) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true /*forCurrentCellChange*/)) 
                                    {
                                        return true;
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X,
                                        nextVisibleRowIndex,
                                        true  /*setAnchorCellAddress*/, 
                                        false /*validateCurrentCell*/,
                                        false /*throughMouseClick*/); 
                                    if (!success) 
                                    {
                                        moved = false; 
                                    }
                                }
                            }
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (this.MultiSelect) 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptAnchorCell.Y == -1 || this.ptCurrentCell.X == -1 ||
                                            IsRowOutOfBounds(lastVisibleRowIndex))
                                        {
                                            moved = false; 
                                            return true;
                                        } 
                                        ClearSelection(); 
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        SelectRowRange(this.ptAnchorCell.Y, lastVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, false, false, false);
                                        if (!success)
                                        {
                                            moved = false; 
                                        }
                                    } 
                                    else 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                        {
                                            return true;
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                        {
                                            moved = false; 
                                            return true; 
                                        }
                                        SetSelectedRowCore(this.ptCurrentCell.Y, false); 
                                        SetSelectedRowCore(lastVisibleRowIndex, true);
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                        if (!success)
                                        { 
                                            moved = false;
                                        } 
                                    } 
                                }
                            } 
                            else
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex))
                                    { 
                                        moved = false;
                                        return true;
                                    }
                                    ClearSelection(); 
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false); 
                                    if (!success) 
                                    {
                                        moved = false; 
                                    }
                                }
                            }
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1)
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex))
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    if (this.MultiSelect) 
                                    {
                                        if (this.ptAnchorCell.X == -1) 
                                        {
                                            moved = false;
                                            return true;
                                        } 
                                        if (nextVisibleRowIndex >= this.ptAnchorCell.Y)
                                        { 
                                            SelectRowRange(this.ptAnchorCell.Y, nextVisibleRowIndex, true); 
                                        }
                                        else 
                                        {
                                            SelectRowRange(nextVisibleRowIndex, this.ptAnchorCell.Y, true);
                                        }
                                    } 
                                    else
                                    { 
                                        SetSelectedRowCore(nextVisibleRowIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, !this.MultiSelect, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1)
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex))
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedRowCore(nextVisibleRowIndex, true); 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    {
                                        moved = false;
                                    }
                                } 
                            }
                        } 
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                    {
                                        moved = false; 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    { 
                                        moved = false;
                                    }
                                }
                                else 
                                {
                                    if (this.MultiSelect) 
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                        { 
                                            return true;
                                        }
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        if (this.ptAnchorCell.Y == -1 || this.ptCurrentCell.Y == -1 || 
                                            IsRowOutOfBounds(lastVisibleRowIndex))
                                        { 
                                            moved = false; 
                                            return true;
                                        } 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                        {
                                            ClearSelection();
                                            SelectRowRange(this.ptAnchorCell.Y, lastVisibleRowIndex, true); 
                                        }
                                        else 
                                        { 
                                            //ClearSelection();
                                            //SelectCellRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex); 
                                        }
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, false, false, false); 
                                        if (!success) 
                                        {
                                            moved = false; 
                                        }
                                    }
                                    else
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                        { 
                                            return true; 
                                        }
                                        if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                        {
                                            moved = false;
                                            return true;
                                        } 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                        { 
                                            SetSelectedRowCore(this.ptCurrentCell.Y, false); 
                                            SetSelectedRowCore(lastVisibleRowIndex, true);
                                        } 
                                        else
                                        {
                                            SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                            SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                        }
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false); 
                                        if (!success) 
                                        {
                                            moved = false; 
                                        }
                                    }
                                }
                            } 
                            else
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                                else 
                                { 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(lastVisibleRowIndex))
                                    { 
                                        moved = false;
                                        return true; 
                                    } 
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    { 
                                        ClearSelection();
                                        SetSelectedRowCore(lastVisibleRowIndex, true);
                                    }
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                            } 
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (nextVisibleRowIndex == -1) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    {
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection();
                                        if (this.MultiSelect)
                                        { 
                                            if (this.ptAnchorCell.Y == -1)
                                            { 
                                                moved = false; 
                                                return true;
                                            } 
                                            if (nextVisibleRowIndex >= this.ptAnchorCell.Y)
                                            {
                                                SelectRowRange(this.ptAnchorCell.Y, nextVisibleRowIndex, true);
                                            } 
                                            else
                                            { 
                                                SelectRowRange(nextVisibleRowIndex, this.ptAnchorCell.Y, true); 
                                            }
                                        } 
                                        else
                                        {
                                            SetSelectedRowCore(nextVisibleRowIndex, true);
                                        } 
                                    }
                                    else 
                                    { 
                                        if (this.MultiSelect)
                                        { 
                                            //SelectCellUnorderedRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            if (this.ptAnchorCell.X == -1) 
                                            {
                                                moved = false; 
                                                return true; 
                                            }
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextVisibleRowIndex);
                                        }
                                        else
                                        { 
                                            ClearSelection();
                                            SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true); 
                                        } 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, !this.MultiSelect, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1)
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(nextVisibleRowIndex))
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    { 
                                        ClearSelection();
                                        SetSelectedRowCore(nextVisibleRowIndex, true); 
                                    }
                                    else
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    { 
                                        moved = false;
                                    }
                                }
                            } 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection(); 
                                SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                { 
                                    moved = false;
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false); 
                                if (!success)
                                { 
                                    moved = false; 
                                }
                            } 
                            else
                            {
                                if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                {
                                    moved = false; 
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                if (!success) 
                                {
                                    moved = false; 
                                } 
                            }
                        } 
                        else
                        {
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                {
                                    moved = false;
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                if (!success) 
                                { 
                                    moved = false;
                                } 
                            }
                            else
                            {
                                if (nextVisibleRowIndex == -1) 
                                {
                                    moved = false; 
                                    return true; 
                                }
                                if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                {
                                    return true;
                                }
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                {
                                    moved = false; 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, true, false, false); 
                                if (!success)
                                {
                                    moved = false;
                                } 
                            }
                        } 
                        return true; 
                }
            } 
            finally
            {
                this.NoSelectionChangeCount--;
            } 
            return true;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ]
        protected bool ProcessEndKey(Keys keyData)
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, 
                DataGridViewElementStates.None); 
            int lastVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
            int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
            if (lastVisibleColumnIndex == -1 || firstVisibleRowIndex == -1)
            {
                return false; 
            }
 
            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex); 
                        } 
                        else
                        { 
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                            {
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex))
                            { 
                                return true; 
                            }
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0)
                                {
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex); 
                                }
                                else 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false);
                            } 
                            else 
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            }
                            // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                            // DataGridView changes.
                            // See vsWhidbey: 325296. 
                            // Debug.Assert(success); 
                        }
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == 0)
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else 
                        {
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true)) 
                            {
                                return true;
                            }
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex)) 
                            {
                                return true; 
                            } 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0)
                                {
                                    if (this.ptCurrentCell.Y > -1 &&
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection(); 
                                        SelectRowRange(this.ptCurrentCell.Y, lastVisibleRowIndex, true); 
                                    }
                                    else 
                                    {
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex);
                                    } 
                                } 
                                else
                                { 
                                    if (this.ptCurrentCell.Y > -1 &&
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(lastVisibleRowIndex, true);
                                    } 
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                    }
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false); 
                            }
                            else 
                            { 
                                if (this.ptCurrentCell.Y > -1 &&
                                    (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                {
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                } 
                                else
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            }
                            // Debug.Assert(success);
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if ((keyData & Keys.Control) == 0)
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else
                        { 
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                            { 
                                return true; 
                            }
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex)) 
                            {
                                return true;
                            }
                            ClearSelection(); 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptCurrentCell.X >= 0) 
                                {
                                    SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false); 
                            } 
                            else
                            { 
                                SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            }
                            // Debug.Assert(success); 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    if (this.MultiSelect)
                                    {
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        } 
                                        SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true); 
                                    }
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    if (this.MultiSelect && this.ptCurrentCell.X >= 0) 
                                    {
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex); 
                                    }
                                    else 
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    }
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false);
                                // Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                }
                                else
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true); 
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                // Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == 0) 
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else
                        {
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                            { 
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            ClearSelection();
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptCurrentCell.Y >= 0)
                                { 
                                    if (this.ptAnchorCell.Y == -1) 
                                    {
                                        return true; 
                                    }
                                    SelectRowRange(this.ptAnchorCell.Y, lastVisibleRowIndex, true);
                                }
                                else 
                                {
                                    SetSelectedRowCore(lastVisibleRowIndex, true); 
                                } 

                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false); 
                            }
                            else
                            {
                                SetSelectedRowCore(lastVisibleRowIndex, true); 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            } 
                            // Debug.Assert(success); 
                        }
                        return true; 
                }
            }
            finally
            { 
                this.NoSelectionChangeCount--;
            } 
            return true; 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessEnterKey(Keys keyData)
        { 
            bool moved = false, ret = true, commitRow = true; 
            if ((keyData & Keys.Control) == 0)
            { 
                // Enter behaves like down arrow - it commits the potential editing and goes down one cell.
                commitRow = false;
                keyData &= ~Keys.Shift;
                ret = ProcessDownKeyInternal(keyData, out moved); 
            }
 
            if (!moved) 
            {
                DataGridViewCell dataGridViewCurrentCell = null; 
                // Try to commit the potential editing
                if (this.EditMode == DataGridViewEditMode.EditOnEnter)
                {
                    if (this.ptCurrentCell.X != -1) 
                    {
                        dataGridViewCurrentCell = this.CurrentCellInternal; 
                        DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, 
                            DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit,
                            DataGridViewValidateCellInternal.WhenChanged, 
                            false /*fireCellLeave*/,
                            false /*fireCellEnter*/,
                            false /*fireRowLeave*/,
                            false /*fireRowEnter*/, 
                            false /*fireLeave*/);
                        if (null != dgvdee) 
                        { 
                            if (dgvdee.ThrowException)
                            { 
                                throw dgvdee.Exception;
                            }
                        }
                    } 
                }
                else 
                { 
                    EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit,
                        DataGridViewValidateCellInternal.WhenChanged /*validateCell*/, 
                        false /*fireCellLeave*/,
                        false /*fireCellEnter*/,
                        false /*fireRowLeave*/,
                        false /*fireRowEnter*/, 
                        false /*fireLeave*/,
                        true /*keepFocus*/, 
                        true /*resetCurrentCell unused here*/, 
                        true /*resetAnchorCell unused here*/);
                } 
                if (commitRow && this.IsCurrentRowDirty)
                {
                    dataGridViewCurrentCell = null;
                    int columnIndex = this.ptCurrentCell.X; 
                    int rowIndex = this.ptCurrentCell.Y;
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                    { 
                        return ret;
                    } 
                    if (!OnRowValidating(ref dataGridViewCurrentCell, columnIndex, rowIndex))
                    {
                        if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                        { 
                            return ret;
                        } 
                        OnRowValidated(ref dataGridViewCurrentCell, columnIndex, rowIndex); 
                    }
                } 
            }
            return ret;
        }
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode), 
            SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters") // Derived controls may need keyData.
        ] 
        protected bool ProcessEscapeKey(Keys keyData)
        {
            if (this.IsEscapeKeyEffective)
            { 
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] ||
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] || 
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || 
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] ||
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) 
                {
                    ResetTrackingState();
                }
                else 
                {
                    CancelEdit(true /*endEdit, DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.InitialValueRestoration*/); 
                } 
                return true;
            } 
            return false;
        }

        ///  
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode), 
            SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters") // Derived controls may need keyData. 
        ]
        protected bool ProcessF2Key(Keys keyData) 
        {
            if (this.ptCurrentCell.X != -1 &&
                !this.IsCurrentCellInEditMode &&
                ModifierKeys == 0) 
            {
                Debug.Assert(this.ptCurrentCell.Y != -1); 
                Debug.Assert(this.CurrentCellInternal != null); 
                Debug.Assert(this.EditMode != DataGridViewEditMode.EditOnEnter ||
                    (IsSharedCellReadOnly(this.CurrentCellInternal, this.ptCurrentCell.Y) || !ColumnEditable(this.ptCurrentCell.X))); 
                if (ColumnEditable(this.ptCurrentCell.X) &&
                    !IsSharedCellReadOnly(this.CurrentCellInternal, this.ptCurrentCell.Y) &&
                    (this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2 ||
                     this.EditMode == DataGridViewEditMode.EditOnF2)) 
                {
                    bool success = ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                    Debug.Assert(success); 
                    BeginEditInternal(this.EditMode == DataGridViewEditMode.EditOnF2 /*selectAll*/);
                    return true; 
                }
            }
            return false;
        } 

        ///  
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessHomeKey(Keys keyData)
        {
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            {
                return false; 
            }

            this.noSelectionChangeCount++;
            try 
            {
                switch (this.SelectionMode) 
                { 
                    case DataGridViewSelectionMode.CellSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true)) 
                            { 
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            {
                                return true;
                            } 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0) 
                                {
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                } 
                                else
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false);
                            }
                            else
                            { 
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            }
                            // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                            // DataGridView changes.
                            // See vsWhidbey: 325296.
                            // Debug.Assert(success);
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        if ((keyData & Keys.Control) == 0)
                        { 
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else
                        { 
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                            { 
                                return true; 
                            }
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                            {
                                return true;
                            }
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0) 
                                { 
                                    if (this.ptCurrentCell.Y > -1 &&
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection();
                                        SelectRowRange(firstVisibleRowIndex, this.ptAnchorCell.Y, true);
                                    } 
                                    else
                                    { 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                    }
                                }
                                else 
                                {
                                    if (this.ptCurrentCell.Y > -1 && 
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(firstVisibleRowIndex, true);
                                    }
                                    else
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    } 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false); 
                            }
                            else
                            {
                                if (this.ptCurrentCell.Y > -1 && 
                                    (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                { 
                                    ClearSelection(); 
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                } 
                                else
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            } 
                            // Debug.Assert(success);
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        } 
                        else
                        { 
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                            {
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            { 
                                return true; 
                            }
                            ClearSelection(); 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.MultiSelect && this.ptCurrentCell.X >= 0)
                                { 
                                    if (this.ptAnchorCell.X == -1)
                                    { 
                                        return true; 
                                    }
                                    SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                }
                                else
                                {
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false); 
                            } 
                            else
                            { 
                                SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                            }
                            // Debug.Assert(success); 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    if (this.MultiSelect)
                                    {
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        } 
                                        SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                    }
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    if (this.MultiSelect && this.ptCurrentCell.X >= 0) 
                                    {
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex); 
                                    }
                                    else 
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    }
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false);
                                // Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                }
                                else
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                // Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == 0) 
                        { 
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else
                        {
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                            { 
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            ClearSelection();
                            SetSelectedRowCore(firstVisibleRowIndex, true);
                            success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            // Debug.Assert(success);
                        } 
                        return true; 
                }
            } 
            finally
            {
                this.NoSelectionChangeCount--;
            } 
            return true;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ]
        protected bool ProcessInsertKey(Keys keyData)
        { 
            if (((keyData & (Keys.Shift | Keys.Control | Keys.Alt)) == Keys.Control ||
                 ((keyData & (Keys.Shift | Keys.Control | Keys.Alt)) == (Keys.Control | Keys.Shift) && (keyData & Keys.KeyCode) == Keys.C)) && 
                this.ClipboardCopyMode != DataGridViewClipboardCopyMode.Disable) 
            {
                DataObject dataObject = GetClipboardContent(); 
                if (dataObject != null)
                {
                    Clipboard.SetDataObject(dataObject);
                    return true; 
                }
            } 
            return false; 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
        ] 
        protected override bool ProcessKeyEventArgs(ref Message m)
        { 
            if (m.Msg == NativeMethods.WM_SYSKEYDOWN || m.Msg == NativeMethods.WM_KEYDOWN) 
            {
                if (this.ptCurrentCell.X != -1) 
                {
                    DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                    Debug.Assert(dataGridViewCell != null);
 
                    if (!this.IsCurrentCellInEditMode &&
                        ColumnEditable(this.ptCurrentCell.X) && 
                        !IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) && 
                        (this.EditMode == DataGridViewEditMode.EditOnKeystroke || this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2))
                    { 
                        KeyEventArgs ke = new KeyEventArgs((Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys);
                        if (ke.KeyCode != Keys.ProcessKey || (int) m.LParam != 0x01) // Changing IME context does not trigger editing mode
                        {
                            Type editControlType = dataGridViewCell.EditType; 
                            Type editingCellInterface = null;
                            if (editControlType == null) 
                            { 
                                // Current cell does not have an editing control. Does it implement IDataGridViewEditingCell?
                                editingCellInterface = dataGridViewCell.GetType().GetInterface("System.Windows.Forms.IDataGridViewEditingCell"); 
                            }

                            if ((editControlType != null || editingCellInterface == null) &&
                                dataGridViewCell.KeyEntersEditMode(ke)) 
                            {
                                // Cell wants to go to edit mode 
                                bool success = ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                Debug.Assert(success);
                                if (BeginEditInternal(!(ke.KeyCode == Keys.F2 && ModifierKeys == 0 && this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2) /*selectAll*/)) 
                                {
                                    // Forward the key message to the editing control if any
                                    if (this.editingControl != null)
                                    { 
                                        this.editingControl.SendMessage(m.Msg, m.WParam, m.LParam);
                                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] = true; 
                                        return true; 
                                    }
                                } 
                            }
                        }
                    }
                } 
            }
            else if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] && 
                     (m.Msg == NativeMethods.WM_SYSCHAR || m.Msg == NativeMethods.WM_CHAR  || m.Msg == NativeMethods.WM_IME_CHAR)) 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] = false; 
                if (this.editingControl != null)
                {
                    this.editingControl.SendMessage(m.Msg, m.WParam, m.LParam);
                    return true; 
                }
            } 
            return base.ProcessKeyEventArgs(ref m); 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected override bool ProcessKeyPreview(ref Message m)
        { 
            bool dataGridViewWantsInputKey; 
            KeyEventArgs ke = new KeyEventArgs((Keys)((int)m.WParam) | ModifierKeys);
            switch (ke.KeyCode) 
            {
                case Keys.Delete:
                case Keys.Down:
                case Keys.End: 
                case Keys.Enter:
                case Keys.Escape: 
                case Keys.F2: 
                case Keys.Home:
                case Keys.Left: 
                case Keys.Next:
                case Keys.Prior:
                case Keys.Right:
                case Keys.Space: 
                case Keys.Tab:
                case Keys.Up: 
                    dataGridViewWantsInputKey = true; 
                    break;
 
                default:
                    dataGridViewWantsInputKey = false;
                    break;
            } 

            if (this.editingControl != null && (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN)) 
            { 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_currentCellWantsInputKey] = ((IDataGridViewEditingControl)this.editingControl).EditingControlWantsInputKey(ke.KeyData, dataGridViewWantsInputKey);
            } 

            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_currentCellWantsInputKey])
            {
                return base.ProcessKeyPreview(ref m); 
            }
 
            if (dataGridViewWantsInputKey) 
            {
                if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN) 
                {
                    if (ProcessDataGridViewKey(ke))
                    {
                        return true; 
                        // Ctrl-Tab will be sent as a tab paired w/ a control on the KeyUp message
                    } 
                    else 
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_currentCellWantsInputKey] = true; 
                    }
                }
                else
                { 
                    return true;
                } 
            } 
            return base.ProcessKeyPreview(ref m);
        } 

        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessLeftKey(Keys keyData) 
        { 
            if (this.RightToLeftInternal)
            { 
                return ProcessRightKeyPrivate(keyData);
            }
            else
            { 
                return ProcessLeftKeyPrivate(keyData);
            } 
        } 

        private bool ProcessLeftKeyPrivate(Keys keyData) 
        {
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            { 
                return false;
            } 
            int previousVisibleColumnIndex = -1;
            if (this.ptCurrentCell.X != -1)
            {
                dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.ptCurrentCell.X], 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None); 
                if (dataGridViewColumn != null) 
                {
                    previousVisibleColumnIndex = dataGridViewColumn.Index; 
                }
            }

            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control)
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else 
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success);
                                } 
                                else
                                { 
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.MultiSelect)
                                    {
                                        Debug.Assert(this.ptAnchorCell.X >= 0);
                                        //SelectCellUnorderedRange(previousVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1) 
                                        {
                                            return true; 
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, previousVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    } 
                                    else
                                    { 
                                        ClearSelection(); 
                                        SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    } 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                            else
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    ClearSelection(); 
                                    SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                }
                            }
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    ClearSelection(); 
                                    if (this.MultiSelect)
                                    { 
                                        if (this.ptAnchorCell.X == -1)
                                        {
                                            return true;
                                        } 
                                        if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, previousVisibleColumnIndex))
                                        { 
                                            SelectColumnRange(this.ptAnchorCell.X, previousVisibleColumnIndex, true); 
                                        }
                                        else 
                                        {
                                            SelectColumnRange(previousVisibleColumnIndex, this.ptAnchorCell.X, true);
                                        }
                                    } 
                                    else
                                    { 
                                        SetSelectedColumnCore(previousVisibleColumnIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false); 
                                    Debug.Assert(success);
                                }
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (previousVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedColumnCore(previousVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (previousVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected) 
                                    { 
                                        ClearSelection();
                                        if (this.MultiSelect) 
                                        {
                                            if (this.ptAnchorCell.X == -1)
                                            {
                                                return true; 
                                            }
                                            if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, previousVisibleColumnIndex)) 
                                            { 
                                                SelectColumnRange(this.ptAnchorCell.X, previousVisibleColumnIndex, true);
                                            } 
                                            else
                                            {
                                                SelectColumnRange(previousVisibleColumnIndex, this.ptAnchorCell.X, true);
                                            } 
                                        }
                                        SetSelectedColumnCore(previousVisibleColumnIndex, true); 
                                    } 
                                    else
                                    { 
                                        if (this.MultiSelect)
                                        {
                                            //SelectCellUnorderedRange(previousVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true);
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            if (this.ptAnchorCell.X == -1) 
                                            { 
                                                return true;
                                            } 
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, previousVisibleColumnIndex,
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                        }
                                        else 
                                        {
                                            ClearSelection(); 
                                            SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                        }
                                    } 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                            else
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    if (this.Columns[this.ptCurrentCell.X].Selected) 
                                    {
                                        ClearSelection(); 
                                        SetSelectedColumnCore(previousVisibleColumnIndex, true);
                                    }
                                    else
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    } 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.FullRowSelect: 
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else
                        {
                            if (this.ptCurrentCell.X == -1) 
                            {
                                ClearSelection(); 
                                SetSelectedRowCore(firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                {
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success); 
                            } 
                            else
                            { 
                                if (previousVisibleColumnIndex == -1)
                                {
                                    return true;
                                } 
                                if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success);
                            } 
                        } 
                        return true;
                } 
            }
            finally
            {
                this.NoSelectionChangeCount--; 
            }
            return true; 
        } 

        // Ctrl Left <==> Home 
        // Shift Ctrl Left <==> Shift Home
        private bool ProcessLeftMost(bool shift, int firstVisibleColumnIndex, int firstVisibleRowIndex)
        {
            bool success; 

            this.noSelectionChangeCount++; 
            try 
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if (shift) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else
                            {
                                if (this.MultiSelect)
                                { 
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true; 
                                    }
                                    //ClearSelection(); 
                                    Debug.Assert(this.ptAnchorCell.X >= 0);
                                    //SelectCellRange(firstVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true);
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                    if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 ||
                                        IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                                    { 
                                        return true;
                                    } 
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false);
                                    Debug.Assert(success); 
                                }
                                else 
                                { 
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    //SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                        }
                        else 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            }
                            else
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y  == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                ClearSelection(); 
                                SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success); 
                            }
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if (shift) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else
                            {
                                if (this.MultiSelect)
                                { 
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true; 
                                    }
                                    if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.Y == -1 || 
                                        IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    {
                                        return true;
                                    } 
                                    ClearSelection();
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    { 
                                        return true;
                                    }
                                    SetSelectedColumnCore(this.ptCurrentCell.X, false);
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                } 
                            }
                        } 
                        else
                        {
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else 
                            {
                                if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true;
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                                {
                                    return true; 
                                } 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                Debug.Assert(success);
                            }
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (shift)
                        { 
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            } 
                            else
                            { 
                                if (this.MultiSelect) 
                                {
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true;
                                    }
                                    if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 || 
                                        IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    { 
                                        return true; 
                                    }
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    {
                                        ClearSelection();
                                        SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                    }
                                    else 
                                    { 
                                        //ClearSelection();
                                        //SelectCellRange(firstVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex); 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || 
                                        IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    {
                                        SetSelectedColumnCore(this.ptCurrentCell.X, false); 
                                        SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                    } 
                                    else 
                                    {
                                        SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                        SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            } 
                            else
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true; 
                                }
                                if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex))
                                {
                                    return true; 
                                }
                                if (this.Columns[this.ptCurrentCell.X].Selected) 
                                { 
                                    ClearSelection();
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success);
                            } 
                        }
                        return true;

                    case DataGridViewSelectionMode.FullRowSelect: 
                        if (this.ptCurrentCell.X == -1)
                        { 
                            ClearSelection(); 
                            SetSelectedRowCore(firstVisibleRowIndex, true);
                            success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                            Debug.Assert(success);
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            {
                                return true; 
                            }
                            success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            Debug.Assert(success); 
                        }
                        else 
                        {
                            if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                            {
                                return true; 
                            }
                            if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                            { 
                                return true;
                            } 
                            success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                            Debug.Assert(success);
                        }
                        return true; 
                }
            } 
            finally 
            {
                this.NoSelectionChangeCount--; 
            }
            return true;
        }
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessNextKey(Keys keyData) 
        {
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            if (firstVisibleColumnIndex == -1)
            { 
                return false; 
            }
            int nextScreenVisibleRowIndexTmp, nextScreenVisibleRowIndex = -1, jumpRows = 0; 
            if (this.ptCurrentCell.Y == -1)
            {
                nextScreenVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                if (nextScreenVisibleRowIndex == -1) 
                {
                    return false; 
                } 
            }
            else 
            {
                nextScreenVisibleRowIndex = this.ptCurrentCell.Y;
            }
 
            if ((this.Rows.GetRowState(nextScreenVisibleRowIndex) & DataGridViewElementStates.Frozen) != 0)
            { 
                if (this.displayedBandsInfo.FirstDisplayedScrollingRow > 0) 
                {
                    int firstDisplayedScrollingRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                    Debug.Assert(firstDisplayedScrollingRowIndex != -1);
                    if (!ScrollIntoView(this.ptCurrentCell.X == -1 ? firstVisibleColumnIndex : this.ptCurrentCell.X,
                        firstDisplayedScrollingRowIndex, true))
                    { 
                        return true;
                    } 
                    jumpRows = this.Rows.GetRowCount(DataGridViewElementStates.Visible, 
                        this.ptCurrentCell.Y,
                        firstDisplayedScrollingRowIndex)-1; 
                }
                else
                {
                    jumpRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows; 
                }
            } 
            jumpRows += this.displayedBandsInfo.NumTotallyDisplayedScrollingRows; 

            nextScreenVisibleRowIndexTmp = nextScreenVisibleRowIndex; 
            Debug.Assert(nextScreenVisibleRowIndexTmp != -1);
            if (jumpRows == 0)
            {
                jumpRows = 1; 
            }
            while (jumpRows > 0 && nextScreenVisibleRowIndexTmp != -1) 
            { 
                nextScreenVisibleRowIndexTmp = this.Rows.GetNextRow(nextScreenVisibleRowIndex, DataGridViewElementStates.Visible);
                if (nextScreenVisibleRowIndexTmp != -1) 
                {
                    nextScreenVisibleRowIndex = nextScreenVisibleRowIndexTmp;
                    jumpRows--;
                } 
            }
 
            this.noSelectionChangeCount++; 
            try
            { 
                if (this.ptCurrentCell.X == -1)
                {
                    ClearSelection();
                    switch (this.SelectionMode) 
                    {
                        case DataGridViewSelectionMode.CellSelect: 
                        case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        case DataGridViewSelectionMode.RowHeaderSelect:
                            SetSelectedCellCore(firstVisibleColumnIndex, nextScreenVisibleRowIndex, true); 
                            break;
                        case DataGridViewSelectionMode.FullRowSelect:
                            SetSelectedRowCore(nextScreenVisibleRowIndex, true);
                            break; 
                        case DataGridViewSelectionMode.FullColumnSelect:
                            SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                            break; 
                    }
                    success = ScrollIntoView(firstVisibleColumnIndex, nextScreenVisibleRowIndex, false); 
                    Debug.Assert(success);
                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, nextScreenVisibleRowIndex))
                    {
                        return true; 
                    }
                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, nextScreenVisibleRowIndex, true, false, false); 
                    // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                    // DataGridView changes.
                    // See vsWhidbey: 325296. 
                    // Debug.Assert(success);
                    return true;
                }
 
                switch (this.SelectionMode)
                { 
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true)) 
                        {
                            return true;
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex)) 
                        {
                            return true; 
                        } 
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                            if (this.ptAnchorCell.Y == -1) 
                            {
                                return true; 
                            } 
                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextScreenVisibleRowIndex); 
                        }
                        else
                        {
                            ClearSelection(); 
                            SetSelectedCellCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true);
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, false, false, false); 
                        Debug.Assert(success);
                        return true; 

                    case DataGridViewSelectionMode.FullRowSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true))
                        { 
                            return true;
                        } 
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex)) 
                        {
                            return true; 
                        }
                        ClearSelection();
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            if (this.ptAnchorCell.Y == -1) 
                            { 
                                return true;
                            } 
                            if (this.ptAnchorCell.Y < nextScreenVisibleRowIndex)
                            {
                                SelectRowRange(this.ptAnchorCell.Y, nextScreenVisibleRowIndex, true);
                            } 
                            else
                            { 
                                SelectRowRange(nextScreenVisibleRowIndex, this.ptAnchorCell.Y, true); 
                            }
                        } 
                        else
                        {
                            SetSelectedRowCore(nextScreenVisibleRowIndex, true);
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, false, false, false);
                        // Debug.Assert(success); 
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true))
                        {
                            return true;
                        } 
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex))
                        { 
                            return true; 
                        }
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect) 
                        {
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            if (this.ptAnchorCell.Y == -1)
                            { 
                                return true;
                            } 
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                            {
                                ClearSelection(); 
                                if (this.ptAnchorCell.Y < nextScreenVisibleRowIndex)
                                {
                                    SelectRowRange(this.ptAnchorCell.Y, nextScreenVisibleRowIndex, true);
                                } 
                                else
                                { 
                                    SelectRowRange(nextScreenVisibleRowIndex, this.ptAnchorCell.Y, true); 
                                }
                            } 
                            else
                            {
                                int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                    this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextScreenVisibleRowIndex); 
                            } 
                        }
                        else 
                        {
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                            {
                                ClearSelection(); 
                                SetSelectedRowCore(nextScreenVisibleRowIndex, true);
                            } 
                            else 
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true);
                            }
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, !this.MultiSelect, false, false); 
                        // Debug.Assert(success);
                        return true; 
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true)) 
                        {
                            return true;
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex)) 
                        {
                            return true; 
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true, false, false);
                        // Debug.Assert(success); 
                        return true;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 
            return true;
        } 

        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessPriorKey(Keys keyData) 
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            if (firstVisibleColumnIndex == -1)
            {
                return false; 
            }
            int previousScreenVisibleRowIndexTmp, previousScreenVisibleRowIndex = -1; 
            if (this.ptCurrentCell.Y == -1) 
            {
                previousScreenVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                if (previousScreenVisibleRowIndex == -1)
                {
                    return false;
                } 
            }
            else 
            { 
                previousScreenVisibleRowIndex = this.ptCurrentCell.Y;
            } 

            int jumpRows;
            if ((this.Rows.GetRowState(previousScreenVisibleRowIndex) & DataGridViewElementStates.Frozen) != 0)
            { 
                jumpRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows;
            } 
            else 
            {
                jumpRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows; 
            }
            if (jumpRows == 0)
            {
                jumpRows = 1; 
            }
            previousScreenVisibleRowIndexTmp = previousScreenVisibleRowIndex; 
            Debug.Assert(previousScreenVisibleRowIndexTmp != -1); 
            while (jumpRows > 0 && previousScreenVisibleRowIndexTmp != -1)
            { 
                previousScreenVisibleRowIndexTmp = this.Rows.GetPreviousRow(previousScreenVisibleRowIndex, DataGridViewElementStates.Visible);
                if (previousScreenVisibleRowIndexTmp != -1)
                {
                    previousScreenVisibleRowIndex = previousScreenVisibleRowIndexTmp; 
                }
                jumpRows--; 
            } 

            if ((this.Rows.GetRowState(previousScreenVisibleRowIndex) & DataGridViewElementStates.Frozen) != 0) 
            {
                // Make sure the first scrolling row is visible if any
                int firstDisplayedScrollingRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                if (firstDisplayedScrollingRowIndex != -1 && 
                    !ScrollIntoView(this.ptCurrentCell.X == -1 ? firstVisibleColumnIndex : this.ptCurrentCell.X,
                    firstDisplayedScrollingRowIndex, true)) 
                { 
                    return true;
                } 
                // Also, first visible frozen row should become current one - there is no reason to jump to another frozen row.
                previousScreenVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            }
            Debug.Assert(previousScreenVisibleRowIndex != -1); 

            this.noSelectionChangeCount++; 
            try 
            {
                if (this.ptCurrentCell.X == -1) 
                {
                    ClearSelection();
                    switch (this.SelectionMode)
                    { 
                        case DataGridViewSelectionMode.CellSelect:
                        case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        case DataGridViewSelectionMode.RowHeaderSelect: 
                            SetSelectedCellCore(firstVisibleColumnIndex, previousScreenVisibleRowIndex, true);
                            break; 
                        case DataGridViewSelectionMode.FullRowSelect:
                            SetSelectedRowCore(previousScreenVisibleRowIndex, true);
                            break;
                        case DataGridViewSelectionMode.FullColumnSelect: 
                            SetSelectedColumnCore(firstVisibleColumnIndex, true);
                            break; 
                    } 
                    success = ScrollIntoView(firstVisibleColumnIndex, previousScreenVisibleRowIndex, false);
                    Debug.Assert(success); 
                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, previousScreenVisibleRowIndex))
                    {
                        return true;
                    } 
                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, previousScreenVisibleRowIndex, true, false, false);
                    // Debug.Assert(success); 
                    return true; 
                }
 
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true))
                        { 
                            return true; 
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex)) 
                        {
                            return true;
                        }
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect) 
                        {
                            Debug.Assert(this.ptAnchorCell.Y >= 0); 
                            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                            if (this.ptAnchorCell.X == -1) 
                            {
                                return true;
                            }
                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousScreenVisibleRowIndex);
                        } 
                        else 
                        {
                            ClearSelection(); 
                            SetSelectedCellCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true);
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, false, false, false);
                        // Debug.Assert(success); 
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true))
                        { 
                            return true;
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex))
                        { 
                            return true;
                        } 
                        ClearSelection(); 
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            if (this.ptAnchorCell.Y == -1)
                            {
                                return true; 
                            }
                            if (this.ptAnchorCell.Y < previousScreenVisibleRowIndex) 
                            { 
                                SelectRowRange(this.ptAnchorCell.Y, previousScreenVisibleRowIndex, true);
                            } 
                            else
                            {
                                SelectRowRange(previousScreenVisibleRowIndex, this.ptAnchorCell.Y, true);
                            } 
                        }
                        else 
                        { 
                            SetSelectedRowCore(previousScreenVisibleRowIndex, true);
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, false, false, false);
                        // Debug.Assert(success);
                        return true;
 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true)) 
                        { 
                            return true;
                        } 
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex))
                        {
                            return true;
                        } 
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0); 
                            if (this.ptAnchorCell.Y == -1)
                            { 
                                return true;
                            }
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                            { 
                                ClearSelection();
                                if (this.ptAnchorCell.Y < previousScreenVisibleRowIndex) 
                                { 
                                    SelectRowRange(this.ptAnchorCell.Y, previousScreenVisibleRowIndex, true);
                                } 
                                else
                                {
                                    SelectRowRange(previousScreenVisibleRowIndex, this.ptAnchorCell.Y, true);
                                } 
                            }
                            else 
                            { 
                                int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                    this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousScreenVisibleRowIndex);
                            }
                        } 
                        else
                        { 
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                            {
                                ClearSelection(); 
                                SetSelectedRowCore(previousScreenVisibleRowIndex, true);
                            }
                            else
                            { 
                                ClearSelection();
                                SetSelectedCellCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true); 
                            } 
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, !this.MultiSelect, false, false); 
                        // Debug.Assert(success);
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true))
                        { 
                            return true; 
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex)) 
                        {
                            return true;
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true, false, false); 
                        // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the
                        // DataGridView changes. 
                        // See vsWhidbey: 325296. 
                        // Debug.Assert(success);
                        return true; 
                }
            }
            finally
            { 
                this.NoSelectionChangeCount--;
            } 
            return true; 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessRightKey(Keys keyData)
        { 
            if (this.RightToLeftInternal) 
            {
                return ProcessLeftKeyPrivate(keyData); 
            }
            else
            {
                return ProcessRightKeyPrivate(keyData); 
            }
        } 
 
        private bool ProcessRightKeyPrivate(Keys keyData)
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible,
                DataGridViewElementStates.None);
            int lastVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (lastVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            { 
                return false;
            } 
            int nextVisibleColumnIndex = -1;
            if (this.ptCurrentCell.X != -1)
            {
                dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.ptCurrentCell.X], 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None); 
                if (dataGridViewColumn != null) 
                {
                    nextVisibleColumnIndex = dataGridViewColumn.Index; 
                }
            }

            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control)
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else 
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success);
                                } 
                                else
                                { 
                                    if (nextVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.MultiSelect)
                                    {
                                        //SelectCellUnorderedRange(this.ptAnchorCell.X, this.ptCurrentCell.Y, nextVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        if (this.ptAnchorCell.X == -1) 
                                        { 
                                            return true;
                                        } 
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, nextVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    }
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    }
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false); 
                                    Debug.Assert(success);
                                }
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    if (this.MultiSelect) 
                                    {
                                        if (this.ptAnchorCell.X == -1) 
                                        {
                                            return true;
                                        }
                                        if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, nextVisibleColumnIndex)) 
                                        {
                                            SelectColumnRange(this.ptAnchorCell.X, nextVisibleColumnIndex, true); 
                                        } 
                                        else
                                        { 
                                            SelectColumnRange(nextVisibleColumnIndex, this.ptAnchorCell.X, true);
                                        }
                                    }
                                    else 
                                    {
                                        SetSelectedColumnCore(nextVisibleColumnIndex, true); 
                                    } 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                            else
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true;
                                    } 
                                    ClearSelection();
                                    SetSelectedColumnCore(nextVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                } 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true;
                                    } 
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    { 
                                        ClearSelection(); 
                                        if (this.MultiSelect)
                                        { 
                                            if (this.ptAnchorCell.X == -1)
                                            {
                                                return true;
                                            } 
                                            if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, nextVisibleColumnIndex))
                                            { 
                                                SelectColumnRange(this.ptAnchorCell.X, nextVisibleColumnIndex, true); 
                                            }
                                            else 
                                            {
                                                SelectColumnRange(nextVisibleColumnIndex, this.ptAnchorCell.X, true);
                                            }
                                        } 
                                        else
                                        { 
                                            SetSelectedColumnCore(nextVisibleColumnIndex, true); 
                                        }
                                    } 
                                    else
                                    {
                                        if (this.MultiSelect)
                                        { 
                                            if (this.ptAnchorCell.X == -1)
                                            { 
                                                return true; 
                                            }
                                            //SelectCellUnorderedRange(this.ptAnchorCell.X, this.ptCurrentCell.Y, nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, nextVisibleColumnIndex,
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex); 
                                        }
                                        else 
                                        { 
                                            ClearSelection();
                                            SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                        }
                                    }
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success); 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success);
                                }
                                else 
                                {
                                    if (nextVisibleColumnIndex == -1) 
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    { 
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected) 
                                    {
                                        ClearSelection();
                                        SetSelectedColumnCore(nextVisibleColumnIndex, true);
                                    } 
                                    else
                                    { 
                                        ClearSelection(); 
                                        SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    } 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedRowCore(firstVisibleRowIndex, true); 
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else
                            {
                                if (nextVisibleColumnIndex == -1)
                                { 
                                    return true;
                                } 
                                if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success); 
                            }
                        } 
                        return true;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 
            return true;
        } 

        // Ctrl Right <==> End
        // Shift Ctrl Right <==> Shift End
        private bool ProcessRightMost(bool shift, int lastVisibleColumnIndex, int firstVisibleRowIndex) 
        {
            bool success; 
 
            this.noSelectionChangeCount++;
            try 
            {
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if (shift) 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            }
                            else
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                if (this.MultiSelect) 
                                {
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return true; 
                                    }
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                } 
                            } 
                        }
                        else 
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true;
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                { 
                                    return true;
                                } 
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success);
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if (shift) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            {
                                ClearSelection();
                                SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            }
                            else 
                            {
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                {
                                    return true;
                                } 
                                if (this.MultiSelect)
                                { 
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return true; 
                                    }
                                    ClearSelection();
                                    Debug.Assert(this.ptAnchorCell.X >= 0);
                                    SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false);
                                    Debug.Assert(success); 
                                } 
                                else
                                { 
                                    SetSelectedColumnCore(this.ptCurrentCell.X, false);
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection();
                                SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            } 
                            else
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                {
                                    return true; 
                                }
                                ClearSelection(); 
                                SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if (shift) 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            }
                            else
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                if (this.MultiSelect) 
                                {
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    {
                                        ClearSelection(); 
                                        SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true);
                                    } 
                                    else 
                                    {
                                        //ClearSelection(); 
                                        //SelectCellRange(this.ptAnchorCell.X, this.ptCurrentCell.Y, lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    { 
                                        SetSelectedColumnCore(this.ptCurrentCell.X, false);
                                        SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                    } 
                                    else
                                    { 
                                        SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                        SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                } 
                            } 
                        }
                        else 
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true;
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                { 
                                    return true;
                                } 
                                if (this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                }
                                else
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if (this.ptCurrentCell.X == -1) 
                        { 
                            ClearSelection();
                            SetSelectedRowCore(firstVisibleRowIndex, true); 
                            success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                            Debug.Assert(success);
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                            { 
                                return true;
                            } 
                            success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            Debug.Assert(success);
                        } 
                        else
                        {
                            if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                            { 
                                return true;
                            } 
                            if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex)) 
                            {
                                return true; 
                            }
                            success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                            Debug.Assert(success);
                        } 
                        return true;
                } 
            } 
            finally
            { 
                this.NoSelectionChangeCount--;
            }
            return true;
        } 

        ///  
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessSpaceKey(Keys keyData)
        {
            if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Shift &&
                this.ptCurrentCell.X != -1) 
            {
                this.noSelectionChangeCount++; 
                bool switchedToBulkPaint = false; 
                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                { 
                    this.inBulkPaintCount++;
                    switchedToBulkPaint = true;
                }
                try 
                {
                    if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) 
                    { 
                        // Same as clicking the column header cell
                        Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                        int bandIndex = 0;
                        while (bandIndex < this.selectedBandIndexes.Count)
                        {
                            if (this.selectedBandIndexes[bandIndex] != this.ptCurrentCell.X) 
                            {
                                // deselect currently selected column 
                                SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false); 
                            }
                            else 
                            {
                                bandIndex++;
                            }
                        } 
                        RemoveIndividuallySelectedCells();
                        if (!this.Columns[this.ptCurrentCell.X].Selected) 
                        { 
                            Debug.Assert(!this.selectedBandIndexes.Contains(this.ptCurrentCell.X));
                            SetSelectedColumnCore(this.ptCurrentCell.X, true); 
                        }
                        return true;
                    }
                    else if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) 
                    {
                        // Same as clicking the row header cell 
                        Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                        int bandIndex = 0;
                        while (bandIndex < this.selectedBandIndexes.Count) 
                        {
                            if (this.selectedBandIndexes[bandIndex] != this.ptCurrentCell.Y)
                            {
                                // deselect currently selected row 
                                SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false);
                            } 
                            else 
                            {
                                bandIndex++; 
                            }
                        }
                        RemoveIndividuallySelectedCells();
                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) == 0) 
                        {
                            Debug.Assert(!this.selectedBandIndexes.Contains(this.ptCurrentCell.Y)); 
                            SetSelectedRowCore(this.ptCurrentCell.Y, true); 
                        }
                        return true; 
                    }
                }
                finally
                { 
                    this.NoSelectionChangeCount--;
                    if (switchedToBulkPaint) 
                    { 
                        ExitBulkPaint(-1, -1);
                    } 
                }
            }
            return false;
        } 

        ///  
        ///  
        ///    
        ///       Gets a value indicating whether the Tab key should be processed. 
        ///    
        /// 
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        protected bool ProcessTabKey(Keys keyData) 
        {
            if (this.StandardTab) 
            { 
                if ((keyData & Keys.Control) == Keys.Control)
                { 
                    if ((keyData & Keys.Shift) == Keys.Shift)
                    {
                        if (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell)
                        { 
                            // Goto previous control
                            return false; 
                        } 
                        else
                        { 
                            // Goto previous cell
                            return TabToPreviousCell();
                        }
                    } 
                    else
                    { 
                        if (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell) 
                        {
                            // Goto next control 
                            return false;
                        }
                        else
                        { 
                            // Goto next cell
                            return TabToNextCell(); 
                        } 
                    }
                } 
                else
                {
                    /*
                    if ((keyData & Keys.Shift) == Keys.Shift) 
                    {
                        // Goto previous control 
                    } 
                    else
                    { 
                        // Goto next control
                    }
                    */
                    return false; 
                }
            } 
            else 
            {
                if ((keyData & Keys.Control) == Keys.Control) 
                {
                    /*
                    if ((keyData & Keys.Shift) == Keys.Shift)
                    { 
                        // Goto previous control
                    } 
                    else 
                    {
                        // Goto next control 
                    }
                    */
                    return false;
                } 
                else
                { 
                    if ((keyData & Keys.Shift) == Keys.Shift) 
                    {
                        if (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell) 
                        {
                            // Goto previous control
                            return false;
                        } 
                        else
                        { 
                            // Goto previous cell 
                            return TabToPreviousCell();
                        } 
                    }
                    else
                    {
                        if (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell) 
                        {
                            // Goto next control 
                            return false; 
                        }
                        else 
                        {
                            // Goto next cell
                            return TabToNextCell();
                        } 
                    }
                } 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Processes keys for dataGridView navigation. 
        ///    
        ///  
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
            SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers") 
        ]
        protected virtual bool ProcessDataGridViewKey(KeyEventArgs e)
        {
            switch (e.KeyCode) 
            {
                case Keys.Tab: 
                { 
                    return ProcessTabKey(e.KeyData);
                } 
                case Keys.Up:
                {
                    return ProcessUpKey(e.KeyData);
                } 
                case Keys.Down:
                { 
                    return ProcessDownKey(e.KeyData); 
                }
                case Keys.Next: 
                {
                    return ProcessNextKey(e.KeyData);
                }
                case Keys.Prior: 
                {
                    return ProcessPriorKey(e.KeyData); 
                } 
                case Keys.Left:
                { 
                    return ProcessLeftKey(e.KeyData);
                }
                case Keys.Right:
                { 
                    return ProcessRightKey(e.KeyData);
                } 
                case Keys.F2: 
                {
                    return ProcessF2Key(e.KeyData); 
                }
                case Keys.Home:
                {
                    return ProcessHomeKey(e.KeyData); 
                }
                case Keys.D0: 
                case Keys.NumPad0: 
                {
                    return ProcessZeroKey(e.KeyData); 
                }
                case Keys.Delete:
                {
                    return ProcessDeleteKey(e.KeyData); 
                }
                case Keys.End: 
                { 
                    return ProcessEndKey(e.KeyData);
                } 
                case Keys.Enter:
                {
                    return ProcessEnterKey(e.KeyData);
                } 
                case Keys.Escape:
                { 
                    return ProcessEscapeKey(e.KeyData); 
                }
                case Keys.A: 
                {
                    return ProcessAKey(e.KeyData);
                }
                case Keys.C: 
                case Keys.Insert:
                { 
                    return ProcessInsertKey(e.KeyData); 
                }
                case Keys.Space: 
                {
                    return ProcessSpaceKey(e.KeyData);
                }
            } 
            return false;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ]
        protected bool ProcessUpKey(Keys keyData)
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            {
                return false;
            }
            int previousVisibleRowIndex = -1; 
            if (this.ptCurrentCell.Y != -1)
            { 
                previousVisibleRowIndex = this.Rows.GetPreviousRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible); 
            }
 
            this.noSelectionChangeCount++;
            try
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the
                                    // DataGridView changes. 
                                    // See vsWhidbey: 325296. 
                                    // Debug.Assert(success);
                                } 
                                else
                                {
                                    if (this.MultiSelect)
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                        { 
                                            return true; 
                                        }
                                        if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 || 
                                            IsRowOutOfBounds(firstVisibleRowIndex))
                                        {
                                            return true;
                                        } 
                                        //ClearSelection();
                                        Debug.Assert(this.ptAnchorCell.Y >= 0); 
                                        //SelectCellRange(this.ptCurrentCell.X, firstVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, false, false, false);
                                        // Debug.Assert(success); 
                                    }
                                    else 
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                        { 
                                            return true;
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex))
                                        { 
                                            return true;
                                        } 
                                        //SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                        ClearSelection();
                                        SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                        // Debug.Assert(success);
                                    }
                                } 
                            }
                            else 
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                }
                                else
                                { 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                    { 
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    ClearSelection(); 
                                    SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success); 
                                }
                            } 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else
                                {
                                    if (previousVisibleRowIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    if (this.MultiSelect) 
                                    { 
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        if (this.ptAnchorCell.Y == -1) 
                                        {
                                            return true;
                                        }
                                        //SelectCellUnorderedRange(this.ptCurrentCell.X, previousVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousVisibleRowIndex);
                                    } 
                                    else
                                    {
                                        ClearSelection();
                                        SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, !this.MultiSelect, false, false); 
                                    // Debug.Assert(success); 
                                }
                            } 
                            else
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else 
                                {
                                    if (previousVisibleRowIndex == -1) 
                                    {
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    ClearSelection();
                                    SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true); 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                } 
                            }
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                }
                                else
                                { 
                                    if (this.MultiSelect)
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true)) 
                                        {
                                            return true; 
                                        }
                                        if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 ||
                                            IsRowOutOfBounds(firstVisibleRowIndex))
                                        { 
                                            return true;
                                        } 
                                        ClearSelection(); 
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        SelectRowRange(firstVisibleRowIndex, this.ptAnchorCell.Y, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, false, false, false);
                                        // Debug.Assert(success);
                                    }
                                    else 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true)) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex))
                                        {
                                            return true;
                                        } 
                                        SetSelectedRowCore(this.ptCurrentCell.Y, false);
                                        SetSelectedRowCore(firstVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false); 
                                        // Debug.Assert(success);
                                    } 
                                }
                            }
                            else
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                    { 
                                        return true;
                                    } 
                                    ClearSelection();
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else 
                                {
                                    if (previousVisibleRowIndex == -1) 
                                    {
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    ClearSelection();
                                    if (this.MultiSelect) 
                                    {
                                        if (this.ptAnchorCell.Y == -1) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptAnchorCell.Y >= previousVisibleRowIndex)
                                        {
                                            SelectRowRange(previousVisibleRowIndex, this.ptAnchorCell.Y, true);
                                        } 
                                        else
                                        { 
                                            SelectRowRange(this.ptAnchorCell.Y, previousVisibleRowIndex, true); 
                                        }
                                    } 
                                    else
                                    {
                                        SetSelectedRowCore(previousVisibleRowIndex, true);
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, !this.MultiSelect, false, false);
                                    // Debug.Assert(success); 
                                } 
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1)
                                {
                                    ClearSelection(); 
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                                else 
                                { 
                                    if (previousVisibleRowIndex == -1)
                                    { 
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true))
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    ClearSelection();
                                    SetSelectedRowCore(previousVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                            } 
                        }
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                                else
                                {
                                    if (this.MultiSelect) 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true)) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 ||
                                            IsRowOutOfBounds(firstVisibleRowIndex))
                                        {
                                            return true; 
                                        }
                                        Debug.Assert(this.ptAnchorCell.Y >= 0); 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                        {
                                            ClearSelection(); 
                                            SelectRowRange(firstVisibleRowIndex, this.ptAnchorCell.Y, true);
                                        }
                                        else
                                        { 
                                            //ClearSelection();
                                            //SelectCellRange(this.ptCurrentCell.X, firstVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                        }
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, false, false, false);
                                        // Debug.Assert(success); 
                                    }
                                    else 
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                        { 
                                            return true;
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex))
                                        { 
                                            return true;
                                        } 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                        {
                                            SetSelectedRowCore(this.ptCurrentCell.Y, false); 
                                            SetSelectedRowCore(firstVisibleRowIndex, true);
                                        }
                                        else
                                        { 
                                            SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                            SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true); 
                                        } 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                        // Debug.Assert(success); 
                                    }
                                }
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else
                                {
                                    if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(firstVisibleRowIndex, true);
                                    } 
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true);
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else 
                                {
                                    if (previousVisibleRowIndex == -1) 
                                    {
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    { 
                                        ClearSelection();
                                        if (this.MultiSelect) 
                                        { 
                                            if (this.ptAnchorCell.Y == -1)
                                            { 
                                                return true;
                                            }
                                            if (this.ptAnchorCell.Y >= previousVisibleRowIndex)
                                            { 
                                                SelectRowRange(previousVisibleRowIndex, this.ptAnchorCell.Y, true);
                                            } 
                                            else 
                                            {
                                                SelectRowRange(this.ptAnchorCell.Y, previousVisibleRowIndex, true); 
                                            }
                                        }
                                        SetSelectedRowCore(previousVisibleRowIndex, true);
                                    } 
                                    else
                                    { 
                                        if (this.MultiSelect) 
                                        {
                                            //SelectCellUnorderedRange(this.ptCurrentCell.X, previousVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            if (this.ptAnchorCell.Y == -1)
                                            { 
                                                return true;
                                            } 
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousVisibleRowIndex);
                                        } 
                                        else
                                        {
                                            ClearSelection();
                                            SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true); 
                                        }
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, !this.MultiSelect, false, false); 
                                    // Debug.Assert(success);
                                } 
                            }
                            else
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                } 
                                else
                                { 
                                    if (previousVisibleRowIndex == -1)
                                    {
                                        return true;
                                    } 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true))
                                    { 
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(previousVisibleRowIndex, true); 
                                    }
                                    else 
                                    {
                                        ClearSelection();
                                        SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true);
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                } 
                            }
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                // Debug.Assert(success);
                            } 
                            else
                            {
                                if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                // Debug.Assert(success);
                            } 
                        }
                        else 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                // Debug.Assert(success);
                            }
                            else
                            { 
                                if (previousVisibleRowIndex == -1)
                                { 
                                    return true; 
                                }
                                if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                {
                                    return true;
                                }
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex)) 
                                {
                                    return true; 
                                } 
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false);
                                // Debug.Assert(success); 
                            }
                        }
                        return true;
                } 
            }
            finally 
            { 
                this.NoSelectionChangeCount--;
            } 
            return true;
        }

        ///  
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ] 
        protected bool ProcessZeroKey(Keys keyData)
        { 
            if (this.ptCurrentCell.X != -1 && !this.IsCurrentCellInEditMode && ColumnEditable(this.ptCurrentCell.X))
            {
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                Debug.Assert(dataGridViewCell != null); 

                if (!IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) && 
                    (this.EditMode == DataGridViewEditMode.EditOnKeystroke || this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2) && 
                    dataGridViewCell.EditType != null)
                { 
                    bool success = ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                    Debug.Assert(success);
                    if (!BeginEditInternal(false /*selectAll*/))
                    { 
                        return false;
                    } 
                } 
            }
 
            if ((keyData & (Keys.Alt | Keys.Shift | Keys.Control)) == Keys.Control &&
                this.IsCurrentCellInEditMode)
            {
                DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal; 
                Debug.Assert(dataGridViewCurrentCell != null);
                object nullValue = dataGridViewCurrentCell.GetInheritedStyle(null, this.ptCurrentCell.Y, false).NullValue; 
                if (nullValue == null || 
                    (dataGridViewCurrentCell.FormattedValueType != null && dataGridViewCurrentCell.FormattedValueType.IsAssignableFrom(nullValue.GetType())))
                { 
                    if (this.editingControl != null)
                    {
                        ((IDataGridViewEditingControl) this.editingControl).EditingControlFormattedValue = nullValue;
                        ((IDataGridViewEditingControl) this.editingControl).EditingControlValueChanged = true; 
                        ((IDataGridViewEditingControl) this.editingControl).PrepareEditingControlForEdit(true /*selectAll*/);
                    } 
                    else 
                    {
                        Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); 
                        IDataGridViewEditingCell dataGridViewEditingCell = dataGridViewCurrentCell as IDataGridViewEditingCell;
                        Debug.Assert(dataGridViewEditingCell != null);
                        dataGridViewEditingCell.EditingCellFormattedValue = nullValue;
                        dataGridViewEditingCell.EditingCellValueChanged = true; 
                        dataGridViewEditingCell.PrepareEditingCellForEdit(true /*selectAll*/);
                        InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); 
                    } 
                    NotifyCurrentCellDirty(true);
                    return true; 
                }
                return false;
            }
            return false; 
        }
 
        private void PushAllowUserToAddRows() 
        {
            if (this.AllowUserToAddRowsInternal) 
            {
                if (this.Columns.Count > 0 && this.newRowIndex == -1)
                {
                    AddNewRow(false); 
                }
            } 
            else if (this.newRowIndex != -1) 
            {
                // Delete the 'new' row 
                Debug.Assert(this.newRowIndex == this.Rows.Count - 1);
                this.Rows.RemoveAtInternal(this.newRowIndex, false /*force*/);
            }
        } 

        private bool PushFormattedValue(ref DataGridViewCell dataGridViewCurrentCell, object formattedValue, out Exception exception) 
        { 
            Debug.Assert(this.IsCurrentCellInEditMode);
 
            exception = null;

            DataGridViewCellStyle cellStyle = this.InheritedEditingCellStyle;
 
            DataGridViewCellParsingEventArgs dgvcpe = OnCellParsing(this.ptCurrentCell.Y,
                                                                    this.ptCurrentCell.X, 
                                                                    formattedValue, 
                                                                    dataGridViewCurrentCell.ValueType,
                                                                    cellStyle); 
            if (dgvcpe.ParsingApplied &&
                dgvcpe.Value != null &&
                dataGridViewCurrentCell.ValueType != null &&
                dataGridViewCurrentCell.ValueType.IsAssignableFrom(dgvcpe.Value.GetType())) 
            {
                if (dataGridViewCurrentCell.RowIndex == -1) 
                { 
                    dataGridViewCurrentCell = this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X]; // unsharing the row before pushing the new value
                } 
                return dataGridViewCurrentCell.SetValueInternal(this.ptCurrentCell.Y, dgvcpe.Value);
            }

            object val; 
            try
            { 
                val = dataGridViewCurrentCell.ParseFormattedValue(formattedValue, dgvcpe.InheritedCellStyle, null, null); 
            }
            catch (Exception e) 
            {
                if (ClientUtils.IsCriticalException(e))
                {
                    throw; 
                }
                exception = e; 
                return false; 
            }
            if (dataGridViewCurrentCell.RowIndex == -1) 
            {
                dataGridViewCurrentCell = this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X]; // unsharing the row before pushing the new value
            }
            return dataGridViewCurrentCell.SetValueInternal(this.ptCurrentCell.Y, val); 
        }
 
        private void RecordCellMouseClick(DataGridViewCellMouseEventArgs dgvcme) 
        {
            Debug.Assert(dgvcme.Clicks == 1); 
            this.lastMouseClickInfo.button = dgvcme.Button;
            this.lastMouseClickInfo.timeStamp = DateTime.Now.Ticks;
            this.lastMouseClickInfo.x = dgvcme.X;
            this.lastMouseClickInfo.y = dgvcme.Y; 
            this.lastMouseClickInfo.col = dgvcme.ColumnIndex;
            this.lastMouseClickInfo.row = dgvcme.RowIndex; 
        } 

        private void RefreshColumnsAndRows() 
        {
            this.Rows.ClearInternal(false /*recreateNewRow*/);
            RefreshColumns();
            RefreshRows(true /*scrollIntoView*/); 
        }
 
        private void RefreshColumns() 
        {
            // if AutoGenerateColumns == true then: 
            // 1. remove the columns which were previously bound
            // 2. add new columns based on data source
            //
 
            bool startUpdateInternal = this.Visible;
            if (startUpdateInternal) 
            { 
                BeginUpdateInternal();
            } 

            this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns] = true;
            try
            { 
                DataGridViewColumnCollection dataGridViewCols = this.Columns;
                DataGridViewColumn[] boundColumns = null; 
 
                if (this.dataConnection != null)
                { 
                    boundColumns = this.dataConnection.GetCollectionOfBoundDataGridViewColumns();
                }

                if (this.AutoGenerateColumns) 
                {
                    AutoGenerateDataBoundColumns(boundColumns); 
                } 
                else
                { 
                    for (int j = 0; j < dataGridViewCols.Count; j ++)
                    {
                        // when we refresh the columns, always clear whatever binding information we had on the columns
                        dataGridViewCols[j].IsDataBoundInternal = false; 
                        dataGridViewCols[j].BoundColumnIndex = -1;
                        dataGridViewCols[j].BoundColumnConverter = null; 
                        // set up the columns which have DataPropertyName set to something 
                        if (this.DataSource != null && dataGridViewCols[j].DataPropertyName.Length != 0)
                        { 
                            MapDataGridViewColumnToDataBoundField(dataGridViewCols[j]);
                        }
                    }
                } 

                if (this.DataSource != null) 
                { 
                    this.dataConnection.ApplySortingInformationFromBackEnd();
                } 
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns] = false; 

                if (startUpdateInternal) 
                { 
                    EndUpdateInternal(false);
                    Invalidate(true); 
                }
            }
        }
 
        /// 
        //  Returns true for success, and false if an OnDataError event was raised and cancelled the operation (e.Cancel = true). 
        public bool RefreshEdit() 
        {
            if (this.ptCurrentCell.X != -1 && this.IsCurrentCellInEditMode) 
            {
                Debug.Assert(this.ptCurrentCell.Y != -1);
                DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal;
                DataGridViewCellStyle dataGridViewCellStyle = dataGridViewCurrentCell.GetInheritedStyle(null, this.ptCurrentCell.Y, true); 
                if (this.editingControl != null)
                { 
                    if (InitializeEditingControlValue(ref dataGridViewCellStyle, dataGridViewCurrentCell)) 
                    {
                        if (((IDataGridViewEditingControl) this.editingControl).RepositionEditingControlOnValueChange) 
                        {
                            PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                        }
                        ((IDataGridViewEditingControl) this.editingControl).PrepareEditingControlForEdit(true /*selectAll*/); 
                        ((IDataGridViewEditingControl) this.editingControl).EditingControlValueChanged = false;
                        this.IsCurrentCellDirtyInternal = false; 
                        return true; 
                    }
                    return false; 
                }
                else
                {
                    Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); 
                    if (InitializeEditingCellValue(ref dataGridViewCellStyle, ref dataGridViewCurrentCell))
                    { 
                        IDataGridViewEditingCell dataGridViewEditingCell = dataGridViewCurrentCell as IDataGridViewEditingCell; 
                        Debug.Assert(dataGridViewEditingCell != null);
                        dataGridViewEditingCell.PrepareEditingCellForEdit(true /*selectAll*/); 
                        dataGridViewEditingCell.EditingCellValueChanged = false;
                        this.IsCurrentCellDirtyInternal = false;
                        return true;
                    } 
                    return false;
                } 
            } 
            return true;
        } 

        private void RefreshRows(bool scrollIntoView)
        {
            bool startBeginUpdate = this.Visible; 
            if (startBeginUpdate)
            { 
                BeginUpdateInternal(); 
            }
 
            try
            {
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange])
                { 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] = true;
                } 
 
                // Clear existing rows
                this.Rows.ClearInternal(true /*recreateNewRow*/); 

                // Add a row for each object in the data source
                if (this.dataConnection != null && this.Columns.Count > 0)
                { 
                    IList list = this.dataConnection.List;
                    if (list != null && list.Count > 0) 
                    { 
                        int rowsCount = list.Count;
                        bool oldDoNotChangePositionInTheCurrencyManager = this.dataConnection.DoNotChangePositionInTheCurrencyManager; 

                        // scroll into view when we have a non-empty list
                        // and the layout is not dirty and we are not in a sort operation.
                        bool matchPositionInCurrencyManagerAfterRecreatingRows = !this.layout.dirty && !this.InSortOperation; 

                        if (matchPositionInCurrencyManagerAfterRecreatingRows) 
                        { 
                            // Prevent the data connection from changing position in the currency manager.
                            // But only if the data grid view will set the position in the currency manager after recreating the rows collection. 
                            this.dataConnection.DoNotChangePositionInTheCurrencyManager = true;
                        }
                        try
                        { 
                            this.Rows.AddInternal(this.RowTemplateClone);
                            Debug.Assert(list.Count == rowsCount); 
                            if (rowsCount > 1) 
                            {
                                this.Rows.AddCopiesInternal(0, rowsCount-1); 
                            }
                        }
                        finally
                        { 
                            this.dataConnection.DoNotChangePositionInTheCurrencyManager = oldDoNotChangePositionInTheCurrencyManager;
                        } 
 
                        if (matchPositionInCurrencyManagerAfterRecreatingRows)
                        { 
                            dataConnection.MatchCurrencyManagerPosition(scrollIntoView, true /*clearSelection*/);
                        }
                    }
                } 
            }
            finally 
            { 
                if (startBeginUpdate)
                { 
                    EndUpdateInternal(false);
                    Invalidate(true);
                }
            } 
        }
 
        private void RealeaseMouse() 
        {
            Cursor.ClipInternal = Rectangle.Empty; 
            this.CaptureInternal = false;
        }

        private void RemoveIndividualReadOnlyCellsInColumn(int columnIndex) 
        {
            int cellIndex = 0; 
            while (cellIndex < this.individualReadOnlyCells.Count) 
            {
                DataGridViewCell dataGridViewCell = this.individualReadOnlyCells[cellIndex]; 
                if (dataGridViewCell.ColumnIndex == columnIndex)
                {
                    SetReadOnlyCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                } 
                else
                { 
                    cellIndex++; 
                }
            } 
        }

        private void RemoveIndividualReadOnlyCellsInRow(int rowIndex)
        { 
            int cellIndex = 0;
            while (cellIndex < this.individualReadOnlyCells.Count) 
            { 
                DataGridViewCell dataGridViewCell = this.individualReadOnlyCells[cellIndex];
                if (dataGridViewCell.RowIndex == rowIndex) 
                {
                    SetReadOnlyCellCore(dataGridViewCell.ColumnIndex, rowIndex, false);
                }
                else 
                {
                    cellIndex++; 
                } 
            }
        } 

        private void RemoveIndividuallySelectedCells()
        {
            Debug.Assert(this.noSelectionChangeCount > 0); 
            bool switchedToBulkPaint = false;
            if (this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold) 
            { 
                this.inBulkPaintCount++;
                switchedToBulkPaint = true; 
            }
            try
            {
                while (this.individualSelectedCells.Count > 0) 
                {
                    DataGridViewCell dataGridViewCell = this.individualSelectedCells.HeadCell; 
                    SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false); 
                }
            } 
            finally
            {
                if (switchedToBulkPaint)
                { 
                    ExitBulkPaint(-1, -1);
                } 
            } 
        }
 
        private void RemoveIndividuallySelectedCells(int columnIndexException, int rowIndexException)
        {
            Debug.Assert(this.noSelectionChangeCount > 0);
            bool switchedToBulkPaint = false; 
            if (this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold)
            { 
                this.inBulkPaintCount++; 
                switchedToBulkPaint = true;
            } 
            try
            {
                while (this.individualSelectedCells.Count > 0)
                { 
                    DataGridViewCell dataGridViewCell = this.individualSelectedCells.HeadCell;
                    if (dataGridViewCell.ColumnIndex != columnIndexException || dataGridViewCell.RowIndex != rowIndexException) 
                    { 
                        SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                    } 
                    else
                    {
                        while (this.individualSelectedCells.Count > 1)
                        { 
                            dataGridViewCell = this.individualSelectedCells[1];
                            Debug.Assert(dataGridViewCell.ColumnIndex != columnIndexException || dataGridViewCell.RowIndex != rowIndexException); 
                            SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false); 
                        }
                        break; 
                    }
                }
            }
            finally 
            {
                if (switchedToBulkPaint) 
                { 
                    ExitBulkPaint(-1, -1);
                } 
            }
        }

        private void RemoveIndividuallySelectedCellsInColumn(int columnIndex) 
        {
            Debug.Assert(this.noSelectionChangeCount > 0); 
            int cellIndex = 0; 
            int cellCountInColumn = 0;
            bool switchToBulkOperation = false; 
            DataGridViewCell dataGridViewCell;

            while (cellIndex < this.individualSelectedCells.Count)
            { 
                dataGridViewCell = this.individualSelectedCells[cellIndex];
                if (dataGridViewCell.ColumnIndex == columnIndex) 
                { 
                    SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                    cellCountInColumn++; 
                    if (cellCountInColumn > DATAGRIDVIEW_bulkPaintThreshold)
                    {
                        switchToBulkOperation = true;
                        break; 
                    }
                } 
                else 
                {
                    cellIndex++; 
                }
            }

            if (switchToBulkOperation) 
            {
                this.inBulkPaintCount++; 
                try 
                {
                    while (cellIndex < this.individualSelectedCells.Count) 
                    {
                        dataGridViewCell = this.individualSelectedCells[cellIndex];
                        if (dataGridViewCell.ColumnIndex == columnIndex)
                        { 
                            SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                        } 
                        else 
                        {
                            cellIndex++; 
                        }
                    }
                }
                finally 
                {
                    ExitBulkPaint(columnIndex, -1); 
                } 
            }
        } 

        private void RemoveIndividuallySelectedCellsInRow(int rowIndex)
        {
            Debug.Assert(this.noSelectionChangeCount > 0); 
            // Since there are typically not many columns in a row, we don't try to switch into a bulk operation
            // as we do in RemoveIndividuallySelectedCellsInColumn. 
            int cellIndex = 0; 
            while (cellIndex < this.individualSelectedCells.Count)
            { 
                DataGridViewCell dataGridViewCell = this.individualSelectedCells[cellIndex];
                if (dataGridViewCell.RowIndex == rowIndex)
                {
                    SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false); 
                }
                else 
                { 
                    cellIndex++;
                } 
            }
        }

        // required by the Designer 
        private void ResetBackgroundColor()
        { 
            this.BackgroundColor = DefaultBackgroundBrush.Color; 
        }
 
        // required by the Designer
        private void ResetGridColor()
        {
            this.GridColor = DefaultGridColor; 
        }
 
        ///  
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override void ResetText() 
        {
            base.ResetText();
        }
 
        /// 
        ///      Re-initializes all tracking related state. 
        ///  
        private void ResetTrackingState()
        { 
            if (this.horizScrollTimer != null && this.horizScrollTimer.Enabled)
            {
                this.horizScrollTimer.Enabled = false;
            } 
            if (this.vertScrollTimer != null && this.vertScrollTimer.Enabled)
            { 
                this.vertScrollTimer.Enabled = false; 
            }
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] = false; 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = false; 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = false; 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = false;
            this.trackColumn = -1; 
            this.trackRow = -1;
            this.ptMouseDownCell.X = -2;
            this.ptMouseDownCell.Y = -2;
 
            if (this.currentRowSplitBar != -1)
            { 
                Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar), true); 
                this.lastRowSplitBar = this.currentRowSplitBar = -1;
            } 
            if (this.currentColSplitBar != -1)
            {
                Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar), true);
                this.lastColSplitBar = this.currentColSplitBar = -1; 
            }
            if (this.lastHeaderShadow != -1) 
            { 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = false;
                this.trackColumnEdge = -1; 
                this.lastHeaderShadow = -1;
                Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders));
            }
            RealeaseMouse(); 
        }
 
        ///  
        ///      Re-initializes all UI related state.
        ///  
        internal void ResetUIState(bool useRowShortcut, bool computeVisibleRows)
        {
            PerformLayoutPrivate(useRowShortcut, computeVisibleRows, true /*invalidInAdjustFillingColumns*/, !useRowShortcut /*repositionEditingControl*/);
            if (!useRowShortcut) 
            {
                Invalidate(); 
                InvalidateScrollBars(); 
            }
        } 

        private void RestoreRowsCachedThickness()
        {
            // Switch to batch operation 
            this.inBulkPaintCount++;
            this.inBulkLayoutCount++; 
            try 
            {
                // Only height of visible rows are restored since invisible rows are not autosized. 
                for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                    rowIndex != -1;
                    rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                { 
                    DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                    int height, minimumHeight; 
                    dataGridViewRow.GetHeightInfo(rowIndex, out height, out minimumHeight); 
                    if (height != dataGridViewRow.CachedThickness &&
                        !OnRowHeightInfoPushed(rowIndex, dataGridViewRow.CachedThickness, minimumHeight)) 
                    {
                        dataGridViewRow.ThicknessInternal = dataGridViewRow.CachedThickness;
                    }
                } 
            }
            finally 
            { 
                ExitBulkLayout(true /*invalidInAdjustFillingColumns*/);
                ExitBulkPaint(-1, -1); 
            }
        }

        // we need to access the GetRowState, otherwise we would unshare the row 
        private bool RowIsResizable(int rowIndex)
        { 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if ((rowState & DataGridViewElementStates.ResizableSet) == DataGridViewElementStates.ResizableSet)
            { 
                return (rowState & DataGridViewElementStates.Resizable) == DataGridViewElementStates.Resizable;
            }
            else
            { 
                return this.AllowUserToResizeRows;
            } 
        } 

        private bool RowNeedsDisplayedState(int rowIndex, int lastDisplayedFrozenRowIndex, int lastDisplayedScrollingRowIndex) 
        {
            Debug.Assert(rowIndex >= 0);
            Debug.Assert(rowIndex < this.Rows.Count);
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
 
            if ((rowState & DataGridViewElementStates.Visible) == 0) 
            {
                return false; 
            }

            if ((rowState & DataGridViewElementStates.Frozen) != 0)
            { 
                return rowIndex <= lastDisplayedFrozenRowIndex;
            } 
            else if (this.displayedBandsInfo.FirstDisplayedScrollingRow != -1 && 
                     rowIndex >= this.displayedBandsInfo.FirstDisplayedScrollingRow &&
                     rowIndex <= lastDisplayedScrollingRowIndex) 
            {
                return true;
            }
            return false; 
        }
 
        private void ScrollBar_MouseEnter(object sender, System.EventArgs e) 
        {
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected]) 
            {
                OnMouseEnter(EventArgs.Empty);
            }
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 
        }
 
        private void ScrollBar_MouseLeave(object sender, System.EventArgs e) 
        {
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 
            Point ptMouse = PointToClient(Control.MousePosition);
            if (!this.ClientRectangle.Contains(ptMouse))
            {
                OnMouseLeave(EventArgs.Empty); 
            }
        } 
 
        private bool ScrollColumnIntoView(int columnIndex, int rowIndex, bool committed, bool forCurrentCellChange)
        { 
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count);

            if (this.displayedBandsInfo.FirstDisplayedScrollingCol != -1 &&
                !this.Columns[columnIndex].Frozen && 
                (columnIndex != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.negOffset > 0))
            { 
                int columnsToScroll; 
                if (this.Columns.DisplayInOrder(columnIndex, this.displayedBandsInfo.FirstDisplayedScrollingCol))
                { 
                    if (!committed && this.ptCurrentCell.X >= 0 &&
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex),
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/)) 
                    {
                        return false; 
                    } 

                    columnsToScroll = this.Columns.GetColumnCount(DataGridViewElementStates.Visible, columnIndex, this.displayedBandsInfo.FirstDisplayedScrollingCol); 
                    if (this.negOffset > 0)
                    {
                        columnsToScroll++;
                    } 
                    ScrollColumns(-columnsToScroll);
                } 
                else if (columnIndex == this.displayedBandsInfo.FirstDisplayedScrollingCol && this.negOffset > 0) 
                {
                    if (!committed && this.ptCurrentCell.X >= 0 && 
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex),
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/))
                    { 
                        return false;
                    } 
                    ScrollColumns(-1); 
                }
                else if (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol == -1 || 
                         (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol != columnIndex &&
                          this.Columns.DisplayInOrder(this.displayedBandsInfo.LastTotallyDisplayedScrollingCol, columnIndex)))
                {
                    if (!committed && this.ptCurrentCell.X >= 0 && 
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex), 
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/)) 
                    {
                        return false; 
                    }

                    columnsToScroll = 0;
                    int firstDisplayedScrollingColumn = this.displayedBandsInfo.FirstDisplayedScrollingCol; 
                    int xColumnRightEdge;
 
                    if (this.RightToLeftInternal) 
                    {
                        xColumnRightEdge = GetColumnXFromIndex(columnIndex) - this.Columns[columnIndex].Width; 
                        while (xColumnRightEdge < this.layout.Data.X && this.Columns.DisplayInOrder(firstDisplayedScrollingColumn, columnIndex))
                        {
                            xColumnRightEdge += this.Columns[firstDisplayedScrollingColumn].Width;
                            if (firstDisplayedScrollingColumn == this.displayedBandsInfo.FirstDisplayedScrollingCol) 
                            {
                                xColumnRightEdge -= this.negOffset; 
                            } 
                            columnsToScroll++;
                            if (xColumnRightEdge < this.layout.Data.X) 
                            {
                                firstDisplayedScrollingColumn = this.Columns.GetNextColumn(this.Columns[firstDisplayedScrollingColumn],
                                                                                           DataGridViewElementStates.Visible,
                                                                                           DataGridViewElementStates.None).Index; 
                            }
                        } 
                    } 
                    else
                    { 
                        xColumnRightEdge = GetColumnXFromIndex(columnIndex) + this.Columns[columnIndex].Width;
                        while (xColumnRightEdge > this.layout.Data.Right && this.Columns.DisplayInOrder(firstDisplayedScrollingColumn, columnIndex))
                        {
                            xColumnRightEdge -= this.Columns[firstDisplayedScrollingColumn].Width; 
                            if (firstDisplayedScrollingColumn == this.displayedBandsInfo.FirstDisplayedScrollingCol)
                            { 
                                xColumnRightEdge += this.negOffset; 
                            }
                            columnsToScroll++; 
                            if (xColumnRightEdge > this.layout.Data.Right)
                            {
                                firstDisplayedScrollingColumn = this.Columns.GetNextColumn(this.Columns[firstDisplayedScrollingColumn],
                                                                                           DataGridViewElementStates.Visible, 
                                                                                           DataGridViewElementStates.None).Index;
                            } 
                        } 
                    }
                    if (columnsToScroll != 0) 
                    {
                        ScrollColumns(columnsToScroll);
                    }
                } 
            }
            return true; 
        } 

        private void ScrollColumns(int columns) 
        {
            DataGridViewColumn newFirstVisibleScrollingCol = null;
            DataGridViewColumn dataGridViewColumnTmp;
            int colCount = 0; 
            //ScrollEventType scrollEventType;
            if (columns > 0) 
            { 
                //scrollEventType = columns > 1 ? ScrollEventType.LargeIncrement : ScrollEventType.SmallIncrement;
                if (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0) 
                {
                    dataGridViewColumnTmp = this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol];
                    while (colCount < columns && dataGridViewColumnTmp != null)
                    { 
                        dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp,
                            DataGridViewElementStates.Visible, 
                            DataGridViewElementStates.None); 
                        colCount++;
                    } 

                    if (dataGridViewColumnTmp == null)
                    {
                        // no more column to display on the right of the last totally seen column 
                        return;
                    } 
                } 
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0);
                dataGridViewColumnTmp = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
                colCount = 0;
                while (colCount < columns && dataGridViewColumnTmp != null)
                {
                    dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, 
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.None); 
                    colCount++; 
                }
                newFirstVisibleScrollingCol = dataGridViewColumnTmp; 
            }

            if (columns < 0)
            { 
                //scrollEventType = columns < -1 ? ScrollEventType.LargeDecrement : ScrollEventType.SmallDecrement;
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0); 
                dataGridViewColumnTmp = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
                if (this.negOffset > 0)
                { 
                    colCount++;
                }
                while (colCount < -columns && dataGridViewColumnTmp != null)
                { 
                    dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp,
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.Frozen); 
                    colCount++;
                } 
                newFirstVisibleScrollingCol = dataGridViewColumnTmp;
                if (newFirstVisibleScrollingCol == null)
                {
                    if (this.negOffset == 0) 
                    {
                        // no more column to display on the left of the first seen column 
                        FlushDisplayedChanged(); 
                        return;
                    } 
                    else
                    {
                        newFirstVisibleScrollingCol = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                    } 
                }
            } 
 
            int newColOffset = 0;
            for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, 
                     DataGridViewElementStates.Frozen);
                dataGridViewColumn != newFirstVisibleScrollingCol;
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                DataGridViewElementStates.Visible, 
                DataGridViewElementStates.None))
            { 
                newColOffset += dataGridViewColumn.Thickness; 
            }
 
            this.HorizontalOffset = newColOffset;
        }

        private bool ScrollIntoView(int columnIndex, int rowIndex, bool forCurrentCellChange) 
        {
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= -1 && this.displayedBandsInfo.FirstDisplayedScrollingCol < this.Columns.Count); 
            Debug.Assert(this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= -1 && this.displayedBandsInfo.LastTotallyDisplayedScrollingCol < this.Columns.Count);
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); 
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= -1 && this.displayedBandsInfo.FirstDisplayedScrollingRow < this.Rows.Count);
            Debug.Assert(this.Columns[columnIndex].Visible);
            Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0);
 
            bool committed = false;
            if (this.ptCurrentCell.X >= 0 && 
                (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex)) 
            {
                if (!CommitEditForOperation(columnIndex, rowIndex, forCurrentCellChange)) 
                {
                    return false;
                }
                committed = true; 
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    return false; 
                }
            } 

            //scroll horizontally
            if (!ScrollColumnIntoView(columnIndex, rowIndex, committed, forCurrentCellChange))
            { 
                return false;
            } 
 
            if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
            { 
                return false;
            }

            //scroll vertically 
            return ScrollRowIntoView(columnIndex, rowIndex, committed, forCurrentCellChange);
        } 
 
        private void ScrollRectangles(NativeMethods.RECT[] rects, int change)
        { 
            if (rects != null)
            {
                if (MouseButtons != MouseButtons.None)
                { 
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] = true;
                } 
 
                NativeMethods.RECT scroll;
                for (int r = 0; r < rects.Length; r++) 
                {
                    scroll = rects[r];
                    SafeNativeMethods.ScrollWindow(new HandleRef(this, this.Handle),
                        change, 
                        0,
                        ref scroll, 
                        ref scroll); 
                }
            } 
        }

        private bool ScrollRowIntoView(int columnIndex, int rowIndex, bool committed, bool forCurrentCellChange)
        { 
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
 
            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) == 0) 
            {
                int rowsToScroll; 
                if (rowIndex < this.displayedBandsInfo.FirstDisplayedScrollingRow)
                {
                    if (!committed && this.ptCurrentCell.X >= 0 &&
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex),
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/)) 
                    { 
                        return false;
                    } 

                    rowsToScroll = this.Rows.GetRowCount(DataGridViewElementStates.Visible, rowIndex, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                    ScrollRowsByCount(-rowsToScroll, rowsToScroll > 1 ? ScrollEventType.LargeDecrement : ScrollEventType.SmallDecrement);
                } 
                else if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0 &&
                         rowIndex > this.displayedBandsInfo.FirstDisplayedScrollingRow) 
                { 
                    rowsToScroll = 0;
                    int firstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                    int yRowBottomEdge = GetRowYFromIndex(rowIndex) + this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                    while (yRowBottomEdge > this.layout.Data.Bottom && rowIndex > firstDisplayedScrollingRow)
                    {
                        yRowBottomEdge -= this.Rows.SharedRow(firstDisplayedScrollingRow).GetHeight(firstDisplayedScrollingRow); 
                        rowsToScroll++;
                        if (yRowBottomEdge > this.layout.Data.Bottom) 
                        { 
                            firstDisplayedScrollingRow = this.Rows.GetNextRow(firstDisplayedScrollingRow, DataGridViewElementStates.Visible);
                            Debug.Assert(firstDisplayedScrollingRow != -1); 
                        }
                    }
                    if (rowsToScroll != 0)
                    { 
                        if (!committed && this.ptCurrentCell.X >= 0 &&
                            !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                        forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex), 
                                        this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/))
                        { 
                            return false;
                        }
                        ScrollRowsByCount(rowsToScroll, rowsToScroll > 1 ? ScrollEventType.LargeIncrement : ScrollEventType.SmallIncrement);
                    } 
                }
            } 
            return true; 
        }
 
        private void ScrollRows(int rowCount, int deltaY, ScrollEventType scrollEventType)
        {
            bool invalidateTopOfRowHeaders = false;
            Debug.Assert(rowCount != 0); 
            Debug.Assert(deltaY != 0);
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen)); 
            this.verticalOffset -= deltaY; 
            if (this.vertScrollBar.Enabled)
            { 
                this.vertScrollBar.Value = this.verticalOffset;
            }
            ClearRegionCache();
            int frozenRowsThickness = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            Rectangle rowsRect = this.layout.Data;
            if (this.layout.RowHeadersVisible) 
            { 
                rowsRect = Rectangle.Union(rowsRect, this.layout.RowHeaders);
                if (this.SingleHorizontalBorderAdded) 
                {
                    rowsRect.Y++;
                    rowsRect.Height--;
                    invalidateTopOfRowHeaders = true; 
                }
            } 
            else if (this.SingleVerticalBorderAdded) 
            {
                Debug.Assert(rowsRect.X > 0); 
                rowsRect.X--;
                rowsRect.Width++;
            }
            rowsRect.Y += frozenRowsThickness; 
            rowsRect.Height -= frozenRowsThickness;
            Debug.Assert(rowsRect.Height >= 0); 
 
            if (this.editingControl != null &&
                (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Frozen) == 0) 
            {
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow > -1);
                PositionEditingControl(true /*setLocation*/, false /*setSize*/, false /*setFocus*/);
            } 

            if (MouseButtons != MouseButtons.None) 
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] = true;
            } 

            // The mouse probably is not over the same cell after the scroll.
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
 
            NativeMethods.RECT scrollArea = NativeMethods.RECT.FromXYWH(rowsRect.X, rowsRect.Y, rowsRect.Width, rowsRect.Height);
            SafeNativeMethods.ScrollWindow(new HandleRef(this, this.Handle), 0, deltaY, ref scrollArea, ref scrollArea); 
            if (invalidateTopOfRowHeaders) 
            {
                rowsRect.X = this.layout.Inside.X; 
                rowsRect.Y = this.layout.Inside.Y;
                rowsRect.Width = this.layout.RowHeaders.Width;
                rowsRect.Height = 1;
                Invalidate(rowsRect); 
            }
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll]) 
            { 
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                int firstVisibleScrollingRow = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                Debug.Assert(firstVisibleScrollingRow != -1);
                int newScrolledOffRowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible, firstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                Debug.Assert(newScrolledOffRowCount >= rowCount);
                OnScroll(scrollEventType, newScrolledOffRowCount - rowCount, newScrolledOffRowCount, ScrollOrientation.VerticalScroll); 
            }
        } 
 
        private void ScrollRowsByCount(int rows, ScrollEventType scrollEventType)
        { 
            Debug.Assert(rows != 0);
            Debug.Assert((rows > 0 && (scrollEventType == ScrollEventType.SmallIncrement || scrollEventType == ScrollEventType.LargeIncrement)) ||
                         (rows < 0 && (scrollEventType == ScrollEventType.SmallDecrement || scrollEventType == ScrollEventType.LargeDecrement)));
 
            int deltaY = 0;
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
            int newFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
            if (rows > 0)
            { 
                for (int rowCount = rows; rowCount > 0; rowCount--)
                {
                    deltaY -= this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                    newFirstVisibleScrollingRow = this.Rows.GetNextRow(newFirstVisibleScrollingRow, 
                        DataGridViewElementStates.Visible);
 
                    Debug.Assert(newFirstVisibleScrollingRow != -1); 
                }
                if (newFirstVisibleScrollingRow != -1) 
                {
                    int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                    // Tentative target value for this.displayedBandsInfo.FirstDisplayedScrollingRow.
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = newFirstVisibleScrollingRow; 
                    // This sets the actual value of this.displayedBandsInfo.FirstDisplayedScrollingRow
                    ComputeVisibleRows(); 
                    // Compute the actual deltaY given the new this.displayedBandsInfo.FirstDisplayedScrollingRow 
                    if (this.displayedBandsInfo.FirstDisplayedScrollingRow > oldFirstVisibleScrollingRow)
                    { 
                        deltaY = -this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                        rows = this.Rows.GetRowCount(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                    }
                    else 
                    {
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow == oldFirstVisibleScrollingRow); 
                        rows = 0; 
                    }
                } 
            }
            else
            {
                for (int rowCount = rows; rowCount < 0; rowCount++) 
                {
                    newFirstVisibleScrollingRow = this.Rows.GetPreviousRow(newFirstVisibleScrollingRow, 
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.Frozen);
                    if (newFirstVisibleScrollingRow != -1) 
                    {
                        deltaY += this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                    }
                } 
                if (newFirstVisibleScrollingRow != -1)
                { 
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = newFirstVisibleScrollingRow; 
                    ComputeVisibleRows();
                    Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow == newFirstVisibleScrollingRow); 
                }
            }

            if (newFirstVisibleScrollingRow != -1 && rows != 0) 
            {
                ScrollRows(rows, deltaY, scrollEventType); 
            } 

            FlushDisplayedChanged(); 
        }

        private void ScrollRowsByHeight(int height)
        { 
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
            int deltaY, scrollHeight = 0; 
            int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
            int newFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
            if (height > 0) 
            {
                deltaY = this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                while (deltaY <= height)
                { 
                    newFirstVisibleScrollingRow = this.Rows.GetNextRow(newFirstVisibleScrollingRow, DataGridViewElementStates.Visible);
                    if (newFirstVisibleScrollingRow == -1) 
                    { 
                        throw new InvalidOperationException(); // Occurs in case of VSWhidbey 533407
                    } 
                    else
                    {
                        deltaY += this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                    } 
                }
            } 
            else 
            {
                newFirstVisibleScrollingRow = this.Rows.GetPreviousRow(newFirstVisibleScrollingRow, 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
                Debug.Assert(newFirstVisibleScrollingRow != -1);
                deltaY = -this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow); 
                while (deltaY >= height)
                { 
                    int scrollingRowTmp = this.Rows.GetPreviousRow(newFirstVisibleScrollingRow, 
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.Frozen); 
                    if (scrollingRowTmp != -1)
                    {
                        deltaY -= this.Rows.SharedRow(scrollingRowTmp).GetHeight(scrollingRowTmp);
                        if (deltaY >= height) 
                        {
                            newFirstVisibleScrollingRow = scrollingRowTmp; 
                        } 
                    }
                    else 
                    {
                        break;
                    }
                } 
            }
 
            // Tentative target value for this.displayedBandsInfo.FirstDisplayedScrollingRow. 
            this.displayedBandsInfo.FirstDisplayedScrollingRow = newFirstVisibleScrollingRow;
            // This sets the actual value of this.displayedBandsInfo.FirstDisplayedScrollingRow 
            ComputeVisibleRows();
            ScrollEventType scrollEventType = ScrollEventType.EndScroll;
            int rowCount = 0;
            // Compute the scrollHeight given the new this.displayedBandsInfo.FirstDisplayedScrollingRow 
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow > oldFirstVisibleScrollingRow)
            { 
                scrollHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow); 
                rowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                scrollEventType = rowCount > 1 ? ScrollEventType.LargeIncrement : ScrollEventType.SmallIncrement; 
            }
            else if (this.displayedBandsInfo.FirstDisplayedScrollingRow < oldFirstVisibleScrollingRow)
            {
                scrollHeight = -this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, oldFirstVisibleScrollingRow); 
                rowCount = -this.Rows.GetRowCount(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, oldFirstVisibleScrollingRow);
                scrollEventType = rowCount < -1 ? ScrollEventType.LargeDecrement : ScrollEventType.SmallDecrement; 
            } 
            if (scrollHeight != 0)
            { 
                ScrollRows(rowCount, -scrollHeight, scrollEventType);
            }

            FlushDisplayedChanged(); 
        }
 
        ///  
        // Does not seem to be a valid fxcop violation report. Contacting fxcop team to double-check.
        [SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops")] 
        public void SelectAll()
        {
            if (!this.MultiSelect)
            { 
                return;
            } 
            this.inBulkPaintCount++; 
            this.noDimensionChangeCount++;
            this.noSelectionChangeCount++; 
            try
            {
                DataGridViewRow dataGridViewRow = null;
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    { 
                        // Bonjour the scalability issues! We select each cell, one at the time.
                        int maxColumnIndex = this.Columns.Count; 
                        int rowIndex = 0, maxRowIndex = this.Rows.Count;
                        while (rowIndex < maxRowIndex)
                        {
                            dataGridViewRow = this.Rows[rowIndex];  //unsharing each row! 
                            int columnIndex = 0;
                            while (columnIndex < maxColumnIndex) 
                            { 
                                SetSelectedCellCore(columnIndex, rowIndex, true);
                                columnIndex++; 
                            }
                            rowIndex++;
                        }
                        break; 
                    }
 
                    case DataGridViewSelectionMode.FullRowSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    { 
                        int rowIndex = 0, maxRowIndex = this.Rows.Count;
                        while (rowIndex < maxRowIndex)
                        {
                            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
                            if ((rowState & DataGridViewElementStates.Selected) == 0)
                            { 
                                SetSelectedRowCore(rowIndex, true); 
                            }
                            rowIndex++; 
                        }
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    { 
                        int columnIndex = 0, maxColumnIndex = this.Columns.Count;
                        while (columnIndex < maxColumnIndex) 
                        {
                            if (!this.Columns[columnIndex].Selected)
                            {
                                SetSelectedColumnCore(columnIndex, true); 
                            }
                            columnIndex++; 
                        } 
                        break;
                    } 
                }
            }
            finally
            { 
                this.noDimensionChangeCount--;
                this.noSelectionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0); 
                Debug.Assert(this.noSelectionChangeCount >= 0);
                ExitBulkPaint(-1, -1); 
            }

            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
            if (dataGridViewColumn != null && firstVisibleRowIndex != -1)
            { 
                // This is the only place in the code outside of SetCurrentCellAddressCore where this.ptAnchorCell gets changed. 
                // There is no way in SetCurrentCellAddressCore to just change the anchor cell.
                this.ptAnchorCell.X = dataGridViewColumn.Index; 
                this.ptAnchorCell.Y = firstVisibleRowIndex;
            }
            else
            { 
                this.ptAnchorCell.X = -1;
                this.ptAnchorCell.Y = -1; 
            } 

            if (this.noSelectionChangeCount == 0) 
            {
                FlushSelectionChanged();
            }
        } 

        private DataGridViewCell SelectedCell(int index) 
        { 
            Debug.Assert(index >= 0);
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.CellSelect:
                {
                    if (index < this.individualSelectedCells.Count) 
                    {
                        return this.individualSelectedCells[index]; 
                    } 
                    break;
                } 
                case DataGridViewSelectionMode.FullColumnSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                {
                    int selectedBand = 0, selectedBands = this.selectedBandIndexes.Count; 
                    while (selectedBand < selectedBands && index >= 0)
                    { 
                        if (index >= this.Rows.Count) 
                        {
                            index -= this.Rows.Count; 
                            selectedBand++;
                        }
                        else
                        { 
                            int columnIndex = this.selectedBandIndexes[selectedBand];
                            return this.Rows.SharedRow(index).Cells[columnIndex]; 
                        } 
                    }
 
                    if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect &&
                        index < this.individualSelectedCells.Count)
                    {
                        return this.individualSelectedCells[index]; 
                    }
                    break; 
                } 
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect: 
                {
                    int selectedBand = 0, selectedBands = this.selectedBandIndexes.Count;
                    while (selectedBand < selectedBands && index >= 0)
                    { 
                        if (index >= this.Columns.Count)
                        { 
                            index -= this.Columns.Count; 
                            selectedBand++;
                        } 
                        else
                        {
                            int rowIndex = this.selectedBandIndexes[selectedBand];
                            return this.Rows.SharedRow(rowIndex).Cells[index]; 
                        }
                    } 
 
                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect &&
                        index < this.individualSelectedCells.Count) 
                    {
                        return this.individualSelectedCells[index];
                    }
                    break; 
                }
            } 
            return null; 
        }
 
        private void SetColumnHeadersHeightInternal(int columnHeadersHeight, bool invalidInAdjustFillingColumns)
        {
            using (LayoutTransaction.CreateTransactionIf(this.AutoSize, this.ParentInternal, this, PropertyNames.ColumnHeadersHeight))
            { 
                Debug.Assert(this.columnHeadersHeight != columnHeadersHeight);
                Debug.Assert(columnHeadersHeight >= minimumColumnHeadersHeight); 
                Debug.Assert(columnHeadersHeight <= maxHeadersThickness); 
                this.columnHeadersHeight = columnHeadersHeight;
                if (this.AutoSize) 
                {
                    InvalidateInside();
                }
                else 
                {
                    if (this.layout.ColumnHeadersVisible) 
                    { 
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, true /*repositionEditingControl*/);
                        InvalidateInside(); 
                    }
                }
                OnColumnHeadersHeightChanged(EventArgs.Empty);
            } 
        }
 
        ///  
        protected virtual bool SetCurrentCellAddressCore(int columnIndex,
            int rowIndex, 
            bool setAnchorCellAddress,
            bool validateCurrentCell,
            bool throughMouseClick)
        { 
            if (columnIndex < -1 ||
                (columnIndex >= 0 && rowIndex == -1) || 
                columnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("columnIndex"); 
            }
            if (rowIndex < -1 ||
                (columnIndex == -1 && rowIndex >= 0) ||
                rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            } 

            if (columnIndex > -1 && 
                rowIndex > -1 &&
                !IsSharedCellVisible(this.Rows.SharedRow(rowIndex).Cells[columnIndex], rowIndex))
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CurrentCellCannotBeInvisible)); 
            }
 
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] &&                      // Allow the code to be re-entrant only as a result of 
                (this.dataConnection == null || !this.dataConnection.ProcessingListChangedEvent))   // underlying data changing.
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_SetCurrentCellAddressCoreNotReentrant));
            }

            this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] = true; 
            try
            { 
                DataGridViewCell dataGridViewCellTmp = null; 

                if (columnIndex > -1) 
                {
                    Debug.Assert(rowIndex >= 0 &&
                        columnIndex < this.Columns.Count &&
                        rowIndex < this.Rows.Count); 

                    if (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex) 
                    { 
                        if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell])
                        { 
                            this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false;
                            this.ptCurrentCell.X = columnIndex;
                            this.ptCurrentCell.Y = rowIndex;
                            if (this.cachedEditingControl != null) 
                            {
                                this.editingControl = this.cachedEditingControl; 
                                ((IDataGridViewEditingControl)this.editingControl).EditingControlRowIndex = rowIndex; 
                                this.cachedEditingControl = null;
                                PositionEditingControl(true, true, false); 
                            }
                            OnCurrentCellChanged(EventArgs.Empty);
                            return true;
                        } 

                        DataGridViewCell currentCell; 
                        int oldCurrentCellX = this.ptCurrentCell.X; 
                        int oldCurrentCellY = this.ptCurrentCell.Y;
                        if (oldCurrentCellX >= 0) 
                        {
                            currentCell = this.CurrentCellInternal;
                            if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange,
                                        validateCurrentCell ? DataGridViewValidateCellInternal.Always : DataGridViewValidateCellInternal.Never /*validateCell*/, 
                                        validateCurrentCell /*fireCellLeave*/,
                                        false /*fireCellEnter*/, 
                                        validateCurrentCell && oldCurrentCellY != rowIndex /*fireRowLeave*/, 
                                        false /*fireRowEnter*/,
                                        false /*fireLeave*/, 
                                        this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/,
                                        false /*resetCurrentCell*/,
                                        false /*resetAnchorCell unused here*/))
                            { 
                                return false;
                            } 
                            if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                            {
                                currentCell = this.Rows.SharedRow(oldCurrentCellY).Cells[oldCurrentCellX]; 
                                if (currentCell.LeaveUnsharesRowInternal(oldCurrentCellY, throughMouseClick))
                                {
                                    currentCell = this.Rows[oldCurrentCellY].Cells[oldCurrentCellX]; // unsharing the current row
                                } 
                                currentCell.OnLeaveInternal(oldCurrentCellY, throughMouseClick);
                            } 
                            if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                            {
                                return false; 
                            }
                            if (oldCurrentCellY != rowIndex)
                            {
                                if (validateCurrentCell) 
                                {
                                    if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY)) 
                                    { 
                                        if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                        { 
                                            // Row validation was cancelled
                                            Debug.Assert(oldCurrentCellX == this.ptCurrentCell.X);
                                            Debug.Assert(oldCurrentCellY == this.ptCurrentCell.Y);
                                            OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); 
                                            if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                            { 
                                                currentCell.OnEnterInternal(oldCurrentCellY, throughMouseClick); 
                                                OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);
                                            } 
                                        }
                                        return false;
                                    }
                                    if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                    } 
                                }
                            } 
                        }

                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] = false;
 
                        try
                        { 
                            if (oldCurrentCellY != rowIndex) 
                            {
                                //Tentatively commenting out for bug #321924 
                                //this.ptCurrentCell.X = -1;
                                //this.ptCurrentCell.Y = -1;
                                //OnCurrentCellChanged(EventArgs.Empty);
                                if (!IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                                {
                                    OnRowEnter(ref dataGridViewCellTmp, columnIndex, rowIndex, true /*canCreateNewRow*/, false /*validationFailureOccurred*/); 
                                } 
                            }
 
                            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell])
                            {
                                //
                                // The rows collection was cleared while processing OnRowEnter. 
                                // If the new list is too small for rowIndex, fail the call to SetCurrentCellAddressCore.
                                // 
                                if (rowIndex >= this.Rows.Count) 
                                {
                                    return false; 
                                }
                                // rowIndex = Math.Min(rowIndex, this.Rows.GetRowCount(DataGridViewElementStates.Visible) - 1);
                            }
 
                            if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                            { 
                                return false; 
                            }
 
                            this.ptCurrentCell.X = columnIndex;
                            this.ptCurrentCell.Y = rowIndex;
                            if (this.editingControl != null)
                            { 
                                ((IDataGridViewEditingControl)this.editingControl).EditingControlRowIndex = rowIndex;
                            } 
                            OnCurrentCellChanged(EventArgs.Empty); 
                            if (setAnchorCellAddress)
                            { 
                                this.ptAnchorCell.X = columnIndex;
                                this.ptAnchorCell.Y = rowIndex;
                            }
 
                            #if FALSE
                            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell]) 
                            { 
                                // DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell bit will be cleared while executing the
                                // "finally" block. 
                                return true;
                            }
                            #endif
 
                            currentCell = this.CurrentCellInternal;
                            if (currentCell.EnterUnsharesRowInternal(rowIndex, throughMouseClick)) 
                            { 
                                currentCell = this.Rows[rowIndex].Cells[columnIndex]; // unsharing the row
                            } 
                            currentCell.OnEnterInternal(rowIndex, throughMouseClick);
                            OnCellEnter(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                            if (oldCurrentCellX >= 0)
                            { 
                                Debug.Assert(oldCurrentCellY >= 0);
                                if (oldCurrentCellX < this.Columns.Count && oldCurrentCellY < this.Rows.Count) 
                                { 
                                    InvalidateCellPrivate(oldCurrentCellX, oldCurrentCellY);
                                } 
                                if (oldCurrentCellY != this.ptCurrentCell.Y && this.RowHeadersVisible && oldCurrentCellY < this.Rows.Count)
                                {
                                    InvalidateCellPrivate(-1, oldCurrentCellY);
                                } 
                            }
                            InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); 
                            if (this.RowHeadersVisible && oldCurrentCellY != this.ptCurrentCell.Y) 
                            {
                                InvalidateCellPrivate(-1, this.ptCurrentCell.Y); 
                            }
                            if (this.Focused &&
                                this.ptCurrentCell.X != -1 &&
                                !this.IsCurrentCellInEditMode && 
                                !this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] &&      // don't edit if the rows collection changed
                                (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                                (this.EditMode != DataGridViewEditMode.EditProgrammatically && currentCell.EditType == null))) 
                            {
                                BeginEditInternal(true /*selectAll*/); 
                            }
                        }
                        finally
                        { 
                            this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] = false;
                        } 
 
                        // Accessibility
                        if (this.ptCurrentCell.X != -1) 
                        {
                            AccessibilityNotifyCurrentCellChanged(new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y));
                        }
                    } 
                    else
                    { 
                        // this.ptCurrentCell.X == columnIndex && this.ptCurrentCell.Y == rowIndex 
                        // Not trying to change the current cell, but may need to edit it.
                        if (setAnchorCellAddress) 
                        {
                            this.ptAnchorCell.X = columnIndex;
                            this.ptAnchorCell.Y = rowIndex;
                        } 
                        if (this.Focused &&
                            (!this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                            (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)))) 
                        {
                            BeginEditInternal(true /*selectAll*/); 
                        }
                        else
                        {
                            CorrectFocus(false /*onlyIfGridHasFocus*/); 
                        }
                    } 
                } 
                else
                { 
                    int oldCurrentCellX = this.ptCurrentCell.X;
                    int oldCurrentCellY = this.ptCurrentCell.Y;
                    if (oldCurrentCellX >= 0 &&
                        !this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] && 
                        !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose])
                    { 
                        DataGridViewCell currentCell = this.CurrentCellInternal; 
                        if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange,
                                    validateCurrentCell ? DataGridViewValidateCellInternal.Always : DataGridViewValidateCellInternal.Never, 
                                    validateCurrentCell /*fireCellLeave*/,
                                    false /*fireCellEnter*/,
                                    validateCurrentCell /*fireRowLeave*/,
                                    false /*fireRowEnter*/, 
                                    false /*fireLeave*/,
                                    this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/, 
                                    false /*resetCurrentCell*/, 
                                    false /*resetAnchorCell unused here*/))
                        { 
                            return false;
                        }
                        if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                        { 
                            currentCell = this.Rows.SharedRow(oldCurrentCellY).Cells[oldCurrentCellX];
                            if (currentCell.LeaveUnsharesRowInternal(oldCurrentCellY, throughMouseClick)) 
                            { 
                                currentCell = this.Rows[oldCurrentCellY].Cells[oldCurrentCellX]; // unsharing the current row
                            } 
                            currentCell.OnLeaveInternal(oldCurrentCellY, throughMouseClick);
                        }
                        if (validateCurrentCell)
                        { 
                            if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY))
                            { 
                                if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                {
                                    // Row validation was cancelled 
                                    Debug.Assert(oldCurrentCellX == this.ptCurrentCell.X);
                                    Debug.Assert(oldCurrentCellY == this.ptCurrentCell.Y);
                                    OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/);
                                    if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        currentCell.OnEnterInternal(oldCurrentCellY, throughMouseClick); 
                                        OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                    }
                                } 
                                return false;
                            }
                            if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                            { 
                                OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);
                            } 
                        } 
                    }
                    if (this.ptCurrentCell.X != -1) 
                    {
                        this.ptCurrentCell.X = -1;
                        this.ptCurrentCell.Y = -1;
                        OnCurrentCellChanged(EventArgs.Empty); 
                    }
                    if (setAnchorCellAddress) 
                    { 
                        this.ptAnchorCell.X = -1;
                        this.ptAnchorCell.Y = -1; 
                    }
                    if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell])
                    {
                        if (this.editingControl != null) 
                        {
                            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_discardEditingControl]) 
                            { 
                                this.dataGridViewState2[DATAGRIDVIEWSTATE2_discardEditingControl] = false;
                            } 
                            else
                            {
                                this.cachedEditingControl = this.editingControl;
                            } 
                            this.editingControl = null;
                        } 
                    } 
                    else if (oldCurrentCellX >= 0 && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose])
                    { 
                        Debug.Assert(oldCurrentCellY >= 0);
                        if (oldCurrentCellX < this.Columns.Count && oldCurrentCellY < this.Rows.Count)
                        {
                            InvalidateCellPrivate(oldCurrentCellX, oldCurrentCellY); 
                        }
                        if (this.RowHeadersVisible && oldCurrentCellY < this.Rows.Count) 
                        { 
                            InvalidateCellPrivate(-1, oldCurrentCellY);
                        } 
                    }
                }
            }
            finally 
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] = false; 
            } 
            return true;
        } 

        internal void SetCurrentCellAddressCoreInternal(int columnIndex,
            int rowIndex,
            bool setAnchorCellAddress, 
            bool validateCurrentCell,
            bool throughMouseClick) 
        { 
            SetCurrentCellAddressCore(columnIndex, rowIndex, setAnchorCellAddress, validateCurrentCell, throughMouseClick);
        } 

        private void SelectCellRange(int columnIndexFrom, int rowIndexFrom, int columnIndexTo, int rowIndexTo, bool select)
        {
            Debug.Assert(columnIndexFrom >= 0 && columnIndexTo >= 0); 
            Debug.Assert((this.Columns[columnIndexFrom]).DisplayIndex <= (this.Columns[columnIndexTo]).DisplayIndex);
            Debug.Assert(rowIndexFrom >= 0 && rowIndexTo >= 0); 
            Debug.Assert(rowIndexFrom <= rowIndexTo); 
            Debug.Assert(this.noSelectionChangeCount > 0);
 
            bool switchedToBulkPaint = false;
            if (rowIndexTo - rowIndexFrom > DATAGRIDVIEW_bulkPaintThreshold)
            {
                // Switch to batch operation 
                this.inBulkPaintCount++;
                switchedToBulkPaint = true; 
            } 
            try
            { 
                // Selection and deselection are done in reverse order for perf. reasons.
                if (select)
                {
                    int columnIndex = columnIndexFrom; 
                    do
                    { 
                        for (int rowIndex = rowIndexFrom; rowIndex <= rowIndexTo; rowIndex++) 
                        {
                            SetSelectedCellCore(columnIndex, rowIndex, true); 
                        }
                        if (columnIndex != columnIndexTo)
                        {
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[columnIndex], 
                                DataGridViewElementStates.Visible,
                                DataGridViewElementStates.None); 
                            Debug.Assert(dataGridViewColumn != null); 
                            columnIndex = dataGridViewColumn.Index;
                        } 
                    }
                    while (columnIndex != columnIndexTo);

                    if (columnIndexFrom != columnIndexTo) 
                    {
                        for (int rowIndex = rowIndexFrom; rowIndex <= rowIndexTo; rowIndex++) 
                        { 
                            SetSelectedCellCore(columnIndex, rowIndex, true);
                        } 
                    }
                }
                else
                { 
                    int columnIndex = columnIndexTo;
                    do 
                    { 
                        for (int rowIndex = rowIndexTo; rowIndex >= rowIndexFrom; rowIndex--)
                        { 
                            SetSelectedCellCore(columnIndex, rowIndex, false);
                        }
                        if (columnIndex != columnIndexFrom)
                        { 
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[columnIndex],
                                DataGridViewElementStates.Visible, 
                                DataGridViewElementStates.None); 
                            Debug.Assert(dataGridViewColumn != null);
                            columnIndex = dataGridViewColumn.Index; 
                        }
                    }
                    while (columnIndex != columnIndexFrom);
 
                    if (columnIndexFrom != columnIndexTo)
                    { 
                        for (int rowIndex = rowIndexTo; rowIndex >= rowIndexFrom; rowIndex--) 
                        {
                            SetSelectedCellCore(columnIndex, rowIndex, false); 
                        }
                    }
                }
            } 
            finally
            { 
                if (switchedToBulkPaint) 
                {
                    ExitBulkPaint(-1, -1); 
                }
            }
        }
 
        private void SelectCellUnorderedRange(int columnIndexFrom, int rowIndexFrom, int columnIndexTo, int rowIndexTo, bool select)
        { 
            Debug.Assert(this.noSelectionChangeCount > 0); 
            int columnIndexFromTmp, rowIndexFromTmp, columnIndexToTmp, rowIndexToTmp;
 
            if (this.Columns.DisplayInOrder(columnIndexFrom, columnIndexTo))
            {
                columnIndexFromTmp = columnIndexFrom;
                columnIndexToTmp = columnIndexTo; 
            }
            else 
            { 
                columnIndexFromTmp = columnIndexTo;
                columnIndexToTmp = columnIndexFrom; 
            }

            if (rowIndexFrom < rowIndexTo)
            { 
                rowIndexFromTmp = rowIndexFrom;
                rowIndexToTmp = rowIndexTo; 
            } 
            else
            { 
                rowIndexFromTmp = rowIndexTo;
                rowIndexToTmp = rowIndexFrom;
            }
 
            SelectCellRange(columnIndexFromTmp, rowIndexFromTmp, columnIndexToTmp, rowIndexToTmp, select);
        } 
 
        private void SelectColumnRange(int columnIndexFrom, int columnIndexTo, bool select)
        { 
            Debug.Assert(columnIndexFrom >= 0 && columnIndexTo >= 0);
            Debug.Assert((this.Columns[columnIndexFrom]).DisplayIndex <= (this.Columns[columnIndexTo]).DisplayIndex);
            Debug.Assert(this.noSelectionChangeCount > 0);
 
            int columnIndex = columnIndexFrom;
            do 
            { 
                if (select)
                { 
                    if (!this.selectedBandIndexes.Contains(columnIndex))
                    {
                        SetSelectedColumnCore(columnIndex, true);
                    } 
                }
                else 
                { 
                    Debug.Assert(this.selectedBandIndexes.Contains(columnIndex));
                    SetSelectedColumnCore(columnIndex, false); 
                }
                if (columnIndex != columnIndexTo)
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[columnIndex], 
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null); 
                    columnIndex = dataGridViewColumn.Index;
                } 
            }
            while (columnIndex != columnIndexTo);

            if (columnIndexFrom != columnIndexTo) 
            {
                if (select) 
                { 
                    if (!this.selectedBandIndexes.Contains(columnIndexTo))
                    { 
                        SetSelectedColumnCore(columnIndexTo, true);
                    }
                }
                else 
                {
                    Debug.Assert(this.selectedBandIndexes.Contains(columnIndexTo)); 
                    SetSelectedColumnCore(columnIndexTo, false); 
                }
            } 
        }

        private void SelectRowRange(int rowIndexFrom, int rowIndexTo, bool select)
        { 
            Debug.Assert(rowIndexFrom >= 0 && rowIndexTo >= 0);
            Debug.Assert(rowIndexFrom <= rowIndexTo); 
            Debug.Assert(this.noSelectionChangeCount > 0); 

            bool switchedToBulkPaint = false; 
            if (rowIndexTo - rowIndexFrom > DATAGRIDVIEW_bulkPaintThreshold)
            {
                // Switch to batch operation
                this.inBulkPaintCount++; 
                switchedToBulkPaint = true;
            } 
            try 
            {
                // Selecting and deselecting rows in reverse order for perf. reasons 
                if (select)
                {
                    for (int rowIndex = rowIndexFrom; rowIndex <= rowIndexTo; rowIndex++)
                    { 
                        if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) == 0)
                        { 
                            Debug.Assert(!this.selectedBandIndexes.Contains(rowIndex)); 
                            SetSelectedRowCore(rowIndex, true);
                        } 
                    }
                }
                else
                { 
                    for (int rowIndex = rowIndexTo; rowIndex >= rowIndexFrom; rowIndex--)
                    { 
                        Debug.Assert(this.selectedBandIndexes.Contains(rowIndex)); 
                        SetSelectedRowCore(rowIndex, false);
                    } 
                }
            }
            finally
            { 
                if (switchedToBulkPaint)
                { 
                    ExitBulkPaint(-1, -1); 
                }
            } 
        }

        private bool SetAndSelectCurrentCellAddress(int columnIndex,
            int rowIndex, 
            bool setAnchorCellAddress,
            bool validateCurrentCell, 
            bool throughMouseClick, 
            bool clearSelection,
            bool forceCurrentCellSelection) 
        {
            if (!SetCurrentCellAddressCore(columnIndex, rowIndex, setAnchorCellAddress, validateCurrentCell, throughMouseClick))
            {
                return false; 
            }
            if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
            { 
                return false;
            } 
            if (clearSelection)
            {
                ClearSelection(columnIndex, rowIndex, true /*selectException*/);    // we always select the new current cell when clearSelection is true
            } 
            else
            { 
                if (forceCurrentCellSelection) 
                {
                    SetSelectedElementCore(columnIndex, rowIndex, true); 
                }
                else
                {
                    if (this.MultiSelect && (this.individualSelectedCells.Count + this.selectedBandIndexes.Count) > 1) 
                    {
                        return true;   // Do not discard the multi-selection 
                    } 
                    if (this.individualSelectedCells.Count == 1)
                    { 
                        DataGridViewCell dataGridViewCell = this.individualSelectedCells.HeadCell;
                        if (dataGridViewCell.ColumnIndex != columnIndex || dataGridViewCell.RowIndex != rowIndex)
                        {
                            return true; 
                        }
                    } 
                    else if (this.selectedBandIndexes.Count == 1) 
                    {
                        switch (this.SelectionMode) 
                        {
                            case DataGridViewSelectionMode.FullColumnSelect:
                            case DataGridViewSelectionMode.ColumnHeaderSelect:
                            { 
                                if (this.selectedBandIndexes.HeadInt != columnIndex)
                                { 
                                    return true;  // Do not change a single selection that does not match the new current cell 
                                }
                                break; 
                            }
                            case DataGridViewSelectionMode.FullRowSelect:
                            case DataGridViewSelectionMode.RowHeaderSelect:
                            { 
                                if (this.selectedBandIndexes.HeadInt != rowIndex)
                                { 
                                    return true;  // Do not change a single selection that does not match the new current cell 
                                }
                                break; 
                            }
                        }
                    }
                    SetSelectedElementCore(columnIndex, rowIndex, true); 
                }
            } 
            return true; 
        }
 
        /// 
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        {
            if ((specified & BoundsSpecified.Width) == BoundsSpecified.Width && width > upperSize) { 
                throw new ArgumentOutOfRangeException("width", width, SR.GetString(SR.DataGridView_SizeTooLarge, (upperSize).ToString(CultureInfo.CurrentCulture)));
            } 
            if ((specified & BoundsSpecified.Height) == BoundsSpecified.Height && height > upperSize) { 
                throw new ArgumentOutOfRangeException("height", height, SR.GetString(SR.DataGridView_SizeTooLarge, (upperSize).ToString(CultureInfo.CurrentCulture)));
            } 
            base.SetBoundsCore(x, y, width, height, specified);
        }

        [ 
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ] 
        internal void SetReadOnlyCellCore(int columnIndex, int rowIndex, bool readOnly) 
        {
            Debug.Assert(columnIndex >= 0 && rowIndex >= 0 && 
                columnIndex < this.Columns.Count &&
                rowIndex < this.Rows.Count);

            // cell's readonly state changes 
            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if (IsSharedCellReadOnly(dataGridViewRow.Cells[columnIndex], rowIndex) != readOnly) 
            {
                DataGridViewCell dataGridViewCell = this.Rows[rowIndex].Cells[columnIndex]; 
                if (readOnly)
                {
                    if ((rowState & DataGridViewElementStates.ReadOnly) == 0 &&
                        !this.Columns[columnIndex].ReadOnly) 
                    {
                        this.individualReadOnlyCells.Add(dataGridViewCell); 
                        dataGridViewCell.ReadOnlyInternal = true; 
                    }
                } 
                else
                {
                    if (this.individualReadOnlyCells.Contains(dataGridViewCell))
                    { 
                        this.individualReadOnlyCells.Remove(dataGridViewCell);
                    } 
                    else 
                    {
                        DataGridViewCell dataGridViewCellTmp; 
                        if (this.Columns[columnIndex].ReadOnly)
                        {
                            this.Columns[columnIndex].ReadOnlyInternal = false;
                            // Perf Issue: this unshares all rows! 
                            for (int row = 0; row < rowIndex; row++)
                            { 
                                dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                dataGridViewCellTmp.ReadOnlyInternal = true;
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            }
                            for (int row = rowIndex+1; row < this.Rows.Count; row++)
                            {
                                dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                dataGridViewCellTmp.ReadOnlyInternal = true;
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            } 
                        }
                        if ((rowState & DataGridViewElementStates.ReadOnly) != 0) 
                        {
                            this.Rows.SetRowState(rowIndex, DataGridViewElementStates.ReadOnly, false);
                            for (int column = 0; column < columnIndex; column++)
                            { 
                                dataGridViewCellTmp = this.Rows[rowIndex].Cells[column];
                                dataGridViewCellTmp.ReadOnlyInternal = true; 
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            }
                            for (int column = columnIndex+1; column < this.Columns.Count; column++) 
                            {
                                dataGridViewCellTmp = this.Rows[rowIndex].Cells[column];
                                dataGridViewCellTmp.ReadOnlyInternal = true;
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            }
                        } 
                    } 
                    if (dataGridViewCell.ReadOnly)
                    { 
                        dataGridViewCell.ReadOnlyInternal = false;
                    }
                }
            } 
        }
 
        internal void SetReadOnlyColumnCore(int columnIndex, bool readOnly) 
        {
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 

            if (this.Columns[columnIndex].ReadOnly != readOnly)
            {
                // ReadOnly state of entire column changes 
                if (readOnly)
                { 
                    // column is made read-only 
                    // remove individual read-only cells of this column
                    try 
                    {
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = true;
                        RemoveIndividualReadOnlyCellsInColumn(columnIndex);
                    } 
                    finally
                    { 
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = false; 
                    }
                    this.Columns[columnIndex].ReadOnlyInternal = true; 
                }
                else
                {
                    // column is made read-write 
                    this.Columns[columnIndex].ReadOnlyInternal = false;
                } 
            } 
            else if (!readOnly)
            { 
                // remove any potentially individual read-only cells in the column
                RemoveIndividualReadOnlyCellsInColumn(columnIndex);
            }
        } 

        internal void SetReadOnlyRowCore(int rowIndex, bool readOnly) 
        { 
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
            if (((rowState & DataGridViewElementStates.ReadOnly) != 0) != readOnly)
            {
                // ReadOnly state of entire row changes 
                if (readOnly)
                { 
                    // row is made read-only 
                    // first remove individual read-only cells of this row
                    try 
                    {
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = true;
                        RemoveIndividualReadOnlyCellsInRow(rowIndex);
                    } 
                    finally
                    { 
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = false; 
                    }
                    this.Rows.SetRowState(rowIndex, DataGridViewElementStates.ReadOnly, true); 
                }
                else
                {
                    // row is made read-write 
                    this.Rows.SetRowState(rowIndex, DataGridViewElementStates.ReadOnly, false);
                } 
            } 
            else if (!readOnly)
            { 
                // remove any potentially individual read-only cells in the row
                RemoveIndividualReadOnlyCellsInRow(rowIndex);
            }
        } 

        ///  
        [ 
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ] 
        protected virtual void SetSelectedCellCore(int columnIndex, int rowIndex, bool selected)
        {
            if (columnIndex < 0 || columnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("columnIndex");
            } 
 
            if (rowIndex < 0 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex");
            }

            // cell selection changes 
            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if (IsSharedCellSelected(dataGridViewRow.Cells[columnIndex], rowIndex) != selected) 
            {
                DataGridViewCell dataGridViewCell = this.Rows[rowIndex].Cells[columnIndex]; 
                if (selected)
                {
                    if ((rowState & DataGridViewElementStates.Selected) == 0 &&
                        !this.Columns[columnIndex].Selected) 
                    {
                        this.individualSelectedCells.Add(dataGridViewCell); 
                        dataGridViewCell.SelectedInternal = true; 
                    }
                } 
                else
                {
                    if ((dataGridViewCell.State & DataGridViewElementStates.Selected) != 0)
                    { 
                        Debug.Assert(this.individualSelectedCells.Contains(dataGridViewCell));
                        this.individualSelectedCells.Remove(dataGridViewCell); 
                    } 
                    else
                    { 
                        DataGridViewCell dataGridViewCellTmp;
                        bool switchedToBulkPaint = false;
                        if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)
                        { 
                            if (this.Rows.Count > DATAGRIDVIEW_bulkPaintThreshold)
                            { 
                                this.inBulkPaintCount++; 
                                switchedToBulkPaint = true;
                            } 
                            try
                            {
                                Debug.Assert(this.selectedBandIndexes.Contains(columnIndex));
                                this.selectedBandIndexes.Remove(columnIndex); 
                                this.Columns[columnIndex].SelectedInternal = false;
                                // Perf Issue: this unshares all rows! 
                                for (int row = 0; row < rowIndex; row++) 
                                {
                                    dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                    dataGridViewCellTmp.SelectedInternal = true;
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                }
                                for (int row = rowIndex+1; row < this.Rows.Count; row++) 
                                {
                                    dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                    dataGridViewCellTmp.SelectedInternal = true; 
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                } 
                            }
                            finally
                            {
                                if (switchedToBulkPaint) 
                                {
                                    ExitBulkPaint(columnIndex, -1); 
                                } 
                            }
                        } 
                        else if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                        {
                            if (this.Columns.Count > DATAGRIDVIEW_bulkPaintThreshold)
                            { 
                                this.inBulkPaintCount++;
                                switchedToBulkPaint = true; 
                            } 
                            try
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(rowIndex));
                                this.selectedBandIndexes.Remove(rowIndex);
                                this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Selected, false);
                                for (int column = 0; column < columnIndex; column++) 
                                {
                                    dataGridViewCellTmp = this.Rows[rowIndex].Cells[column]; 
                                    dataGridViewCellTmp.SelectedInternal = true; 
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                } 
                                for (int column = columnIndex+1; column < this.Columns.Count; column++)
                                {
                                    dataGridViewCellTmp = this.Rows[rowIndex].Cells[column];
                                    dataGridViewCellTmp.SelectedInternal = true; 
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                } 
                            } 
                            finally
                            { 
                                if (switchedToBulkPaint)
                                {
                                    ExitBulkPaint(-1, rowIndex);
                                } 
                            }
                        } 
                    } 
                    if (dataGridViewCell.Selected)
                    { 
                        dataGridViewCell.SelectedInternal = false;
                    }
                }
            } 
        }
 
        internal void SetSelectedCellCoreInternal(int columnIndex, int rowIndex, bool selected) 
        {
            if (selected && !this.MultiSelect) 
            {
                if (!this.Columns[columnIndex].Visible ||
                    (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) == 0)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CurrentCellCannotBeInvisible));
                } 
 
                if (!ScrollIntoView(columnIndex, rowIndex, true))
                { 
                    return;
                }
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    return;
                } 
            } 

            this.noSelectionChangeCount++; 
            try
            {
                switch (this.SelectionMode)
                { 
                    case DataGridViewSelectionMode.CellSelect:
                    { 
                        if (selected && !this.MultiSelect) 
                        {
                            Debug.Assert(this.individualSelectedCells.Count <= 1); 
                            RemoveIndividuallySelectedCells();
                        }
                        SetSelectedCellCore(columnIndex, rowIndex, selected);
                        break; 
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                    {
                        if (selected) 
                        {
                            if (!this.MultiSelect)
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1); 
                                int bandIndex = 0;
                                while (bandIndex < this.selectedBandIndexes.Count) 
                                { 
                                    if (this.selectedBandIndexes[bandIndex] != columnIndex)
                                    { 
                                        // deselect currently selected column
                                        SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false);
                                    }
                                    else 
                                    {
                                        bandIndex++; 
                                    } 
                                }
                            } 
                            if (!this.selectedBandIndexes.Contains(columnIndex))
                            {
                                SetSelectedColumnCore(columnIndex, true);
                            } 
                        }
                        else 
                        { 
                            if (this.selectedBandIndexes.Contains(columnIndex))
                            { 
                                SetSelectedColumnCore(columnIndex, false);
                            }
                        }
                        break; 
                    }
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    {
                        if (selected) 
                        {
                            if (!this.MultiSelect)
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1); 
                                if (this.selectedBandIndexes.Count > 0)
                                { 
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); 
                                }
                                else 
                                {
                                    RemoveIndividuallySelectedCells();
                                }
                            } 
                            SetSelectedCellCore(columnIndex, rowIndex, true);
                        } 
                        else 
                        {
                            if (!this.MultiSelect) 
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0)
                                { 
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false);
                                } 
                                else 
                                {
                                    SetSelectedCellCore(columnIndex, rowIndex, false); 
                                }
                            }
                            else
                            { 
                                SetSelectedCellCore(columnIndex, rowIndex, false);
                            } 
                        } 
                        break;
                    } 

                    case DataGridViewSelectionMode.FullRowSelect:
                    {
                        if (selected) 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                int bandIndex = 0; 
                                while (bandIndex < this.selectedBandIndexes.Count)
                                {
                                    if (this.selectedBandIndexes[bandIndex] != rowIndex)
                                    { 
                                        // deselect currently selected row
                                        SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false); 
                                    } 
                                    else
                                    { 
                                        bandIndex++;
                                    }
                                }
                            } 
                            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) == 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(rowIndex) == 
                                             ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0));
                                SetSelectedRowCore(rowIndex, true); 
                            }
                        }
                        else
                        { 
                            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(rowIndex) == 
                                             ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0));
                                SetSelectedRowCore(rowIndex, false); 
                            }
                        }
                        break;
                    } 

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                    { 
                        if (selected)
                        { 
                            if (!this.MultiSelect)
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); 
                                } 
                                else
                                { 
                                    RemoveIndividuallySelectedCells();
                                }
                            }
                            SetSelectedCellCore(columnIndex, rowIndex, true); 
                        }
                        else 
                        { 
                            if (!this.MultiSelect)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0)
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); 
                                }
                                else 
                                { 
                                    SetSelectedCellCore(columnIndex, rowIndex, false);
                                } 
                            }
                            else
                            {
                                SetSelectedCellCore(columnIndex, rowIndex, false); 
                            }
                        } 
                        break; 
                    }
                } 
            }
            finally
            {
                this.NoSelectionChangeCount--; 
            }
 
            if (selected && !this.MultiSelect) 
            {
                bool success = SetCurrentCellAddressCore(columnIndex, rowIndex, true, false, true); 
                Debug.Assert(success);
            }
        }
 
        /// 
        protected virtual void SetSelectedColumnCore(int columnIndex, bool selected) 
        { 
            if (columnIndex < 0 || columnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("columnIndex");
            }

            this.noSelectionChangeCount++; 
            try
            { 
                if (this.Columns[columnIndex].Selected != selected) 
                {
                    // selection of entire column changes 
                    if (selected)
                    {
                        // column is selected
                        // remove individually selected cells of this column 
                        RemoveIndividuallySelectedCellsInColumn(columnIndex);
                        this.Columns[columnIndex].SelectedInternal = true; 
                        Debug.Assert(!this.selectedBandIndexes.Contains(columnIndex)); 
                        this.selectedBandIndexes.Add(columnIndex);
                    } 
                    else
                    {
                        // column is deselected
                        Debug.Assert(this.selectedBandIndexes.Contains(columnIndex)); 
                        this.Columns[columnIndex].SelectedInternal = false;
                        this.selectedBandIndexes.Remove(columnIndex); 
                    } 
                }
                else if (!selected) 
                {
                    // remove any potentially individually selected cells in the column
                    RemoveIndividuallySelectedCellsInColumn(columnIndex);
                } 
            }
            finally 
            { 
                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1);
                this.NoSelectionChangeCount--; 
            }
        }

        internal void SetSelectedColumnCoreInternal(int columnIndex, bool selected) 
        {
            this.noSelectionChangeCount++; 
            try 
            {
                if (!this.MultiSelect) 
                {
                    Debug.Assert(this.selectedBandIndexes.Count <= 1);
                    if (this.selectedBandIndexes.Count > 0)
                    { 
                        int columnIndexSelected = this.selectedBandIndexes.HeadInt;
                        if (columnIndexSelected != columnIndex) 
                        { 
                            SetSelectedColumnCore(columnIndexSelected, false);
                        } 
                    }
                }
                SetSelectedColumnCore(columnIndex, selected);
            } 
            finally
            { 
                this.NoSelectionChangeCount--; 
            }
        } 

        private void SetSelectedElementCore(int columnIndex, int rowIndex, bool selected)
        {
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.CellSelect: 
                { 
                    SetSelectedCellCore(columnIndex, rowIndex, selected);
                    break; 
                }
                case DataGridViewSelectionMode.RowHeaderSelect:
                {
                    if (columnIndex == -1) 
                    {
                        SetSelectedRowCore(rowIndex, selected); 
                    } 
                    else
                    { 
                        SetSelectedCellCore(columnIndex, rowIndex, selected);
                    }
                    break;
                } 
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                { 
                    if (rowIndex == -1) 
                    {
                        SetSelectedColumnCore(columnIndex, selected); 
                    }
                    else
                    {
                        SetSelectedCellCore(columnIndex, rowIndex, selected); 
                    }
                    break; 
                } 
                case DataGridViewSelectionMode.FullRowSelect:
                { 
                    SetSelectedRowCore(rowIndex, selected);
                    break;
                }
                case DataGridViewSelectionMode.FullColumnSelect: 
                {
                    SetSelectedColumnCore(columnIndex, selected); 
                    break; 
                }
            } 
        }

        /// 
        protected virtual void SetSelectedRowCore(int rowIndex, bool selected) 
        {
            if (rowIndex < 0 || rowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("rowIndex");
            } 

            this.noSelectionChangeCount++;
            try
            { 
                DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
                if (((rowState & DataGridViewElementStates.Selected) != 0) != selected) 
                { 
                    // selection of entire row changes
                    if (selected) 
                    {
                        // row is selected
                        // first remove individually selected cells of this row
                        RemoveIndividuallySelectedCellsInRow(rowIndex); 
                        Debug.Assert(!this.selectedBandIndexes.Contains(rowIndex));
                        this.selectedBandIndexes.Add(rowIndex); 
                        this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Selected, true); 
                    }
                    else 
                    {
                        // row is deselected
                        Debug.Assert(this.selectedBandIndexes.Contains(rowIndex));
                        this.selectedBandIndexes.Remove(rowIndex); 
                        this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Selected, false);
                    } 
                } 
                else if (!selected)
                { 
                    // remove any potentially individually selected cells in the row
                    RemoveIndividuallySelectedCellsInRow(rowIndex);
                }
            } 
            finally
            { 
                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                this.NoSelectionChangeCount--;
            } 
        }

        internal void SetSelectedRowCoreInternal(int rowIndex, bool selected)
        { 
            this.noSelectionChangeCount++;
            try 
            { 
                if (!this.MultiSelect)
                { 
                    Debug.Assert(this.selectedBandIndexes.Count <= 1);
                    if (this.selectedBandIndexes.Count > 0)
                    {
                        int rowIndexSelected = this.selectedBandIndexes.HeadInt; 
                        if (rowIndexSelected != rowIndex)
                        { 
                            SetSelectedRowCore(rowIndexSelected, false); 
                        }
                    } 
                }
                SetSelectedRowCore(rowIndex, selected);
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 
        }
 
        private bool ShouldSerializeAlternatingRowsDefaultCellStyle()
        {
            DataGridViewCellStyle defaultStyle = new DataGridViewCellStyle();
            return !this.AlternatingRowsDefaultCellStyle.Equals(defaultStyle); 
        }
 
        private bool ShouldSerializeColumnHeadersDefaultCellStyle() 
        {
            return !this.ColumnHeadersDefaultCellStyle.Equals(this.DefaultColumnHeadersDefaultCellStyle); 
        }

        private bool ShouldSerializeDefaultCellStyle()
        { 
            return !this.DefaultCellStyle.Equals(this.DefaultDefaultCellStyle);
        } 
 
        private bool ShouldSerializeRowHeadersDefaultCellStyle()
        { 
            return !this.RowHeadersDefaultCellStyle.Equals(this.DefaultRowHeadersDefaultCellStyle);
        }

        private bool ShouldSerializeRowsDefaultCellStyle() 
        {
            DataGridViewCellStyle defaultStyle = new DataGridViewCellStyle(); 
            return !this.RowsDefaultCellStyle.Equals(defaultStyle); 
        }
 
        /// 
        public virtual void Sort(DataGridViewColumn dataGridViewColumn, ListSortDirection direction)
        {
            if (dataGridViewColumn == null) 
            {
                throw new ArgumentNullException("dataGridViewColumn"); 
            } 

            if (direction != ListSortDirection.Ascending && direction != ListSortDirection.Descending) 
            {
                throw new InvalidEnumArgumentException("direction", (int)direction, typeof(ListSortDirection));
            }
 
            if (dataGridViewColumn.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            }
 
            if (this.VirtualMode && !dataGridViewColumn.IsDataBound)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_OperationDisabledInVirtualMode));
            } 

            SortInternal(null, dataGridViewColumn, direction); 
        } 

        ///  
        public virtual void Sort(IComparer comparer)
        {
            if (comparer == null)
            { 
                throw new ArgumentNullException("comparer");
            } 
 
            if (this.VirtualMode)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_OperationDisabledInVirtualMode));
            }

            // can't sort a data bound dataGridView control using a comparer 
            if (this.DataSource != null)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotUseAComparerToSortDataGridViewWhenDataBound)); 
            }
 
            SortInternal(comparer, null, ListSortDirection.Ascending);
        }

        private void SortDataBoundDataGridView_PerformCheck(DataGridViewColumn dataGridViewColumn) 
        {
            IBindingList ibl = this.dataConnection.List as IBindingList; 
            if (ibl == null) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotSortDataBoundDataGridViewBoundToNonIBindingList)); 
            }

            if (!ibl.SupportsSorting)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_IBindingListNeedsToSupportSorting));
            } 
 
            if (!dataGridViewColumn.IsDataBound)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnNeedsToBeDataBoundWhenSortingDataBoundDataGridView), "dataGridViewColumn");
            }
        }
 
        private void SortInternal(IComparer comparer, DataGridViewColumn dataGridViewColumn, ListSortDirection direction)
        { 
            Debug.Assert(!(comparer != null && this.DataSource != null)); 
            Debug.Assert(direction == ListSortDirection.Ascending || direction == ListSortDirection.Descending);
 
            // Exit editing mode if needed
            this.ptCurrentCellCache.X = this.ptCurrentCell.X;
            this.ptCurrentCellCache.Y = this.ptCurrentCell.Y;
            this.dataGridViewOper[DATAGRIDVIEWOPER_inSort] = true; 
            try
            { 
                if (!SetCurrentCellAddressCore(-1, -1, true, true, false)) 
                {
                    // Just cancel operation silently instead of throwing InvalidOperationException 
                    // 'finally' below resets this.dataGridViewOper[DATAGRIDVIEWOPER_inSort] to false
                    return;
                }
 
                int firstDisplayedScrollingRowCache = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                int visibleFrozenRows = this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                if (visibleFrozenRows > 0 && this.DataSource == null) 
                {
                    int rowVFIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    Debug.Assert(rowVFIndex != -1);
                    this.Rows.SetRowState(rowVFIndex, DataGridViewElementStates.Frozen, false);
                    Debug.Assert(0 == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen));
                } 

                if (this.sortedColumn != null && 
                    this.sortedColumn.SortMode == DataGridViewColumnSortMode.Automatic && 
                    this.sortedColumn.HasHeaderCell)
                { 
                    this.sortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
                }

                if (comparer == null) 
                {
                    Debug.Assert(dataGridViewColumn != null); 
                    this.sortedColumn = dataGridViewColumn; 
                    this.sortOrder = (direction == ListSortDirection.Ascending) ? SortOrder.Ascending : SortOrder.Descending;
                    if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && dataGridViewColumn.HasHeaderCell) 
                    {
                        dataGridViewColumn.HeaderCell.SortGlyphDirection = this.sortOrder;
                    }
                } 
                else
                { 
                    this.sortedColumn = null; 
                    this.sortOrder = SortOrder.None;
                } 

                if (this.DataSource == null)
                {
                    // Displayed rows may end up all spread out in the final layout. 
                    // So we simply reset their displayed state before the sort.
                    UpdateRowsDisplayedState(false /*displayed*/); 
                    this.Rows.Sort(comparer, direction == ListSortDirection.Ascending); 
                }
                else 
                {
                    SortDataBoundDataGridView_PerformCheck(dataGridViewColumn);
                    // the check passed, do the sorting
                    this.dataConnection.Sort(dataGridViewColumn, direction); 
                }
 
                if (this.ptCurrentCellCache.X != -1) 
                {
                    if (!IsInnerCellOutOfBounds(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y)) 
                    {
                        SetAndSelectCurrentCellAddress(this.ptCurrentCellCache.X,
                                                   this.ptCurrentCellCache.Y,
                                                   true, 
                                                   false,
                                                   false, 
                                                   false /*clearSelection*/, 
                                                   false /*forceCurrentCellSelection*/);
                    } 
                }
                if (visibleFrozenRows > 0)
                {
                    int rowVIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                    Debug.Assert(rowVIndex != -1);
                    while (visibleFrozenRows > 1) 
                    { 
                        rowVIndex = this.Rows.GetNextRow(rowVIndex, DataGridViewElementStates.Visible);
                        Debug.Assert(rowVIndex != -1); 
                        visibleFrozenRows--;
                    }
                    this.Rows.SetRowState(rowVIndex, DataGridViewElementStates.Frozen, true);
                } 
                this.displayedBandsInfo.FirstDisplayedScrollingRow = firstDisplayedScrollingRowCache;
            } 
            finally 
            {
                Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inSort]); 
                this.dataGridViewOper[DATAGRIDVIEWOPER_inSort] = false;
            }
            // Same effect as changing a top level cell style
            OnGlobalAutoSize(); 
            if (this.DataSource == null)
            { 
                // VSWhidbey 500898. Ensure that the Displayed states get set properly because they were wiped out by UpdateRowsDisplayedState above. 
                this.displayedBandsInfo.EnsureDirtyState();
            } 
            ResetUIState(false /*useRowShortcut*/, false /*computeVisibleRows*/);
            OnSorted(EventArgs.Empty);
        }
 
        internal void SwapSortedRows(int rowIndex1, int rowIndex2)
        { 
            Debug.Assert(rowIndex1 != this.newRowIndex); 
            Debug.Assert(rowIndex2 != this.newRowIndex);
            if (rowIndex1 == rowIndex2) 
            {
                return;
            }
 
            // Follow the move of the old current cell
            if (rowIndex1 == this.ptCurrentCellCache.Y) 
            { 
                this.ptCurrentCellCache.Y = rowIndex2;
            } 
            else if (rowIndex2 == this.ptCurrentCellCache.Y)
            {
                this.ptCurrentCellCache.Y = rowIndex1;
            } 

            switch (this.SelectionMode) 
            { 
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect: 
                    int row1Selected = this.selectedBandIndexes.IndexOf(rowIndex1);
                    int row2Selected = this.selectedBandIndexes.IndexOf(rowIndex2);
                    if (row1Selected != -1 && row2Selected == -1)
                    { 
                        this.selectedBandIndexes[row1Selected] = rowIndex2;
                    } 
                    else if (row1Selected == -1 && row2Selected != -1) 
                    {
                        this.selectedBandIndexes[row2Selected] = rowIndex1; 
                    }
                    if (this.selectedBandSnapshotIndexes != null)
                    {
                        row1Selected = this.selectedBandSnapshotIndexes.IndexOf(rowIndex1); 
                        row2Selected = this.selectedBandSnapshotIndexes.IndexOf(rowIndex2);
                        if (row1Selected != -1 && row2Selected == -1) 
                        { 
                            this.selectedBandSnapshotIndexes[row1Selected] = rowIndex2;
                        } 
                        else if (row1Selected == -1 && row2Selected != -1)
                        {
                            this.selectedBandSnapshotIndexes[row2Selected] = rowIndex1;
                        } 
                    }
                    break; 
            } 
        }
 
        private void DataGridViewHScrolled(object sender, ScrollEventArgs se)
        {
            if (!this.Enabled)
            { 
                return;
            } 
 
            /* VS Whidbey bug 262445 - no more commit on scroll
            if (this.ptCurrentCell.X >= 0) 
            {
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll])
                {
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition); 
                    se.NewValue = this.HorizontalOffset;
                    return; 
                } 
                this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition);
                this.horizScrollBar.Invalidate(); 
                if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                false /*forCurrentCellChange-/, false /*forCurrentRowChange-/))
                {
                    se.NewValue = this.HorizontalOffset; 
                    if (se.Type == ScrollEventType.SmallIncrement || se.Type == ScrollEventType.SmallDecrement)
                    { 
                        // Workaround for a pbm where the scrollbar ends up in a bad state after a validation failure dialog is displayed. 
                        this.horizScrollBar.RecreateScrollBarHandle();
                    } 
                    else
                    {
                        this.horizScrollBar.Invalidate();
                    } 
                    return;
                } 
                else 
                {
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll] = false; 
                }
            }
            */
 
            if (se.Type == ScrollEventType.SmallIncrement ||
                se.Type == ScrollEventType.SmallDecrement) 
            { 
                int dCols = (se.Type == ScrollEventType.SmallIncrement) ? 1 : -1;
                ScrollColumns(dCols); 
                se.NewValue = this.HorizontalOffset;
            }
            else if (se.Type != ScrollEventType.EndScroll)
            { 
                this.HorizontalOffset = se.NewValue;
            } 
        } 

        private void DataGridViewVScrolled(object sender, ScrollEventArgs se) 
        {
            if (!this.Enabled)
            {
                return; 
            }
 
            /* VS Whidbey bug 262445 - no more commit on scroll 
            if (this.ptCurrentCell.X >= 0)
            { 
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll])
                {
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition);
                    se.NewValue = this.VerticalOffset; 
                    return;
                } 
                this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition); 
                this.vertScrollBar.Invalidate();
                if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                false /*forCurrentCellChange-/, false /*forCurrentRowChange-/))
                {
                    se.NewValue = this.VerticalOffset;
                    if (se.Type == ScrollEventType.SmallIncrement || se.Type == ScrollEventType.SmallDecrement) 
                    {
                        // Workaround for a pbm where the scrollbar ends up in a bad state after a validation failure dialog is displayed. 
                        this.vertScrollBar.RecreateScrollBarHandle(); 
                    }
                    else 
                    {
                        this.vertScrollBar.Invalidate();
                    }
                    return; 
                }
                else 
                { 
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll] = false;
                } 
            }
            */

            int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            switch (se.Type)
            { 
                case ScrollEventType.SmallIncrement: 
                {
                    // Making sure that when the last visible scrolling row is taller than the data area, it does not get scrolled off screen 
                    Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                    if (this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <=
                        this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight))
                    { 
                        ScrollRowsByCount(1, ScrollEventType.SmallIncrement);
                    } 
                    se.NewValue = this.VerticalOffset; 
                    break;
                } 
                case ScrollEventType.SmallDecrement:
                {
                    if (this.vertScrollBar.Value != this.vertScrollBar.Minimum)
                    { 
                        ScrollRowsByCount(-1, ScrollEventType.SmallDecrement);
                    } 
                    se.NewValue = this.VerticalOffset; 
                    break;
                } 
                case ScrollEventType.LargeIncrement:
                {
                    Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                    int firstDisplayedScrollingRowHeight = this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow); 
                    this.VerticalOffset += Math.Max(firstDisplayedScrollingRowHeight, this.vertScrollBar.LargeChange);
                    se.NewValue = this.VerticalOffset; 
                    break; 
                }
                case ScrollEventType.LargeDecrement: 
                {
                    this.VerticalOffset -= this.vertScrollBar.LargeChange;
                    se.NewValue = this.VerticalOffset;
                    break; 
                }
                case ScrollEventType.ThumbTrack: 
                case ScrollEventType.First: 
                case ScrollEventType.Last:
                { 
                    if (se.NewValue >= this.vertScrollBar.Maximum - this.vertScrollBar.LargeChange)
                    {
                        // Need to display the last scrolling row
                        this.VerticalOffset = this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight); 
                    }
                    else 
                    { 
                        this.VerticalOffset = se.NewValue;
                    } 
                    break;
                }
            }
        } 

        private bool TabToNextCell() 
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1)
            { 
                return false;
            } 
            int nextVisibleColumnIndex = -1; 
            if (this.ptCurrentCell.X != -1)
            { 
                dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.ptCurrentCell.X],
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None);
                if (dataGridViewColumn != null) 
                {
                    nextVisibleColumnIndex = dataGridViewColumn.Index; 
                } 
            }
            int nextVisibleRowIndex = -1; 
            if (this.ptCurrentCell.Y != -1)
            {
                nextVisibleRowIndex = this.Rows.GetNextRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
            } 
            int targetRowIndex = -1, targetColumnIndex = -1;
 
            this.noSelectionChangeCount++; 
            try
            { 
                if (this.ptCurrentCell.X == -1)
                {
                    ClearSelection();
                } 
                else
                { 
                    if (nextVisibleColumnIndex == -1) 
                    {
                        targetRowIndex = (nextVisibleRowIndex == -1) ? firstVisibleRowIndex : nextVisibleRowIndex; 
                        targetColumnIndex = firstVisibleColumnIndex;
                    }
                    else
                    { 
                        targetRowIndex = this.ptCurrentCell.Y;
                        targetColumnIndex = nextVisibleColumnIndex; 
                    } 
                    if (!ScrollIntoView(targetColumnIndex, targetRowIndex, true))
                    { 
                        return true;
                    }
                }
 
                switch (this.SelectionMode)
                { 
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (this.ptCurrentCell.X == -1)
                        {
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            { 
                                return true;
                            } 
                            SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                        }
                        else 
                        {
                            if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex))
                            {
                                return true; 
                            }
                            ClearSelection(); 
                            SetSelectedCellCore(targetColumnIndex, targetRowIndex, true); 
                        }
                        break; 

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if (this.ptCurrentCell.X == -1)
                        { 
                            if (IsColumnOutOfBounds(firstVisibleColumnIndex))
                            { 
                                return true; 
                            }
                            SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                        }
                        else
                        {
                            if (IsColumnOutOfBounds(targetColumnIndex)) 
                            {
                                return true; 
                            } 
                            ClearSelection();
                            SetSelectedColumnCore(targetColumnIndex, true); 
                        }
                        break;

                    case DataGridViewSelectionMode.FullRowSelect: 
                        if (this.ptCurrentCell.X == -1)
                        { 
                            if (IsRowOutOfBounds(firstVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            SetSelectedRowCore(firstVisibleRowIndex, true);
                        }
                        else 
                        {
                            if (targetRowIndex != this.ptCurrentCell.Y || this.MultiSelect) 
                            { 
                                if (IsRowOutOfBounds(targetRowIndex))
                                { 
                                    return true;
                                }
                                ClearSelection();
                                SetSelectedRowCore(targetRowIndex, true); 
                            }
                        } 
                        break; 
                }
            } 
            finally
            {
                this.NoSelectionChangeCount--;
            } 

            if (this.ptCurrentCell.X == -1) 
            { 
                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                Debug.Assert(success); 
                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                {
                    return true;
                } 
                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                // DataGridView changes. 
                // See vsWhidbey: 325296.
                // Debug.Assert(success); 
            }
            else
            {
                if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex)) 
                {
                    return true; 
                } 
                success = SetCurrentCellAddressCore(targetColumnIndex, targetRowIndex, true, false, false);
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                // DataGridView changes.
                // See vsWhidbey: 325296.
                // Debug.Assert(success);
            } 
            return true;
        } 
 
        private bool TabToPreviousCell()
        { 
            bool success;

            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            { 
                return false;
            } 

            int previousVisibleColumnIndex = -1;
            if (this.ptCurrentCell.X != -1)
            { 
                dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.ptCurrentCell.X],
                    DataGridViewElementStates.Visible, 
                    DataGridViewElementStates.None); 
                if (dataGridViewColumn != null)
                { 
                    previousVisibleColumnIndex = dataGridViewColumn.Index;
                }
            }
 
            int previousVisibleRowIndex = -1;
            if (this.ptCurrentCell.Y != -1) 
            { 
                previousVisibleRowIndex = this.Rows.GetPreviousRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
            } 

            dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible,
                DataGridViewElementStates.None);
            Debug.Assert(dataGridViewColumn != null); 
            int lastVisibleColumnIndex = dataGridViewColumn.Index;
            int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); 
            Debug.Assert(lastVisibleRowIndex != -1); 

            int targetRowIndex = -1, targetColumnIndex = -1; 

            this.noSelectionChangeCount++;
            try
            { 
                if (this.ptCurrentCell.X == -1)
                { 
                    ClearSelection(); 
                }
                else 
                {
                    if (previousVisibleColumnIndex == -1)
                    {
                        targetRowIndex = (previousVisibleRowIndex == -1) ? lastVisibleRowIndex : previousVisibleRowIndex; 
                        targetColumnIndex = lastVisibleColumnIndex;
                    } 
                    else 
                    {
                        targetRowIndex = this.ptCurrentCell.Y; 
                        targetColumnIndex = previousVisibleColumnIndex;
                    }
                    if (!ScrollIntoView(targetColumnIndex, targetRowIndex, true))
                    { 
                        return true;
                    } 
                } 

                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (this.ptCurrentCell.X == -1)
                        { 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                        }
                        else 
                        {
                            if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex)) 
                            { 
                                return true;
                            } 
                            ClearSelection();
                            SetSelectedCellCore(targetColumnIndex, targetRowIndex, true);
                        }
                        break; 

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if (this.ptCurrentCell.X == -1) 
                        {
                            if (IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                            {
                                return true;
                            }
                            SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                        }
                        else 
                        { 
                            if (IsColumnOutOfBounds(targetColumnIndex))
                            { 
                                return true;
                            }
                            ClearSelection();
                            SetSelectedColumnCore(targetColumnIndex, true); 
                        }
                        break; 
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if (this.ptCurrentCell.X == -1) 
                        {
                            if (IsRowOutOfBounds(firstVisibleRowIndex))
                            {
                                return true; 
                            }
                            SetSelectedRowCore(firstVisibleRowIndex, true); 
                        } 
                        else
                        { 
                            if (targetRowIndex != this.ptCurrentCell.Y || this.MultiSelect)
                            {
                                if (IsRowOutOfBounds(targetRowIndex))
                                { 
                                    return true;
                                } 
                                ClearSelection(); 
                                SetSelectedRowCore(targetRowIndex, true);
                            } 
                        }
                        break;
                }
            } 
            finally
            { 
                this.NoSelectionChangeCount--; 
            }
 
            if (this.ptCurrentCell.X == -1)
            {
                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                Debug.Assert(success); 
                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                { 
                    return true; 
                }
                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the
                // DataGridView changes.
                // See vsWhidbey: 325296.
                // Debug.Assert(success); 
            }
            else 
            { 
                if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex))
                { 
                    return true;
                }
                success = SetCurrentCellAddressCore(targetColumnIndex, targetRowIndex, true, false, false);
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                // DataGridView changes.
                // See vsWhidbey: 325296. 
                // Debug.Assert(success); 
            }
 
            return true;
        }

        private void UnwireEditingControlEvents() 
        {
            Debug.Assert(this.editingPanel != null); 
            this.editingPanel.Click -= new System.EventHandler(EditingControls_Click); 
            this.editingPanel.DoubleClick -= new System.EventHandler(EditingControls_DoubleClick);
            this.editingPanel.MouseClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick); 
            this.editingPanel.MouseDoubleClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick);
            this.editingPanel.MouseDown -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown);
            this.editingPanel.MouseEnter -= new System.EventHandler(EditingControls_MouseEnter);
            this.editingPanel.MouseLeave -= new System.EventHandler(EditingControls_MouseLeave); 
            this.editingPanel.MouseMove -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove);
            this.editingPanel.MouseUp -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp); 
 
            Debug.Assert(this.editingControl != null);
            this.editingControl.Click -= new System.EventHandler(EditingControls_Click); 
            this.editingControl.DoubleClick -= new System.EventHandler(EditingControls_DoubleClick);
            this.editingControl.MouseClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick);
            this.editingControl.MouseDoubleClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick);
            this.editingControl.MouseDown -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown); 
            this.editingControl.MouseEnter -= new System.EventHandler(EditingControls_MouseEnter);
            this.editingControl.MouseLeave -= new System.EventHandler(EditingControls_MouseLeave); 
            this.editingControl.MouseMove -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove); 
            this.editingControl.MouseUp -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp);
        } 

        private void UnwireScrollBarsEvents()
        {
            if (this.horizScrollBar != null) 
            {
                this.horizScrollBar.MouseEnter -= new System.EventHandler(ScrollBar_MouseEnter); 
                this.horizScrollBar.MouseLeave -= new System.EventHandler(ScrollBar_MouseLeave); 
            }
            if (this.vertScrollBar != null) 
            {
                this.vertScrollBar.MouseEnter -= new System.EventHandler(ScrollBar_MouseEnter);
                this.vertScrollBar.MouseLeave -= new System.EventHandler(ScrollBar_MouseLeave);
            } 
        }
 
        ///  
        public void UpdateCellErrorText(int columnIndex, int rowIndex)
        { 
            if (columnIndex < -1 || columnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("columnIndex");
            } 
            if (rowIndex < -1 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex"); 
            }
            if (this.IsHandleCreated) 
            {
                InvalidateCellPrivate(columnIndex, rowIndex);
            }
        } 

        ///  
        public void UpdateCellValue(int columnIndex, int rowIndex) 
        {
            if (columnIndex < 0 || columnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("columnIndex");
            }
            if (rowIndex < 0 || rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            } 
            if (this.IsHandleCreated)
            { 
                OnCellCommonChange(columnIndex, rowIndex);
            }
        }
 
        private void UpdateColumnsDisplayedState(bool displayed)
        { 
            // Make sure all displayed frozen columns have their Displayed state set to this.Visible 
            DataGridViewColumn dataGridViewColumnTmp;
            int numDisplayedFrozenCols = this.displayedBandsInfo.NumDisplayedFrozenCols; 
            if (numDisplayedFrozenCols > 0)
            {
                dataGridViewColumnTmp = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                while (numDisplayedFrozenCols > 0) 
                {
                    Debug.Assert(dataGridViewColumnTmp != null); 
                    if (dataGridViewColumnTmp.Displayed != displayed) 
                    {
                        dataGridViewColumnTmp.DisplayedInternal = displayed; 
                        Debug.Assert(ColumnNeedsDisplayedState(dataGridViewColumnTmp));
                    }
                    dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None);
                    numDisplayedFrozenCols--; 
                }
            } 
 
            // Make sure all displayed scrolling columns have the Displayed state set to this.Visible
            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 != displayed) 
                    {
                        dataGridViewColumnTmp.DisplayedInternal = displayed;
                        Debug.Assert(ColumnNeedsDisplayedState(dataGridViewColumnTmp));
                    } 
                    dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    numDisplayedScrollingCols--; 
                } 
            }
        } 

        /// 
        public void UpdateRowErrorText(int rowIndex)
        { 
            if (rowIndex < 0 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex"); 
            }
            if (this.IsHandleCreated && this.layout.RowHeadersVisible) 
            {
                InvalidateCellPrivate(-1, rowIndex);
            }
        } 

        ///  
        public void UpdateRowErrorText(int rowIndexStart, int rowIndexEnd) 
        {
            if (rowIndexStart < 0 || rowIndexStart >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndexStart");
            }
            if (rowIndexEnd < 0 || rowIndexEnd >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndexEnd"); 
            } 
            if (rowIndexEnd < rowIndexStart)
            { 
                throw new ArgumentOutOfRangeException("rowIndexEnd");
            }
            if (this.IsHandleCreated && this.layout.RowHeadersVisible)
            { 
                Rectangle rectUpper = GetCellAdjustedDisplayRectangle(-1, rowIndexStart, true);
                Rectangle rectLower = GetCellAdjustedDisplayRectangle(-1, rowIndexEnd, true); 
                if (rectUpper.IsEmpty || rectLower.IsEmpty) 
                {
                    if (!rectUpper.IsEmpty || !rectLower.IsEmpty) 
                    {
                        Invalidate(this.layout.RowHeaders);
                    }
                } 
                else
                { 
                    Invalidate(Rectangle.Union(rectUpper, rectLower)); 
                }
            } 
        }

        /// 
        public void UpdateRowHeightInfo(int rowIndex, bool updateToEnd) 
        {
            UpdateRowHeightInfoPrivate(rowIndex, updateToEnd, true /*invalidInAdjustFillingColumns*/); 
        } 

        private void UpdateRowHeightInfoPrivate(int rowIndex, bool updateToEnd, bool invalidInAdjustFillingColumns) 
        {
            if ((updateToEnd && rowIndex < 0) || (!updateToEnd && rowIndex < -1) || rowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            }
 
            this.Rows.InvalidateCachedRowsHeights(); 

            bool rowVisible = (rowIndex >= 0 && (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0); 

            // don't do any layout logic if the handled was not created already
            if (this.IsHandleCreated && (rowIndex == -1 || rowVisible))
            { 
                if (updateToEnd)
                { 
                    int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 

                    if (this.AutoSize) 
                    {
                        LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows);
                    }
                    else 
                    {
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/); 
                    } 

                    Rectangle bottomArea = this.layout.Data; 
                    if (this.layout.RowHeadersVisible)
                    {
                        bottomArea = Rectangle.Union(bottomArea, this.layout.RowHeaders);
                    } 
                    else if (this.SingleVerticalBorderAdded)
                    { 
                        if (!this.RightToLeftInternal) 
                        {
                            bottomArea.X--; 
                        }
                        bottomArea.Width++;
                    }
 
                    if (!rowVisible)
                    { 
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); 
                    }
                    if (rowIndex != -1) 
                    {
                        int topEdge = GetRowYFromIndex(oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow ? rowIndex : this.displayedBandsInfo.FirstDisplayedScrollingRow);
                        bottomArea.Height -= bottomArea.Y - topEdge;
                        bottomArea.Y = topEdge; 
                        Invalidate(bottomArea);
                    } 
 
                    if (this.editingControl != null)
                    { 
                        PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                    }
                }
                else 
                {
                    if (rowIndex == -1) 
                    { 
                        if (this.AutoSize)
                        { 
                            LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows);
                        }
                        else
                        { 
                            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/);
                        } 
                        Invalidate(); 
                    }
                    else 
                    {
                        Debug.Assert(rowVisible);
                        int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
 
                        if (this.inBulkLayoutCount == 0)
                        { 
                            if (this.AutoSize) 
                            {
                                LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows); 
                            }
                            else
                            {
                                PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/); 
                            }
                        } 
 
                        if (this.inBulkPaintCount == 0)
                        { 
                            Rectangle bottomArea = this.layout.Data;
                            if (this.layout.RowHeadersVisible)
                            {
                                bottomArea = Rectangle.Union(bottomArea, this.layout.RowHeaders); 
                            }
                            else if (this.SingleVerticalBorderAdded) 
                            { 
                                if (!this.RightToLeftInternal)
                                { 
                                    bottomArea.X--;
                                }
                                bottomArea.Width++;
                            } 
                            int topEdge = GetRowYFromIndex(oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow ? rowIndex : this.displayedBandsInfo.FirstDisplayedScrollingRow);
                            bottomArea.Height -= bottomArea.Y - topEdge; 
                            bottomArea.Y = topEdge; 
                            Invalidate(bottomArea);
                        } 
                    }

                    if (this.editingControl != null)
                    { 
                        PositionEditingControl(rowIndex == -1 || this.ptCurrentCell.Y != rowIndex, true, false);
                    } 
                } 

                UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 
            }
        }

        private void UpdateRowsDisplayedState(bool displayed) 
        {
            // Make sure all displayed frozen rows have their Displayed state set to 'displayed' 
            int rowIndexTmp, numDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedFrozenRows; 
            if (numDisplayedFrozenRows > 0)
            { 
                rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                while (numDisplayedFrozenRows > 0)
                {
                    Debug.Assert(rowIndexTmp != -1); 
                    if (((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0) == displayed)
                    { 
                        this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, displayed); 
                    }
                    rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    numDisplayedFrozenRows--;
                }
            }
 
            // Make sure all displayed scrolling rows have their Displayed state set to 'displayed'
            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) == displayed)
                    { 
                        this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, displayed); 
                    }
                    rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); 
                    numDisplayedScrollingRows--;
                }
            }
        } 

        private void UpdateMouseEnteredCell(HitTestInfo hti, MouseEventArgs e) 
        { 
            Point ptMouse = PointToClient(Control.MousePosition);
            HitTestInfo htiToUse; 
            if (hti != null)
            {
                htiToUse = hti;
            } 
            else
            { 
                htiToUse = HitTest(ptMouse.X, ptMouse.Y); 
            }
 
            if (htiToUse.Type != DataGridViewHitTestType.None &&
                htiToUse.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                htiToUse.Type != DataGridViewHitTestType.VerticalScrollBar)
            { 
                if (this.ptMouseEnteredCell.X != htiToUse.col || this.ptMouseEnteredCell.Y != htiToUse.row)
                { 
                    DataGridViewCellEventArgs dgvce; 
                    if (this.ptMouseEnteredCell.X >= -1 &&
                        this.ptMouseEnteredCell.X < this.Columns.Count && 
                        this.ptMouseEnteredCell.Y >= -1 &&
                        this.ptMouseEnteredCell.Y < this.Rows.Count)
                    {
                        dgvce = new DataGridViewCellEventArgs(this.ptMouseEnteredCell.X, this.ptMouseEnteredCell.Y); 
                        OnCellMouseLeave(dgvce);
                    } 
                    dgvce = new DataGridViewCellEventArgs(htiToUse.col, htiToUse.row); 
                    OnCellMouseEnter(dgvce);
                } 
                if (e != null)
                {
                    int mouseX = e.X - htiToUse.ColumnX;
                    if (this.RightToLeftInternal) 
                    {
                        mouseX += ((htiToUse.col == -1) ? this.RowHeadersWidth : this.Columns[htiToUse.col].Thickness); 
                    } 
                    DataGridViewCellMouseEventArgs dgvcme = new DataGridViewCellMouseEventArgs(htiToUse.col, htiToUse.row, mouseX, e.Y - htiToUse.RowY, e);
                    OnCellMouseMove(dgvcme); 
                }
            }
            else if (this.ptMouseEnteredCell.X != -2)
            { 
                if (this.ptMouseEnteredCell.X >= -1 &&
                    this.ptMouseEnteredCell.X < this.Columns.Count && 
                    this.ptMouseEnteredCell.Y >= -1 && 
                    this.ptMouseEnteredCell.Y < this.Rows.Count)
                { 
                    DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(this.ptMouseEnteredCell.X, this.ptMouseEnteredCell.Y);
                    OnCellMouseLeave(dgvce);
                }
                else 
                {
                    this.ptMouseEnteredCell.X = this.ptMouseEnteredCell.Y = -2; 
                } 
            }
        } 

        private void UpdateSelectedCellsBlock(int anchorColumnIndex, ref int oldEdgeColumnIndex, int newEdgeColumnIndex,
            int anchorRowIndex, ref int oldEdgeRowIndex, int newEdgeRowIndex)
        { 
            Debug.Assert(anchorColumnIndex >= 0);
            Debug.Assert(anchorRowIndex >= 0); 
            Debug.Assert(newEdgeColumnIndex >= 0); 
            Debug.Assert(newEdgeRowIndex >= 0);
            Debug.Assert(this.noSelectionChangeCount > 0); 
            if ((this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex) &&
                this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex)) ||
                (this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex) &&
                this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex)) || 
                (anchorRowIndex < oldEdgeRowIndex && newEdgeRowIndex < anchorRowIndex) ||
                (oldEdgeRowIndex < anchorRowIndex && anchorRowIndex < newEdgeRowIndex)) 
            { 
                // deselecting all selected block
                SelectCellUnorderedRange(anchorColumnIndex, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false); 
                // and reselecting new block
                SelectCellUnorderedRange(anchorColumnIndex, anchorRowIndex, newEdgeColumnIndex, newEdgeRowIndex, true);
                oldEdgeColumnIndex = newEdgeColumnIndex;
                oldEdgeRowIndex = newEdgeRowIndex; 
                return;
            } 
 
            if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex) &&
                (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex) || anchorColumnIndex == oldEdgeColumnIndex) && 
                oldEdgeRowIndex == newEdgeRowIndex)
            {
                // h1
                DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                Debug.Assert(dataGridViewColumn != null);
                if (anchorRowIndex <= newEdgeRowIndex) 
                { 
                    SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, newEdgeColumnIndex, newEdgeRowIndex, true);
                } 
                else
                {
                    // newEdgeRowIndex < anchorRowIndex
                    SelectCellRange(dataGridViewColumn.Index, newEdgeRowIndex, newEdgeColumnIndex, anchorRowIndex, true); 
                }
            } 
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex) && 
                (this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex) || oldEdgeColumnIndex == anchorColumnIndex) &&
                oldEdgeRowIndex == newEdgeRowIndex) 
            {
                // h2
                DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                Debug.Assert(dataGridViewColumn != null); 
                if (anchorRowIndex <= newEdgeRowIndex)
                { 
                    SelectCellRange(newEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, newEdgeRowIndex, true); 
                }
                else 
                {
                    // newEdgeRowIndex < anchorRowIndex
                    SelectCellRange(newEdgeColumnIndex, newEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, true);
                } 
            }
            else if (newEdgeRowIndex > oldEdgeRowIndex && 
                anchorRowIndex <= oldEdgeRowIndex && 
                newEdgeColumnIndex == oldEdgeColumnIndex)
            { 
                // h3
                if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || anchorColumnIndex == newEdgeColumnIndex)
                {
                    SelectCellRange(anchorColumnIndex, 
                        this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        newEdgeColumnIndex, 
                        newEdgeRowIndex, 
                        true);
                } 
                else
                {
                    // newEdgeColumnIndex before anchorColumnIndex
                    SelectCellRange(newEdgeColumnIndex, 
                        this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        anchorColumnIndex, 
                        newEdgeRowIndex, 
                        true);
                } 
            }
            else if (newEdgeRowIndex < oldEdgeRowIndex &&
                oldEdgeRowIndex <= anchorRowIndex &&
                newEdgeColumnIndex == oldEdgeColumnIndex) 
            {
                // h4 
                if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || anchorColumnIndex == newEdgeColumnIndex) 
                {
                    SelectCellRange(anchorColumnIndex, 
                        newEdgeRowIndex,
                        newEdgeColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        true); 
                }
                else 
                { 
                    // newEdgeColumnIndex before anchorColumnIndex
                    SelectCellRange(newEdgeColumnIndex, 
                        newEdgeRowIndex,
                        anchorColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        true); 
                }
            } 
            else if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex) && 
                !this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex) &&
                newEdgeRowIndex > oldEdgeRowIndex && anchorRowIndex <= oldEdgeRowIndex) 
            {
                // h5
                DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                Debug.Assert(dataGridViewColumn != null); 
                SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, newEdgeColumnIndex, oldEdgeRowIndex, true);
                SelectCellRange(anchorColumnIndex, 
                    this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible), 
                    newEdgeColumnIndex,
                    newEdgeRowIndex, 
                    true);
            }
            else if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex) &&
                newEdgeRowIndex < oldEdgeRowIndex && oldEdgeRowIndex <= anchorRowIndex) 
            {
                if (!this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex)) 
                { 
                    // h6
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, newEdgeColumnIndex, anchorRowIndex, true);
                    SelectCellRange(anchorColumnIndex,
                        newEdgeRowIndex, 
                        newEdgeColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible), 
                        true); 
                }
                else 
                {
                    if (!this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex))
                    {
                        if (anchorRowIndex == oldEdgeRowIndex) 
                        {
                            // g2 
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, anchorColumnIndex, oldEdgeRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex, newEdgeRowIndex, anchorColumnIndex, anchorRowIndex, true);
                        } 
                        else
                        {
                            // b4
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                            Debug.Assert(dataGridViewColumn != null);
                            Debug.Assert(oldEdgeRowIndex < anchorRowIndex); 
                            SelectCellRange(oldEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex,
                                newEdgeRowIndex, 
                                anchorColumnIndex,
                                this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                                true);
                        } 
                    }
                } 
            } 
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex) &&
                newEdgeRowIndex < oldEdgeRowIndex && anchorRowIndex >= oldEdgeRowIndex) 
            {
                if (!this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex))
                {
                    // h7 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectCellRange(newEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, true); 
                    SelectCellRange(newEdgeColumnIndex,
                        newEdgeRowIndex, 
                        anchorColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        true);
                } 
                else
                { 
                    if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex)) 
                    {
                        // a4 
                        DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                        Debug.Assert(dataGridViewColumn != null);
                        Debug.Assert(oldEdgeRowIndex <= anchorRowIndex);
                        SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false); 
                        SelectCellRange(anchorColumnIndex,
                            newEdgeRowIndex, 
                            newEdgeColumnIndex, 
                            this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                            true); 
                    }
                    else
                    {
                        // g8 
                        SelectCellRange(anchorColumnIndex, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false);
                        SelectCellRange(newEdgeColumnIndex, newEdgeRowIndex, anchorColumnIndex, anchorRowIndex, true); 
                    } 
                }
            } 
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex) &&
                !this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex) &&
                newEdgeRowIndex > oldEdgeRowIndex && anchorRowIndex <= oldEdgeRowIndex)
            { 
                // h8
                DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                Debug.Assert(dataGridViewColumn != null); 
                SelectCellRange(newEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, true);
                SelectCellRange(newEdgeColumnIndex, 
                    this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                    anchorColumnIndex,
                    newEdgeRowIndex,
                    true); 
            }
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex)) 
            { 
                DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                if (newEdgeRowIndex == oldEdgeRowIndex) 
                {
                    if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex))
                    {
                        // a1 
                        Debug.Assert(dataGridViewColumn != null);
                        if (oldEdgeRowIndex > anchorRowIndex) 
                        { 
                            SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false);
                        } 
                        else
                        {
                            SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false);
                        } 
                    }
                } 
                else if (newEdgeRowIndex < oldEdgeRowIndex) 
                {
                    if (oldEdgeRowIndex > anchorRowIndex) 
                    {
                        if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex))
                        {
                            if (anchorRowIndex <= newEdgeRowIndex) 
                            {
                                if (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex)) 
                                { 
                                    if (!this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex))
                                    { 
                                        // a2
                                        Debug.Assert(dataGridViewColumn != null);
                                        SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false);
                                        SelectCellRange(anchorColumnIndex, 
                                            this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                            newEdgeColumnIndex, 
                                            oldEdgeRowIndex, 
                                            false);
                                    } 
                                }
                                else
                                {
                                    // d3 
                                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    Debug.Assert(dataGridViewColumn != null); 
                                    SelectCellRange(oldEdgeColumnIndex, 
                                        this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        anchorColumnIndex, 
                                        oldEdgeRowIndex,
                                        false);
                                    SelectCellRange(newEdgeColumnIndex,
                                        anchorRowIndex, 
                                        dataGridViewColumn.Index,
                                        newEdgeRowIndex, 
                                        true); 
                                }
                            } 
                        }
                    }
                }
                else if (newEdgeRowIndex > oldEdgeRowIndex) 
                {
                    if (oldEdgeRowIndex < anchorRowIndex) 
                    { 
                        if ((this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex)) &&
                            newEdgeRowIndex <= anchorRowIndex) 
                        {
                            // a3
                            Debug.Assert(dataGridViewColumn != null);
                            SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false); 
                            SelectCellRange(anchorColumnIndex,
                                oldEdgeRowIndex, 
                                newEdgeColumnIndex, 
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                false); 
                        }
                        else
                        {
                            if (!this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex)) 
                            {
                                if (newEdgeRowIndex <= anchorRowIndex) 
                                { 
                                    // c3
                                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    Debug.Assert(dataGridViewColumn != null);
                                    SelectCellRange(oldEdgeColumnIndex,
                                        oldEdgeRowIndex,
                                        anchorColumnIndex, 
                                        this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        false); 
                                    SelectCellRange(newEdgeColumnIndex, 
                                        newEdgeRowIndex,
                                        dataGridViewColumn.Index, 
                                        anchorRowIndex,
                                        true);
                                }
                            } 
                        }
                    } 
                    else 
                    {
                        if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex)) 
                        {
                            // a5
                            Debug.Assert(oldEdgeRowIndex >= anchorRowIndex);
                            Debug.Assert(dataGridViewColumn != null); 
                            SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false);
                            SelectCellRange(anchorColumnIndex, 
                                this.Rows.GetNextRow(anchorRowIndex, DataGridViewElementStates.Visible), 
                                newEdgeColumnIndex,
                                newEdgeRowIndex, 
                                true);
                        }
                    }
                } 
            }
            else if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex)) 
            { 
                DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                if (newEdgeRowIndex == oldEdgeRowIndex) 
                {
                    if (this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (newEdgeColumnIndex == anchorColumnIndex))
                    {
                        // b1 
                        Debug.Assert(dataGridViewColumn != null);
                        if (oldEdgeRowIndex > anchorRowIndex) 
                        { 
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, false);
                        } 
                        else
                        {
                            SelectCellRange(oldEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, false);
                        } 
                    }
                } 
                else if (newEdgeRowIndex < oldEdgeRowIndex) 
                {
                    if (oldEdgeRowIndex > anchorRowIndex) 
                    {
                        if ((this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (newEdgeColumnIndex == anchorColumnIndex)) &&
                            newEdgeRowIndex >= anchorRowIndex)
                        { 
                            // b2
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex, 
                                this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                anchorColumnIndex, 
                                oldEdgeRowIndex,
                                false);
                        }
                        else 
                        {
                            if (!this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex)) 
                            { 
                                if (newEdgeRowIndex >= anchorRowIndex)
                                { 
                                    // d2
                                    dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    Debug.Assert(dataGridViewColumn != null);
                                    SelectCellRange(anchorColumnIndex, 
                                        this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        oldEdgeColumnIndex, 
                                        oldEdgeRowIndex, 
                                        false);
                                    SelectCellRange(dataGridViewColumn.Index, 
                                        anchorRowIndex,
                                        newEdgeColumnIndex,
                                        newEdgeRowIndex,
                                        true); 
                                }
                            } 
                        } 
                    }
                } 
                else if (newEdgeRowIndex > oldEdgeRowIndex)
                {
                    if (oldEdgeRowIndex < anchorRowIndex)
                    { 
                        if ((this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex)) &&
                            newEdgeRowIndex <= anchorRowIndex) 
                        { 
                            // b3
                            SelectCellRange(oldEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex,
                                oldEdgeRowIndex,
                                anchorColumnIndex,
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible), 
                                false);
                        } 
                        else 
                        {
                            if (!this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex)) 
                            {
                                if (newEdgeRowIndex <= anchorRowIndex)
                                {
                                    // c2 
                                    dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    Debug.Assert(dataGridViewColumn != null); 
                                    SelectCellRange(anchorColumnIndex, 
                                        oldEdgeRowIndex,
                                        oldEdgeColumnIndex, 
                                        this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        false);
                                    SelectCellRange(dataGridViewColumn.Index,
                                        newEdgeRowIndex, 
                                        newEdgeColumnIndex,
                                        anchorRowIndex, 
                                        true); 
                                }
                            } 
                        }
                    }
                    else
                    { 
                        if (this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex))
                        { 
                            // b5 
                            Debug.Assert(oldEdgeRowIndex >= anchorRowIndex);
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex,
                                this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                                anchorColumnIndex,
                                newEdgeRowIndex, 
                                true);
                        } 
                    } 
                }
            } 
            else if (newEdgeRowIndex > oldEdgeRowIndex)
            {
                if (newEdgeColumnIndex == oldEdgeColumnIndex)
                { 
                    if (newEdgeRowIndex <= anchorRowIndex)
                    { 
                        // c1 
                        if (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex))
                        { 
                            SelectCellRange(anchorColumnIndex,
                                oldEdgeRowIndex,
                                oldEdgeColumnIndex,
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible), 
                                false);
                        } 
                        else 
                        {
                            SelectCellRange(oldEdgeColumnIndex, 
                                oldEdgeRowIndex,
                                anchorColumnIndex,
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                false); 
                        }
                    } 
                } 
            }
            else if (newEdgeRowIndex < oldEdgeRowIndex) 
            {
                if (newEdgeColumnIndex == oldEdgeColumnIndex)
                {
                    if (newEdgeRowIndex >= anchorRowIndex) 
                    {
                        // d1 
                        if (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex)) 
                        {
                            SelectCellRange(anchorColumnIndex, 
                                this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                oldEdgeColumnIndex,
                                oldEdgeRowIndex,
                                false); 
                        }
                        else 
                        { 
                            SelectCellRange(oldEdgeColumnIndex,
                                this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible), 
                                anchorColumnIndex,
                                oldEdgeRowIndex,
                                false);
                        } 
                    }
                } 
            } 
            oldEdgeColumnIndex = newEdgeColumnIndex;
            oldEdgeRowIndex = newEdgeRowIndex; 
        }

        private void VertScrollTimer_Tick(object sender, System.EventArgs e)
        { 
            BeginInvoke(new MethodInvoker(VertScrollTimerHandler));
        } 
 
        private void VertScrollTimerHandler()
        { 
            // Why would the vertical scroll timer be enabled when vertical selection is not occurring
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]);

            Point ptMouse = PointToClient(Control.MousePosition); 
            HitTestInfo hti = HitTest(ptMouse.X, ptMouse.Y);
            int xOffset, yOffset, mouseX = ptMouse.X, mouseY = ptMouse.Y; 
 
            if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset))
            { 
                if (yOffset != 0)
                {
                    int absYOffset = Math.Abs(yOffset), normOffset = yOffset / absYOffset;
                    ScrollRowsByCount(normOffset, normOffset < 0 ? ScrollEventType.SmallDecrement : ScrollEventType.SmallIncrement); 
                    this.vertScrollTimer.Interval = GetRowScrollRate(absYOffset);
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect]) 
                    { 
                        hti = HitTest(mouseX, ptMouse.Y - yOffset - normOffset);
                        if (hti.row >= 0) 
                        {
                            OnRowSelectMouseMove(hti);
                        }
                    } 
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])
                    { 
                        if (xOffset != 0) 
                        {
                            hti = HitTest(ptMouse.X - xOffset - (xOffset / Math.Abs(xOffset)), ptMouse.Y - yOffset - normOffset); 
                        }
                        else
                        {
                            hti = HitTest(mouseX, ptMouse.Y - yOffset - normOffset); 
                        }
                        if (hti.col >= 0 && hti.row >= 0) 
                        { 
                            OnCellSelectMouseMove(hti);
                        } 
                    }
                }
                else
                { 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && hti.row >= 0)
                    { 
                        OnRowSelectMouseMove(hti); 
                    }
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) 
                    {
                        OnCellSelectMouseMove(hti);
                    }
                    this.VertScrollTimer.Enabled = false; 
                }
            } 
        } 

        private void WireEditingControlEvents() 
        {
            Debug.Assert(this.editingPanel != null);
            this.editingPanel.Click += new System.EventHandler(EditingControls_Click);
            this.editingPanel.DoubleClick += new System.EventHandler(EditingControls_DoubleClick); 
            this.editingPanel.MouseClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick);
            this.editingPanel.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick); 
            this.editingPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown); 
            this.editingPanel.MouseEnter += new System.EventHandler(EditingControls_MouseEnter);
            this.editingPanel.MouseLeave += new System.EventHandler(EditingControls_MouseLeave); 
            this.editingPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove);
            this.editingPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp);

            Debug.Assert(this.editingControl != null); 
            this.editingControl.Click += new System.EventHandler(EditingControls_Click);
            this.editingControl.DoubleClick += new System.EventHandler(EditingControls_DoubleClick); 
            this.editingControl.MouseClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick); 
            this.editingControl.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick);
            this.editingControl.MouseDown += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown); 
            this.editingControl.MouseEnter += new System.EventHandler(EditingControls_MouseEnter);
            this.editingControl.MouseLeave += new System.EventHandler(EditingControls_MouseLeave);
            this.editingControl.MouseMove += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove);
            this.editingControl.MouseUp += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp); 
        }
 
        private void WireScrollBarsEvents() 
        {
            if (this.horizScrollBar != null) 
            {
                this.horizScrollBar.MouseEnter += new System.EventHandler(ScrollBar_MouseEnter);
                this.horizScrollBar.MouseLeave += new System.EventHandler(ScrollBar_MouseLeave);
            } 
            if (this.vertScrollBar != null)
            { 
                this.vertScrollBar.MouseEnter += new System.EventHandler(ScrollBar_MouseEnter); 
                this.vertScrollBar.MouseLeave += new System.EventHandler(ScrollBar_MouseLeave);
            } 
        }

        /// 
        ///     Handles the WM_CONTEXTMENU message 
        /// 
        ///  
        internal override void WmContextMenu(ref Message m) 
        {
            ContextMenuStrip contextMenuStrip; 
            int x = (int)(short)m.LParam;
            int y = (int)m.LParam >> 16;
            Point client;
            bool keyboardActivated = false; 
            // lparam will be exactly -1 when the user invokes the context menu
            // with the keyboard. 
            // 
            if ((int)m.LParam == -1)
            { 
                keyboardActivated = true;
                client = new Point(this.Width/2, this.Height/2);
                contextMenuStrip = (ContextMenuStrip) this.ContextMenuStrip;
            } 
            else
            { 
                client = PointToClientInternal(new Point(x, y)); 
                HitTestInfo hti = HitTest(client.X, client.Y);
                DataGridViewCell dataGridViewCell = null; 
                switch (hti.Type)
                {
                    case DataGridViewHitTestType.Cell:
                        dataGridViewCell = this.Rows.SharedRow(hti.row).Cells[hti.col]; 
                        break;
                    case DataGridViewHitTestType.ColumnHeader: 
                        Debug.Assert(hti.row == -1); 
                        dataGridViewCell = this.Columns[hti.col].HeaderCell;
                        break; 
                    case DataGridViewHitTestType.RowHeader:
                        Debug.Assert(hti.col == -1);
                        dataGridViewCell = this.Rows.SharedRow(hti.row).HeaderCell;
                        break; 
                    case DataGridViewHitTestType.TopLeftHeader:
                        Debug.Assert(hti.row == -1); 
                        Debug.Assert(hti.col == -1); 
                        dataGridViewCell = this.TopLeftHeaderCell;
                        break; 
                }
                if (dataGridViewCell != null)
                {
                    contextMenuStrip = dataGridViewCell.GetInheritedContextMenuStrip(hti.row); 
                }
                else 
                { 
                    contextMenuStrip = (ContextMenuStrip) this.ContextMenuStrip;
                } 
            }

            // VisualStudio7 # 156, only show the context menu when clicked in the client area
            if (contextMenuStrip != null && this.ClientRectangle.Contains(client)) 
            {
                contextMenuStrip.ShowInternal(this, client, keyboardActivated); 
            } 
            else
            { 
                DefWndProc(ref m);
            }
        }
 
        /// 
        ///     Handles the WM_GETDLGCODE message 
        ///  
        private void WmGetDlgCode(ref Message m)
        { 
            m.Result = (IntPtr)((long)m.Result | NativeMethods.DLGC_WANTARROWS | NativeMethods.DLGC_WANTCHARS);

            Keys modifierKeys = ModifierKeys;
            if (GetTabKeyEffective((modifierKeys & Keys.Shift) == Keys.Shift, (modifierKeys & Keys.Control) == Keys.Control)) 
            {
                m.Result = (IntPtr) ((long) m.Result | NativeMethods.DLGC_WANTTAB); 
            } 
        }
 
        private unsafe bool WmNotify(ref Message m)
        {
            if (m.LParam == IntPtr.Zero)
            { 
                return false;
            } 
 
            NativeMethods.NMHDR* nmhdr = (NativeMethods.NMHDR *)m.LParam;
            if (nmhdr->code == NativeMethods.TTN_GETDISPINFO && !DesignMode) 
            {
                string toolTip = this.ToolTipPrivate;

                if (!String.IsNullOrEmpty(toolTip)) 
                {
                    // MSDN: Setting the max width has the added benefit of enabling multiline tool tips! 
                    UnsafeNativeMethods.SendMessage(new HandleRef(this, nmhdr->hwndFrom), NativeMethods.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width); 
                    NativeMethods.TOOLTIPTEXT ttt = (NativeMethods.TOOLTIPTEXT) m.GetLParam(typeof(NativeMethods.TOOLTIPTEXT));
 
                    ttt.lpszText = toolTip;

                    if (this.RightToLeft == RightToLeft.Yes)
                    { 
                        ttt.uFlags |= NativeMethods.TTF_RTLREADING;
                    } 
                    Marshal.StructureToPtr(ttt, m.LParam, false); 
                    return true;
                } 
            }

            return false;
        } 

        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        protected override void WndProc(ref Message m)
        { 
            switch (m.Msg)
            {
                case NativeMethods.WM_GETDLGCODE:
                    WmGetDlgCode(ref m); 
                    return;
                case NativeMethods.WM_LBUTTONDBLCLK: 
                case NativeMethods.WM_LBUTTONDOWN: 
                    // If the OnEnter procedure is called, it's because of a mouse down event, and not a TAB key.
                    this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] = true; 
                    try
                    {
                        base.WndProc(ref m);
                    } 
                    finally
                    { 
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] = false; 
                    }
                    return; 
                case NativeMethods.WM_NOTIFY:
                    if (WmNotify(ref m))
                    {
                        // we are done - skip default handling 
                        return;
                    } 
                    break; 

                case NativeMethods.WM_IME_STARTCOMPOSITION: 
                case NativeMethods.WM_IME_COMPOSITION:
                    if (this.editingControl != null)
                    {
                        // Make sure that the first character is forwarded to the editing control. 
                        this.editingControl.SendMessage(m.Msg, m.WParam, m.LParam);
                    } 
                    break; 
            }
 
            base.WndProc(ref m);
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

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; 

    /// 
    public partial class DataGridView
    { 
        /// 
        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);
            } 
            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);
            }
        } 

        ///  
        [ 
            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, 
                                           DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal,
                                           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--; 
            }
 
            //VSWhidbey 538300: Assertion is wrong when multiple rows are added/inserted. Bug was postponed for Whidbey.
            Debug.Assert(dataGridViewColumn.Width == dataGridViewColumn.GetPreferredWidth((DataGridViewAutoSizeColumnMode)autoSizeColumnCriteriaInternal, true /*fixedHeight*/));

            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, inheritedAutoSizeColumnCriteria, 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); 
                } 
            }
        } 

        /// 
        // 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;
        } 
 
        /// 
        ///    Assigns a new parent control to the DataGridView. 
        /// 
        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;
        } 

        ///  
        public void AutoResizeColumn(int columnIndex) 
        {
            AutoResizeColumn(columnIndex, DataGridViewAutoSizeColumnMode.AllCells); 
        }

        /// 
        public void AutoResizeColumn(int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode) 
        {
            AutoResizeColumn(columnIndex, autoSizeColumnMode, true); 
        } 

        ///  
        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);
        } 

        /// 
        public void AutoResizeColumnHeadersHeight()
        { 
            AutoResizeColumnHeadersHeight(true, true);
        } 
 
        /// 
        public void AutoResizeColumnHeadersHeight(int columnIndex) 
        {
            AutoResizeColumnHeadersHeight(columnIndex, true, true);
        }
 
        /// 
        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--; 
            } 
        }
 
        /// 
        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;
        }

        ///  
        public void AutoResizeColumns()
        { 
            AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); 
        }
 
        /// 
        public void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode)
        {
            AutoResizeColumns(autoSizeColumnsMode, true); 
        }
 
        ///  
        protected void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode, bool fixedHeight)
        { 
            for (int columnIndex = 0; columnIndex < this.Columns.Count; columnIndex++)
            {
                AutoResizeColumn(columnIndex, (DataGridViewAutoSizeColumnMode)autoSizeColumnsMode, fixedHeight);
            } 
        }
 
        ///  
        public void AutoResizeRow(int rowIndex)
        { 
            AutoResizeRow(rowIndex, DataGridViewAutoSizeRowMode.AllCells);
        }

        ///  
        public void AutoResizeRow(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode)
        { 
            AutoResizeRow(rowIndex, autoSizeRowMode, true /*fixedWidth*/); 
        }
 
        /// 
        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*/);
        } 

        /// 
        // 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*/);
        } 

        /// 
        // 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--; 
            }
        }

        ///  
        public void AutoResizeRowHeadersWidth(int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode)
        { 
            AutoResizeRowHeadersWidth(rowIndex, 
                                      rowHeadersWidthSizeMode,
                                      true /*fixedColumnHeadersHeight*/, 
                                      true /*fixedRowHeight*/);
        }

        ///  
        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--;
            } 
        }

        /// 
        public void AutoResizeRows() 
        {
            AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCells); 
        } 

        ///  
        public void AutoResizeRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode)
        {
            AutoResizeRows(autoSizeRowsMode, true /*fixedWidth*/);
        } 

        ///  
        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*/); 
        }
 
        /// 
        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)
        {
            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)
        {
            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 mouseX, int mouseBarOffset, int index) 
        {
            Rectangle clip = Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data); 
            int leftEdge = GetColumnXFromIndex(index); 
            if (this.RightToLeftInternal)
            { 
                clip.X = this.layout.Data.X - mouseBarOffset - 1;
                clip.Width = leftEdge - this.Columns[index].MinimumThickness - this.layout.Data.X + 3;
                int overflowWidth = leftEdge - mouseBarOffset - clip.Left - DataGridViewBand.maxBandThickness + 1;
                if (overflowWidth > 0) 
                {
                    clip.X += overflowWidth; 
                    clip.Width -= overflowWidth; 
                }
            } 
            else
            {
                clip.X = leftEdge + this.Columns[index].MinimumThickness - mouseBarOffset - 1;
                clip.Width = this.layout.Data.Right - leftEdge - 1; 
                int overflowWidth = clip.Right + mouseBarOffset - leftEdge - DataGridViewBand.maxBandThickness;
                if (overflowWidth > 0) 
                { 
                    clip.Width -= overflowWidth;
                } 
            }
            CaptureMouse(clip);

            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] = true; 
            this.trackColAnchor = mouseX;
            this.trackColumn = index; 
 
            this.mouseBarOffset = mouseBarOffset;
            Debug.Assert(this.lastColSplitBar == -1); 
            this.currentColSplitBar = mouseX;
            Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar));
        }
 
        /// 
        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 = this.CurrentCellInternal;
                }
                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)
        { 
            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) 
        {
            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;
        }
 
        /// 
        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; 
            }
        }

        // 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; 
        }

        /// 
        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); 
                        }
                        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);
                } 
            }
        } 
 
        /// 
        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); 
        } 

        ///  
        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);
 
                    // [....]: 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); 
            }
        } 
 
        /// 
        ///      Determines which column is the first visible scrolling 
        ///      column given the object's horizontalOffset.
        /// 
        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)
                    { 
                        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;
            }
        }
 
        /// 
        protected override AccessibleObject CreateAccessibilityInstance() 
        { 
            return new DataGridViewAccessibleObject(this);
        } 

        /// 
        protected override Control.ControlCollection CreateControlsInstance()
        { 
            return new DataGridViewControlCollection(this);
        } 
 
        /// 
        ///  
        ///     Constructs the new instance of the Columns collection objects. Subclasses
        ///     should not call base.CreateColumnsInstance.
        /// 
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected virtual DataGridViewColumnCollection CreateColumnsInstance()
        { 
            return new DataGridViewColumnCollection(this); 
        }
 
        /// 
        /// 
        ///     Constructs the new instance of the Rows collection objects. Subclasses
        ///     should not call base.CreateRowsInstance. 
        /// 
        [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; 
            }
        }

        ///  
        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;
        }
 
        /// 
        public int DisplayedRowCount(bool includePartialRow) 
        { 
            return includePartialRow ? (this.displayedBandsInfo.NumDisplayedFrozenRows + this.displayedBandsInfo.NumDisplayedScrollingRows) :
                (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows + this.displayedBandsInfo.NumTotallyDisplayedScrollingRows); 
        }

        /// 
        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;
                    }
 
                    DisposeCachedGraphics();
 
                    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;
                    } 
                    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 DisposeCachedGraphics()
        {
            if (this.cachedGraphics != null) 
            {
                this.cachedGraphics.Dispose(); 
                this.cachedGraphics = null; 
            }
        } 

        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);
                } 
            }
        } 
 
        /// 
        ///      Draws an XOR region to give UI feedback for Column Resizing. 
        ///      This looks just like the Splitter control's UI when resizing.
        /// 
        private void DrawColSplitBar(int mouseX)
        { 
            Rectangle r = CalcColResizeFeedbackRect(mouseX);
            DrawSplitBar(r); 
        } 

        ///  
        ///      Draws an XOR region to give UI feedback for Row Resizing.
        ///      This looks just like the Splitter control's UI when resizing.
        /// 
        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));
        } 

        /// 
        ///      Draws an XOR region to give UI feedback for Column/Row Resizing.
        ///      This looks just like the Splitter control's UI when resizing. 
        /// 
        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
            { 
                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.X); 
                    delta = GetColumnXFromIndex(this.trackColumn) - this.Columns[this.trackColumn].Thickness - x + 1;
                } 
                else
                {
                    x = Math.Min(e.X + this.mouseBarOffset, this.layout.Data.Right - 1);
                    delta = x - (GetColumnXFromIndex(this.trackColumn) + this.Columns[this.trackColumn].Thickness) + 1; 
                }
 
                if (this.trackColAnchor != x && 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;
                } 
            }
            finally 
            { 
                RealeaseMouse();
            } 
        }

        /// 
        public bool EndEdit() 
        {
            return EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit); 
        } 

        ///  
        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); 
            }
        } 
 
        /// 
        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); 
        }
 
        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

        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 (this.SingleVerticalBorderAdded && columnIndex == this.FirstDisplayedColumnIndex) 
            {
                if (!this.RightToLeftInternal) 
                {
                    rect.X--;
                }
                rect.Width++; 
            }
            if (this.SingleHorizontalBorderAdded && rowIndex == this.FirstDisplayedRowIndex) 
            { 
                rect.Y--;
                rect.Width++; 
            }
            return rect;
        }
 
        /// 
        [ 
            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; 
        }

        /// 
        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; 
                } 
            }
        } 

        /// 
        [
            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*/, 
                                                                                                            true /*inFirstRow*/,
                                                                                                            false /*inLastRow*/, 
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    while (prevDataGridViewColumn != null)
                                    { 
                                        dataGridViewColumn = prevDataGridViewColumn;
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/,
                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                true /*inFirstRow*/,
                                                                                                                false /*inLastRow*/,
                                                                                                                format) as string;
                                        if (cellContent != null) 
                                        {
                                            sbContent.Append(cellContent); 
                                        } 
                                    }
                                } 
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*firstCell*/, 
                                                                                                     true /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/, 
                                                                                                     format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                            }
                            else 
                            { 
                                if (includeRowHeaders)
                                { 
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     true /*firstCell*/,
                                                                                                     this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/,
                                                                                                     format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                }
                                // Cycle through the visible columns in their display order
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
                                if (dataGridViewColumn != null)
                                { 
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            !includeRowHeaders /*firstCell*/, 
                                                                                                            nextDataGridViewColumn == null /*lastCell*/,
                                                                                                            true /*inFirstRow*/,
                                                                                                            false /*inLastRow*/,
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = nextDataGridViewColumn;
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/,
                                                                                                                nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                true /*inFirstRow*/, 
                                                                                                                false /*inLastRow*/,
                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        {
                                            sbContent.Append(cellContent);
                                        } 
                                    }
                                } 
                            } 
                        }
                        // Cycle through the visible selected rows. 
                        bool firstRowIndex = true;
                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);
                        Debug.Assert(rowIndex != -1);
                        int nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected); 
                        while (rowIndex != -1)
                        { 
                            if (this.RightToLeftInternal) 
                            {
                                dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None); 

                                // Cycle through the visible columns in their reverse display order
                                if (dataGridViewColumn != null)
                                { 
                                    prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, 
                                                                                                                                            true /*firstCell*/, 
                                                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                            format) as string;
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                    while (prevDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = prevDataGridViewColumn; 
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                                false /*firstCell*/,
                                                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        { 
                                            sbContent.Append(cellContent);
                                        }
                                    }
                                } 

                                // Get the row header clipboard content 
                                if (includeRowHeaders) 
                                {
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, 
                                                                                                                       this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*firstCell*/,
                                                                                                                       true /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                       nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                       format) as string;
                                    if (cellContent != null) 
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                }
                            }
                            else
                            { 
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
 
                                // Get the row header clipboard content 
                                if (includeRowHeaders)
                                { 
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex,
                                                                                                                       true /*firstCell*/,
                                                                                                                       dataGridViewColumn == null /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                       nextRowIndex == -1 /*inLastRow*/,
                                                                                                                       format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                }

                                // Cycle through the visible columns in their display order 
                                if (dataGridViewColumn != null)
                                { 
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            !includeRowHeaders /*firstCell*/, 
                                                                                                                                            nextDataGridViewColumn == null /*lastCell*/,
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = nextDataGridViewColumn;
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, 
                                                                                                                                                false /*firstCell*/,
                                                                                                                                                nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        {
                                            sbContent.Append(cellContent);
                                        } 
                                    }
                                } 
                            } 
                            rowIndex = nextRowIndex;
                            if (rowIndex != -1) 
                            {
                                nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);
                            }
                            firstRowIndex = false; 
                        }
                        if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase)) 
                        { 
                            GetClipboardContentForHtml(sbContent);
                        } 
                        dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString());
                    }
                    break;
 
                case DataGridViewSelectionMode.FullColumnSelect:
                    if (this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) == 0) 
                    { 
                        return null;
                    } 

                    if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText)
                    {
                        includeColumnHeaders = true; 
                        includeRowHeaders = (this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Selected) == null);
                    } 
                    else 
                    {
                        includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText); 
                    }

                    includeColumnHeaders &= this.ColumnHeadersVisible;
                    includeRowHeaders &= this.RowHeadersVisible; 

                    int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
 
                    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 & selected columns in their display order 
                                DataGridViewColumn lastDataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                dataGridViewColumn = lastDataGridViewColumn; 
                                Debug.Assert(dataGridViewColumn != null); 
                                if (dataGridViewColumn != null)
                                { 
                                    prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            true /*firstCell*/,
                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                            true /*inFirstRow*/,
                                                                                                            firstVisibleRowIndex == -1 /*inLastRow*/, 
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    while (prevDataGridViewColumn != null)
                                    { 
                                        dataGridViewColumn = prevDataGridViewColumn;
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/,
                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                true /*inFirstRow*/,
                                                                                                                firstVisibleRowIndex == -1 /*inLastRow*/,
                                                                                                                format) as string;
                                        if (cellContent != null) 
                                        {
                                            sbContent.Append(cellContent); 
                                        } 
                                    }
                                } 
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     lastDataGridViewColumn == null /*firstCell*/, 
                                                                                                     true /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     firstVisibleRowIndex == -1 /*inLastRow*/, 
                                                                                                     format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                            }
                            else 
                            { 
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);
 
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1,
                                                                                                     true /*firstCell*/, 
                                                                                                     dataGridViewColumn == null /*lastCell*/,
                                                                                                     true /*inFirstRow*/, 
                                                                                                     firstVisibleRowIndex == -1 /*inLastRow*/, 
                                                                                                     format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                                // Cycle through the visible & selected columns in their display order
                                Debug.Assert(dataGridViewColumn != null); 
                                if (dataGridViewColumn != null) 
                                {
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            !includeRowHeaders /*firstCell*/,
                                                                                                            nextDataGridViewColumn == null /*lastCell*/,
                                                                                                            true /*inFirstRow*/, 
                                                                                                            firstVisibleRowIndex == -1 /*inLastRow*/,
                                                                                                            format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null)
                                    {
                                        dataGridViewColumn = nextDataGridViewColumn; 
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                        cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, 
                                                                                                                false /*firstCell*/, 
                                                                                                                nextDataGridViewColumn == null /*lastCell*/,
                                                                                                                true /*inFirstRow*/, 
                                                                                                                firstVisibleRowIndex == -1 /*inLastRow*/,
                                                                                                                format) as string;
                                        if (cellContent != null)
                                        { 
                                            sbContent.Append(cellContent);
                                        } 
                                    } 
                                }
                            } 
                        }
                        // Cycle through the visible rows.
                        bool firstRowIndex = true;
                        int rowIndex = firstVisibleRowIndex; 
                        int nextRowIndex = -1;
                        if (rowIndex != -1) 
                        { 
                            nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                        } 
                        while (rowIndex != -1)
                        {
                            if (this.RightToLeftInternal)
                            { 
                                DataGridViewColumn lastDataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
 
                                // Cycle through the visible & selected columns in their reverse display order 
                                dataGridViewColumn = lastDataGridViewColumn;
                                if (dataGridViewColumn != null) 
                                {
                                    prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None);
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            true /*firstCell*/, 
                                                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                    while (prevDataGridViewColumn != null) 
                                    {
                                        dataGridViewColumn = prevDataGridViewColumn; 
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                                false /*firstCell*/, 
                                                                                                                                                !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                                format) as string; 
                                        if (cellContent != null)
                                        { 
                                            sbContent.Append(cellContent); 
                                        }
                                    } 
                                }

                                // Get the row header clipboard content
                                if (includeRowHeaders) 
                                {
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, 
                                                                                                                       lastDataGridViewColumn == null /*firstCell*/, 
                                                                                                                       true /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                       nextRowIndex == -1 /*inLastRow*/,
                                                                                                                       format) as string;
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                } 
                            }
                            else 
                            {
                                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected);

                                // Get the row header clipboard content 
                                if (includeRowHeaders)
                                { 
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, 
                                                                                                                       true /*firstCell*/,
                                                                                                                       dataGridViewColumn == null /*lastCell*/, 
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                       nextRowIndex == -1 /*inLastRow*/,
                                                                                                                       format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    } 
                                }
 
                                // Cycle through the visible & selected columns in their display order
                                if (dataGridViewColumn != null)
                                {
                                    nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            !includeRowHeaders /*firstCell*/, 
                                                                                                                                            nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string;
                                    if (cellContent != null)
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    while (nextDataGridViewColumn != null) 
                                    { 
                                        dataGridViewColumn = nextDataGridViewColumn;
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); 
                                        cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                                false /*firstCell*/,
                                                                                                                                                nextDataGridViewColumn == null /*lastCell*/,
                                                                                                                                                !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                                                nextRowIndex == -1 /*inLastRow*/,
                                                                                                                                                format) as string; 
                                        if (cellContent != null) 
                                        {
                                            sbContent.Append(cellContent); 
                                        }
                                    }
                                }
                            } 
                            rowIndex = nextRowIndex;
                            if (rowIndex != -1) 
                            { 
                                nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                            } 
                            firstRowIndex = false;
                        }
                        if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase))
                        { 
                            GetClipboardContentForHtml(sbContent);
                        } 
                        dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString()); 
                    }
                    break; 

                case DataGridViewSelectionMode.CellSelect:
                case DataGridViewSelectionMode.RowHeaderSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    bool selectedVisibleCellExists = false;
                    bool selectedVisibleColumnExists = false; 
                    bool selectedVisibleRowExists = false; 
                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                    { 
                        selectedVisibleRowExists = this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) != 0;
                        selectedVisibleCellExists = selectedVisibleRowExists && this.Columns.GetColumnCount(DataGridViewElementStates.Visible) != 0;
                    }
                    else if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) 
                    {
                        selectedVisibleColumnExists = this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) != 0; 
                        selectedVisibleCellExists = selectedVisibleColumnExists && this.Rows.GetRowCount(DataGridViewElementStates.Visible) != 0; 
                    }
                    if (!selectedVisibleCellExists && this.individualSelectedCells.Count > 0) 
                    {
                        foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells)
                        {
                            if (dataGridViewCell.Visible) 
                            {
                                selectedVisibleCellExists = true; 
                                break; 
                            }
                        } 
                    }
                    if (!selectedVisibleCellExists)
                    {
                        return null; 
                    }
 
                    // There is at least one selected visible cell. 
                    if (this.SelectionMode == DataGridViewSelectionMode.CellSelect)
                    { 
                        includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText);
                        includeColumnHeaders &= this.ColumnHeadersVisible;
                        includeRowHeaders &= this.RowHeadersVisible;
                    } 
                    else
                    { 
                        includeColumnHeaders = includeRowHeaders = false; 
                        if (this.ColumnHeadersVisible)
                        { 
                            if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText)
                            {
                                if (selectedVisibleColumnExists)
                                { 
                                    includeColumnHeaders = true;
                                } 
                                /* Use this code if column headers should be included when all cells are selected in a visible column. 
                                else
                                { 
                                    // Include column headers if there is a column where all visible cells are selected
                                    DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                                    Debug.Assert(dataGridViewColumn != null);
                                    while (dataGridViewColumn != null) 
                                    {
                                        // Cycle through the visible rows, see if the cell in that column is selected 
                                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                                        while (rowIndex != -1)
                                        { 
                                            if (!this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].Selected)
                                            {
                                                break;
                                            } 
                                            rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                                        } 
                                        if (rowIndex == -1) 
                                        {
                                            // All visible cells in column are selected 
                                            includeColumnHeaders = true;
                                            break;
                                        }
                                        dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    }
                                } 
                                */ 
                            }
                            else 
                            {
                                includeColumnHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText);
                            }
                        } 

                        if (this.RowHeadersVisible) 
                        { 
                            if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText)
                            { 
                                if (selectedVisibleRowExists)
                                {
                                    includeRowHeaders = true;
                                } 
                                /* Use this code if row headers should be included when all cells are selected in a visible row.
                                else 
                                { 
                                    // Include row headers if there is a row where all visible cells are selected
                                    int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                                    Debug.Assert(rowIndex != -1);
                                    while (rowIndex != -1)
                                    {
                                        // Cycle through the visible columns, see if the cell in that row is selected 
                                        DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                                        Debug.Assert(dataGridViewColumn != null); 
                                        while (dataGridViewColumn != null) 
                                        {
                                            if (!this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].Selected) 
                                            {
                                                break;
                                            }
                                            dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        }
                                        if (dataGridViewColumn == null) 
                                        { 
                                            // All visible cells in row are selected
                                            includeRowHeaders = true; 
                                            break;
                                        }
                                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                                    } 
                                }
                                */ 
                            } 
                            else
                            { 
                                includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText);
                            }
                        }
                    } 

                    // Get the four corners of the 'selected table' 
                    int lRowIndex = int.MaxValue; 
                    int uRowIndex = -1;
                    DataGridViewColumn lColumn = null, uColumn = null; 

                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                    {
                        DataGridViewColumn firstVisibleColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
                        DataGridViewColumn lastVisibleColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None);
 
                        Debug.Assert(firstVisibleColumn != null); 
                        Debug.Assert(lastVisibleColumn != null);
                        foreach (int rowIndex in this.selectedBandIndexes) 
                        {
                            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0)
                            {
                                if (rowIndex < lRowIndex) 
                                {
                                    lRowIndex = rowIndex; 
                                } 
                                if (rowIndex > uRowIndex)
                                { 
                                    uRowIndex = rowIndex;
                                }
                                lColumn = firstVisibleColumn;
                                uColumn = lastVisibleColumn; 
                            }
                        } 
                    } 
                    else if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)
                    { 
                        firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                        int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                        Debug.Assert(firstVisibleRowIndex != -1);
                        Debug.Assert(lastVisibleRowIndex != -1); 
                        foreach (int columnIndex in this.selectedBandIndexes)
                        { 
                            if (this.Columns[columnIndex].Visible) 
                            {
                                if (lColumn == null || this.Columns.DisplayInOrder(columnIndex, lColumn.Index)) 
                                {
                                    lColumn = this.Columns[columnIndex];
                                }
                                if (uColumn == null || this.Columns.DisplayInOrder(uColumn.Index, columnIndex)) 
                                {
                                    uColumn = this.Columns[columnIndex]; 
                                } 
                                lRowIndex = firstVisibleRowIndex;
                                uRowIndex = lastVisibleRowIndex; 
                            }
                        }
                    }
 
                    // Go through the individually selected cells to potentially stretch the current 'selected table'.
                    foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells) 
                    { 
                        if (dataGridViewCell.Visible)
                        { 
                            if (dataGridViewCell.RowIndex < lRowIndex)
                            {
                                lRowIndex = dataGridViewCell.RowIndex;
                            } 
                            if (dataGridViewCell.RowIndex > uRowIndex)
                            { 
                                uRowIndex = dataGridViewCell.RowIndex; 
                            }
                            if (lColumn == null || this.Columns.DisplayInOrder(dataGridViewCell.ColumnIndex, lColumn.Index)) 
                            {
                                lColumn = dataGridViewCell.OwningColumn;
                            }
                            if (uColumn == null || this.Columns.DisplayInOrder(uColumn.Index, dataGridViewCell.ColumnIndex)) 
                            {
                                uColumn = dataGridViewCell.OwningColumn; 
                            } 
                        }
                    } 

                    Debug.Assert(lRowIndex != -1);
                    Debug.Assert(uRowIndex != -1);
                    Debug.Assert(lColumn != null); 
                    Debug.Assert(uColumn != null);
                    Debug.Assert(lColumn.Index == uColumn.Index || this.Columns.DisplayInOrder(lColumn.Index, uColumn.Index)); 
                    Debug.Assert(lRowIndex <= uRowIndex); 

                    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 from uColumn to lColumn
                                dataGridViewColumn = uColumn; 
                                Debug.Assert(dataGridViewColumn != null); 
                                while (dataGridViewColumn != null)
                                { 
                                    if (dataGridViewColumn != lColumn)
                                    {
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        Debug.Assert(prevDataGridViewColumn != null); 
                                    }
                                    else 
                                    { 
                                        prevDataGridViewColumn = null;
                                    } 
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            dataGridViewColumn == uColumn /*firstCell*/,
                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/,
                                                                                                            true /*inFirstRow*/, 
                                                                                                            false /*inLastRow*/,
                                                                                                            format) as string; 
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    dataGridViewColumn = prevDataGridViewColumn;
                                }
                                if (includeRowHeaders) 
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, 
                                                                                                     false /*firstCell*/, 
                                                                                                     true /*lastCell*/,
                                                                                                     true  /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/,
                                                                                                     format) as string;
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    } 
                                } 
                            }
                            else 
                            {
                                if (includeRowHeaders)
                                {
                                    cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, 
                                                                                                     true  /*firstCell*/,
                                                                                                     false /*lastCell*/, 
                                                                                                     true  /*inFirstRow*/, 
                                                                                                     false /*inLastRow*/,
                                                                                                     format) as string; 
                                    if (cellContent != null)
                                    {
                                        sbContent.Append(cellContent);
                                    } 
                                }
                                // Cycle through the visible columns from lColumn to uColumn 
                                dataGridViewColumn = lColumn; 
                                Debug.Assert(dataGridViewColumn != null);
                                while (dataGridViewColumn != null) 
                                {
                                    if (dataGridViewColumn != uColumn)
                                    {
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        Debug.Assert(nextDataGridViewColumn != null);
                                    } 
                                    else 
                                    {
                                        nextDataGridViewColumn = null; 
                                    }
                                    cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1,
                                                                                                            !includeRowHeaders && dataGridViewColumn == lColumn /*firstCell*/,
                                                                                                            nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                            true /*inFirstRow*/,
                                                                                                            false /*inLastRow*/, 
                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    dataGridViewColumn = nextDataGridViewColumn;
                                } 
                            }
                        } 
                        // Cycle through the visible rows from lRowIndex to uRowIndex. 
                        bool firstRowIndex = true;
                        int rowIndex = lRowIndex; 
                        int nextRowIndex = -1;
                        Debug.Assert(rowIndex != -1);
                        while (rowIndex != -1)
                        { 
                            if (rowIndex != uRowIndex)
                            { 
                                nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); 
                                Debug.Assert(nextRowIndex != -1);
                            } 
                            else
                            {
                                nextRowIndex = -1;
                            } 

                            if (this.RightToLeftInternal) 
                            { 
                                // Cycle through the visible columns from uColumn to lColumn
                                dataGridViewColumn = uColumn; 
                                Debug.Assert(dataGridViewColumn != null);
                                while (dataGridViewColumn != null)
                                {
                                    if (dataGridViewColumn != lColumn) 
                                    {
                                        prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                        Debug.Assert(prevDataGridViewColumn != null); 
                                    }
                                    else 
                                    {
                                        prevDataGridViewColumn = null;
                                    }
 
                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            dataGridViewColumn == uColumn /*firstCell*/, 
                                                                                                                                            !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string;
                                    if (cellContent != null)
                                    {
                                        sbContent.Append(cellContent); 
                                    }
                                    dataGridViewColumn = prevDataGridViewColumn; 
                                } 

                                if (includeRowHeaders) 
                                {
                                    // Get the row header clipboard content
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex,
                                                                                                                       false /*firstCell*/, 
                                                                                                                       true /*lastCell*/,
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/, 
                                                                                                                       nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                       format) as string;
                                    if (cellContent != null) 
                                    {
                                        sbContent.Append(cellContent);
                                    }
                                } 
                            }
                            else 
                            { 
                                if (includeRowHeaders)
                                { 
                                    // Get the row header clipboard content
                                    cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex,
                                                                                                                       true /*firstCell*/,
                                                                                                                       false /*lastCell*/, 
                                                                                                                       !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                       nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                       format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                }
 
                                // Cycle through the visible columns from lColumn to uColumn
                                dataGridViewColumn = lColumn; 
                                Debug.Assert(dataGridViewColumn != null); 
                                while (dataGridViewColumn != null)
                                { 
                                    if (dataGridViewColumn != uColumn)
                                    {
                                        nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                        Debug.Assert(nextDataGridViewColumn != null); 
                                    }
                                    else 
                                    { 
                                        nextDataGridViewColumn = null;
                                    } 

                                    cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex,
                                                                                                                                            !includeRowHeaders && dataGridViewColumn == lColumn /*firstCell*/,
                                                                                                                                            nextDataGridViewColumn == null /*lastCell*/, 
                                                                                                                                            !includeColumnHeaders && firstRowIndex /*inFirstRow*/,
                                                                                                                                            nextRowIndex == -1 /*inLastRow*/, 
                                                                                                                                            format) as string; 
                                    if (cellContent != null)
                                    { 
                                        sbContent.Append(cellContent);
                                    }
                                    dataGridViewColumn = nextDataGridViewColumn;
                                } 
                            }
                            rowIndex = nextRowIndex; 
                            firstRowIndex = false; 
                        }
                        if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase)) 
                        {
                            GetClipboardContentForHtml(sbContent);
                        }
                        dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString()); 
                    }
                    break; 
            } 
            return dataObject;
        } 

        private static void GetClipboardContentForHtml(StringBuilder sbContent)
        {
            // Marshal.SystemDefaultCharSize is 2 on WinXP Pro - so the offsets seem to be in character counts instead of bytes. 
            // Test on JPN and Win9x machines.
            int bytecountEndOfFragment = 135 + sbContent.Length; 
            int bytecountEndOfHtml = bytecountEndOfFragment + 36; 
            string prefix = string.Format(CultureInfo.InvariantCulture, DATAGRIDVIEW_htmlPrefix, bytecountEndOfHtml.ToString("00000000", CultureInfo.InvariantCulture), bytecountEndOfFragment.ToString("00000000", CultureInfo.InvariantCulture)) + DATAGRIDVIEW_htmlStartFragment;
            sbContent.Insert(0, prefix); 
            sbContent.Append(DATAGRIDVIEW_htmlEndFragment);
            #if DEBUG
            string strContent = sbContent.ToString();
            Debug.Assert(strContent[97] == '<'); 
            Debug.Assert(strContent[bytecountEndOfHtml-1] == '>');
            Debug.Assert(strContent[133] == '<'); 
            Debug.Assert(strContent[bytecountEndOfFragment] == '<'); 
            #endif
        } 

        /// 
        // Rectangle returned includes the potential column header
        public Rectangle GetColumnDisplayRectangle(int columnIndex, bool cutOverflow) 
        {
            if (columnIndex < 0 || columnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("columnIndex");
            } 
            return GetColumnDisplayRectanglePrivate(columnIndex, cutOverflow);
        }

        private Rectangle GetColumnDisplayRectanglePrivate(int columnIndex, bool cutOverflow) 
        {
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 
 
            if (!this.Columns[columnIndex].Displayed)
            { 
                return Rectangle.Empty;
            }

            Rectangle data = this.layout.Data; 
            int cx;
            bool columnFound = false; 
            DataGridViewColumn dataGridViewColumn; 
            if (this.RightToLeftInternal)
            { 
                cx = data.Right;
            }
            else
            { 
                cx = data.X;
            } 
            for (dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                dataGridViewColumn != null && !columnFound;
                ) 
            {
                if ((this.RightToLeftInternal && cx < data.X) ||
                    (!this.RightToLeftInternal && cx > data.Right))
                { 
                    break;
                } 
                if (dataGridViewColumn.Index == columnIndex) 
                {
                    columnFound = true; 
                }
                else
                {
                    if (this.RightToLeftInternal) 
                    {
                        cx -= dataGridViewColumn.Thickness; 
                    } 
                    else
                    { 
                        cx += dataGridViewColumn.Thickness;
                    }
                    dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, 
                        DataGridViewElementStates.None);
                } 
            } 

            if (!columnFound && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) 
            {
                for (dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                    dataGridViewColumn != null && !columnFound;
                    ) 
                {
                    if ((this.RightToLeftInternal && cx < data.X) || 
                        (!this.RightToLeftInternal && cx > data.Right)) 
                    {
                        break; 
                    }
                    if (dataGridViewColumn.Index == columnIndex)
                    {
                        columnFound = true; 
                    }
                    else 
                    { 
                        if (this.RightToLeftInternal)
                        { 
                            cx -= dataGridViewColumn.Thickness;
                        }
                        else
                        { 
                            cx += dataGridViewColumn.Thickness;
                        } 
                        if (dataGridViewColumn.Index == this.displayedBandsInfo.FirstDisplayedScrollingCol) 
                        {
                            if (this.RightToLeftInternal) 
                            {
                                cx += this.negOffset;
                            }
                            else 
                            {
                                cx -= this.negOffset; 
                            } 
                        }
                        dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None);
                    }
                } 
            }
 
            if (columnFound) 
            {
                Debug.Assert(dataGridViewColumn != null); 
                int displayWidth, viewedColumnWidth = dataGridViewColumn.Thickness;
                if (dataGridViewColumn.Index == this.displayedBandsInfo.FirstDisplayedScrollingCol)
                {
                    viewedColumnWidth -= this.negOffset; 
                }
                if (cutOverflow && 
                    ((!this.RightToLeftInternal && cx + viewedColumnWidth > data.Right) || 
                     (this.RightToLeftInternal && cx - viewedColumnWidth < data.X)))
                { 
                    if (this.RightToLeftInternal)
                    {
                        displayWidth = cx - data.X;
                    } 
                    else
                    { 
                        displayWidth = data.Right - cx; 
                    }
                } 
                else
                {
                    displayWidth = viewedColumnWidth;
                } 

                Rectangle columnRect; 
                if (this.RightToLeftInternal) 
                {
                    columnRect = new Rectangle(cx - displayWidth, data.Y, displayWidth, data.Height); 
                }
                else
                {
                    columnRect = new Rectangle(cx, data.Y, displayWidth, data.Height); 
                }
                if (this.layout.ColumnHeadersVisible) 
                { 
                    columnRect.Height += this.layout.ColumnHeaders.Height;
                    columnRect.Y      -= this.layout.ColumnHeaders.Height; 
                }
                return columnRect;
            }
 
            return Rectangle.Empty;
        } 
 
        // xColumnLeftEdge returns the left edge of the column when RightToLeft is false.
        // xColumnLeftEdge returns the right edge of the column when RightToLeft is true. 
        private int GetColumnIndexFromX(int x, out int xColumnLeftEdge)
        {
            Rectangle data = this.layout.Data;
            Debug.Assert(this.RightToLeftInternal || (x >= data.X - 1 && x < data.Right), "x must be inside the horizontal bounds of this.layout.Data"); 
            Debug.Assert(!this.RightToLeftInternal || (x >= data.X && x <= data.Right), "x must be inside the horizontal bounds of this.layout.Data");
 
            if (!this.RightToLeftInternal && x == data.X - 1) 
            {
                x++; 
            }
            else if (this.RightToLeftInternal && x == data.Right)
            {
                x--; 
            }
 
            int cx; 
            if (this.RightToLeftInternal)
            { 
                cx = data.Right-1;
            }
            else
            { 
                cx = data.X;
            } 
 
            // first try to match x against a frozen column
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            while (dataGridViewColumn != null &&
                   ((!this.RightToLeftInternal && cx < data.Right) || (this.RightToLeftInternal && cx >= data.X)))
            {
                if (this.RightToLeftInternal) 
                {
                    cx -= dataGridViewColumn.Thickness; 
                } 
                else
                { 
                    cx += dataGridViewColumn.Thickness;
                }
                if (!this.RightToLeftInternal && cx > x)
                { 
                    xColumnLeftEdge = cx - dataGridViewColumn.Thickness;
                    return dataGridViewColumn.Index; 
                } 
                else if (this.RightToLeftInternal && cx < x)
                { 
                    xColumnLeftEdge = cx + dataGridViewColumn.Thickness;
                    return dataGridViewColumn.Index;
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                    DataGridViewElementStates.None); 
            } 

            if (this.RightToLeftInternal) 
            {
                cx += this.negOffset;
            }
            else 
            {
                cx -= this.negOffset; 
            } 

            // second try to match x against a scrolling column 
            if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0)
            {
                dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                while (dataGridViewColumn != null && 
                       ((!this.RightToLeftInternal && cx < data.Right) || (this.RightToLeftInternal && cx >= data.X)))
                { 
                    Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); 
                    if (this.RightToLeftInternal)
                    { 
                        cx -= dataGridViewColumn.Thickness;
                    }
                    else
                    { 
                        cx += dataGridViewColumn.Thickness;
                    } 
                    if (!this.RightToLeftInternal && cx > x) 
                    {
                        xColumnLeftEdge = cx - dataGridViewColumn.Thickness; 
                        return dataGridViewColumn.Index;
                    }
                    else if (this.RightToLeftInternal && cx < x)
                    { 
                        xColumnLeftEdge = cx + dataGridViewColumn.Thickness;
                        return dataGridViewColumn.Index; 
                    } 
                    dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.None);
                }
            }
 
            xColumnLeftEdge = -1;
            return -1; 
        } 

        private static int GetColumnScrollRate(int xOffset) 
        {
            Debug.Assert(xOffset > 0);
            // Counting 20ms for executing the actual column scrolling
            if (xOffset <= 10) 
            {
                return 480;     // Two columns per second 
            } 
            if (xOffset <= 15)
            { 
                return 313;     // Three columns per second
            }
            if (xOffset <= 25)
            { 
                return 180;     // Five columns per second
            } 
            if (xOffset <= 35) 
            {
                return 123;     // Seven columns per second 
            }
            return Math.Max(1, 4000 / xOffset);
        }
 
        /// 
        ///      Returns the coordinate of the left edge of the given column. Note that 
        ///      the column does not need to be completely visible on the display area. 
        ///      Value returned is not necessarily within layout.Data because of the
        ///      this.negOffset value, or because the column may start to the right of 
        ///      data area, or behind the frozen area, or completely on the left of the control.
        ///      The right edge is returned in RightToLeft mode.
        /// 
        internal int GetColumnXFromIndex(int index) 
        {
            Debug.Assert(index < this.Columns.Count); 
            Debug.Assert(this.Columns[index].Visible); 

            int x; 
            if (this.RightToLeftInternal)
            {
                x = this.layout.Data.Right-1;
            } 
            else
            { 
                x = this.layout.Data.X; 
            }
 
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            while (dataGridViewColumn != null)
            {
                if (index == dataGridViewColumn.Index) 
                {
                    return x; 
                } 
                if (this.RightToLeftInternal)
                { 
                    x -= dataGridViewColumn.Thickness;
                }
                else
                { 
                    x += dataGridViewColumn.Thickness;
                } 
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                    DataGridViewElementStates.None); 
            }

            if (this.RightToLeftInternal)
            { 
                x += this.negOffset;
            } 
            else 
            {
                x -= this.negOffset; 
            }

            int xFirstVisibleScrollingCol = x;
 
            if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0)
            { 
                dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
            }
            else 
            {
                dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
            }
            Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); 

            while (dataGridViewColumn != null) 
            { 
                if (index == dataGridViewColumn.Index)
                { 
                    return x;
                }
                if (this.RightToLeftInternal)
                { 
                    x -= dataGridViewColumn.Thickness;
                } 
                else 
                {
                    x += dataGridViewColumn.Thickness; 
                }
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None); 
            }
 
            // The column is completely hidden on the left/right of the dataGridView 
            x = xFirstVisibleScrollingCol;
            dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
            dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn,
                DataGridViewElementStates.Visible,
                DataGridViewElementStates.Frozen);
            while (dataGridViewColumn != null) 
            {
                if (this.RightToLeftInternal) 
                { 
                    x += dataGridViewColumn.Thickness;
                } 
                else
                {
                    x -= dataGridViewColumn.Thickness;
                } 
                if (index == dataGridViewColumn.Index)
                { 
                    return x; 
                }
                dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
            }
 
            Debug.Fail("Could not find column in GetColumnXFromIndex");
            return 0; 
        } 

        private int GetNegOffsetFromHorizontalOffset(int horizontalOffset) 
        {
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
            while (dataGridViewColumn != null && dataGridViewColumn.Thickness <= horizontalOffset)
            { 
                horizontalOffset -= dataGridViewColumn.Thickness;
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
            } 
            return horizontalOffset;
        } 

        private bool GetOutOfBoundCorrectedHitTestInfo(ref HitTestInfo hti, ref int mouseX, ref int mouseY, out int xOffset, out int yOffset)
        {
            xOffset = yOffset = 0; 
            Rectangle rectScrollingArea = this.layout.Data;
            int visibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); 
            int frozenVisibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            int fittingTrailingScrollingRowsHeight = ComputeHeightOfFittingTrailingScrollingRows(frozenVisibleRowsHeight);
            int trailingScrollingRowsHeight = ComputeHeightOfTrailingScrollingRows(); 
            int emptyBackgroundWidth = Math.Max(0, this.layout.Data.Width - this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible));
            int emptyBackgroundHeight = Math.Max(0, this.layout.Data.Height - frozenVisibleRowsHeight - trailingScrollingRowsHeight);

            Debug.Assert(!this.vertScrollBar.Enabled || 
                         !this.vertScrollBar.Visible ||
                         this.vertScrollBar.Maximum == visibleRowsHeight - frozenVisibleRowsHeight); 
            //VSWhidbey 525671 
            //Debug.Assert(!this.vertScrollBar.Enabled ||
            //             !this.vertScrollBar.Visible || 
            //             this.vertScrollBar.Value >= this.verticalOffset);

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect])
            { 
                if (this.layout.RowHeadersVisible)
                { 
                    // Include row headers 
                    rectScrollingArea = Rectangle.Union(rectScrollingArea, this.layout.RowHeaders);
                } 
                // Discard frozen rows
                DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight,
                                            false /*discardFrozenColumns*/, true /*discardFrozenRows*/);
 
                if (mouseY >= rectScrollingArea.Top && mouseY <= rectScrollingArea.Bottom)
                { 
                    // Mouse's Y is in-bound -- correct X value 
                    hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right-1 : rectScrollingArea.Left, mouseY);
                    if (this.ptAnchorCell.Y != -1 && 
                        (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) != 0 &&
                        this.trackRowEdge != -1 &&
                        (this.Rows.GetRowState(this.trackRowEdge) & DataGridViewElementStates.Frozen) != 0 &&
                        hti.row >= 0 && 
                        (this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Frozen) == 0)
                    { 
                        // Anchor cell is in frozen row and target cell is in unfrozen row. Make sure no row is scrolled off. 
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                        int firstUnfrozenRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                        int firstColumnIndex;
                        if (hti.col >= 0)
                        {
                            firstColumnIndex = hti.col; 
                        }
                        else 
                        { 
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                            firstColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
                        }
                        if (firstColumnIndex >= 0 && firstUnfrozenRowIndex >= 0)
                        {
                            if (!ScrollIntoView(firstColumnIndex, firstUnfrozenRowIndex, false /*forCurrentCellChange*/)) 
                            {
                                return false; 
                            } 
                            hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right : rectScrollingArea.Left, mouseY);
                        } 
                    }
                    return true;
                }
 
                // Mouse's Y is outside of scrolling bands
                if (mouseY < rectScrollingArea.Top) 
                { 
                    if (this.ptAnchorCell.Y != -1 &&
                        ((this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) == 0 || 
                         (this.trackRowEdge != -1 && (this.Rows.GetRowState(this.trackRowEdge) & DataGridViewElementStates.Frozen) == 0)) &&
                        this.verticalOffset != 0)
                    {
                        // Up scrolling is required because the anchor's row is unfrozen 
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                        yOffset = mouseY - rectScrollingArea.Top;   // yOffset strictly negative 
                        if (this.RightToLeftInternal) 
                        {
                            mouseX = rectScrollingArea.Right-1; 
                        }
                        else
                        {
                            mouseX = rectScrollingArea.Left+1; 
                        }
                    } 
                    else 
                    {
                        hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right : rectScrollingArea.Left, mouseY); 
                    }
                }
                else
                { 
                    Debug.Assert(mouseY > rectScrollingArea.Bottom);
                    if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
                    { 
                        if (this.verticalOffset + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <=
                            visibleRowsHeight - frozenVisibleRowsHeight - fittingTrailingScrollingRowsHeight) 
                        {
                            // Down scrolling is required
                            yOffset = mouseY - rectScrollingArea.Bottom;   // yOffset strictly positive
                            if (this.RightToLeftInternal) 
                            {
                                mouseX = rectScrollingArea.Right-1; 
                            } 
                            else
                            { 
                                mouseX = rectScrollingArea.Left+1;
                            }
                        }
                    } 
                }
                return true; 
            } 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect]) 
            {
                if (this.layout.ColumnHeadersVisible)
                {
                    // Include column headers 
                    rectScrollingArea = Rectangle.Union(rectScrollingArea, this.layout.ColumnHeaders);
                } 
 
                // Discard frozen columns
                DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight, 
                                            true /*discardFrozenColumns*/, false /*discardFrozenRows*/);

                if (mouseX >= rectScrollingArea.Left && mouseX <= rectScrollingArea.Right)
                { 
                    // Mouse's X is in-bound -- correct Y value
                    hti = HitTest(mouseX, rectScrollingArea.Top); 
                    if (this.ptAnchorCell.X != -1 && 
                        this.Columns[this.ptAnchorCell.X].Frozen &&
                        this.trackColumnEdge != -1 && 
                        this.Columns[this.trackColumnEdge].Frozen &&
                        hti.col >= 0 &&
                        !this.Columns[hti.col].Frozen)
                    { 
                        // Anchor cell is in frozen column and target cell is in unfrozen column. Make sure no column is scrolled off.
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0); 
                        int firstUnfrozenColumnIndex = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen).Index; 
                        int firstRowIndex;
                        if (hti.row >= 0) 
                        {
                            firstRowIndex = hti.row;
                        }
                        else 
                        {
                            firstRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                        } 
                        if (firstRowIndex >= 0 && firstUnfrozenColumnIndex >= 0)
                        { 
                            if (!ScrollIntoView(firstUnfrozenColumnIndex, firstRowIndex, false /*forCurrentCellChange*/))
                            {
                                return false;
                            } 
                            hti = HitTest(mouseX, rectScrollingArea.Top);
                        } 
                    } 
                    return true;
                } 

                // Mouse's X is outside of scrolling bands
                if ((!this.RightToLeftInternal && mouseX < rectScrollingArea.Left) ||
                    (this.RightToLeftInternal && mouseX > rectScrollingArea.Right)) 
                {
                    if (this.ptAnchorCell.X != -1 && 
                        (!this.Columns[this.ptAnchorCell.X].Frozen || 
                         (this.trackColumnEdge != -1 && !this.Columns[this.trackColumnEdge].Frozen)) &&
                        this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && 
                        (this.negOffset > 0 ||
                         this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) != null))
                    {
                        // xOffset strictly negative 
                        if (this.RightToLeftInternal)
                        { 
                            // Right scrolling is required 
                            xOffset = rectScrollingArea.Right - mouseX;
                        } 
                        else
                        {
                            // Left scrolling is required
                            xOffset = mouseX - rectScrollingArea.Left; 
                        }
                        mouseY = rectScrollingArea.Top+1; 
                    } 
                    else
                    { 
                        hti = HitTest(mouseX, rectScrollingArea.Top);
                    }
                }
                else 
                {
                    Debug.Assert((!this.RightToLeftInternal && mouseX > rectScrollingArea.Right) || (this.RightToLeftInternal && mouseX < rectScrollingArea.Left)); 
                    if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) 
                    {
                        if (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol != -1 && 
                            this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None) == null)
                        {
                            // No more columns to scroll
                            return true; 
                        }
 
                        DataGridViewColumn newFirstVisibleScrollingCol = this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], 
                                                                                                             DataGridViewElementStates.Visible,
                                                                                                             DataGridViewElementStates.None); 
                        int newColOffset = 0;
                        for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible,
                                                                                                          DataGridViewElementStates.Frozen);
                            dataGridViewColumn != newFirstVisibleScrollingCol; 
                            dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                            DataGridViewElementStates.Visible, 
                            DataGridViewElementStates.None)) 
                        {
                            newColOffset += dataGridViewColumn.Thickness; 
                        }

                        if (this.HorizontalOffset != newColOffset)
                        { 
                            // xOffset strictly positive
                            if (this.RightToLeftInternal) 
                            { 
                                // Left scrolling is required
                                xOffset = rectScrollingArea.Left - mouseX; 
                            }
                            else
                            {
                                // Right scrolling is required 
                                xOffset = mouseX - rectScrollingArea.Right;
                            } 
                            mouseY = rectScrollingArea.Top+1; 
                        }
                    } 
                }
                return true;
            }
 
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])
            { 
                bool recomputeHitTestInfo = false; 

                // Discard frozen columns and rows 
                DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight,
                                            true /*discardFrozenColumns*/, true /*discardFrozenRows*/);

                if (mouseY < rectScrollingArea.Top) 
                {
                    // Mouse's Y is above scrolling bands 
                    if ( 
                        (
                         (this.ptAnchorCell.Y != -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) == 0) 
                         ||
                         (this.ptCurrentCell.Y != -1 && (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Frozen) == 0)
                        )
                        && 
                        this.verticalOffset != 0
                       ) 
                    { 
                        // Up scrolling is required - the anchor's row is unfrozen
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
                        yOffset = mouseY - rectScrollingArea.Top;   // yOffset strictly negative
                    }
                    else
                    { 
                        // Correct mouse's Y - no scrolling can be performed
                        if (mouseY < this.layout.Data.Top) 
                        { 
                            mouseY = this.layout.Data.Top+1;
                            recomputeHitTestInfo = true; 
                        }
                    }
                }
                else if (mouseY > rectScrollingArea.Bottom) 
                {
                    // Mouse's Y is below scrolling bands 
                    if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
                    {
                        if (this.verticalOffset + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <= 
                            visibleRowsHeight - frozenVisibleRowsHeight - fittingTrailingScrollingRowsHeight)
                        {
                            // Down scrolling is required
                            yOffset = mouseY - rectScrollingArea.Bottom;   // yOffset strictly positive 
                        }
                        else 
                        { 
                            // Correct mouse's Y - no scrolling can be performed
                            mouseY = rectScrollingArea.Bottom-1; 
                            recomputeHitTestInfo = true;
                        }
                    }
                    else 
                    {
                        // Correct mouse's Y - no scrolling can be performed 
                        mouseY = rectScrollingArea.Bottom-1; 
                        recomputeHitTestInfo = true;
                    } 
                }
#if DEBUG
                else
                { 
                    // Mouse's Y is in-bound
                    Debug.Assert(mouseY >= rectScrollingArea.Top && mouseY <= rectScrollingArea.Bottom); 
                } 
#endif
                if ((!this.RightToLeftInternal && mouseX < rectScrollingArea.Left) || 
                    (this.RightToLeftInternal && mouseX > rectScrollingArea.Right))
                {
                    // Mouse's X is on the left of scrolling bands (LTR)
                    if ( 
                        (
                         (this.ptAnchorCell.X != -1 && !this.Columns[this.ptAnchorCell.X].Frozen) 
                         || 
                         (this.ptCurrentCell.X != -1 && !this.Columns[this.ptCurrentCell.X].Frozen)
                        ) 
                        &&
                        this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 &&
                        (this.negOffset > 0 ||
                         this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) != null) 
                       )
                    { 
                        // xOffset strictly negative 
                        if (this.RightToLeftInternal)
                        { 
                            // Right scrolling is required - anchor's column is unfrozen
                            xOffset = rectScrollingArea.Right - mouseX;
                        }
                        else 
                        {
                            // Left scrolling is required - anchor's column is unfrozen 
                            xOffset = mouseX - rectScrollingArea.Left; 
                        }
                    } 
                    else
                    {
                        // Correct mouse's X - no scrolling can be performed
                        if (!this.RightToLeftInternal && mouseX < this.layout.Data.Left) 
                        {
                            mouseX = this.layout.Data.Left+1; 
                            recomputeHitTestInfo = true; 
                        }
                        else if (this.RightToLeftInternal && mouseX > this.layout.Data.Right) 
                        {
                            mouseX = this.layout.Data.Right-1;
                            recomputeHitTestInfo = true;
                        } 
                    }
                } 
                else if ((!this.RightToLeftInternal && mouseX > rectScrollingArea.Right) || 
                         (this.RightToLeftInternal && mouseX < rectScrollingArea.Left))
                { 
                    // Mouse's X is on the right of scrolling bands (LTR)
                    if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 &&
                        (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol == -1 ||
                         this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None) != null)) 
                    {
                        DataGridViewColumn newFirstVisibleScrollingCol = this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], 
                                                                                                            DataGridViewElementStates.Visible, 
                                                                                                            DataGridViewElementStates.None);
                        int newColOffset = 0; 
                        for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible,
                                                                                                          DataGridViewElementStates.Frozen);
                            dataGridViewColumn != newFirstVisibleScrollingCol;
                            dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, 
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None)) 
                        { 
                            newColOffset += dataGridViewColumn.Thickness;
                        } 
                        if (this.HorizontalOffset != newColOffset)
                        {
                            // xOffset strictly positive
                            if (this.RightToLeftInternal) 
                            {
                                // Left scrolling is required 
                                xOffset = rectScrollingArea.Left - mouseX; 
                            }
                            else 
                            {
                                // Right scrolling is required
                                xOffset = mouseX - rectScrollingArea.Right;
                            } 
                        }
                        else 
                        { 
                            // Correct mouse's X - no scrolling can be performed
                            if (this.RightToLeftInternal) 
                            {
                                mouseX = rectScrollingArea.Left+1;
                            }
                            else 
                            {
                                mouseX = rectScrollingArea.Right-1; 
                            } 
                            recomputeHitTestInfo = true;
                        } 
                    }
                    else
                    {
                        // Correct mouse's X - no scrolling can be performed 
                        if (this.RightToLeftInternal)
                        { 
                            mouseX = rectScrollingArea.Left+1; 
                        }
                        else 
                        {
                            mouseX = rectScrollingArea.Right-1;
                        }
                        recomputeHitTestInfo = true; 
                    }
                } 
#if DEBUG 
                else
                { 
                    // Mouse's X is in-bound
                    Debug.Assert(mouseX >= rectScrollingArea.Left && mouseX <= rectScrollingArea.Right);
                }
#endif 
                if (recomputeHitTestInfo)
                { 
                    hti = HitTest(mouseX, mouseY); 
                }
            } 
            return true;
        }

        internal override Size GetPreferredSizeCore(Size proposedConstraints) 
        {
            int bordersAndPaddingWidth = 2*(this.BorderWidth + this.Padding.Size.Width); 
            int bordersAndPaddingHeight = 2*(this.BorderWidth + this.Padding.Size.Height); 

            bool allowHorizScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Horizontal); 
            bool allowVertScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Vertical);

            int minimumWidth = 16 + bordersAndPaddingWidth;
            if (allowVertScrollbar) 
            {
                minimumWidth += this.vertScrollBar.Width; 
            } 
            if (this.RowHeadersVisible)
            { 
                minimumWidth += this.RowHeadersWidth;
            }
            int preferredWidth = Math.Min(minimumWidth + this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible), proposedConstraints.Width);
            if (preferredWidth < minimumWidth) 
            {
                preferredWidth = minimumWidth; 
            } 

            int minimumHeight = 16 + bordersAndPaddingHeight; 
            if (allowHorizScrollbar)
            {
                minimumHeight += this.horizScrollBar.Height;
            } 
            if (this.ColumnHeadersVisible)
            { 
                minimumHeight += this.ColumnHeadersHeight; 
            }
            int preferredHeight = Math.Min(minimumHeight + this.Rows.GetRowsHeight(DataGridViewElementStates.Visible), proposedConstraints.Height); 
            if (preferredHeight < minimumHeight)
            {
                preferredHeight = minimumHeight;
            } 

            return new Size(preferredWidth, preferredHeight); 
        } 

        ///  
        // Rectangle returned includes the potential row header
        public Rectangle GetRowDisplayRectangle(int rowIndex, bool cutOverflow)
        {
            if (rowIndex < 0 || rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            } 
            return GetRowDisplayRectanglePrivate(rowIndex, cutOverflow);
        } 

        private Rectangle GetRowDisplayRectanglePrivate(int rowIndex, bool cutOverflow)
        {
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); 

            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) == 0) 
            { 
                return Rectangle.Empty;
            } 

            Rectangle data = this.layout.Data;
            int cy = data.Y;
            bool rowFound = false; 
            int indexTmp;
            for (indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                indexTmp != -1 && !rowFound; 
                )
            { 
                if (cy > data.Bottom)
                {
                    break;
                } 
                if (indexTmp == rowIndex)
                { 
                    rowFound = true; 
                }
                else 
                {
                    cy += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                    indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                } 
            }
 
            if (!rowFound && this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
            {
                for (indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                    indexTmp != -1 && !rowFound;
                    )
                {
                    if (cy > data.Bottom) 
                    {
                        break; 
                    } 
                    if (indexTmp == rowIndex)
                    { 
                        rowFound = true;
                    }
                    else
                    { 
                        cy += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                        indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); 
                    } 
                }
            } 

            if (rowFound)
            {
                int displayHeight; 
                if (cutOverflow && cy + this.Rows.SharedRow(indexTmp).GetHeight(indexTmp) > data.Bottom)
                { 
                    displayHeight = data.Bottom - cy; 
                }
                else 
                {
                    displayHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                }
 
                Rectangle rowRect = new Rectangle(data.X,
                    cy, 
                    data.Width, 
                    displayHeight);
                if (this.layout.RowHeadersVisible) 
                {
                    rowRect.Width += this.layout.RowHeaders.Width;
                    if (!this.RightToLeftInternal)
                    { 
                        rowRect.X -= this.layout.RowHeaders.Width;
                    } 
                } 
                return rowRect;
            } 

            return Rectangle.Empty;
        }
 
        private int GetRowIndexFromY(int y, out int yRowTopEdge)
        { 
            Rectangle data = this.layout.Data; 
            Debug.Assert(y >= data.Y-1 && y < data.Bottom, "y must be inside the vertical bounds of the data area.");
 
            if (y == data.Y-1)
            {
                y++;
            } 

            int rowHeight; 
            int cy = data.Y; 

            // first try to match y against a frozen rows 
            int indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            while (indexTmp != -1 && cy < data.Bottom)
            {
                rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                cy += rowHeight;
                if (cy > y) 
                { 
                    yRowTopEdge = cy - rowHeight;
                    return indexTmp; 
                }
                indexTmp = this.Rows.GetNextRow(indexTmp,
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            } 

            // second try to match y against a scrolling row 
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
            {
                indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0 &&
                    (this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0);

                while (indexTmp != -1 && cy < data.Bottom) 
                {
                    rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                    cy += rowHeight; 
                    if (cy > y)
                    { 
                        yRowTopEdge = cy - rowHeight;
                        return indexTmp;
                    }
                    indexTmp = this.Rows.GetNextRow(indexTmp, 
                        DataGridViewElementStates.Visible);
                } 
            } 

            yRowTopEdge = -1; 
            return -1;
        }

        private static int GetRowScrollRate(int yOffset) 
        {
            Debug.Assert(yOffset > 0); 
            // Counting 10ms for executing the actual row scrolling 
            if (yOffset <= 10)
            { 
                return 90;      // Ten rows per second
            }
            if (yOffset <= 15)
            { 
                return 57;     // Fifteen rows per second
            } 
            if (yOffset <= 25) 
            {
                return 30;     // Twenty-five rows per second 
            }
            if (yOffset <= 35)
            {
                return 18;     // Thirty-five rows per second 
            }
            return Math.Max(1, 600 / yOffset); 
        } 

        ///  
        ///      Returns the coordinate of the upper edge of the given row. Note that
        ///      the row does not need to be completely visible on the display area.
        ///      Value returned is not necessarily within layout.Data because the row
        ///      may start below the data area. 
        /// 
        internal int GetRowYFromIndex(int index) 
        { 
            Debug.Assert(index >= 0 && index < this.Rows.Count);
            Debug.Assert((this.Rows.GetRowState(index) & DataGridViewElementStates.Visible) != 0); 

            int y = this.layout.Data.Y;

            int indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            while (indexTmp != -1)
            { 
                if (index == indexTmp) 
                {
                    return y; 
                }
                y += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                indexTmp = this.Rows.GetNextRow(indexTmp,
                    DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            }
 
            int yFirstVisibleScrollingRow = y; 

            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) 
            {
                if (index >= this.displayedBandsInfo.FirstDisplayedScrollingRow)
                {
                    // index is part of the scrolling rows below the frozen rows 
                    indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                } 
                else 
                {
                    // index is part of the rows hidden behind the frozen rows or on top of the control 
                    indexTmp = -1;
                }
            }
            else 
            {
                // frozen rows cover all the rows real-estate. Look for index starting at the first visible non-frozen row. 
                indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                Debug.Assert(indexTmp != -1);
            } 

            if (indexTmp != -1)
            {
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0 && 
                    (this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0);
 
                while (indexTmp != -1) 
                {
                    if (index == indexTmp) 
                    {
                        return y;
                    }
                    y += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                    indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible);
                } 
            } 

            // Row is completely hidden behind frozen rows or on top of control 
            y = yFirstVisibleScrollingRow;
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow != -1);
            indexTmp = this.Rows.GetPreviousRow(this.displayedBandsInfo.FirstDisplayedScrollingRow,
                DataGridViewElementStates.Visible, 
                DataGridViewElementStates.Frozen);
            while (indexTmp != -1) 
            { 
                y -= this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                if (index == indexTmp) 
                {
                    return y;
                }
                indexTmp = this.Rows.GetPreviousRow(indexTmp, 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen); 
            } 

            Debug.Fail("Could not find row in GetRowYFromIndex"); 
            return 0;
        }

        private bool GetTabKeyEffective(bool shift, bool ctrl) 
        {
            if (this.StandardTab) 
            { 
                return ctrl &&
                       !((!shift && (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell)) || 
                         (shift && (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell)));
            }
            else
            { 
                return !ctrl &&
                       !((!shift && (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell)) || 
                         (shift && (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell))); 
            }
        } 

        /// 
        public HitTestInfo HitTest(int x, int y)
        { 
            HitTestInfo hti = new HitTestInfo();
 
            if (!this.layout.Inside.Contains(x, y)) 
            {
                return hti; 
            }

            if (this.horizScrollBar != null && this.horizScrollBar.Visible && this.horizScrollBar.Bounds.Contains(x, y))
            { 
                hti.type = DataGridViewHitTestType.HorizontalScrollBar;
                return hti; 
            } 

            if (this.vertScrollBar != null && this.vertScrollBar.Visible && this.vertScrollBar.Bounds.Contains(x, y)) 
            {
                hti.type = DataGridViewHitTestType.VerticalScrollBar;
                return hti;
            } 

            if (this.layout.TopLeftHeader.Contains(x, y)) 
            { 
                hti.type = DataGridViewHitTestType.TopLeftHeader;
                hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeader; 
                if (this.RightToLeftInternal)
                {
                    hti.colStart = this.layout.TopLeftHeader.Right-1;
                } 
                else
                { 
                    hti.colStart = this.layout.TopLeftHeader.Left; 
                }
                hti.rowStart = this.layout.TopLeftHeader.Top; 
                if ((!this.RightToLeftInternal && this.layout.TopLeftHeader.Right - x < DATAGRIDVIEW_columnSizingHotZone) ||
                    (this.RightToLeftInternal && x - this.layout.TopLeftHeader.Left < DATAGRIDVIEW_columnSizingHotZone))
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Right; 
                    if (this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft; 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = this.layout.TopLeftHeader.Left - x - 1;
                        }
                        else
                        { 
                            hti.mouseBarOffset = this.layout.TopLeftHeader.Right - x - 1;
                        } 
                    } 
                }
                else if (this.layout.TopLeftHeader.Top + this.layout.TopLeftHeader.Height - y < DATAGRIDVIEW_rowSizingHotZone) 
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom;
                    if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop;
                        hti.mouseBarOffset = this.layout.TopLeftHeader.Top + this.layout.TopLeftHeader.Height - y - 1; 
                    } 
                }
                return hti; 
            }

            // check for column resize / insertion
            if (this.layout.ColumnHeaders.Contains(x, y)) 
            {
                int xColumnLeftEdge; // this is actually the right edge in RTL mode 
                hti.col = GetColumnIndexFromX(x, out xColumnLeftEdge); 
                if (hti.col < 0)
                { 
                    return HitTestInfo.Nowhere;
                }
                Debug.Assert(xColumnLeftEdge == GetColumnXFromIndex(hti.col));
                hti.type = DataGridViewHitTestType.ColumnHeader; 
                hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeader;
                hti.rowStart = this.layout.ColumnHeaders.Top; 
                hti.colStart = xColumnLeftEdge; 
                int columnWidth = this.Columns[hti.col].Thickness;
                if ((!this.RightToLeftInternal && xColumnLeftEdge + columnWidth - x < DATAGRIDVIEW_columnSizingHotZone) || 
                    (this.RightToLeftInternal && x - xColumnLeftEdge + columnWidth < DATAGRIDVIEW_columnSizingHotZone))
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Right;
                    if (this.RightToLeftInternal) 
                    {
                        hti.mouseBarOffset = xColumnLeftEdge - columnWidth - x + 1; 
                    } 
                    else
                    { 
                        hti.mouseBarOffset = xColumnLeftEdge + columnWidth - x - 1;
                    }
                    DataGridViewColumn dataGridViewColumn = this.Columns[hti.col];
                    if (dataGridViewColumn.Resizable == DataGridViewTriState.True && 
                        (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill))
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeRight; 
                    }
                    else 
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeaderRight;
                    }
                } 
                else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) ||
                         (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone)) 
                { 
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Left;
                    DataGridViewColumn dataGridViewColumn = null; 
                    // VS Whidbey bug 317105 - Condition unnecessary
                    //if (hti.col != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0)
                    //{
                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], 
                                                                                 DataGridViewElementStates.Visible,
                                                                                 DataGridViewElementStates.None); 
                    //} 
                    if (dataGridViewColumn != null)
                    { 
                        hti.adjacentCol = dataGridViewColumn.Index;
                        if (this.RightToLeftInternal)
                        {
                            hti.mouseBarOffset = xColumnLeftEdge - x + 1; 
                        }
                        else 
                        { 
                            hti.mouseBarOffset = xColumnLeftEdge - x - 1;
                        } 
                        if (dataGridViewColumn.Resizable == DataGridViewTriState.True &&
                            (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill))
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeLeft; 
                        }
                        else 
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeaderLeft;
                        } 
                    }
                    else
                    {
                        if (this.RowHeadersVisible && this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) 
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight; 
                            if (this.RightToLeftInternal) 
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x; 
                            }
                            else
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x - 1; 
                            }
                        } 
                        else 
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft; 
                        }
                    }
                }
                else if (this.layout.ColumnHeaders.Bottom - y < DATAGRIDVIEW_rowSizingHotZone) 
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom; 
                    if (/*!this.RowHeadersVisible &&*/ this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) 
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom; 
                        hti.mouseBarOffset = this.layout.ColumnHeaders.Bottom - y - 1;
                    }
                }
            } 

            // check for row resize 
            if (this.layout.RowHeaders.Contains(x, y)) 
            {
                int yRowTopEdge; 
                hti.row = GetRowIndexFromY(y, out yRowTopEdge);
                if (hti.row < 0)
                {
                    return HitTestInfo.Nowhere; 
                }
                Debug.Assert(yRowTopEdge == GetRowYFromIndex(hti.row)); 
                hti.type = DataGridViewHitTestType.RowHeader; 
                hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeader;
                hti.rowStart = yRowTopEdge; 
                if (this.RightToLeftInternal)
                {
                    hti.colStart = this.layout.RowHeaders.Right-1;
                } 
                else
                { 
                    hti.colStart = this.layout.RowHeaders.Left; 
                }
                int rowHeight = this.Rows.SharedRow(hti.row).GetHeight(hti.row); 
                if (yRowTopEdge + rowHeight - y < DATAGRIDVIEW_rowSizingHotZone)
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom;
 
                    if (RowIsResizable(hti.row) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeBottom; 
                        hti.mouseBarOffset = yRowTopEdge + rowHeight - y - 1;
                    } 
                }
                else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone)
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Top; 
                    int indexTmp = -1;
                    if (hti.row != this.displayedBandsInfo.FirstDisplayedScrollingRow || this.displayedBandsInfo.NumDisplayedFrozenRows > 0) 
                    { 
                        indexTmp = this.Rows.GetPreviousRow(hti.row, DataGridViewElementStates.Visible);
                    } 
                    if (indexTmp != -1)
                    {
                        if (RowIsResizable(indexTmp) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeTop;
                            hti.adjacentRow = indexTmp; 
                            hti.mouseBarOffset = yRowTopEdge - y - 1; 
                        }
                    } 
                    else
                    {
                        if (this.ColumnHeadersVisible && this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing)
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom;
                            hti.mouseBarOffset = yRowTopEdge - y - 1; 
                        } 
                    }
                } 
                else if ((!this.RightToLeftInternal && this.layout.RowHeaders.Right - x < DATAGRIDVIEW_columnSizingHotZone) ||
                         (this.RightToLeftInternal && x - this.layout.RowHeaders.Left < DATAGRIDVIEW_columnSizingHotZone))
                {
                    //hti.edge = DataGridViewHitTestTypeCloseEdge.Right; 
                    if (this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing)
                    { 
                        hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeRight; 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = this.layout.RowHeaders.Left - x - 1;
                        }
                        else
                        { 
                            hti.mouseBarOffset = this.layout.RowHeaders.Right - x - 1;
                        } 
                    } 
                }
            } 

            if (this.layout.Data.Contains(x, y))
            {
                int xColumnLeftEdge, yRowTopEdge; 
                hti.col = GetColumnIndexFromX(x, out xColumnLeftEdge);
                hti.row = GetRowIndexFromY(y, out yRowTopEdge); 
                if (hti.col < 0 || hti.row < 0) 
                {
                    return HitTestInfo.Nowhere; 
                }
                Debug.Assert(xColumnLeftEdge == GetColumnXFromIndex(hti.col));
                Debug.Assert(yRowTopEdge == GetRowYFromIndex(hti.row));
                hti.type = DataGridViewHitTestType.Cell; 
                hti.typeInternal = DataGridViewHitTestTypeInternal.Cell;
                hti.rowStart = yRowTopEdge; 
                hti.colStart = xColumnLeftEdge; 
                if (!this.ColumnHeadersVisible)
                { 
                    int columnWidth = this.Columns[hti.col].Thickness;
                    if ((!this.RightToLeftInternal && xColumnLeftEdge + columnWidth - x < DATAGRIDVIEW_columnSizingHotZone) ||
                        (this.RightToLeftInternal && x - xColumnLeftEdge + columnWidth < DATAGRIDVIEW_columnSizingHotZone))
                    { 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = xColumnLeftEdge - columnWidth - x + 1; 
                        }
                        else 
                        {
                            hti.mouseBarOffset = xColumnLeftEdge + columnWidth - x - 1;
                        }
                        DataGridViewColumn dataGridViewColumn = this.Columns[hti.col]; 
                        if (dataGridViewColumn.Resizable == DataGridViewTriState.True &&
                            (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) 
                        { 
                            hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeRight;
                        } 
                        return hti;
                    }
                    else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) ||
                             (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone)) 
                    {
                        DataGridViewColumn dataGridViewColumn = null; 
                        if (hti.col != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0) 
                        {
                            dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], 
                                DataGridViewElementStates.Visible,
                                DataGridViewElementStates.None);
                        }
                        if (dataGridViewColumn != null) 
                        {
                            hti.adjacentCol = dataGridViewColumn.Index; 
                            if (this.RightToLeftInternal) 
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x + 1; 
                            }
                            else
                            {
                                hti.mouseBarOffset = xColumnLeftEdge - x - 1; 
                            }
                            if (dataGridViewColumn.Resizable == DataGridViewTriState.True && 
                                (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) 
                            {
                                hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeLeft; 
                            }
                            return hti;
                        }
                        else 
                        {
                            if (this.RowHeadersVisible && this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) 
                            { 
                                hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeLeft;
                                if (this.RightToLeftInternal) 
                                {
                                    hti.mouseBarOffset = xColumnLeftEdge - x;
                                }
                                else 
                                {
                                    hti.mouseBarOffset = xColumnLeftEdge - x - 1; 
                                } 
                                return hti;
                            } 
                        }
                    }
                }
                else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) || 
                         (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone))
                { 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
                    Debug.Assert(dataGridViewColumn != null);
                    if (hti.col == dataGridViewColumn.Index && 
                        this.RowHeadersVisible &&
                        this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing)
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeLeft; 
                        if (this.RightToLeftInternal)
                        { 
                            hti.mouseBarOffset = xColumnLeftEdge - x; 
                        }
                        else 
                        {
                            hti.mouseBarOffset = xColumnLeftEdge - x - 1;
                        }
                        return hti; 
                    }
                } 
 
                if (!this.RowHeadersVisible)
                { 
                    int rowHeight = this.Rows.SharedRow(hti.row).GetHeight(hti.row);
                    if (yRowTopEdge + rowHeight - y < DATAGRIDVIEW_rowSizingHotZone)
                    {
                        if (RowIsResizable(hti.row) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) 
                        {
                            hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeBottom; 
                            hti.mouseBarOffset = yRowTopEdge + rowHeight - y - 1; 
                        }
                    } 
                    else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone)
                    {
                        int indexTmp = -1;
                        if (hti.row != this.displayedBandsInfo.FirstDisplayedScrollingRow || this.displayedBandsInfo.NumDisplayedFrozenRows > 0) 
                        {
                            indexTmp = this.Rows.GetPreviousRow(hti.row, 
                                DataGridViewElementStates.Visible); 
                        }
                        if (indexTmp != -1) 
                        {
                            if (RowIsResizable(indexTmp) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                            {
                                hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeTop; 
                                hti.adjacentRow = indexTmp;
                                hti.mouseBarOffset = yRowTopEdge - y - 1; 
                            } 
                        }
                        else 
                        {
                            if (this.ColumnHeadersVisible && this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing)
                            {
                                hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop; 
                                hti.mouseBarOffset = yRowTopEdge - y - 1;
                            } 
                        } 
                    }
                } 
                else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone)
                {
                    int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                    Debug.Assert(rowIndex >= 0); 
                    if (hti.row == rowIndex &&
                        this.ColumnHeadersVisible && 
                        this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) 
                    {
                        hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop; 
                        hti.mouseBarOffset = yRowTopEdge - y - 1;
                    }
                }
            } 

            return hti; 
        } 

        private void HorizScrollTimer_Tick(object sender, System.EventArgs e) 
        {
            BeginInvoke(new MethodInvoker(HorizScrollTimerHandler));
        }
 
        private void HorizScrollTimerHandler()
        { 
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]); 

            Point ptMouse = PointToClient(Control.MousePosition); 
            HitTestInfo hti = HitTest(ptMouse.X, ptMouse.Y);
            int xOffset, yOffset, mouseX = ptMouse.X, mouseY = ptMouse.Y;
            if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset))
            { 
                if (xOffset != 0)
                { 
                    int absXOffset = Math.Abs(xOffset), normOffset = xOffset / absXOffset; 
                    ScrollColumns(normOffset);
                    this.horizScrollTimer.Interval = GetColumnScrollRate(absXOffset); 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect])
                    {
                        hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), mouseY);
                        if (hti.col >= 0) 
                        {
                            OnColumnSelectMouseMove(hti); 
                        } 
                    }
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]) 
                    {
                        if (yOffset != 0)
                        {
                            hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), ptMouse.Y-yOffset-(yOffset/Math.Abs(yOffset))); 
                        }
                        else 
                        { 
                            hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), mouseY);
                        } 
                        if (hti.col >= 0 && hti.row >= 0)
                        {
                            OnCellSelectMouseMove(hti);
                        } 
                    }
                } 
                else 
                {
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && hti.col >= 0) 
                    {
                        OnColumnSelectMouseMove(hti);
                    }
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) 
                    {
                        OnCellSelectMouseMove(hti); 
                    } 
                    this.HorizScrollTimer.Enabled = false;
                } 
            }
        }

        // Returns true for success, returns false when the OnDataError event cancels the operation. 
        private bool InitializeEditingCellValue(ref DataGridViewCellStyle dataGridViewCellStyle, ref DataGridViewCell dataGridViewCell)
        { 
            DataGridViewDataErrorEventArgs dgvdee = null; 
            // Save unedited value so we can restore it later if parsing of new value fails
            this.uneditedFormattedValue = dataGridViewCell.GetFormattedValue(this.ptCurrentCell.Y, ref dataGridViewCellStyle, DataGridViewDataErrorContexts.Formatting); 
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true;
            try
            {
                IDataGridViewEditingCell dataGridViewEditingCell = dataGridViewCell as IDataGridViewEditingCell; 
                Debug.Assert(dataGridViewEditingCell != null);
                object currentFormattedValue = dataGridViewEditingCell.GetEditingCellFormattedValue(DataGridViewDataErrorContexts.Formatting); 
                if ((currentFormattedValue == null && this.uneditedFormattedValue != null) || 
                    (currentFormattedValue != null && this.uneditedFormattedValue == null) ||
                    (currentFormattedValue != null && !this.uneditedFormattedValue.Equals(currentFormattedValue))) 
                {
                    Debug.Assert(this.ptCurrentCell.X == dataGridViewCell.ColumnIndex);
                    dataGridViewCell = this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X]; // unshare the edited cell
                    dataGridViewEditingCell = dataGridViewCell as IDataGridViewEditingCell; 
                    dataGridViewEditingCell.EditingCellFormattedValue = this.uneditedFormattedValue;
                    dataGridViewEditingCell.EditingCellValueChanged = false; 
                } 
            }
            catch (Exception exception) 
            {
                if (ClientUtils.IsCriticalException(exception))
                {
                    throw; 
                }
                dgvdee = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X, 
                    this.ptCurrentCell.Y, 
                    DataGridViewDataErrorContexts.InitialValueRestoration);
                OnDataErrorInternal(dgvdee); 
            }
            finally
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false; 
            }
            if (dgvdee != null) 
            { 
                if (dgvdee.ThrowException)
                { 
                    throw dgvdee.Exception;
                }
                return !dgvdee.Cancel;
            } 
            return true;
        } 
 
        // Returns true for success, returns false when the OnDataError event cancels the operation.
        private bool InitializeEditingControlValue(ref DataGridViewCellStyle dataGridViewCellStyle, DataGridViewCell dataGridViewCell) 
        {
            Debug.Assert(dataGridViewCell != null);
            Debug.Assert(this.editingControl != null);
 
            DataGridViewDataErrorEventArgs dgvdee = null;
            object initialFormattedValue = dataGridViewCell.GetFormattedValue(this.ptCurrentCell.Y, ref dataGridViewCellStyle, DataGridViewDataErrorContexts.Formatting); 
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true; 
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true;
            try 
            {
                dataGridViewCell.InitializeEditingControl(this.ptCurrentCell.Y, initialFormattedValue, dataGridViewCellStyle);
                ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged = false;
            } 
            catch (Exception exception)
            { 
                if (ClientUtils.IsCriticalException(exception)) 
                {
                    throw; 
                }
                dgvdee = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X,
                    this.ptCurrentCell.Y,
                    DataGridViewDataErrorContexts.InitialValueRestoration); 
                OnDataErrorInternal(dgvdee);
            } 
            finally 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = false; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false;
            }
            if (dgvdee != null)
            { 
                if (dgvdee.ThrowException)
                { 
                    throw dgvdee.Exception; 
                }
                return !dgvdee.Cancel; 
            }

            // Save unedited value so we can restore it later if parsing of new value fails
            this.uneditedFormattedValue = initialFormattedValue; 
            return true;
        } 
 
        /// 
        public void InvalidateCell(DataGridViewCell dataGridViewCell) 
        {
            if (dataGridViewCell == null)
            {
                throw new ArgumentNullException("dataGridViewCell"); 
            }
            if (dataGridViewCell.DataGridView != this) 
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_CellDoesNotBelongToDataGridView));
            } 
            InvalidateCellPrivate(dataGridViewCell);
        }

        private void InvalidateCellPrivate(DataGridViewCell dataGridViewCell) 
        {
            Debug.Assert(dataGridViewCell != null); 
            Debug.Assert(dataGridViewCell.DataGridView == this); 
            InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex);
        } 

        /// 
        public void InvalidateCell(int columnIndex, int rowIndex)
        { 
            if (columnIndex < -1 || columnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("columnIndex"); 
            }
            if (rowIndex < -1 || rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex");
            }
            InvalidateCellPrivate(columnIndex, rowIndex); 
        }
 
        private void InvalidateCellPrivate(int columnIndex, int rowIndex) 
        {
            if (this.IsHandleCreated) 
            {
                Rectangle cellDisplayRect = GetCellAdjustedDisplayRectangle(columnIndex, rowIndex, true);
                if (!cellDisplayRect.IsEmpty)
                { 
                    Invalidate(cellDisplayRect);
                } 
            } 
        }
 
        /// 
        /// 
        ///      Invalidate the painting region for the column specified.
        ///  
        public void InvalidateColumn(int columnIndex)
        { 
            if (columnIndex < 0 || columnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("columnIndex"); 
            }
            InvalidateColumnInternal(columnIndex);
        }
 
        internal void InvalidateColumnInternal(int columnIndex)
        { 
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 

            if (this.IsHandleCreated) 
            {
                Rectangle columnDisplayRect = GetColumnDisplayRectanglePrivate(columnIndex, true);
                if (!columnDisplayRect.IsEmpty)
                { 
                    Invalidate(columnDisplayRect);
                } 
            } 
        }
 
        private void InvalidateData()
        {
            if (this.IsHandleCreated)
            { 
                Invalidate(this.layout.Data);
            } 
        } 

        ///  
        ///      Invalidates the scrollable area of the DataGridView.
        /// 
        private void InvalidateInside()
        { 
            if (this.IsHandleCreated)
            { 
                Invalidate(this.layout.Inside); 
            }
        } 

        /// 
        /// 
        ///      Invalidate the painting region for the row specified. 
        /// 
        public void InvalidateRow(int rowIndex) 
        { 
            if (rowIndex < 0 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex");
            }
            InvalidateRowPrivate(rowIndex);
        } 

        private void InvalidateRowPrivate(int rowIndex) 
        { 
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
 
            if (this.IsHandleCreated)
            {
                Rectangle rowDisplayRect = GetRowDisplayRectanglePrivate(rowIndex, true);
                if (!rowDisplayRect.IsEmpty) 
                {
                    Invalidate(rowDisplayRect); 
                } 
            }
        } 

        private void InvalidateRowHeights()
        {
            this.Rows.InvalidateCachedRowsHeights(); 
            if (this.IsHandleCreated)
            { 
                PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
                Invalidate();
            } 
        }

        private void InvalidateRows(int lo, int hi)
        { 
            Debug.Assert(lo <= hi);
            Debug.Assert(lo < this.Rows.Count); 
            Debug.Assert(hi < this.Rows.Count); 

            if (this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 0) 
            {
                return;
            }
 
            Rectangle rowDisplayRect, data;
            int top, bottom; 
 
            data = this.layout.Data;
 
            // If "lo" is not visible, then get the next visible row
            if ((this.Rows.GetRowState(lo) & DataGridViewElementStates.Visible) == 0)
            {
                lo = this.Rows.GetNextRow(lo, DataGridViewElementStates.Visible); 
            }
 
            if (lo == -1) 
            {
                // there are no visible rows below "lo" so there is nothing to invalidate. 
                return;
            }

            // If "hi" is not visible, then get the previous visible row 
            if ((this.Rows.GetRowState(hi) & DataGridViewElementStates.Visible) == 0)
            { 
                hi = this.Rows.GetPreviousRow(hi, DataGridViewElementStates.Visible); 
            }
 
            Debug.Assert(lo <= hi);
            Debug.Assert(lo > -1);

            rowDisplayRect = this.GetRowDisplayRectangle(lo, true /*cutOverflow*/); 

            if (rowDisplayRect.IsEmpty) 
            { 
                // The top row is offscreen
                if ((this.Rows.GetRowState(lo) & DataGridViewElementStates.Frozen) != 0) 
                {
                    // "lo" is a frozen row which is offscreen.
                    // This means that "lo" and any other row below it are offscreen.
                    return; 
                }
                else if (this.displayedBandsInfo.NumDisplayedScrollingRows == 0) 
                { 
                    // "lo" and all the rows below are scrolling rows but no scrolling rows are displayed.
                    return; 
                }
                else if (lo >= this.displayedBandsInfo.FirstDisplayedScrollingRow &&
                    this.Rows.GetRowCount(DataGridViewElementStates.Visible,
                                          this.displayedBandsInfo.FirstDisplayedScrollingRow, 
                                          lo) >= this.displayedBandsInfo.NumDisplayedScrollingRows)
                { 
                    // "lo" is a scrolling row whose coordinates are below the last visible row. 
                    return;
                } 
                else
                {
                    // "lo" is a scrolling row "behind" frozen rows.
                    // Start invalidating at the top of the first displayed scrolling row. 
                    top = this.GetRowDisplayRectangle(this.displayedBandsInfo.FirstDisplayedScrollingRow, true /*cutOverflow*/).Top;
                } 
            } 
            else
            { 
                top = rowDisplayRect.Top;
            }

            rowDisplayRect = this.GetRowDisplayRectangle(hi, true /*cutOverflow*/); 

            if (rowDisplayRect.IsEmpty) 
            { 
                // The bottom row is offscreen.
                if ((this.Rows.GetRowState(hi) & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen) 
                {
                    // "hi" is a frozen row offscreen and "lo" is a frozen row on screen.
                    // Invalidate all the way to the bottom
                    bottom = data.Bottom; 
                }
                else if (hi > this.displayedBandsInfo.FirstDisplayedScrollingRow) 
                { 
                    // "hi" is a scrolling row offscreen which is beyond the firstDisplayedScrollingRow
                    // Invalidate all the way to the bottom again. 
                    bottom = data.Bottom;
                }
                else if (this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) == 0)
                { 
                    // "hi" is a scrolling row above the first displayed scrolling row and there are no frozen rows.
                    // There is nothing to invalidate. 
                    return; 
                }
                else 
                {
                    // "hi" is a scrolling row which is "behind" the frozen rows.
                    // Invalidate all the way to the bottom of the frozen rows
                    // Compute the bottom of the last displayed frozen row. 
                    // There may be invisible rows between the frozen rows.
                    bottom = 0; 
                    for (int i = 0; i < this.displayedBandsInfo.NumDisplayedFrozenRows;) 
                    {
                        if ((this.Rows.GetRowState(i) & DataGridViewElementStates.Visible) == 0) 
                        {
                            continue;
                        }
 
                        if (i == this.displayedBandsInfo.NumDisplayedFrozenRows - 1)
                        { 
                            bottom = this.GetRowDisplayRectangle(i, true /*cutOverflow*/).Bottom; 
                            break;
                        } 

                        i ++;
                    }
 
                    if (bottom <= top)
                    { 
                        // In this case both "lo" and "hi" are two scrolling rows behind the frozen rows. 
                        // Nothing to invalidate.
                        return; 
                    }
                }
            }
            else 
            {
                bottom = rowDisplayRect.Bottom; 
            } 

            Invalidate(new Rectangle(data.X, top, data.Width, bottom - top)); 
        }

        private void InvalidateScrollBars()
        { 
            // invalidate the horizontal and the vertical scrollbars
            // note that the scrollbars can be null - this happens when 
            // the control has been disposed. 
            if (this.horizScrollBar != null && this.horizScrollBar.Visible)
            { 
                this.horizScrollBar.Invalidate();
            }
            if (this.vertScrollBar != null && this.vertScrollBar.Visible)
            { 
                this.vertScrollBar.Invalidate();
            } 
        } 

        private bool IsColumnOutOfBounds(int columnIndex) 
        {
            return columnIndex >= this.Columns.Count || columnIndex == -1;
        }
 
        private bool IsInnerCellOutOfBounds(int columnIndex, int rowIndex)
        { 
            return columnIndex >= this.Columns.Count || rowIndex >= this.Rows.Count || columnIndex == -1 || rowIndex == -1; 
        }
 
        private bool IsRowOutOfBounds(int rowIndex)
        {
            return rowIndex >= this.Rows.Count || rowIndex == -1;
        } 

        ///  
        protected override bool IsInputChar(char charCode) 
        {
            if (this.editingControl != null && 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage])
            {
                // Do not process key press in ProcessDialogChar.
                return true; 
            }
            else 
            { 
                return base.IsInputChar(charCode);
            } 
        }

        /// 
        protected override bool IsInputKey(Keys keyData) 
        {
            if ((keyData & Keys.Alt) == Keys.Alt) 
            { 
                return false;
            } 
            switch (keyData & Keys.KeyCode)
            {
                case Keys.Escape:
                { 
                    return this.IsEscapeKeyEffective;
                } 
 
                case Keys.Tab:
                { 
                    return GetTabKeyEffective((keyData & Keys.Shift) == Keys.Shift, (keyData & Keys.Control) == Keys.Control);
                }

                case Keys.A: 
                {
                    if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Control) 
                    { 
                        return true;
                    } 
                    break;
                }

                case Keys.C: 
                case Keys.Insert:
                { 
                    if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Control) 
                    {
                        return true; 
                    }
                    break;
                }
 
                case Keys.Space:
                { 
                    if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Shift && 
                        (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect ||
                         this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) && 
                        this.ptCurrentCell.X != -1)
                    {
                        return true;
                    } 
                    break;
                } 
 
                case Keys.Up:
                case Keys.Down: 
                case Keys.Left:
                case Keys.Right:
                case Keys.Home:
                case Keys.End: 
                case Keys.Next:
                case Keys.Prior: 
                case Keys.Enter: 
                case Keys.Delete:
                case Keys.D0: 
                case Keys.NumPad0:
                case Keys.F2:
                {
                    return true; 
                }
            } 
            return base.IsInputKey(keyData); 
        }
 
        /// 
        ///      Determines if Scrollbars should be visible,
        ///      updates their bounds and the bounds of all
        ///      other regions in the dataGridView's Layout. 
        /// 
        private void LayoutScrollBars() 
        { 
            SuspendLayout();
            try 
            {
                // Scrollbars are a tricky issue.
                // We need to see if we can cram our columns and rows
                // in without scrollbars and if they don't fit, we make 
                // scrollbars visible and then fixup our regions for the
                // data. 
                bool allowHorizScrollbar = ((this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Horizontal)) && 
                                           this.dataGridViewState2[DATAGRIDVIEWSTATE2_allowHorizontalScrollbar];
                bool allowVertScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Vertical); 
                bool needHorizScrollbarWithoutVertScrollbar = false;
                bool needHorizScrollbar = false;
                bool needVertScrollbar = false;
                bool rightToLeftInternal = this.RightToLeftInternal; 
                int oldfirstDisplayedScrollingRow;
 
                int totalVisibleColCount = this.Columns.GetColumnCount(DataGridViewElementStates.Visible); 
                int totalVisibleRowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible);
                int totalVisibleWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible); 
                int totalVisibleFrozenWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);

                // Expensive call - dataGridView could have a mode where no row is resizable which would result in better perfs
                int totalVisibleHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); 
                int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
 
                int horizScrollBarHeight = this.horizScrollBar.Height = SystemInformation.HorizontalScrollBarHeight; 
                int vertScrollBarWidth = this.vertScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
 
                if (allowHorizScrollbar &&
                    totalVisibleWidth > this.layout.Data.Width && totalVisibleFrozenWidth < this.layout.Data.Width &&
                    horizScrollBarHeight <= this.layout.Data.Height)
                { 
                    int oldDataHeight = this.layout.Data.Height;
                    this.layout.Data.Height -= horizScrollBarHeight; 
                    Debug.Assert(this.layout.Data.Height >= 0); 
                    needHorizScrollbarWithoutVertScrollbar = needHorizScrollbar = true;
                    if (totalVisibleWidth - this.layout.Data.Width <= vertScrollBarWidth || 
                        this.layout.Data.Width - totalVisibleFrozenWidth <= vertScrollBarWidth)
                    {
                        // Would we still need a horizontal scrollbar if there were a vertical one?
                        oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                        ComputeVisibleRows();
                        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)))
                        { 
                            needHorizScrollbar = (totalVisibleFrozenWidth < this.layout.Data.Width - vertScrollBarWidth);
                        }
                        this.displayedBandsInfo.FirstDisplayedScrollingRow = oldfirstDisplayedScrollingRow;
                    } 

                    if (needHorizScrollbar) 
                    { 
                        if (this.layout.RowHeadersVisible)
                        { 
                            this.layout.RowHeaders.Height -= horizScrollBarHeight;
                            Debug.Assert(this.layout.RowHeaders.Height >= 0);
                        }
                    } 
                    else
                    { 
                        // Restore old data height because turns out a horizontal scroll bar wouldn't make sense 
                        this.layout.Data.Height = oldDataHeight;
                    } 
                }

                oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
 
                ComputeVisibleRows();
                if (allowVertScrollbar && 
                    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 &&
                    vertScrollBarWidth <= this.layout.Data.Width)
                {
                    this.layout.Data.Width -= vertScrollBarWidth; 
                    Debug.Assert(this.layout.Data.Width >= 0);
                    if (rightToLeftInternal) 
                    { 
                        this.layout.Data.X += vertScrollBarWidth;
                    } 
                    if (this.layout.ColumnHeadersVisible)
                    {
                        this.layout.ColumnHeaders.Width -= vertScrollBarWidth;
                        Debug.Assert(this.layout.ColumnHeaders.Width >= 0); 
                        if (rightToLeftInternal)
                        { 
                            this.layout.ColumnHeaders.X += vertScrollBarWidth; 
                        }
                    } 
                    needVertScrollbar = true;
                }

                this.displayedBandsInfo.FirstDisplayedScrollingCol = ComputeFirstVisibleScrollingColumn(); 
                // we compute the number of visible columns only after we set up the vertical scroll bar.
                ComputeVisibleColumns(); 
 
                if (allowHorizScrollbar &&
                    needVertScrollbar && !needHorizScrollbar && 
                    totalVisibleWidth > this.layout.Data.Width && totalVisibleFrozenWidth < this.layout.Data.Width &&
                    horizScrollBarHeight <= this.layout.Data.Height)
                {
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = oldfirstDisplayedScrollingRow; 
                    if (this.layout.ColumnHeadersVisible)
                    { 
                        this.layout.ColumnHeaders.Width += vertScrollBarWidth; 
                        if (rightToLeftInternal)
                        { 
                            this.layout.ColumnHeaders.X -= vertScrollBarWidth;
                        }
                    }
                    this.layout.Data.Width += vertScrollBarWidth; 
                    if (rightToLeftInternal)
                    { 
                        this.layout.Data.X -= vertScrollBarWidth; 
                    }
                    this.layout.Data.Height -= horizScrollBarHeight; 
                    Debug.Assert(this.layout.Data.Height >= 0);
                    needVertScrollbar = false;

                    ComputeVisibleRows(); 
                    if (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) &&
                        this.displayedBandsInfo.NumTotallyDisplayedScrollingRows != totalVisibleRowCount && 
                        (totalVisibleHeight - totalVisibleFrozenHeight != ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) && 
                        this.layout.Data.Height > totalVisibleFrozenHeight &&
                        vertScrollBarWidth <= this.layout.Data.Width) 
                    {
                        this.layout.Data.Width -= vertScrollBarWidth;
                        Debug.Assert(this.layout.Data.Width >= 0);
                        if (rightToLeftInternal) 
                        {
                            this.layout.Data.X += vertScrollBarWidth; 
                        } 
                        if (this.layout.ColumnHeadersVisible)
                        { 
                            this.layout.ColumnHeaders.Width -= vertScrollBarWidth;
                            Debug.Assert(this.layout.ColumnHeaders.Width >= 0);
                            if (rightToLeftInternal)
                            { 
                                this.layout.ColumnHeaders.X += vertScrollBarWidth;
                            } 
                        } 
                        needVertScrollbar = true;
                    } 
                    if (needVertScrollbar)
                    {
                        needHorizScrollbar = true;
                    } 
                    else
                    { 
                        needHorizScrollbar = needHorizScrollbarWithoutVertScrollbar; 
                    }
                } 

                this.layout.ResizeBoxRect = new Rectangle();
                if (needVertScrollbar && needHorizScrollbar)
                { 
                    this.layout.ResizeBoxRect = new Rectangle(
                        rightToLeftInternal ? this.layout.Data.X - this.vertScrollBar.Width : this.layout.Data.Right, 
                        this.layout.Data.Bottom, 
                        this.vertScrollBar.Width,
                        this.horizScrollBar.Height); 
                }

                if (needHorizScrollbar && totalVisibleColCount > 0)
                { 
                    int widthNotVisible = totalVisibleWidth - this.layout.Data.Width;
 
                    this.horizScrollBar.Minimum = 0; 
                    this.horizScrollBar.Maximum = totalVisibleWidth - totalVisibleFrozenWidth;
                    Debug.Assert(this.horizScrollBar.Maximum > 0); 
                    this.horizScrollBar.SmallChange = 1;
                    this.horizScrollBar.LargeChange = Math.Max(totalVisibleWidth - totalVisibleFrozenWidth - widthNotVisible, 0);
                    this.horizScrollBar.Enabled = this.Enabled;
                    this.horizScrollBar.Bounds = new Rectangle( 
                        rightToLeftInternal ? this.layout.Inside.X + this.layout.ResizeBoxRect.Width : this.layout.Inside.X,
                        this.layout.Data.Bottom, 
                        this.layout.Inside.Width - this.layout.ResizeBoxRect.Width, 
                        this.horizScrollBar.Height);
                    this.horizScrollBar.Visible = true; 
                    this.horizScrollBar.Invalidate();
                }
                else
                { 
                    this.horizScrollBar.Visible = false;
                    this.HorizontalOffset = 0; 
 
                    this.horizScrollBar.Enabled = false;
                    this.horizScrollBar.Minimum = 0; 
                    this.horizScrollBar.Maximum = 1;
                    this.horizScrollBar.SmallChange = 1;
                    this.horizScrollBar.LargeChange = 1;
                    this.horizScrollBar.Value = 0; 
                }
 
                if (needVertScrollbar) 
                {
                    int vertScrollBarTop = this.layout.Data.Y; 
                    int vertScrollBarHeight = this.layout.Data.Height;
                    if (this.layout.ColumnHeadersVisible)
                    {
                        vertScrollBarTop = this.layout.ColumnHeaders.Y; 
                        vertScrollBarHeight += this.layout.ColumnHeaders.Height;
                    } 
                    else if (this.SingleHorizontalBorderAdded) 
                    {
                        vertScrollBarTop--; 
                        vertScrollBarHeight++;
                    }

                    this.vertScrollBar.Minimum = 0; 
                    this.vertScrollBar.Maximum = totalVisibleHeight - totalVisibleFrozenHeight;
                    Debug.Assert(this.vertScrollBar.Maximum > 0); 
                    this.vertScrollBar.Value = ComputeHeightOfScrolledOffRows(); 
                    this.vertScrollBar.LargeChange = this.layout.Data.Height - totalVisibleFrozenHeight;
                    this.vertScrollBar.Bounds = new Rectangle( 
                        rightToLeftInternal ? this.layout.Data.X - this.vertScrollBar.Width : this.layout.Data.Right,
                        vertScrollBarTop,
                        this.vertScrollBar.Width,
                        vertScrollBarHeight); 
                    this.vertScrollBar.Enabled = this.Enabled;
                    this.vertScrollBar.Visible = true; 
                    this.vertScrollBar.Invalidate(); 

                    this.verticalOffset = this.vertScrollBar.Value; 
                }
                else
                {
                    this.vertScrollBar.Visible = false; 
                    this.verticalOffset = 0;
 
                    this.vertScrollBar.Enabled = false; 
                    this.vertScrollBar.Minimum = 0;
                    this.vertScrollBar.Maximum = 1; 
                    this.vertScrollBar.LargeChange = 1;
                    this.vertScrollBar.Value = 0;
                }
            } 
            finally
            { 
                ResumeLayout(false); 
            }
        } 

        private void MakeFirstDisplayedCellCurrentCell(bool includeNewRow)
        {
            // No current cell - try to set the first displayed cell to be the current one. 
            Point firstDisplayedCellAddress = this.FirstDisplayedCellAddress;
            if (firstDisplayedCellAddress.X != -1 && 
                (includeNewRow || 
                 !this.AllowUserToAddRowsInternal ||
                 firstDisplayedCellAddress.Y != this.Rows.Count - 1)) 
            {
                bool success = SetAndSelectCurrentCellAddress(firstDisplayedCellAddress.X,
                                                              firstDisplayedCellAddress.Y,
                                                              true /*setAnchorCellAddress*/, 
                                                              false /*validateCurrentCell*/,
                                                              false /*throughMouseClick*/, 
                                                              true /*clearSelection*/, 
                                                              false /*forceCurrentCellSelection (unused)*/);
                Debug.Assert(success); 
            }
        }

        private static DataGridViewAutoSizeRowMode MapAutoSizeRowsModeToRowMode(DataGridViewAutoSizeRowsMode autoSizeRowsMode) 
        {
            switch (autoSizeRowsMode) 
            { 
                case DataGridViewAutoSizeRowsMode.AllHeaders:
                    return DataGridViewAutoSizeRowMode.RowHeader; 
                case DataGridViewAutoSizeRowsMode.DisplayedHeaders:
                    return DataGridViewAutoSizeRowMode.RowHeader;
                case DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders:
                    return DataGridViewAutoSizeRowMode.AllCellsExceptHeader; 
                case DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders:
                    return DataGridViewAutoSizeRowMode.AllCellsExceptHeader; 
                case DataGridViewAutoSizeRowsMode.AllCells: 
                    return DataGridViewAutoSizeRowMode.AllCells;
                case DataGridViewAutoSizeRowsMode.DisplayedCells: 
                    return DataGridViewAutoSizeRowMode.AllCells;
                default:
                    Debug.Fail("Unexpected autoSizeRowsMode value in MapAutoSizeRowsModeToRowMode");
                    return DataGridViewAutoSizeRowMode.RowHeader; 
            }
        } 
 
        private void MoveColumnHeadersOrRowResize(MouseEventArgs e)
        { 
            this.lastRowSplitBar = this.currentRowSplitBar;
            this.currentRowSplitBar = e.Y;
            Rectangle lastSplitBarRect = CalcRowResizeFeedbackRect(this.lastRowSplitBar);
            if (this.editingControl != null && 
                !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] &&
                this.editingPanel.Bounds.IntersectsWith(lastSplitBarRect)) 
            { 
                this.editingPanel.Invalidate();
                this.editingPanel.Update(); 
                this.editingControl.Invalidate();
                this.editingControl.Update();
            }
            Invalidate(lastSplitBarRect); 
            Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar));
        } 
 
        private void MapDataGridViewColumnToDataBoundField(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(this.DataSource != null, "this method should only be called when we have a data connection");
            Debug.Assert(dataGridViewColumn.DataPropertyName.Length != 0, "this method should be called only for columns which have DataPropertyName set");
            DataGridViewDataConnection conn = this.DataConnection;
 
            int boundColumnIndex = ((conn == null) ? -1 : conn.BoundColumnIndex(dataGridViewColumn.DataPropertyName));
            if (boundColumnIndex != -1) 
            { 
                dataGridViewColumn.IsDataBoundInternal = true;
                dataGridViewColumn.BoundColumnIndex = boundColumnIndex; 
                dataGridViewColumn.BoundColumnConverter = conn.BoundColumnConverter(boundColumnIndex);
                dataGridViewColumn.ValueType = conn.BoundColumnValueType(boundColumnIndex);
                dataGridViewColumn.ReadOnly = conn.DataFieldIsReadOnly(dataGridViewColumn.BoundColumnIndex) || dataGridViewColumn.ReadOnly;
                InvalidateColumnInternal(dataGridViewColumn.Index); 

                // Set the Sorting information on the data grid view according to the new DataPropertyName. 
                // RefreshColumns() has its own routine for setting the Sorting information so don't do this step 
                // if we are in RefreshColumns();
                if (dataGridViewColumn.SortMode != DataGridViewColumnSortMode.NotSortable && 
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns])
                {
                    dataGridViewColumn.HeaderCell.SortGlyphDirection = conn.BoundColumnSortOrder(boundColumnIndex);
                    if (this.sortedColumn == null && dataGridViewColumn.HeaderCell.SortGlyphDirection != SortOrder.None) 
                    {
                        this.sortedColumn = dataGridViewColumn; 
                        this.sortOrder = dataGridViewColumn.HeaderCell.SortGlyphDirection; 
                        // no need to sort because the back end is already sorted....
                    } 
                }
            }
            else
            { 
                dataGridViewColumn.IsDataBoundInternal = false;
                dataGridViewColumn.BoundColumnIndex = -1; 
                dataGridViewColumn.BoundColumnConverter = null; 
                InvalidateColumnInternal(dataGridViewColumn.Index);
            } 
        }

        private void MoveColumnRelocation(MouseEventArgs e, HitTestInfo hti)
        { 
            this.lastHeaderShadow = e.X;
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = ColumnRelocationTarget(e, hti, out this.trackColumnEdge); 
            Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders)); 
        }
 
        private void MoveRowHeadersOrColumnResize(MouseEventArgs e)
        {
            this.lastColSplitBar = this.currentColSplitBar;
            this.currentColSplitBar = e.X; 
            Rectangle lastSplitBarRect = CalcColResizeFeedbackRect(this.lastColSplitBar);
            if (this.editingControl != null && 
                !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] && 
                this.editingPanel.Bounds.IntersectsWith(lastSplitBarRect))
            { 
                this.editingPanel.Invalidate();
                this.editingPanel.Update();
                this.editingControl.Invalidate();
                this.editingControl.Update(); 
            }
            Invalidate(lastSplitBarRect); 
            Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar)); 
        }
 
        /// 
        public virtual void NotifyCurrentCellDirty(bool dirty)
        {
            Debug.Assert(this.ptCurrentCell.X >= 0 && this.ptCurrentCell.X < this.Columns.Count); 
            Debug.Assert(this.ptCurrentCell.Y >= 0 && this.ptCurrentCell.Y < this.Rows.Count);
 
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] == false) 
            {
                // autosizing has no effect since edited value hasn't been committed 
                // and autosizing code only looks at committed values.

                this.IsCurrentCellDirtyInternal = dirty;
                if (dirty && this.editingControl != null && ((IDataGridViewEditingControl) this.editingControl).RepositionEditingControlOnValueChange) 
                {
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); 
                } 
            }
        } 

        internal void OnAddedColumn(DataGridViewColumn dataGridViewColumn)
        {
            Debug.Assert(dataGridViewColumn.Index >= 0); 
            Debug.Assert(dataGridViewColumn.Index < this.Columns.Count);
            Debug.Assert(dataGridViewColumn.DataGridView == this); 
 
            if (dataGridViewColumn.DisplayIndex == -1 || dataGridViewColumn.DisplayIndex >= this.Columns.Count)
            { 
                // Developer did not assign a DisplayIndex or picked a large number.
                // Choose the Index as the DisplayIndex.
                dataGridViewColumn.DisplayIndexInternal = dataGridViewColumn.Index;
            } 

            CorrectColumnDisplayIndexesAfterInsertion(dataGridViewColumn); 
 
            if (dataGridViewColumn.HasHeaderCell)
            { 
                dataGridViewColumn.HeaderCell.DataGridViewInternal = this;
            }

            AdjustExpandingRows(dataGridViewColumn.Index, false /*fixedWidth*/); 
            DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode;
            Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); 
            bool fixedColumnWidth = autoSizeColumnMode == DataGridViewAutoSizeColumnMode.None || 
                                    autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill;
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth);
            }
 
            if (!fixedColumnWidth)
            { 
                // This is the first time the column autosizes. Save current column width for later reuse. 
                dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness;
                AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/); 

                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                {
                    // Second round of column headers autosizing 
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
                } 
            } 

            // Raise the ColumnAdded event 
            OnColumnAdded(new DataGridViewColumnEventArgs(dataGridViewColumn));
        }

        internal void OnAddedRow_PreNotification(int rowIndex) 
        {
            Debug.Assert(rowIndex >= 0); 
 
            if (this.AllowUserToAddRowsInternal && this.newRowIndex == -1)
            { 
                // The added row is necessarily the 'new row'
                // Set the this.newRowIndex variable as early as possible.
                Debug.Assert(rowIndex == this.Rows.Count - 1);
                this.newRowIndex = rowIndex; 
            }
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 

#if DEBUG 
            DataGridViewRow dataGridViewRowDebug = this.Rows.SharedRow(rowIndex);
            foreach (DataGridViewCell dataGridViewCell in dataGridViewRowDebug.Cells)
            {
                Debug.Assert(!dataGridViewCell.Selected); 
                Debug.Assert(dataGridViewRowDebug.Index != -1 || !dataGridViewCell.HasValue);
            } 
#endif 

            // Update this.individualReadOnlyCells 
            if ((rowState & DataGridViewElementStates.ReadOnly) == 0 &&
                !this.ReadOnly)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); 
                foreach (DataGridViewCell dataGridViewCell in dataGridViewRow.Cells)
                { 
                    if (!dataGridViewCell.OwningColumn.ReadOnly && IsSharedCellReadOnly(dataGridViewCell, rowIndex)) 
                    {
                        this.individualReadOnlyCells.Add(dataGridViewCell); 
                    }
                }
            }
        } 

        internal void OnAddedRow_PostNotification(int rowIndex) 
        { 
            Debug.Assert(rowIndex >= 0);
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);

            if ((rowState & DataGridViewElementStates.Visible) != 0)
            { 
                bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0;
 
                DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode; 

                bool autoSizeRow = false; 
                // Auto size row if needed
                if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None &&
                    !((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed))
                { 
                    // this call may unshare the row.
                    int rowHeight = this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); 
                    this.Rows.SharedRow(rowIndex).CachedThickness = rowHeight; 
                    AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/);
                    autoSizeRow = true; 
                }

                // Auto size columms also if needed
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; 
                if (rowDisplayed)
                { 
                    autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; 
                }
                bool columnAutoSized; 
                if (this.Rows.GetRowCount(DataGridViewElementStates.Visible) > 1)
                {
                    // Columns can only expand, and not collapse.
                    columnAutoSized = AdjustExpandingColumns(autoSizeColumnCriteriaFilter, rowIndex); 
                }
                else 
                { 
                    columnAutoSized = AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/);
                } 
                bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize;
                bool rowHeadersAutoSize = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                                          this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing;
 
                if (!rowHeadersAutoSize && !columnAutoSized)
                { 
                    // No need to autosize the column headers when the row headers and columns don't change. 
                    fixedColumnHeadersHeight = true;
                } 

                // Auto size row headers
                if (rowHeadersAutoSize)
                { 
                    AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, fixedColumnHeadersHeight, true /*fixedRowsHeight*/);
                } 
 
                // Auto size column headers
                if (!fixedColumnHeadersHeight) 
                {
                    AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
                }
 
                if (autoSizeRow)
                { 
                    // Second round of row autosizing 
                    AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/);
                } 

                if (rowHeadersAutoSize && !fixedColumnHeadersHeight)
                {
                    // Second round of row headers autosizing 
                    AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
                } 
            } 
        }
 
        internal void OnAddedRows_PreNotification(DataGridViewRow[] dataGridViewRows)
        {
            // Note: no row can be added that breaks the frozen row packing on the top
 
            foreach(DataGridViewRow dataGridViewRow in dataGridViewRows)
            { 
                OnAddedRow_PreNotification(dataGridViewRow.Index); 
            }
        } 

        internal void OnAddedRows_PostNotification(DataGridViewRow[] dataGridViewRows)
        {
            foreach (DataGridViewRow dataGridViewRow in dataGridViewRows) 
            {
                OnAddedRow_PostNotification(dataGridViewRow.Index); 
            } 
        }
 
        internal void OnAddingColumn(DataGridViewColumn dataGridViewColumn)
        {
            // throw an exception if the column to be added breaks the rules
            if (dataGridViewColumn == null) 
            {
                throw new ArgumentNullException("dataGridViewColumn"); 
            } 
            if (dataGridViewColumn.DataGridView != null)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView));
            }

            if (!this.InInitialization && 
                dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic &&
                (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || 
                 this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString())); 
            }

            if (dataGridViewColumn.Visible)
            { 
                // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used
 
                // Make sure the column does not autosize based only on header while column headers are invisible 
                if (!this.ColumnHeadersVisible &&
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader))) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn));
                }
 
                // Make sure the column is not frozen and auto fills
                if (dataGridViewColumn.Frozen && 
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill))) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn)); 
                }

                // UsedFillWeight values need to be updated
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; 
            }
 
            // Make sure the sum of the column weights does not exceed ushort.MaxValue 
            float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) + dataGridViewColumn.FillWeight;
            if (weightSum > (float)ushort.MaxValue) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture)));
            }
 
            // check for correctness of frozen state - throws exception if state is incorrect.
            CorrectColumnFrozenState(dataGridViewColumn, this.Columns.Count); 
 
            // prepare the existing rows by appending cells of correct type
            if (this.Rows.Count > 0) 
            {
                // Only require a default cell type when there are rows to fill
                if (dataGridViewColumn.CellType == null)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn));
                } 
 
                if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1)
                { 
                    // New row needs to be unshared before addition of new cell with a Value != null
                    DataGridViewRow newRow = this.Rows[this.newRowIndex];
                }
 
                int newColumnCount = this.Columns.Count + 1;
 
                try 
                {
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) 
                    {
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        if (dataGridViewRow.Cells.Count < newColumnCount)
                        { 
                            DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone();
                            dataGridViewRow.Cells.AddInternal(dataGridViewCellNew); 
                            if (rowIndex == this.newRowIndex) 
                            {
                                dataGridViewCellNew.SetValueInternal(rowIndex, dataGridViewCellNew.DefaultNewRowValue); 
                            }
                            dataGridViewCellNew.DataGridViewInternal = this;
                            dataGridViewCellNew.OwningRowInternal = dataGridViewRow;
                            dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn; 
                        }
                    } 
                } 
                catch
                { 
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
                    {
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        if (dataGridViewRow.Cells.Count == newColumnCount) 
                        {
                            dataGridViewRow.Cells.RemoveAtInternal(newColumnCount - 1); 
                        } 
                        else
                        { 
                            Debug.Assert(dataGridViewRow.Cells.Count < newColumnCount);
                            break;
                        }
                    } 
                    throw;
                } 
            } 
        }
 
        [
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // not legitimate
        ]
        internal void OnAddingColumns(DataGridViewColumn[] dataGridViewColumns) 
        {
            // Make sure the sum of the column weights does not exceed ushort.MaxValue 
            float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None); 
            Debug.Assert(weightSum <= (float)ushort.MaxValue);
 
            // throw an exception if any of the columns to be added breaks the rules
            Debug.Assert(dataGridViewColumns != null);
            foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns)
            { 
                if (dataGridViewColumn == null)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_AtLeastOneColumnIsNull)); 
                }
                if (dataGridViewColumn.DataGridView != null) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView));
                }
                // Only require a default cell type when there are rows to fill 
                if (this.Rows.Count > 0 && dataGridViewColumn.CellType == null)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn)); 
                }
 
                if (!this.InInitialization &&
                    dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic &&
                    (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect ||
                     this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString())); 
                } 

                if (dataGridViewColumn.Visible) 
                {
                    // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used

                    // Make sure the column does not autosize based only on header while column headers are invisible 
                    if (!this.ColumnHeadersVisible &&
                        (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader))) 
                    { 
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn));
                    } 

                    // Make sure the column is not frozen and auto fills
                    if (dataGridViewColumn.Frozen &&
                        (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill))) 
                    {
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn)); 
                    } 

                    // UsedFillWeight values need to be updated 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
                }

                weightSum += dataGridViewColumn.FillWeight; 
                if (weightSum > (float)ushort.MaxValue)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); 
                }
            } 

            Debug.Assert(weightSum <= (float)ushort.MaxValue);

            // make sure no two columns are identical 
            int columnCount = dataGridViewColumns.Length;
            for (int column1 = 0; column1 < columnCount - 1; column1++) 
            { 
                for (int column2 = column1 + 1; column2 < columnCount; column2++)
                { 
                    if (dataGridViewColumns[column1] == dataGridViewColumns[column2])
                    {
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddIdenticalColumns));
                    } 
                }
            } 
 
            // check for correctness of frozen states - throws exception if any state is incorrect.
            CorrectColumnFrozenStates(dataGridViewColumns); 

            // prepare the existing rows by appending cells of correct type
            if (this.Rows.Count > 0)
            { 
                foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns)
                { 
                    Debug.Assert(dataGridViewColumn.CellType != null); 
                    if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1)
                    { 
                        // New row needs to be unshared before addition of new cell with a Value != null
                        DataGridViewRow newRow = this.Rows[this.newRowIndex];
                        break;
                    } 
                }
 
                int previousColumnCount = this.Columns.Count; 
                int addedColumnCount = 0;
 
                try
                {
                    foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns)
                    { 
                        addedColumnCount++;
                        Debug.Assert(dataGridViewColumn.CellType != null); 
                        for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) 
                        {
                            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); 
                            if (dataGridViewRow.Cells.Count < previousColumnCount + addedColumnCount)
                            {
                                DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone();
                                int indexCell = dataGridViewRow.Cells.AddInternal(dataGridViewCellNew); 
                                if (rowIndex == this.newRowIndex)
                                { 
                                    dataGridViewCellNew.Value = dataGridViewCellNew.DefaultNewRowValue; 
                                }
                                dataGridViewCellNew.DataGridViewInternal = this; 
                                dataGridViewCellNew.OwningRowInternal = dataGridViewRow;
                                dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn;
                            }
                        } 
                    }
                } 
                catch 
                {
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) 
                    {
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        while (dataGridViewRow.Cells.Count > previousColumnCount)
                        { 
                            dataGridViewRow.Cells.RemoveAtInternal(dataGridViewRow.Cells.Count - 1);
                        } 
                    } 
                    throw;
                } 
            }
        }

        internal void OnAddingRow(DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, bool checkFrozenState) 
        {
            // Note dataGridViewRow.DataGridView != null for duplication of shared rows. 
 
            // throw an exception if the row to be added breaks the rules
            if (dataGridViewRow == null) 
            {
                throw new ArgumentNullException("dataGridViewRow");
            }
 
            // !Do not check for dataGridViewRow.Selected flag. Caller does it instead!
            // !Do not check for dataGridViewRow.DataGridView != null. Caller does it instead! 
 
            if (checkFrozenState)
            { 
                // check for correctness of frozen state - throws exception if state is incorrect.
                CorrectRowFrozenState(dataGridViewRow, rowState, this.Rows.Count);
            }
 
            if (this.ReadOnly && dataGridViewRow.DataGridView == null && dataGridViewRow.ReadOnly)
            { 
                // Clear the superfluous flag since the whole dataGridView is read-only 
                dataGridViewRow.ReadOnly = false;
            } 

            int columnIndex = 0;
            foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
            { 
                DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex];
                if ((this.ReadOnly || dataGridViewColumn.ReadOnly) && dataGridViewCell.StateIncludes(DataGridViewElementStates.ReadOnly)) 
                { 
                    // Clear superfluous flag since the whole dataGridView or column is ReadOnly
                    dataGridViewCell.ReadOnlyInternal = false; 
                }
                columnIndex++;
            }
        } 

        internal void OnAddingRows(DataGridViewRow[] dataGridViewRows, bool checkFrozenStates) 
        { 
            // throw an exception if any of the rows to be added breaks the rules
            Debug.Assert(dataGridViewRows != null); 

            foreach (DataGridViewRow dataGridViewRow in dataGridViewRows)
            {
                if (dataGridViewRow == null) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_AtLeastOneRowIsNull)); 
                } 

                if (dataGridViewRow.DataGridView != null) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_RowAlreadyBelongsToDataGridView));
                }
 
                if (dataGridViewRow.Selected)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridViewRowCollection_CannotAddOrInsertSelectedRow)); 
                }
 
                if (dataGridViewRow.Cells.Count > this.Columns.Count)
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridViewRowCollection_TooManyCells));
                } 
            }
 
            // make sure no two rows are identical 
            int rowCount = dataGridViewRows.Length;
            for (int row1 = 0; row1 < rowCount - 1; row1++) 
            {
                for (int row2 = row1 + 1; row2 < rowCount; row2++)
                {
                    if (dataGridViewRows[row1] == dataGridViewRows[row2]) 
                    {
                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddIdenticalRows)); 
                    } 
                }
            } 

            if (checkFrozenStates)
            {
                Debug.Assert(!this.AllowUserToAddRowsInternal); 
                CorrectRowFrozenStates(dataGridViewRows, this.Rows.Count /*rowIndexInserted*/);
            } 
 
            foreach (DataGridViewRow dataGridViewRow in dataGridViewRows)
            { 
                CompleteCellsCollection(dataGridViewRow);
                OnAddingRow(dataGridViewRow, dataGridViewRow.State, false /*checkFrozenState*/);
            }
        } 

        internal void OnAdvancedBorderStyleChanged(DataGridViewAdvancedBorderStyle dgvabs) 
        { 
            if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inBorderStyleChange])
            { 
                if (dgvabs == this.advancedCellBorderStyle)
                {
                    OnCellBorderStyleChanged(EventArgs.Empty);
                } 
                else if (dgvabs == this.advancedColumnHeadersBorderStyle)
                { 
                    OnColumnHeadersBorderStyleChanged(EventArgs.Empty); 
                }
                else if (dgvabs == this.advancedRowHeadersBorderStyle) 
                {
                    OnRowHeadersBorderStyleChanged(EventArgs.Empty);
                }
            } 
        }
 
        ///  
        protected virtual void OnAllowUserToAddRowsChanged(EventArgs e)
        { 
            PushAllowUserToAddRows();

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTOADDROWSCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnAllowUserToDeleteRowsChanged(EventArgs e)
        {
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTODELETEROWSCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnAllowUserToOrderColumnsChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTOORDERCOLUMNSCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnAllowUserToResizeColumnsChanged(EventArgs e) 
        {
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTORESIZECOLUMNSCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnAllowUserToResizeRowsChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTORESIZEROWSCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        /// 
        protected virtual void OnAlternatingRowsDefaultCellStyleChanged(EventArgs e) 
        { 
            DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
            if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize) 
            {
                InvalidateData();
            }
            else 
            {
                OnRowsGlobalAutoSize(); 
                if (this.editingControl != null) 
                {
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); 
                }
            }

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALTERNATINGROWSDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnAutoGenerateColumnsChanged(EventArgs e)
        { 
            if (this.AutoGenerateColumns && this.DataSource != null)
            { 
                // refresh the list of columns and the rows 
                RefreshColumnsAndRows();
            } 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOGENERATECOLUMNSCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        internal void OnAutoSizeColumnModeChanged(DataGridViewColumn dataGridViewColumn, DataGridViewAutoSizeColumnMode previousInheritedMode)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewAutoSizeColumnModeEventArgs dgvascme = new DataGridViewAutoSizeColumnModeEventArgs(dataGridViewColumn, previousInheritedMode);
            OnAutoSizeColumnModeChanged(dgvascme);
        } 

        ///  
        protected virtual void OnAutoSizeColumnModeChanged(DataGridViewAutoSizeColumnModeEventArgs e) 
        {
            DataGridViewColumn dataGridViewColumn = e.Column; 
            if (e.Column == null)
            {
                throw new InvalidOperationException(SR.GetString(SR.InvalidNullArgument, "e.Column"));
            } 
            DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode;
            Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); 
 
            DataGridViewAutoSizeColumnMode previousInheritedMode = e.PreviousMode;
            bool previousInheritedModeAutoSized = previousInheritedMode != DataGridViewAutoSizeColumnMode.Fill && 
                                                  previousInheritedMode != DataGridViewAutoSizeColumnMode.None &&
                                                  previousInheritedMode != DataGridViewAutoSizeColumnMode.NotSet;

            if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill || 
                previousInheritedMode == DataGridViewAutoSizeColumnMode.Fill)
            { 
                // UsedFillWeight values need to be updated 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
            } 

            bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0;

            if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None) 
            {
                if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                { 
                    if (!previousInheritedModeAutoSized)
                    { 
                        // Save current column width for later reuse
                        dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness;
                    }
                    AutoResizeColumnInternal(dataGridViewColumn.Index, 
                                             (DataGridViewAutoSizeColumnCriteriaInternal) autoSizeColumnMode,
                                             fixedHeight); 
                } 
            }
            else if (dataGridViewColumn.Thickness != dataGridViewColumn.CachedThickness && previousInheritedModeAutoSized) 
            {
                // Restoring cached column width
                dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness);
            } 

            // Auto fill columns if needed 
            PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 

            // Autosize rows and column headers if needed 
            if (!fixedHeight)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                {
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                } 

                // Column gets autosized with 1 degree of freedom this time. 
                if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill)
                {
                    AutoResizeColumnInternal(dataGridViewColumn.Index,
                                             (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, 
                                             true /*fixedHeight*/);
                } 
            } 

            DataGridViewAutoSizeColumnModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZECOLUMNMODECHANGED] as DataGridViewAutoSizeColumnModeEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.PreviousModes is more precise than just e
        protected virtual void OnAutoSizeColumnsModeChanged(DataGridViewAutoSizeColumnsModeEventArgs e) 
        {
            DataGridViewAutoSizeColumnMode[] previousModes = e.PreviousModes;
            if (previousModes == null)
            { 
                throw new ArgumentNullException("e.PreviousModes");
            } 
            if (previousModes.Length != this.Columns.Count) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_PreviousModesHasWrongLength)); 
            }

            foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
            { 
                if (dataGridViewColumn.Visible)
                { 
                    DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; 
                    Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet);
                    DataGridViewAutoSizeColumnMode previousInheritedMode = previousModes[dataGridViewColumn.Index]; 
                    bool previousInheritedModeAutoSized = previousInheritedMode != DataGridViewAutoSizeColumnMode.Fill &&
                                                          previousInheritedMode != DataGridViewAutoSizeColumnMode.None &&
                                                          previousInheritedMode != DataGridViewAutoSizeColumnMode.NotSet;
                    if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill || 
                        previousInheritedMode == DataGridViewAutoSizeColumnMode.Fill)
                    { 
                        // UsedFillWeight values need to be updated 
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
                    } 

                    if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None)
                    {
                        if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                        {
                            if (!previousInheritedModeAutoSized) 
                            { 
                                // Save current column width for later reuse
                                dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness; 
                            }
                            AutoResizeColumnInternal(dataGridViewColumn.Index,
                                                     (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode,
                                                     (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0 /*fixedHeight*/); 
                        }
                    } 
                    else if (dataGridViewColumn.Thickness != dataGridViewColumn.CachedThickness && previousInheritedModeAutoSized) 
                    {
                        // Restoring cached column width 
                        dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness);
                    }
                }
            } 

            // Auto fill columns if needed 
            PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 

            // Autosize rows and column headers if needed 
            if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                {
                    AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                } 

                // Second pass of column autosizing with 1 degree of freedom 
                foreach (DataGridViewColumn dataGridViewColumn in this.Columns)
                {
                    DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode;
                    Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); 

                    if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                    { 
                        AutoResizeColumnInternal(dataGridViewColumn.Index,
                                                 (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, 
                                                 true /*fixedHeight*/);
                    }
                }
            } 

            DataGridViewAutoSizeColumnsModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZECOLUMNSMODECHANGED] as DataGridViewAutoSizeColumnsModeEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnAutoSizeRowsModeChanged(DataGridViewAutoSizeModeEventArgs e)
        { 
            if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) 
            {
                // restore cached rows thickness 
                RestoreRowsCachedThickness();
            }
            else
            { 
                if (!e.PreviousModeAutoSized)
                { 
                    // Save the rows thickness for later reuse 
                    // Note that only visible rows are affected, contrary to columns in OnAutoSizeColumnsModeChanged where all columns are affected.
                    for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                        rowIndex != -1;
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                    {
                        // this call may unshare the row. 
                        int rowHeight = this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                        this.Rows.SharedRow(rowIndex).CachedThickness = rowHeight; 
                    } 
                }
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }

            DataGridViewAutoSizeModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZEROWSMODECHANGED] as DataGridViewAutoSizeModeEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnBackgroundColorChanged(EventArgs e)
        {
            InvalidateInside(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWBACKGROUNDCOLORCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnBandContextMenuStripChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnContextMenuStripChanged(dgvce);
            }
            else
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowContextMenuStripChanged(dgvre); 
            } 
        }
 
        internal void OnBandDefaultCellStyleChanged(DataGridViewBand dataGridViewBand)
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn;
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnDefaultCellStyleChanged(dgvce); 
            }
            else 
            {
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowDefaultCellStyleChanged(dgvre);
            } 
        }
 
        internal void OnBandDividerThicknessChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null)
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn);
                OnColumnDividerWidthChanged(dgvce); 
            }
            else 
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowDividerHeightChanged(dgvre); 
            }
        }

        internal void OnBandHeaderCellChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnHeaderCellChanged(dgvce);
            }
            else
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowHeaderCellChanged(dgvre); 
            } 
        }
 
        internal void OnBandMinimumThicknessChanged(DataGridViewBand dataGridViewBand)
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn;
            if (dataGridViewColumn != null) 
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
                OnColumnMinimumWidthChanged(dgvce); 
            }
            else 
            {
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowMinimumHeightChanged(dgvre);
            } 
        }
 
        internal void OnBandThicknessChanged(DataGridViewBand dataGridViewBand) 
        {
            DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; 
            if (dataGridViewColumn != null)
            {
                DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn);
                OnColumnWidthChanged(dgvce); 
            }
            else 
            { 
                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand);
                OnRowHeightChanged(dgvre); 
            }
        }

        internal void OnBandThicknessChanging() 
        {
            if (this.InAdjustFillingColumns) 
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter));
            } 
        }

        /// 
        protected override void OnBindingContextChanged(EventArgs e) 
        {
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged]) 
            { 
                return;
            } 

            this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged] = true;
            try
            { 
                if (this.dataConnection != null)
                { 
                    this.CurrentCell = null; 
                    try
                    { 
                        this.dataConnection.SetDataConnection(this.DataSource, this.DataMember);
                    }
                    catch (ArgumentException)
                    { 
                        if (this.DesignMode)
                        { 
                            // This is the minimal fix for vsw 527646. 
                            // If the DataMember became invalid at DesignTime then set it to String.Empty,
                            // regenerate the column collection and DO NOT send BindingContextChanged event. 
                            this.DataMember = String.Empty;
                            RefreshColumnsAndRows();
                            return;
                        } 
                        else
                        { 
                            throw; 
                        }
                    } 
                    RefreshColumnsAndRows();
                    base.OnBindingContextChanged(e);
                    if (this.dataConnection.CurrencyManager != null)
                    { 
                        OnDataBindingComplete(ListChangedType.Reset);
                    } 
                } 
                else
                { 
                    base.OnBindingContextChanged(e);
                }
            }
            finally 
            {
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged] = false; 
            } 
        }
 
        /// 
        protected virtual void OnBorderStyleChanged(EventArgs e)
        {
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWBORDERSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnCancelRowEdit(QuestionEventArgs e)
        { 
            QuestionEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCANCELROWEDIT] as QuestionEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
                CorrectFocus(true /*onlyIfGridHasFocus*/); 
            }
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellBeginEdit(DataGridViewCellCancelEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLBEGINEDIT] as DataGridViewCellCancelEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        /// 
        protected virtual void OnCellBorderStyleChanged(EventArgs e) 
        { 
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            Invalidate(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLBORDERSTYLECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        internal void OnCellClickInternal(DataGridViewCellEventArgs e) 
        {
            OnCellClick(e);
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellClick(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            } 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null); 
            if (e.RowIndex >= 0 && dataGridViewCell.ClickUnsharesRowInternal(e))
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnClickInternal(e); 
            }
            else 
            { 
                dataGridViewCell.OnClickInternal(e);
            } 

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCLICK] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        internal void OnCellCommonChange(int columnIndex, int rowIndex) 
        {
            if (columnIndex == -1)
            {
                // row or topleft header characteristic has changed 
                OnRowHeaderGlobalAutoSize(rowIndex);
            } 
            else 
            {
                if (rowIndex == -1) 
                {
                    // column header characteristic has changed
                    OnColumnHeaderGlobalAutoSize(columnIndex);
                } 
                else
                { 
                    // regular cell characteristic changed 
                    InvalidateCellPrivate(columnIndex, rowIndex);
 
                    bool rowDisplayed = false;
                    if (rowIndex != -1)
                    {
                        rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0; 
                    }
 
                    DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode; 
                    bool autoSizeColumn = (autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.AllRows) != 0;
                    if (rowDisplayed) 
                    {
                        autoSizeColumn |= (autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows) != 0;
                    }
 
                    bool autoSizeRow = (((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0;
                    if (autoSizeRow) 
                    { 
                        AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), !autoSizeColumn /*fixedWidth*/, true /*internalAutosizing*/);
                    } 
                    if (autoSizeColumn)
                    {
                        AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/);
                        if (autoSizeRow) 
                        {
                            // Second round of row autosizing with 1 degree of freedom. 
                            AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
                        }
                    } 
                }
            }
        }
 
        internal void OnCellContentClickInternal(DataGridViewCellEventArgs e)
        { 
            OnCellContentClick(e); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContentClick(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.ContentClickUnsharesRowInternal(e)) 
            { 
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnContentClickInternal(e); 
            }
            else
            {
                dataGridViewCell.OnContentClickInternal(e); 
            }
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTENTCLICK] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnCellContentDoubleClickInternal(DataGridViewCellEventArgs e)
        { 
            OnCellContentDoubleClick(e); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContentDoubleClick(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.ContentDoubleClickUnsharesRowInternal(e)) 
            { 
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnContentDoubleClickInternal(e); 
            }
            else
            {
                dataGridViewCell.OnContentDoubleClickInternal(e); 
            }
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTENTDOUBLECLICK] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnCellContextMenuStripChanged(DataGridViewCell dataGridViewCell)
        { 
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); 
            OnCellContextMenuStripChanged(dgvce);
        } 

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContextMenuStripChanged(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTEXTMENUSTRIPCHANGED] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        internal ContextMenuStrip OnCellContextMenuStripNeeded(int columnIndex, int rowIndex, ContextMenuStrip contextMenuStrip)
        { 
            DataGridViewCellContextMenuStripNeededEventArgs dgvccmsne = new DataGridViewCellContextMenuStripNeededEventArgs(columnIndex, rowIndex, contextMenuStrip);
            OnCellContextMenuStripNeeded(dgvccmsne); 
            return dgvccmsne.ContextMenuStrip; 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellContextMenuStripNeeded(DataGridViewCellContextMenuStripNeededEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellContextMenuStripNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTEXTMENUSTRIPNEEDED] as DataGridViewCellContextMenuStripNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellDoubleClick(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null); 
            if (e.RowIndex >= 0 && dataGridViewCell.DoubleClickUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnDoubleClickInternal(e);
            }
            else
            { 
                dataGridViewCell.OnDoubleClickInternal(e);
            } 
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLDOUBLECLICK] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellEndEdit(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLENDEDIT] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnCellEnter(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) 
        {
            OnCellEnter(new DataGridViewCellEventArgs(columnIndex, rowIndex)); 
            if (dataGridViewCell != null)
            {
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    dataGridViewCell = null;
                } 
                else 
                {
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); 
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                }
            }
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellEnter(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            try 
            {
                this.noDimensionChangeCount++;

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLENTER] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e); 
                }
            } 
            finally
            {
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0); 
            }
        } 
 
        internal void OnCellErrorTextChanged(DataGridViewCell dataGridViewCell)
        { 
            Debug.Assert(dataGridViewCell.RowIndex >= -1);
            Debug.Assert(dataGridViewCell.ColumnIndex >= -1);
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell);
            OnCellErrorTextChanged(dgvce); 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellErrorTextChanged(DataGridViewCellEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            UpdateCellErrorText(e.ColumnIndex, e.RowIndex);

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLERRORTEXTCHANGED] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        internal string OnCellErrorTextNeeded(int columnIndex, int rowIndex, string errorText)
        {
            Debug.Assert(columnIndex >= 0);
            Debug.Assert(rowIndex >= 0); 
            DataGridViewCellErrorTextNeededEventArgs dgvcetne = new DataGridViewCellErrorTextNeededEventArgs(columnIndex, rowIndex, errorText);
            OnCellErrorTextNeeded(dgvcetne); 
            return dgvcetne.ErrorText; 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellErrorTextNeeded(DataGridViewCellErrorTextNeededEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellErrorTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLERRORTEXTNEEDED] as DataGridViewCellErrorTextNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        internal DataGridViewCellFormattingEventArgs OnCellFormatting(int columnIndex, int rowIndex, object val, Type formattedValueType, DataGridViewCellStyle cellStyle)
        {
            DataGridViewCellFormattingEventArgs dgvcfe = new DataGridViewCellFormattingEventArgs(columnIndex, 
                                                                                                 rowIndex,
                                                                                                 val, 
                                                                                                 formattedValueType, 
                                                                                                 cellStyle);
            OnCellFormatting(dgvcfe); 
            return dgvcfe;
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellFormatting(DataGridViewCellFormattingEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellFormattingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLFORMATTING] as DataGridViewCellFormattingEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnCellLeave(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        { 
            OnCellLeave(new DataGridViewCellEventArgs(columnIndex, rowIndex)); 
            if (dataGridViewCell != null)
            { 
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                {
                    dataGridViewCell = null;
                } 
                else
                { 
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); 
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                } 
            }
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellLeave(DataGridViewCellEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            try 
            {
                this.noDimensionChangeCount++; 

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLLEAVE] as DataGridViewCellEventHandler;
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e);
                } 
            } 
            finally
            { 
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0);
            }
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseClick(DataGridViewCellMouseEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseClickUnsharesRowInternal(e))
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseClickInternal(e);
            } 
            else 
            {
                dataGridViewCell.OnMouseClickInternal(e); 
            }
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble] = false;

            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellMouseDoubleClick(DataGridViewCellMouseEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null); 
            if (e.RowIndex >= 0 && dataGridViewCell.MouseDoubleClickUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseDoubleClickInternal(e);
            }
            else
            { 
                dataGridViewCell.OnMouseDoubleClickInternal(e);
            } 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble] = true; 

            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellMouseDown(DataGridViewCellMouseEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 

            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null);
 
            // Only left clicks for now
            Keys nModifier = ModifierKeys; 
            bool isControlDown = (nModifier & Keys.Control) == Keys.Control && (nModifier & Keys.Alt) == 0; 
            bool isShiftDown = (nModifier & Keys.Shift) == Keys.Shift;
            bool isAltDown = (nModifier & Keys.Alt) == Keys.Alt; 

            Point ptGridCoord = ConvertCellToGridCoord(e.ColumnIndex, e.RowIndex, e.X, e.Y);

            HitTestInfo hti = HitTest(ptGridCoord.X, ptGridCoord.Y); 

            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && e.Button == MouseButtons.Left) 
            { 
                Debug.Assert(hti.Type != DataGridViewHitTestType.None &&
                             hti.Type != DataGridViewHitTestType.HorizontalScrollBar && 
                             hti.Type != DataGridViewHitTestType.VerticalScrollBar);
                Debug.Assert(this.ptMouseDownCell.X == hti.col);
                Debug.Assert(this.ptMouseDownCell.Y == hti.row);
 
                switch (hti.typeInternal)
                { 
                    // Check for column/row (headers) resize 
                    case DataGridViewHitTestTypeInternal.ColumnResizeLeft:
                    case DataGridViewHitTestTypeInternal.ColumnResizeRight: 
                    case DataGridViewHitTestTypeInternal.RowResizeBottom:
                    case DataGridViewHitTestTypeInternal.RowResizeTop:
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft:
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight: 
                    case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft:
                    case DataGridViewHitTestTypeInternal.RowHeadersResizeRight: 
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop: 
                    case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom:
                    case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: 
                    case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom:
                    {
                        this.dataGridViewOper[DATAGRIDVIEWOPER_resizingOperationAboutToStart] = (e.Clicks == 1);
                        break; 
                    }
                } 
            } 

            try 
            {
                if (e.RowIndex >= 0 && dataGridViewCell.MouseDownUnsharesRowInternal(e))
                {
                    DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                    GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseDownInternal(e);
                } 
                else 
                {
                    dataGridViewCell.OnMouseDownInternal(e); 
                }

                DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEDOWN] as DataGridViewCellMouseEventHandler;
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
                {
                    eh(this, e); 
                } 

                if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && e.Button == MouseButtons.Left) 
                {
                    switch (hti.typeInternal)
                    {
                        // Check column resize 
                        case DataGridViewHitTestTypeInternal.ColumnResizeLeft:
                        case DataGridViewHitTestTypeInternal.ColumnResizeRight: 
                        { 
                            int columnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight) ? hti.col : hti.adjacentCol;
                            Debug.Assert(this.Columns[columnIndex].Resizable == DataGridViewTriState.True); 
                            if (e.Clicks == 1)
                            {
                                BeginColumnResize(ptGridCoord.X, hti.mouseBarOffset, columnIndex);
                            } 
                            break;
                        } 
 
                        // Check row resize
                        case DataGridViewHitTestTypeInternal.RowResizeBottom: 
                        case DataGridViewHitTestTypeInternal.RowResizeTop:
                        {
                            int rowIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom) ? hti.row : hti.adjacentRow;
                            if (e.Clicks == 1) 
                            {
                                BeginRowResize(ptGridCoord.Y, hti.mouseBarOffset, rowIndex); 
                            } 
                            break;
                        } 

                        // Check for column header mouse down
                        case DataGridViewHitTestTypeInternal.ColumnHeader:
                        case DataGridViewHitTestTypeInternal.ColumnHeaderLeft: 
                        case DataGridViewHitTestTypeInternal.ColumnHeaderRight:
                        case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft: 
                        { 
                            if (isAltDown && this.AllowUserToOrderColumns &&
                                (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || 
                                 this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect))
                            {
                                BeginColumnRelocation(ptGridCoord.X, hti.col);
                            } 
                            else
                            { 
                                OnColumnHeaderMouseDown(hti, isShiftDown, isControlDown); 
                            }
                            break; 
                        }

                        // Check for row header mouse down
                        case DataGridViewHitTestTypeInternal.RowHeader: 
                        {
                            OnRowHeaderMouseDown(hti, isShiftDown, isControlDown); 
                            break; 
                        }
 
                        // Check for cell mouse down
                        case DataGridViewHitTestTypeInternal.Cell:
                        {
                            OnCellMouseDown(hti, isShiftDown, isControlDown); 
                            break;
                        } 
 
                        // Check for top/left header mouse down
                        case DataGridViewHitTestTypeInternal.TopLeftHeader: 
                        {
                            OnTopLeftHeaderMouseDown();
                            break;
                        } 

                        // Check for row headers resize 
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft: 
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight:
                        case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft: 
                        case DataGridViewHitTestTypeInternal.RowHeadersResizeRight:
                        {
                            if (e.Clicks == 1)
                            { 
                                BeginRowHeadersResize(ptGridCoord.X, hti.mouseBarOffset);
                            } 
                            break; 
                        }
 
                        // Check for column headers resize
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop:
                        case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom:
                        case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: 
                        case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom:
                        { 
                            if (e.Clicks == 1) 
                            {
                                BeginColumnHeadersResize(ptGridCoord.Y, hti.mouseBarOffset); 
                            }
                            break;
                        }
                    } 
                    // Make sure that there is a current cell after this mouse down event.
                    if (this.ptCurrentCell.X == -1) 
                    { 
                        MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/);
                    } 
                }
            }
            finally
            { 
                this.dataGridViewOper[DATAGRIDVIEWOPER_resizingOperationAboutToStart] = false;
            } 
        } 

        private void OnCellMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown) 
        {
            Debug.Assert(hti.Type == DataGridViewHitTestType.Cell);
            // Only commit cell if the target cell is different from the current one.
            if (this.ptCurrentCell.X >= 0 && 
                (this.ptCurrentCell.X != hti.col || this.ptCurrentCell.Y != hti.row))
            { 
                Point ptOriginalCurrentCell = this.ptCurrentCell; 
                if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit,
                    this.ptCurrentCell.X != hti.col || this.ptCurrentCell.Y != hti.row /*forCurrentCellChange*/, 
                    this.ptCurrentCell.Y != hti.row /*forCurrentRowChange*/))
                {
                    // Return silently if validating/commit/abort failed
                    return; 
                }
                if (this.ptCurrentCell != ptOriginalCurrentCell) 
                { 
                    // VSWhidbey 492203. Somehow the fact that the current cell was committed altered the current cell value.
                    // To avoid unintentional multi-selections, we act as if Shift and Control keys were up. 
                    isShiftDown = isControlDown = false;
                }
            }
 
            if (hti.col >= this.Columns.Count)
            { 
                DataGridViewColumn dataGridViewLastVisibleColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, 
                                                                                              DataGridViewElementStates.None);
                if (this.ptCurrentCell.X == -1 && dataGridViewLastVisibleColumn != null) 
                {
                    // CurrentCell was reset because CommitEdit deleted column(s).
                    // Since the user clicked on a cell, we don't want to end up
                    // with no CurrentCell. We pick the last visible column in the grid. 
                    hti.col = dataGridViewLastVisibleColumn.Index;
                } 
                else 
                {
                    return; 
                }
            }
            if (hti.row >= this.Rows.Count)
            { 
                int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                if (this.ptCurrentCell.X == -1 && lastVisibleRowIndex != -1) 
                { 
                    // CurrentCell was reset because CommitEdit deleted row(s).
                    // Since the user clicked on a 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'.
                    hti.row = lastVisibleRowIndex;
                } 
                else
                { 
                    return; 
                }
            } 

            bool select = true;
            this.noSelectionChangeCount++;
            try 
            {
                switch (this.SelectionMode) 
                { 
                    case DataGridViewSelectionMode.CellSelect:
                    { 
                        if (isControlDown &&
                            IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row) &&
                            (!isShiftDown || !this.MultiSelect))
                        { 
                            select = false;
                        } 
                        if (select) 
                        {
                            if ((!this.MultiSelect || !isControlDown) && !(this.MultiSelect && isShiftDown)) 
                            {
                                Debug.Assert(this.MultiSelect || this.individualSelectedCells.Count <= 1);
                                RemoveIndividuallySelectedCells(hti.col, hti.row);
                            } 
                            if (this.MultiSelect)
                            { 
                                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) 
                                {
                                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true; 
                                }
                                if (isShiftDown)
                                {
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    if (this.ptAnchorCell.X == -1) 
                                    { 
                                        return;
                                    } 
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col,
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row);
                                }
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, true); 
                                } 
                            }
                            else 
                            {
                                SetSelectedCellCore(hti.col, hti.row, true);
                            }
                        } 
                        else
                        { 
                            SetSelectedCellCore(hti.col, hti.row, false); 
                        }
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); 
                        Debug.Assert(success);
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                    { 
                        if (isControlDown && this.Columns[hti.col].Selected) 
                        {
                            select = false; 
                        }
                        if (select)
                        {
                            bool selectColumnRange = false; 
                            this.trackColumn = hti.col;
                            this.trackColumnEdge = -1; 
                            if (this.MultiSelect && 
                                isShiftDown &&
                                this.ptAnchorCell.X > -1 && 
                                this.Columns[this.ptAnchorCell.X].Selected)
                            {
                                selectColumnRange = true;
                            } 
                            if (!this.MultiSelect || !isControlDown || isShiftDown)
                            { 
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                                {
                                    this.inBulkPaintCount++;
                                    switchedToBulkPaint = true; 
                                }
                                try 
                                { 
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.col)
                                        {
                                            // deselect currently selected column
                                            SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false); 
                                        }
                                        else 
                                        { 
                                            bandIndex++;
                                        } 
                                    }
                                }
                                finally
                                { 
                                    if (switchedToBulkPaint)
                                    { 
                                        ExitBulkPaint(-1, -1); 
                                    }
                                } 
                            }
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                            {
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = true; 
                            }
                            if (selectColumnRange) 
                            { 
                                if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, hti.col))
                                { 
                                    SelectColumnRange(this.ptAnchorCell.X, hti.col, true);
                                }
                                else
                                { 
                                    SelectColumnRange(hti.col, this.ptAnchorCell.X, true);
                                } 
                            } 
                            else if (!this.selectedBandIndexes.Contains(hti.col))
                            { 
                                SetSelectedColumnCore(hti.col, true);
                            }
                        }
                        else 
                        {
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.col)); 
                            SetSelectedColumnCore(hti.col, false); 
                        }
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); 
                        Debug.Assert(success);
                        break;
                    }
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                    { 
                        if (isControlDown && 
                            (this.Columns[hti.col].Selected || IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row)) &&
                            (!isShiftDown || !this.MultiSelect)) 
                        {
                            select = false;
                        }
                        if (select) 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    RemoveIndividuallySelectedCells(); 
                                } 
                                SetSelectedCellCore(hti.col, hti.row, true);
                            } 
                            else
                            {
                                // this.MultiSelect == true
                                if (!isControlDown && !isShiftDown) 
                                {
                                    bool switchedToBulkPaint = false; 
                                    if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) 
                                    {
                                        this.inBulkPaintCount++; 
                                        switchedToBulkPaint = true;
                                    }
                                    try
                                    { 
                                        while (this.selectedBandIndexes.Count > 0)
                                        { 
                                            SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); 
                                        }
                                        RemoveIndividuallySelectedCells(hti.col, hti.row); 
                                    }
                                    finally
                                    {
                                        if (switchedToBulkPaint) 
                                        {
                                            ExitBulkPaint(-1, -1); 
                                        } 
                                    }
                                } 
                                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                                {
                                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true;
                                } 
                                if (isShiftDown)
                                { 
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return;
                                    }
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row);
                                } 
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, true); 
                                }
                            }
                        }
                        else 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, false); 
                                } 
                            }
                            else 
                            {
                                SetSelectedCellCore(hti.col, hti.row, false);
                            }
                        } 
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true);
                        Debug.Assert(success); 
                        break; 
                    }
 
                    case DataGridViewSelectionMode.FullRowSelect:
                    {
                        if (isControlDown &&
                            ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)) 
                        {
                            select = false; 
                        } 
                        if (select)
                        { 
                            bool selectRowRange = false;
                            this.trackRow = hti.row;
                            this.trackRowEdge = -1;
                            if (this.MultiSelect && 
                                isShiftDown &&
                                this.ptAnchorCell.Y > -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Selected) != 0) 
                            { 
                                selectRowRange = true;
                            } 

                            if (!this.MultiSelect || !isControlDown || isShiftDown)
                            {
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) 
                                {
                                    this.inBulkPaintCount++; 
                                    switchedToBulkPaint = true;
                                }
                                try
                                { 
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.row) 
                                        {
                                            // deselect currently selected row 
                                            SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false);
                                        }
                                        else
                                        { 
                                            bandIndex++;
                                        } 
                                    } 
                                }
                                finally 
                                {
                                    if (switchedToBulkPaint)
                                    {
                                        ExitBulkPaint(-1, -1); 
                                    }
                                } 
                            } 
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                            { 
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = true;
                            }
                            if (selectRowRange)
                            { 
                                if (hti.row >= this.ptAnchorCell.Y)
                                { 
                                    SelectRowRange(this.ptAnchorCell.Y, hti.row, true); 
                                }
                                else 
                                {
                                    SelectRowRange(hti.row, this.ptAnchorCell.Y, true);
                                }
                            } 
                            else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) == 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(hti.row) == 
                                             ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0));
                                SetSelectedRowCore(hti.row, true); 
                            }
                        }
                        else
                        { 
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.row));
                            SetSelectedRowCore(hti.row, false); 
                        } 
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true);
                        Debug.Assert(success); 
                        break;
                    }

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                    {
                        if (isControlDown && 
                            (((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0) || 
                            IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row)) &&
                            (!isShiftDown || !this.MultiSelect)) 
                        {
                            select = false;
                        }
                        if (select) 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    RemoveIndividuallySelectedCells(); 
                                } 
                                SetSelectedCellCore(hti.col, hti.row, true);
                            } 
                            else
                            {
                                // this.MultiSelect == true
                                if (!isControlDown && !isShiftDown) 
                                {
                                    bool switchedToBulkPaint = false; 
                                    if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) 
                                    {
                                        this.inBulkPaintCount++; 
                                        switchedToBulkPaint = true;
                                    }
                                    try
                                    { 
                                        while (this.selectedBandIndexes.Count > 0)
                                        { 
                                            SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); 
                                        }
                                        RemoveIndividuallySelectedCells(hti.col, hti.row); 
                                    }
                                    finally
                                    {
                                        if (switchedToBulkPaint) 
                                        {
                                            ExitBulkPaint(-1, -1); 
                                        } 
                                    }
                                } 
                                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                                {
                                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true;
                                } 
                                if (isShiftDown)
                                { 
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return;
                                    }
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row);
                                } 
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, true); 
                                }
                            }
                        }
                        else 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false);
                                }
                                else 
                                {
                                    SetSelectedCellCore(hti.col, hti.row, false); 
                                } 
                            }
                            else 
                            {
                                SetSelectedCellCore(hti.col, hti.row, false);
                            }
                        } 
                        bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true);
 
                        // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                        // DataGridView changes.
                        // See vsWhidbey: 325296. 
                        // Debug.Assert(success);
                        break;
                    }
                } 
            }
            finally 
            { 
                this.NoSelectionChangeCount--;
            } 
        }

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseEnter(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            this.ptMouseEnteredCell.X = e.ColumnIndex; 
            this.ptMouseEnteredCell.Y = e.RowIndex; 

            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseEnterUnsharesRowInternal(e.RowIndex))
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseEnterInternal(e.RowIndex);
            } 
            else 
            {
                dataGridViewCell.OnMouseEnterInternal(e.RowIndex); 
            }

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEENTER] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellMouseLeave(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            this.ptMouseEnteredCell.X = -2; 
            this.ptMouseEnteredCell.Y = -2;
 
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); 
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseLeaveUnsharesRowInternal(e.RowIndex)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex];
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseLeaveInternal(e.RowIndex);
            } 
            else
            { 
                dataGridViewCell.OnMouseLeaveInternal(e.RowIndex); 
            }
 
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSELEAVE] as DataGridViewCellEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseMove(DataGridViewCellMouseEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseMoveUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseMoveInternal(e); 
            }
            else 
            {
                dataGridViewCell.OnMouseMoveInternal(e);
            }
 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEMOVE] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 

            if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] && 
                this.AllowUserToOrderColumns &&
                this.SelectionMode != DataGridViewSelectionMode.FullColumnSelect && 
                this.SelectionMode != DataGridViewSelectionMode.ColumnHeaderSelect &&
                e.Button == MouseButtons.Left &&
                this.ptMouseDownCell.Y == -1 &&
                this.ptMouseDownCell.X >= 0 && 
                this.ptMouseDownCell.X < this.Columns.Count)
            { 
                Point ptGridCoord = ConvertCellToGridCoord(e.ColumnIndex, e.RowIndex, e.X, e.Y); 

                HitTestInfo hti = HitTest(ptGridCoord.X, ptGridCoord.Y); 

                Debug.Assert(hti.Type != DataGridViewHitTestType.None &&
                             hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                             hti.Type != DataGridViewHitTestType.VerticalScrollBar); 

                switch (hti.typeInternal) 
                { 
                    // Check for column header mouse down
                    case DataGridViewHitTestTypeInternal.ColumnHeader: 
                    case DataGridViewHitTestTypeInternal.ColumnHeaderLeft:
                    case DataGridViewHitTestTypeInternal.ColumnHeaderRight:
                    case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft:
                    { 
                        Debug.Assert(!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]);
                        if (Math.Abs(this.ptMouseDownGridCoord.X - ptGridCoord.X) >= DataGridView.DragSize.Width || 
                            Math.Abs(this.ptMouseDownGridCoord.Y - ptGridCoord.Y) >= DataGridView.DragSize.Height) 
                        {
                            BeginColumnRelocation(this.ptMouseDownGridCoord.X, this.ptMouseDownCell.X); 
                        }
                        break;
                    }
                } 
            }
        } 
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellMouseUp(DataGridViewCellMouseEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex);
            Debug.Assert(dataGridViewCell != null);
            if (e.RowIndex >= 0 && dataGridViewCell.MouseUpUnsharesRowInternal(e)) 
            {
                DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; 
                GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseUpInternal(e); 
            }
            else 
            {
                dataGridViewCell.OnMouseUpInternal(e);
            }
 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEUP] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected internal virtual void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            DataGridViewCellPaintingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLPAINTING] as DataGridViewCellPaintingEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal DataGridViewCellParsingEventArgs OnCellParsing(int rowIndex, int columnIndex, object formattedValue, Type valueType, DataGridViewCellStyle cellStyle) 
        {
            DataGridViewCellParsingEventArgs dgvcpe = new DataGridViewCellParsingEventArgs(rowIndex, columnIndex, 
                                                                                           formattedValue, 
                                                                                           valueType,
                                                                                           cellStyle); 
            OnCellParsing(dgvcpe);
            return dgvcpe;
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellParsing(DataGridViewCellParsingEventArgs e) 
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            } 
            DataGridViewCellParsingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLPARSING] as DataGridViewCellParsingEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
        } 

        private void OnCellSelectMouseMove(HitTestInfo hti) 
        { 
            Debug.Assert(this.MultiSelect);
            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
            int oldEdgeRowIndex = this.ptCurrentCell.Y;
            if ((hti.col != this.ptCurrentCell.X || hti.row != this.ptCurrentCell.Y) &&
                !CommitEditForOperation(hti.col, hti.row, true))
            { 
                // Return silently if validating/commit/abort failed
                return; 
            } 
            this.noSelectionChangeCount++;
            try 
            {
                if (this.ptAnchorCell.X == -1 || IsInnerCellOutOfBounds(hti.col, hti.row))
                {
                    return; 
                }
                UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, 
                    this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row); 
                if (hti.col != this.ptCurrentCell.X || hti.row != this.ptCurrentCell.Y)
                { 
                    bool success = SetCurrentCellAddressCore(hti.col, hti.row, false, false, false);
                    Debug.Assert(success);
                }
            } 
            finally
            { 
                this.NoSelectionChangeCount--; 
            }
        } 

        /// 
        protected virtual void OnCellStateChanged(DataGridViewCellStateChangedEventArgs e)
        { 
            // At this point we assume that only the Selected state has an influence on the rendering of the cell.
            // If there is a scenario where another state has an effect, then the dev will have to invalidate the cell by hand. 
            DataGridViewCell dataGridViewCell = e.Cell; 
            if (e.StateChanged == DataGridViewElementStates.Selected)
            { 
                Debug.Assert(dataGridViewCell.RowIndex >= 0);
                if (this.inBulkPaintCount == 0)
                {
                    InvalidateCellPrivate(dataGridViewCell); 
                }
            } 
 
            DataGridViewCellStateChangedEventHandler eh = Events[EVENT_DATAGRIDVIEWCELLSTATECHANGED] as DataGridViewCellStateChangedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
 
            if (e.StateChanged == DataGridViewElementStates.ReadOnly &&
                this.ptCurrentCell.X == dataGridViewCell.ColumnIndex && 
                this.ptCurrentCell.Y == dataGridViewCell.RowIndex && 
                dataGridViewCell.RowIndex > -1 &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
            {
                VerifyImeRestrictedModeChanged();

                if (!dataGridViewCell.ReadOnly && 
                    ColumnEditable(this.ptCurrentCell.X) &&
                    !this.IsCurrentCellInEditMode && 
                    (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                    (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)))
                { 
                    // Current cell becomes read/write. Enter editing mode.
                    BeginEditInternal(true /*selectAll*/);
                }
            } 
        }
 
        internal void OnCellStyleChanged(DataGridViewCell dataGridViewCell) 
        {
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); 
            OnCellStyleChanged(dgvce);
        }

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellStyleChanged(DataGridViewCellEventArgs e) 
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            }
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            OnCellCommonChange(e.ColumnIndex, e.RowIndex); 

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLSTYLECHANGED] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnCellStyleContentChanged(DataGridViewCellStyle dataGridViewCellStyle, DataGridViewCellStyle.DataGridViewCellStylePropertyInternal property) 
        {
            Debug.Assert(dataGridViewCellStyle != null); 
            switch (property)
            {
                case DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.Font:
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.DataGridView) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont]) 
                    {
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] = false; 
                    } 
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.ColumnHeaders) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont])
                    { 
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] = false;
                    }
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.RowHeaders) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont])
                    { 
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] = false;
                    } 
                    break; 

                case DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.ForeColor: 
                    if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.DataGridView) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor])
                    {
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] = false;
                    } 
                    break;
            } 
 
            DataGridViewCellStyleContentChangedEventArgs dgvcscce = new DataGridViewCellStyleContentChangedEventArgs(dataGridViewCellStyle,
                property != DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.Color && 
                property != DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.ForeColor /*changeAffectsPreferredSize*/);
            OnCellStyleContentChanged(dgvcscce);
        }
 
        /// 
        protected virtual void OnCellStyleContentChanged(DataGridViewCellStyleContentChangedEventArgs e) 
        { 
            // We assume that when a color changes, it has no effect on the autosize of elements
            bool repositionEditingControl = false; 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Cell) == DataGridViewCellStyleScopes.Cell && (e.CellStyleScope & DataGridViewCellStyleScopes.DataGridView) == 0)
            {
                // Same processing as in OnDefaultCellStyleChanged 
                if (e.ChangeAffectsPreferredSize)
                { 
                    repositionEditingControl = true; 
                    OnGlobalAutoSize();
                } 
                else
                {
                    Invalidate();
                } 
            }
 
            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Column) == DataGridViewCellStyleScopes.Column) 
            {
                if (e.ChangeAffectsPreferredSize) 
                {
                    repositionEditingControl = true;
                    OnColumnsGlobalAutoSize();
                } 
                else
                { 
                    InvalidateData(); 
                }
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Row) == DataGridViewCellStyleScopes.Row && (e.CellStyleScope & DataGridViewCellStyleScopes.Rows) == 0 && (e.CellStyleScope & DataGridViewCellStyleScopes.AlternatingRows) == 0)
            {
                // Same processing as in OnRowsDefaultCellStyleChanged 
                InvalidateData();
                if (e.ChangeAffectsPreferredSize) 
                { 
                    repositionEditingControl = true;
                    // Autosize rows if needed 
                    if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/);
                    } 
                    // Auto size columms also if needed
                    // Impossible to figure out if DisplayedRows filter should be added or not. Adding it to be on the conservative side. 
                    AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | 
                                                        DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows,
                                                        true /*fixedHeight*/); 
                    // Second round of rows autosizing
                    if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                    }
                } 
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.DataGridView) == DataGridViewCellStyleScopes.DataGridView) 
            {
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize;
                if (e.ChangeAffectsPreferredSize)
                { 
                    repositionEditingControl = false;
                    // OnDefaultCellStyleChanged will reposition the editing control. 
                } 
                OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.ColumnHeaders) == DataGridViewCellStyleScopes.ColumnHeaders)
            {
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; 
                if (e.ChangeAffectsPreferredSize)
                { 
                    repositionEditingControl = false; 
                    // OnColumnHeadersDefaultCellStyleChanged will reposition the editing control.
                } 
                OnColumnHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            }

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.RowHeaders) == DataGridViewCellStyleScopes.RowHeaders) 
            {
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; 
                if (e.ChangeAffectsPreferredSize) 
                {
                    repositionEditingControl = false; 
                    // OnRowHeadersDefaultCellStyleChanged will reposition the editing control.
                }
                OnRowHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if ((e.CellStyleScope & DataGridViewCellStyleScopes.Rows) == DataGridViewCellStyleScopes.Rows) 
            { 
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize;
                if (e.ChangeAffectsPreferredSize) 
                {
                    repositionEditingControl = false;
                    // OnRowsDefaultCellStyleChanged will reposition the editing control.
                } 
                OnRowsDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 
 
            if ((e.CellStyleScope & DataGridViewCellStyleScopes.AlternatingRows) == DataGridViewCellStyleScopes.AlternatingRows)
            { 
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize;
                if (e.ChangeAffectsPreferredSize)
                {
                    repositionEditingControl = false; 
                    // OnAlternatingRowsDefaultCellStyleChanged will reposition the editing control.
                } 
                OnAlternatingRowsDefaultCellStyleChanged(this.CellStyleChangedEventArgs); 
            }
 
            if (repositionEditingControl && this.editingControl != null)
            {
                PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
            } 

            DataGridViewCellStyleContentChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLSTYLECONTENTCHANGED] as DataGridViewCellStyleContentChangedEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnCellToolTipTextChanged(DataGridViewCell dataGridViewCell) 
        {
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); 
            OnCellToolTipTextChanged(dgvce); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellToolTipTextChanged(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLTOOLTIPTEXTCHANGED] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        internal string OnCellToolTipTextNeeded(int columnIndex, int rowIndex, string toolTipText)
        {
            DataGridViewCellToolTipTextNeededEventArgs dgvctttne = new DataGridViewCellToolTipTextNeededEventArgs(columnIndex, rowIndex, toolTipText); 
            OnCellToolTipTextNeeded(dgvctttne);
            return dgvctttne.ToolTipText; 
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellToolTipTextNeeded(DataGridViewCellToolTipTextNeededEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            DataGridViewCellToolTipTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLTOOLTIPTEXTNEEDED] as DataGridViewCellToolTipTextNeededEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        internal void OnCellValidated(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        {
            OnCellValidated(new DataGridViewCellEventArgs(columnIndex, rowIndex));
            if (dataGridViewCell != null) 
            {
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                { 
                    dataGridViewCell = null;
                } 
                else
                {
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; 
                }
            } 
        } 

        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellValidated(DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            } 
            if (e.RowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            try
            { 
                this.noDimensionChangeCount++;
 
                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALIDATED] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e);
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                }
            } 
            finally
            { 
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
            } 
        }

        internal bool OnCellValidating(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, DataGridViewDataErrorContexts context)
        { 
            DataGridViewCell currentCell = (dataGridViewCell == null) ? this.CurrentCellInternal : dataGridViewCell;
            DataGridViewCellStyle dataGridViewCellStyle = currentCell.GetInheritedStyle(null, rowIndex, false); 
            object val = currentCell.GetValueInternal(rowIndex); 
            object editedFormattedValue = currentCell.GetEditedFormattedValue(val, rowIndex, ref dataGridViewCellStyle, context);
            DataGridViewCellValidatingEventArgs dgvcfvce = new DataGridViewCellValidatingEventArgs(columnIndex, rowIndex, editedFormattedValue); 
            OnCellValidating(dgvcfvce);
            if (dataGridViewCell != null)
            {
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                {
                    dataGridViewCell = null; 
                } 
                else
                { 
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                }
            } 
            return dgvcfvce.Cancel;
        } 
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellValidating(DataGridViewCellValidatingEventArgs e)
        {
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex");
            } 
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
            try
            {
                this.noDimensionChangeCount++; 
                this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating] = true;
 
                DataGridViewCellValidatingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALIDATING] as DataGridViewCellValidatingEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e);
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                }
            } 
            finally
            { 
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
                this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating] = false; 
            }
        }

        internal void OnCellValueChangedInternal(DataGridViewCellEventArgs e) 
        {
            // For now, same effect as if the cell style had changed. 
            OnCellValueChanged(e); 
        }
 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellValueChanged(DataGridViewCellEventArgs e)
        { 
            if (e.ColumnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("e.RowIndex");
            }
            OnCellCommonChange(e.ColumnIndex, e.RowIndex); 

            DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUECHANGED] as DataGridViewCellEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal object OnCellValueNeeded(int columnIndex, int rowIndex) 
        {
            DataGridViewCellValueEventArgs dgvcve = this.CellValueEventArgs; 
            dgvcve.SetProperties(columnIndex, rowIndex, null); 
            OnCellValueNeeded(dgvcve);
            return dgvcve.Value; 
        }

        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e 
        protected virtual void OnCellValueNeeded(DataGridViewCellValueEventArgs e)
        { 
            if (e.ColumnIndex < 0 || e.ColumnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex < 0 || e.RowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("e.RowIndex"); 
            }
//#if DEBUG 
            // Some customer scenarios may result in accessing cell values while this.dataStoreAccessAllowed is false. This is bad practice, 
            // but since we're late in Whidbey, throwing an exception would be destabilizing our internal customers.
            // Debug.Assert(this.dataStoreAccessAllowed); 
//#endif
            DataGridViewCellValueEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUENEEDED] as DataGridViewCellValueEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        internal void OnCellValuePushed(int columnIndex, int rowIndex, object value) 
        {
            DataGridViewCellValueEventArgs dgvcve = this.CellValueEventArgs;
            dgvcve.SetProperties(columnIndex, rowIndex, value);
            OnCellValuePushed(dgvcve); 
        }
 
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e
        protected virtual void OnCellValuePushed(DataGridViewCellValueEventArgs e) 
        {
            if (e.ColumnIndex < 0 || e.ColumnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("e.ColumnIndex"); 
            }
            if (e.RowIndex < 0 || e.RowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("e.RowIndex");
            } 
            DataGridViewCellValueEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUEPUSHED] as DataGridViewCellValueEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        internal void OnClearedRows()
        { 
            // Raise the RowStateChanged(Displayed->false) events
            foreach (DataGridViewRow dataGridViewRow in this.lstRows)
            {
                if (dataGridViewRow.Displayed) 
                {
                    dataGridViewRow.DisplayedInternal = false; 
                    DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, DataGridViewElementStates.Displayed); 
                    OnRowStateChanged(-1 /*rowIndex*/, dgvrsce);
                } 
            }
            this.lstRows.Clear();
        }
 
        internal void OnClearingColumns()
        { 
            this.CurrentCell = null; 

            // Rows need to be cleared first. There cannot be rows without also having columns. 
            this.Rows.ClearInternal(false /*recreateNewRow*/);

            // Reset sort related variables.
            this.sortedColumn = null; 
            this.sortOrder = SortOrder.None;
 
            // selectedBandIndexes, individualSelectedCells & individualReadOnlyCells cleared in OnClearingRows. 
        }
 
        [
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ]
        internal void OnClearingRows() 
        {
            // Build a list of displayed rows in order to be able to raise their RowStateChanged(Displayed->false) events later on 
            this.lstRows.Clear(); 
            int numDisplayedRows = this.displayedBandsInfo.NumDisplayedFrozenRows + this.displayedBandsInfo.NumDisplayedScrollingRows;
            if (numDisplayedRows > 0) 
            {
                this.lstRows.Capacity = numDisplayedRows;
                int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Displayed);
                while (numDisplayedRows > 0 && rowIndex != -1) 
                {
                    this.lstRows.Add(this.Rows[rowIndex]); 
                    numDisplayedRows--; 
                    if (numDisplayedRows > 0)
                    { 
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Displayed);
                    }
                }
            } 

            this.CurrentCell = null; 
 
            this.newRowIndex = -1;
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = this.selectedBandIndexes.Count > 0 || 
                                                                                this.individualSelectedCells.Count > 0;
            this.selectedBandIndexes.Clear();
            if (this.selectedBandSnapshotIndexes != null)
            { 
                this.selectedBandSnapshotIndexes.Clear();
            } 
            this.individualSelectedCells.Clear(); 
            this.individualReadOnlyCells.Clear();
        } 

        /// 
        protected virtual void OnColumnAdded(DataGridViewColumnEventArgs e)
        { 
            if (e.Column.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            }
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNADDED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnColumnCollectionChanged_PreNotification(CollectionChangeEventArgs ccea) 
        {
            // we need to map columns w/ DataPropertyName to bound columns 
            if (this.DataSource != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns])
            {
                if (ccea.Action == CollectionChangeAction.Add)
                { 
                    DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)ccea.Element;
                    if (dataGridViewColumn.DataPropertyName.Length != 0) 
                    { 
                        MapDataGridViewColumnToDataBoundField(dataGridViewColumn);
                    } 
                }
                else if (ccea.Action == CollectionChangeAction.Refresh)
                {
                    for (int i = 0; i < this.Columns.Count; i++) 
                    {
                        if (this.Columns[i].DataPropertyName.Length != 0) 
                        { 
                            MapDataGridViewColumnToDataBoundField(this.Columns[i]);
                        } 
                    }
                }
            }
 
            ResetUIState(false /*useRowShortcut*/, false /*computeVisibleRows*/);
        } 
 
        internal void OnColumnCollectionChanged_PostNotification(DataGridViewColumn dataGridViewColumn)
        { 
            if (this.Columns.Count != 0 && this.Rows.Count == 0)
            {
                if (this.DataSource != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns])
                { 
                    // this will create the 'add new row' when AllowUserToAddRowsInternal == true
                    RefreshRows(true /*scrollIntoView*/); 
                } 
                else if (this.AllowUserToAddRowsInternal)
                { 
                    AddNewRow(false);
                }
            }
            if (this.AutoSize && (dataGridViewColumn == null || dataGridViewColumn.Visible)) 
            {
                LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Columns); 
            } 
        }
 
        internal void OnColumnCommonChange(int columnIndex)
        {
            OnColumnGlobalAutoSize(columnIndex);
        } 

        ///  
        protected virtual void OnColumnContextMenuStripChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNCONTEXTMENUSTRIPCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        internal void OnColumnDataPropertyNameChanged(DataGridViewColumn dataGridViewColumn)
        {
            OnColumnDataPropertyNameChanged(new DataGridViewColumnEventArgs(dataGridViewColumn)); 
        }
 
        ///  
        protected virtual void OnColumnDataPropertyNameChanged(DataGridViewColumnEventArgs e)
        { 
            if (e.Column.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            } 
            // map the dataGridView column to some data field
            if (this.DataSource != null && e.Column.DataPropertyName.Length != 0 && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns]) 
            { 
                MapDataGridViewColumnToDataBoundField(e.Column);
            } 
            else if (this.DataSource != null && e.Column.DataPropertyName.Length == 0)
            {
                if (e.Column.IsDataBound)
                { 
                    e.Column.IsDataBoundInternal = false;
                    e.Column.BoundColumnIndex = -1; 
                    e.Column.BoundColumnConverter = null; 
                    InvalidateColumnInternal(e.Column.Index);
                } 
            }

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDATAPROPERTYNAMECHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnColumnDefaultCellStyleChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            OnColumnGlobalAutoSize(e.Column.Index);
 
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDEFAULTCELLSTYLECHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        internal void OnColumnDisplayIndexChanged(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn);
            OnColumnDisplayIndexChanged(dgvce);
        } 

        internal void OnColumnDisplayIndexChanging(DataGridViewColumn dataGridViewColumn, int newDisplayIndex) 
        { 
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(newDisplayIndex != dataGridViewColumn.DisplayIndex); 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments])
            {
                // We are within columns display indexes adjustments. We do not allow changing display indexes while adjusting them. 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterDisplayIndexWithinAdjustments));
            } 
 
            // Throws an exception if the requested move is illegal
            CorrectColumnFrozenStatesForMove(dataGridViewColumn, newDisplayIndex); 

            try
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = true; 

                // Move is legal - let's adjust the affected display indexes. 
                if (newDisplayIndex < dataGridViewColumn.DisplayIndex) 
                {
                    // DisplayIndex decreases. All columns with newDisplayIndex <= DisplayIndex < dataGridViewColumn.DisplayIndex 
                    // get their DisplayIndex incremented.
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns)
                    {
                        if (newDisplayIndex <= dataGridViewColumnTmp.DisplayIndex && dataGridViewColumnTmp.DisplayIndex < dataGridViewColumn.DisplayIndex) 
                        {
                            dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex + 1; 
                            dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on 
                        }
                    } 
                }
                else
                {
                    // DisplayIndex increases. All columns with dataGridViewColumn.DisplayIndex < DisplayIndex <= newDisplayIndex 
                    // get their DisplayIndex incremented.
                    foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) 
                    { 
                        if (dataGridViewColumn.DisplayIndex < dataGridViewColumnTmp.DisplayIndex && dataGridViewColumnTmp.DisplayIndex <= newDisplayIndex)
                        { 
                            dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex - 1;
                            dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on
                        }
                    } 
                }
            } 
            finally 
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = false; 
            }

            // Note that displayIndex of moved column is updated by caller.
        } 

        ///  
        protected virtual void OnColumnDisplayIndexChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
 
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]);
#if DEBUG 
            Debug.Assert(this.Columns.VerifyColumnDisplayIndexes()); 
#endif
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDISPLAYINDEXCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnColumnDisplayIndexChanged_PreNotification() 
        {
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]); 

            // column.DisplayIndex changed - this may require a complete re-layout of the control
            this.Columns.InvalidateCachedColumnsOrder();
 
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            if (this.editingControl != null) 
            { 
                PositionEditingControl(true, true, false);
            } 
            Invalidate(Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data));
        }

        internal void OnColumnDisplayIndexChanged_PostNotification() 
        {
            // Notifications for adjusted display indexes. 
            FlushDisplayIndexChanged(true /*raiseEvent*/); 
        }
 
        /// 
        protected virtual void OnColumnDividerDoubleClick(DataGridViewColumnDividerDoubleClickEventArgs e)
        {
            DataGridViewColumnDividerDoubleClickEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDIVIDERDOUBLECLICK] as DataGridViewColumnDividerDoubleClickEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
 
            if (!e.Handled && e.Button == MouseButtons.Left && e.ColumnIndex < this.Columns.Count)
            {
                if (e.ColumnIndex == -1)
                { 
                    AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders,
                                              true /*fixedColumnHeadersHeight*/, 
                                              true /*fixedRowsHeight*/); 
                }
                else 
                {
                    DataGridViewAutoSizeColumnMode inheritedAutoSizeMode = this.Columns[e.ColumnIndex].InheritedAutoSizeMode;
                    if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
                    { 
                        AutoResizeColumnInternal(e.ColumnIndex, DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows, true /*fixedHeight*/);
                    } 
                    else 
                    {
                        AutoResizeColumnInternal(e.ColumnIndex, (DataGridViewAutoSizeColumnCriteriaInternal)inheritedAutoSizeMode, true /*fixedHeight*/); 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnColumnDividerWidthChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
            OnColumnGlobalAutoSize(e.Column.Index); 

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDIVIDERWIDTHCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnColumnFillWeightChanged(DataGridViewColumn dataGridViewColumn) 
        {
            if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) 
            { 
                // UsedFillWeight properties need to be re-evaluated
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; 
                // Adjust filling columns based on new weight of this column
                PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            }
        } 

        internal void OnColumnFillWeightChanging(DataGridViewColumn dataGridViewColumn, float fillWeight) 
        { 
            if (this.InAdjustFillingColumns)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter));
            }

            // Make sure the sum of the column weights does not exceed ushort.MaxValue 
            float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) - dataGridViewColumn.FillWeight + fillWeight;
            if (weightSum > (float)ushort.MaxValue) 
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture)));
            } 
        }

        private void OnColumnGlobalAutoSize(int columnIndex)
        { 
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count);
 
            if (!this.Columns[columnIndex].Visible) 
            {
                return; 
            }

            InvalidateColumnInternal(columnIndex);
 
            if (this.noAutoSizeCount > 0)
            { 
                return; 
            }
 
            bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0;

            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode;
            if (autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None && 
                autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill)
            { 
                AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, fixedHeight); 
            }
 
            // Autosize rows and column headers if needed
            if (!fixedHeight)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            { 
                AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
            } 
            if (!fixedHeight &&
                autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None &&
                autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill)
            { 
                // Second round of column autosizing with 1 degree of freedom
                AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); 
            } 
        }
 
        /// 
        protected virtual void OnColumnHeaderCellChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 

            OnColumnHeaderGlobalAutoSize(e.Column.Index); 

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERCELLCHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        private void OnColumnHeaderGlobalAutoSize(int columnIndex) 
        {
            if (!this.ColumnHeadersVisible)
            {
                return; 
            }
 
            InvalidateCellPrivate(columnIndex, -1); 

            if (this.noAutoSizeCount > 0) 
            {
                return;
            }
 
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode;
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header; 
            bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0; 

            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, fixedColumnWidth);
            }
 
            if (!fixedColumnWidth)
            { 
                Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None); 
                Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill);
                bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; 
                AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, fixedHeight);
                if (!fixedHeight)
                {
                    AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                    // Second round of column autosizing with 1 degree of freedom
                    AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); 
                } 
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                { 
                    // Second round of column headers autosizing with 1 degree of freedom
                    AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
                }
            } 
        }
 
        ///  
        protected virtual void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
        { 
            if (e.Button == MouseButtons.Left &&
                this.SelectionMode != DataGridViewSelectionMode.FullColumnSelect &&
                this.SelectionMode != DataGridViewSelectionMode.ColumnHeaderSelect)
            { 
                DataGridViewColumn dataGridViewColumn = this.Columns[e.ColumnIndex];
 
                if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && (!this.VirtualMode || dataGridViewColumn.IsDataBound)) 
                {
                    ListSortDirection direction = ListSortDirection.Ascending; 

                    if (this.sortedColumn == dataGridViewColumn)
                    {
                        Debug.Assert(this.sortOrder != SortOrder.None); 
                        if (this.sortOrder == SortOrder.Ascending)
                        { 
                            direction = ListSortDirection.Descending; 
                        }
                    } 

                    if ((this.DataSource == null) ||
                        (this.DataSource != null &&
                         (this.dataConnection.List is IBindingList) && 
                         ((IBindingList) this.dataConnection.List).SupportsSorting &&
                         dataGridViewColumn.IsDataBound)) 
                    { 
                        Sort(dataGridViewColumn, direction);
                    } 
                }
            }

            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERMOUSECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnColumnHeaderMouseDoubleClick(DataGridViewCellMouseEventArgs e)
        { 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        private void OnColumnHeaderMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown)
        { 
            Debug.Assert(hti.Type == DataGridViewHitTestType.ColumnHeader);
            this.noSelectionChangeCount++; 
            try 
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.FullRowSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        break;
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                    { 
                        bool select = true;
                        if (isControlDown && this.Columns[hti.col].Selected)
                        {
                            select = false; 
                        }
                        if (select) 
                        { 
                            int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                            if (rowIndex > -1 && hti.col != this.ptCurrentCell.X) 
                            {
                                // Make sure we will be able to scroll into view
                                int oldCurrentCellX = this.ptCurrentCell.X;
                                int oldCurrentCellY = this.ptCurrentCell.Y; 
                                if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange,
                                            DataGridViewValidateCellInternal.Always /*validateCell*/, 
                                            true /*fireCellLeave*/, 
                                            true /*fireCellEnter*/,
                                            rowIndex != this.ptCurrentCell.Y /*fireRowLeave*/, 
                                            rowIndex != this.ptCurrentCell.Y /*fireRowEnter*/,
                                            false /*fireLeave*/,
                                            this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/,
                                            true /*resetCurrentCell*/, 
                                            false /*resetAnchorCell*/))
                                { 
                                    // Just cancel operation silently instead of throwing InvalidOperationException 
                                    return;
                                } 
                                if (rowIndex != oldCurrentCellY && oldCurrentCellY != -1)
                                {
                                    DataGridViewCell dataGridViewCellTmp = null;
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        return; 
                                    } 
                                    if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY))
                                    { 
                                        // Row validation was cancelled
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                        {
                                            return; 
                                        }
                                        OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); 
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                        {
                                            return; 
                                        }
                                        OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);
                                        return;
                                    } 
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                    { 
                                        return; 
                                    }
                                    OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                }
                            }
                            if (IsColumnOutOfBounds(hti.col))
                            { 
                                return;
                            } 
 
                            bool selectColumnRange = false;
                            this.trackColumn = hti.col; 
                            this.trackColumnEdge = -1;
                            if (this.MultiSelect &&
                                isShiftDown &&
                                this.ptAnchorCell.X > -1 && 
                                this.Columns[this.ptAnchorCell.X].Selected)
                            { 
                                selectColumnRange = true; 
                            }
                            if (!this.MultiSelect || !isControlDown || isShiftDown) 
                            {
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1);
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                                { 
                                    this.inBulkPaintCount++; 
                                    switchedToBulkPaint = true;
                                } 
                                try
                                {
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.col)
                                        { 
                                            // deselect currently selected column 
                                            SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false);
                                        } 
                                        else
                                        {
                                            bandIndex++;
                                        } 
                                    }
                                    if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) 
                                    { 
                                        RemoveIndividuallySelectedCells();
                                    } 
                                    else
                                    {
                                        Debug.Assert(this.individualSelectedCells.Count == 0);
                                    } 
                                }
                                finally 
                                { 
                                    if (switchedToBulkPaint)
                                    { 
                                        ExitBulkPaint(-1, -1);
                                    }
                                }
                            } 
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves])
                            { 
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = true; 
                            }
                            if (selectColumnRange) 
                            {
                                if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, hti.col))
                                {
                                    SelectColumnRange(this.ptAnchorCell.X, hti.col, true); 
                                }
                                else 
                                { 
                                    SelectColumnRange(hti.col, this.ptAnchorCell.X, true);
                                } 
                            }
                            else if (!this.selectedBandIndexes.Contains(hti.col))
                            {
                                SetSelectedColumnCore(hti.col, true); 
                            }
                            // set current cell to the top most visible cell in the column 
                            if (rowIndex != -1) 
                            {
                                if (hti.col != this.ptCurrentCell.X) 
                                {
                                    if (IsInnerCellOutOfBounds(hti.col, rowIndex))
                                    {
                                        return; 
                                    }
                                    bool success = ScrollIntoView(hti.col, rowIndex, false); 
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(hti.col, rowIndex))
                                    { 
                                        return;
                                    }
                                    success = SetCurrentCellAddressCore(hti.col, rowIndex, !isShiftDown, false, true);
                                    Debug.Assert(success); 
                                }
                                else if (-1 != this.ptCurrentCell.X) 
                                { 
                                    // Potentially have to give focus back to the current edited cell.
                                    bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); 
                                    Debug.Assert(success);
                                }
                            }
                            else 
                            {
                                Debug.Assert(this.CurrentCellAddress == new Point(-1, -1)); 
                            } 
                        }
                        else 
                        {
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.col));
                            SetSelectedColumnCore(hti.col, false);
                        } 
                        break;
                    } 
                } 
            }
            finally 
            {
                this.NoSelectionChangeCount--;
            }
        } 

        ///  
        protected virtual void OnColumnHeadersBorderStyleChanged(EventArgs e) 
        {
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
            Invalidate();

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSBORDERSTYLECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnColumnHeadersDefaultCellStyleChanged(EventArgs e)
        {
            if (this.ColumnHeadersVisible) 
            {
                Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders)); 
 
                DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
                if (dgvcsce == null || dgvcsce.ChangeAffectsPreferredSize) 
                {
                    OnColumnHeadersGlobalAutoSize();
                    if (this.editingControl != null)
                    { 
                        PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                    } 
                } 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSDEFAULTCELLSTYLECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        private void OnColumnHeadersGlobalAutoSize()
        { 
            if (this.noAutoSizeCount > 0)
            {
                return;
            } 

            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || 
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize;
 
            if (!fixedColumnHeadersHeight)
            {
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, false /*fixedColumnsWidth*/);
            } 

            if (!fixedRowHeadersWidth) 
            { 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, false /*fixedRowsHeight*/);
            } 

            // Autosize columns
            bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header, false /*fixedHeight*/);
 
            if (!fixedRowHeadersWidth || columnAutoSized)
            { 
                // Autosize rows 
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
            } 

            if (!fixedColumnHeadersHeight)
            {
                // Second round of column headers autosizing 
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            } 
 
            if (!fixedRowHeadersWidth)
            { 
                // Second round of row headers autosizing
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            }
 
            // Second round of columns autosizing
            AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header, true /*fixedHeight*/); 
        } 

        ///  
        protected virtual void OnColumnHeadersHeightChanged(EventArgs e)
        {
            if (this.editingControl != null)
            { 
                PositionEditingControl(true, false, false);
            } 
 
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
 
            OnColumnHeadersGlobalAutoSize();

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSHEIGHTCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnColumnHeadersHeightSizeModeChanged(DataGridViewAutoSizeModeEventArgs e)
        {
            if (this.columnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                if (!e.PreviousModeAutoSized) 
                { 
                    // Save current column headers height for later reuse
                    this.cachedColumnHeadersHeight = this.ColumnHeadersHeight; 
                }
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            }
            else if (e.PreviousModeAutoSized) 
            {
                this.ColumnHeadersHeight = this.cachedColumnHeadersHeight; 
            } 

            DataGridViewAutoSizeModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSHEIGHTSIZEMODECHANGED] as DataGridViewAutoSizeModeEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        internal void OnColumnHidden(DataGridViewColumn dataGridViewColumn) 
        {
            Debug.Assert(dataGridViewColumn != null); 
            if (dataGridViewColumn.Displayed)
            {
                dataGridViewColumn.DisplayedInternal = false;
                DataGridViewColumnStateChangedEventArgs dgvrsce = new DataGridViewColumnStateChangedEventArgs(dataGridViewColumn, DataGridViewElementStates.Displayed); 
                OnColumnStateChanged(dgvrsce);
            } 
        } 

        internal void OnColumnMinimumWidthChanging(DataGridViewColumn dataGridViewColumn, int minimumWidth) 
        {
            if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && dataGridViewColumn.Width < minimumWidth)
            {
                // Force the filled column's width to be minimumWidth 
                try
                { 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; 
                    dataGridViewColumn.DesiredMinimumWidth = minimumWidth;
                    PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
                }
                finally
                {
                    dataGridViewColumn.DesiredMinimumWidth = 0; 
                }
                Debug.Assert(dataGridViewColumn.Width == minimumWidth); 
            } 
        }
 
        /// 
        protected virtual void OnColumnMinimumWidthChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            if (e.Column.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)
            { 
                // Column's width may adjust smaller
                PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            }
 
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNMINIMUMWIDTHCHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        internal void OnColumnNameChanged(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
            OnColumnNameChanged(dgvce); 
        }
 
        /// 
        protected virtual void OnColumnNameChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            // Check if the column name is used as is in the column header
            DataGridViewColumn dataGridViewColumn = e.Column; 

            if (dataGridViewColumn.HasHeaderCell && dataGridViewColumn.HeaderCell.Value is string &&
                String.Compare((string)dataGridViewColumn.HeaderCell.Value, dataGridViewColumn.Name, false, CultureInfo.InvariantCulture) == 0)
            { 
                InvalidateCellPrivate(dataGridViewColumn.Index, -1);
 
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode; 
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header;
                bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0 || !this.ColumnHeadersVisible; 
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                {
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth);
                } 
                if (!fixedColumnWidth)
                { 
                    bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; 
                    AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, fixedHeight);
                    if (!fixedHeight) 
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                        // Second round of column autosizing
                        AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); 
                    }
                    if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                    { 
                        // Second round of column headers autosizing
                        AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                    }
                }
            }
 
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNNAMECHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        internal void OnColumnRemoved(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(dataGridViewColumn.DataGridView == null); 
            OnColumnRemoved(new DataGridViewColumnEventArgs(dataGridViewColumn)); 
        }
 
        /// 
        protected virtual void OnColumnRemoved(DataGridViewColumnEventArgs e)
        {
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNREMOVED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        private void OnColumnSelectMouseMove(HitTestInfo hti)
        {
            Debug.Assert(hti.col >= 0); 
            Debug.Assert(this.MultiSelect);
 
            if (this.ptCurrentCell.X != -1 && 
                hti.col != this.ptCurrentCell.X &&
                !CommitEditForOperation(hti.col, this.ptCurrentCell.Y, true)) 
            {
                // Return silently if validating/commit/abort failed
                return;
            } 
            if (IsColumnOutOfBounds(hti.col))
            { 
                return; 
            }
 
            this.noSelectionChangeCount++;
            try
            {
                if (this.trackColumnEdge >= 0 && (this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) || this.trackColumnEdge == this.trackColumn) && this.Columns.DisplayInOrder(this.trackColumnEdge, hti.col)) 
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(dataGridViewColumn.Index, hti.col, true);
                    this.trackColumnEdge = hti.col; 
                }
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) && this.Columns.DisplayInOrder(hti.col, this.trackColumnEdge) && (this.Columns.DisplayInOrder(this.trackColumn, hti.col) || hti.col == this.trackColumn))
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(dataGridViewColumn.Index, this.trackColumnEdge, false); 
                    this.trackColumnEdge = hti.col; 
                }
                else if (this.trackColumnEdge == -1 && this.Columns.DisplayInOrder(this.trackColumn, hti.col)) 
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(dataGridViewColumn.Index, hti.col, true); 
                    this.trackColumnEdge = hti.col;
                } 
                else if (this.trackColumnEdge >= 0 && (this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn) || this.trackColumnEdge == this.trackColumn) && this.Columns.DisplayInOrder(hti.col, this.trackColumnEdge)) 
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(hti.col, dataGridViewColumn.Index, true);
                    this.trackColumnEdge = hti.col;
                } 
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn) && this.Columns.DisplayInOrder(this.trackColumnEdge, hti.col) && (this.Columns.DisplayInOrder(hti.col, this.trackColumn) || hti.col == this.trackColumn))
                { 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(this.trackColumnEdge, dataGridViewColumn.Index, false); 
                    this.trackColumnEdge = hti.col;
                }
                else if (this.trackColumnEdge == -1 && this.Columns.DisplayInOrder(hti.col, this.trackColumn))
                { 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(hti.col, dataGridViewColumn.Index, true); 
                    this.trackColumnEdge = hti.col;
                } 
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) && this.Columns.DisplayInOrder(hti.col, this.trackColumn))
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(dataGridViewColumn.Index, this.trackColumnEdge, false);
                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectColumnRange(hti.col, dataGridViewColumn.Index, true);
                    this.trackColumnEdge = hti.col; 
                }
                else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, hti.col) && this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn))
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(this.trackColumnEdge, dataGridViewColumn.Index, false); 
                    dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectColumnRange(dataGridViewColumn.Index, hti.col, true); 
                    this.trackColumnEdge = hti.col;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 

            if (this.ptCurrentCell.X != -1 && hti.col != this.ptCurrentCell.X) 
            {
                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(hti.col))
                {
                    return; 
                }
                bool success = SetCurrentCellAddressCore(hti.col, 
                    this.ptCurrentCell.Y, 
                    false /*setAnchorCellAddress*/,
                    false /*validateCurrentCell*/, 
                    false /*throughMouseClick*/);
                Debug.Assert(success);
            }
        } 

        private void OnColumnsGlobalAutoSize() 
        { 
            InvalidateData();
 
            if (this.noAutoSizeCount > 0)
            {
                return;
            } 

            // Auto-size columms if needed 
            bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; 
            bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, fixedHeight);
            // Autosize rows if needed 
            if (!fixedHeight)
            {
                if (columnAutoSized)
                { 
                    AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                } 
                // Second round of columns autosizing 
                AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/);
            } 
        }

        internal void OnColumnSortModeChanged(DataGridViewColumn dataGridViewColumn)
        { 
            Debug.Assert(dataGridViewColumn != null);
            DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); 
            OnColumnSortModeChanged(dgvce); 
        }
 
        /// 
        protected virtual void OnColumnSortModeChanged(DataGridViewColumnEventArgs e)
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            } 
            DataGridViewColumn dataGridViewColumn = e.Column;
 
            if (dataGridViewColumn.HasHeaderCell)
            {
                if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.NotSortable ||
                    (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Programmatic && this.SortedColumn == dataGridViewColumn)) 
                {
                    dataGridViewColumn.HeaderCell.SortGlyphDirection = SortOrder.None; 
                    // This call will trigger OnSortGlyphDirectionChanged which in turn does 
                    // this.sortedColumn = null; and InvalidateCellPrivate(e.Column.Index, -1);
                } 
                // Potential resizing of the column headers and/or affected column.
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode;
                DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header;
                bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0 || !this.ColumnHeadersVisible; 
                if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                { 
                    AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth); 
                }
                if (!fixedColumnWidth) 
                {
                    bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0;
                    AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, fixedHeight);
                    if (!fixedHeight) 
                    {
                        AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                        // Second round of column autosizing 
                        AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, true /*fixedHeight*/);
                    } 
                    if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
                    {
                        // Second round of column headers autosizing
                        AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); 
                    }
                } 
            } 

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNSORTMODECHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        protected virtual void OnColumnStateChanged(DataGridViewColumnStateChangedEventArgs e)
        { 
            // column.Frozen | .Visible changed - this may require a complete re-layout of the control
            DataGridViewColumn dataGridViewColumn = e.Column;
            switch (e.StateChanged)
            { 
                // At this point we assume that only the Selected state has an influence on the rendering of the column.
                // If there is a customer scenario where another state has an influence, the dev must invalidate the column by hand. 
                // case DataGridViewElementStates.ReadOnly: 
                // case DataGridViewElementStates.Resizable:
 
                case DataGridViewElementStates.Selected:
                    if (dataGridViewColumn.Visible && this.inBulkPaintCount == 0)
                    {
                        InvalidateColumnInternal(dataGridViewColumn.Index); 
                    }
                    break; 
 
                case DataGridViewElementStates.Frozen:
                    if (dataGridViewColumn.Visible) 
                    {
                        if (dataGridViewColumn.Frozen)
                        {
                            // visible column became frozen 
                            if (this.horizontalOffset >= dataGridViewColumn.Thickness)
                            { 
                                Debug.Assert(this.Columns.DisplayInOrder(dataGridViewColumn.Index, this.displayedBandsInfo.FirstDisplayedScrollingCol)); 
                                this.horizontalOffset -= dataGridViewColumn.Thickness;
                            } 
                            else
                            {
                                this.horizontalOffset = this.negOffset = 0;
                            } 
                        }
                        else 
                        { 
                            // column was unfrozen - make it the first visible scrolling column if there is room
                            this.horizontalOffset = this.negOffset = 0; 
                        }
                        if (this.horizScrollBar.Enabled)
                        {
                            this.horizScrollBar.Value = this.horizontalOffset; 
                        }
 
                        // UsedFillWeight values need to be updated 
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
 
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/);
                        Invalidate();
                    }
                    break; 

                case DataGridViewElementStates.Visible: 
                    if (!dataGridViewColumn.Visible && dataGridViewColumn.Displayed) 
                    {
                        // Displayed column becomes invisible. Turns off the Displayed state. 
                        dataGridViewColumn.DisplayedInternal = false;
                    }

                    // UsedFillWeight values need to be updated 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true;
 
                    PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); 

                    bool autoSizeRows = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0 || 
                                        ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0 &&
                                        this.RowHeadersVisible);
                    bool autoSizeColumn = false;
                    DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; 
                    Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet);
                    if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && 
                        autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) 
                    {
                        // Column autosizes 
                        int width = dataGridViewColumn.ThicknessInternal;
                        if (dataGridViewColumn.Visible)
                        {
                            // Cache column's width before potential autosizing occurs 
                            dataGridViewColumn.CachedThickness = width;
                            AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, !autoSizeRows /*fixedHeight*/); 
                            autoSizeColumn = true; 
                        }
                        else if (width != dataGridViewColumn.CachedThickness) 
                        {
                            // Columns that are made invisible in the collection take their non-autosized width
                            dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness);
                        } 
                    }
 
                    if (autoSizeRows) 
                    {
                        if (dataGridViewColumn.Visible) 
                        {
                            AdjustExpandingRows(dataGridViewColumn.Index, true /*fixedWidth*/);
                        }
                        else 
                        {
                            AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                        } 
                        if (autoSizeColumn)
                        { 
                            // Second round of column autosizing
                            AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/);
                        }
                    } 
                    else
                    { 
                        Invalidate(); 
                    }
                    break; 
            }

            DataGridViewColumnStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNSTATECHANGED] as DataGridViewColumnStateChangedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 

            if (e.StateChanged == DataGridViewElementStates.ReadOnly && 
                dataGridViewColumn.Index == this.ptCurrentCell.X &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange])
            {
                VerifyImeRestrictedModeChanged(); 

                if (!dataGridViewColumn.ReadOnly && 
                    ColumnEditable(this.ptCurrentCell.X) && 
                    (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.ReadOnly) == 0 &&
                     !this.IsCurrentCellInEditMode && 
                     (this.EditMode == DataGridViewEditMode.EditOnEnter ||
                      (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)))
                {
                    // Current column becomes read/write. Enter editing mode. 
                    BeginEditInternal(true /*selectAll*/);
                } 
            } 
        }
 
        internal void OnColumnToolTipTextChanged(DataGridViewColumn dataGridViewColumn)
        {
            OnColumnToolTipTextChanged(new DataGridViewColumnEventArgs(dataGridViewColumn));
        } 

        ///  
        protected virtual void OnColumnToolTipTextChanged(DataGridViewColumnEventArgs e) 
        {
            if (e.Column.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView));
            }
            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNTOOLTIPTEXTCHANGED] as DataGridViewColumnEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
        { 
            if (e.Column.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            }
            this.Columns.InvalidateCachedColumnsWidths(); 

            // don't do any layout logic if the handle was not created already
            if (e.Column.Visible && this.IsHandleCreated)
            { 
                PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
 
                Rectangle rightArea = this.layout.Data; 
                if (this.layout.ColumnHeadersVisible)
                { 
                    rightArea = Rectangle.Union(rightArea, this.layout.ColumnHeaders);
                }
                else if (this.SingleHorizontalBorderAdded)
                { 
                    rightArea.Y--;
                    rightArea.Height++; 
                } 
                if (rightArea.Width > 0 && rightArea.Height > 0)
                { 
                    int leftEdge = GetColumnXFromIndex(e.Column.Index);
                    if (this.RightToLeftInternal)
                    {
                        rightArea.Width -= rightArea.Right - leftEdge; 
                    }
                    else 
                    { 
                        rightArea.Width -= leftEdge - rightArea.X;
                        rightArea.X = leftEdge; 
                    }
                    if (rightArea.Width > 0 && rightArea.Height > 0)
                    {
                        Invalidate(rightArea); 
                    }
                } 
 
                if (this.editingControl != null)
                { 
                    PositionEditingControl(this.ptCurrentCell.X != e.Column.Index, true, false);
                }

                UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 

                if (this.AutoSize) 
                { 
                    LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Columns);
                } 
            }

            DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNWIDTHCHANGED] as DataGridViewColumnEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 

            if (!this.InAdjustFillingColumns) 
            {
                // Autosize rows and column headers if needed
                OnColumnGlobalAutoSize(e.Column.Index);
            } 
        }
 
        internal void OnCommonCellContentClick(int columnIndex, int rowIndex, bool doubleClick) 
        {
            if (this.ptMouseDownCell.X == -2 || 
                (this.dataGridViewState2[DATAGRIDVIEWSTATE2_cellMouseDownInContentBounds] &&
                 this.ptMouseDownCell.X == columnIndex && this.ptMouseDownCell.Y == rowIndex &&
                 (this.ptMouseDownCell.X == -1 || this.ptMouseDownCell.Y == -1 ||
                  (columnIndex == this.ptCurrentCell.X && rowIndex == this.ptCurrentCell.Y)))) 
            {
                DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); 
                if (doubleClick) 
                {
                    OnCellContentDoubleClick(dgvce); 
                }
                else
                {
                    OnCellContentClick(dgvce); 
                }
            } 
        } 

        ///  
        protected virtual void OnCurrentCellChanged(EventArgs e)
        {
            VerifyImeRestrictedModeChanged();
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCURRENTCELLCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnCurrentCellDirtyStateChanged(EventArgs e)
        { 
            if (this.RowHeadersVisible && this.ShowEditingIcon)
            { 
                // Force the pencil to appear in the row header 
                Debug.Assert(this.ptCurrentCell.Y >= 0);
                InvalidateCellPrivate(-1, this.ptCurrentCell.Y); 
            }
            if (this.IsCurrentCellDirty && this.newRowIndex == this.ptCurrentCell.Y)
            {
                Debug.Assert(this.newRowIndex != -1); 
                Debug.Assert(this.AllowUserToAddRowsInternal);
                // First time the 'new' row gets edited. 
                // It becomes a regular row and a new 'new' row is appened. 
                this.newRowIndex = -1;
                AddNewRow(true /*createdByEditing*/); 
            }

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCURRENTCELLDIRTYSTATECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected override void OnCursorChanged(EventArgs e)
        {
            base.OnCursorChanged(e); 
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_ignoreCursorChange])
            { 
                this.oldCursor = this.Cursor; 
            }
        } 

        internal void OnDataBindingComplete(ListChangedType listChangedType)
        {
            OnDataBindingComplete(new DataGridViewBindingCompleteEventArgs(listChangedType)); 
        }
 
        ///  
        protected virtual void OnDataBindingComplete(DataGridViewBindingCompleteEventArgs e)
        { 
            DataGridViewBindingCompleteEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATABINDINGCOMPLETE] as DataGridViewBindingCompleteEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        [ 
            SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions") // Not using options when RightToLeft == false
        ]
        protected virtual void OnDataError(bool displayErrorDialogIfNoHandler, DataGridViewDataErrorEventArgs e)
        { 
            DataGridViewDataErrorEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATAERROR] as DataGridViewDataErrorEventHandler;
            if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                if (eh == null)
                { 
                    if (displayErrorDialogIfNoHandler)
                    {
                        string errorText;
                        if (e.Exception == null) 
                        {
                            errorText = SR.GetString(SR.DataGridView_ErrorMessageText_NoException); 
                        } 
                        else
                        { 
                            errorText = SR.GetString(SR.DataGridView_ErrorMessageText_WithException, e.Exception);
                        }
                        if (this.RightToLeftInternal)
                        { 
                            MessageBox.Show(errorText, SR.GetString(SR.DataGridView_ErrorMessageCaption), MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading);
                        } 
                        else 
                        {
                            MessageBox.Show(errorText, SR.GetString(SR.DataGridView_ErrorMessageCaption), MessageBoxButtons.OK, MessageBoxIcon.Error); 
                        }
                        CorrectFocus(true /*onlyIfGridHasFocus*/);
                    }
                } 
                else
                { 
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            }
        }

        internal void OnDataErrorInternal(DataGridViewDataErrorEventArgs e) 
        {
            OnDataError(!this.DesignMode /*displayErrorDialogIfNoHandler*/, e); 
        } 

        internal void OnDataGridViewElementStateChanged(DataGridViewElement element, int index, DataGridViewElementStates elementState) 
        {
            DataGridViewColumn dataGridViewColumn = element as DataGridViewColumn;
            if (dataGridViewColumn != null)
            { 
                DataGridViewColumnStateChangedEventArgs dgvcsce = new DataGridViewColumnStateChangedEventArgs(dataGridViewColumn, elementState);
 
                OnColumnStateChanged(dgvcsce); 
            }
            else 
            {
                DataGridViewRow dataGridViewRow = element as DataGridViewRow;
                if (dataGridViewRow != null)
                { 
                    DataGridViewRowStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSTATECHANGED] as DataGridViewRowStateChangedEventHandler;
 
                    if (eh != null && dataGridViewRow.DataGridView != null && dataGridViewRow.Index == -1) 
                    {
                        dataGridViewRow = this.Rows[index]; 
                    }

                    DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, elementState);
 
                    OnRowStateChanged(dataGridViewRow.Index == -1 ? index : dataGridViewRow.Index, dgvrsce);
                } 
                else 
                {
                    DataGridViewCell dataGridViewCell = element as DataGridViewCell; 
                    if (dataGridViewCell != null)
                    {
                        DataGridViewCellStateChangedEventArgs dgvcsce = new DataGridViewCellStateChangedEventArgs(dataGridViewCell, elementState);
 
                        OnCellStateChanged(dgvcsce);
                    } 
                } 
            }
 
            if ((elementState & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected)
            {
                if (this.noSelectionChangeCount > 0)
                { 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = true;
                } 
                else 
                {
                    OnSelectionChanged(EventArgs.Empty); 
                }
            }
        }
 
        internal void OnDataGridViewElementStateChanging(DataGridViewElement element, int index, DataGridViewElementStates elementState)
        { 
            DataGridViewColumn dataGridViewColumn = element as DataGridViewColumn; 
            if (dataGridViewColumn != null)
            { 
                // column.Frozen | .Visible | .ReadOnly changing
                switch (elementState)
                {
                    case DataGridViewElementStates.Frozen: 
                    case DataGridViewElementStates.Visible:
                        if (elementState == DataGridViewElementStates.Visible) 
                        { 
                            if (!dataGridViewColumn.Visible &&
                                dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader && 
                                !this.ColumnHeadersVisible)
                            {
                                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMakeAutoSizedColumnVisible));
                            } 
                            else if (!dataGridViewColumn.Visible &&
                                dataGridViewColumn.Frozen && 
                                dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) 
                            {
                                // alternative: throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMakeAutoFillColumnVisible)); 
                                //              DataGridView_CannotMakeAutoFillColumnVisible=The column cannot be made visible because its autosizing mode is Fill and it is frozen.
                                // Removing the Fill auto size mode when frozen column becomes visible (instead of throwing an exception)
                                dataGridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                            } 
                            else if (dataGridViewColumn.Visible && this.ptCurrentCell.X == dataGridViewColumn.Index)
                            { 
                                // Column of the current cell is made invisible. Trying to reset the current cell. May throw an exception. 
                                ResetCurrentCell();
                                // [....]: Should the current cell be set to some cell after the operation? 
                            }
                        }
                        if (elementState == DataGridViewElementStates.Frozen &&
                            !dataGridViewColumn.Frozen && 
                            dataGridViewColumn.Visible &&
                            dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) 
                        { 
                            // Removing the Fill auto size mode when visible column becomes frozen (instead of throwing an exception)
                            dataGridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; 
                        }
                        CorrectColumnFrozenStates(dataGridViewColumn, elementState == DataGridViewElementStates.Frozen);
                        break;
 
                    case DataGridViewElementStates.ReadOnly:
                        if (this.ptCurrentCell.X == dataGridViewColumn.Index && 
                            this.IsCurrentCellInEditMode && 
                            !dataGridViewColumn.ReadOnly &&
                            !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
                        {
                            Debug.Assert(!this.ReadOnly);
                            // Column becomes read-only. Exit editing mode.
                            if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, 
                                        DataGridViewValidateCellInternal.Always /*validateCell*/,
                                        false /*fireCellLeave*/, 
                                        false /*fireCellEnter*/, 
                                        false /*fireRowLeave*/,
                                        false /*fireRowEnter*/, 
                                        false /*fireLeave*/,
                                        true /*keepFocus*/,
                                        false /*resetCurrentCell*/,
                                        false /*resetAnchorCell*/)) 
                            {
                                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation)); 
                            } 
                        }
                        break; 

                    default:
                        Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging");
                        break; 
                }
            } 
            else 
            {
                DataGridViewRow dataGridViewRow = element as DataGridViewRow; 
                if (dataGridViewRow != null)
                {
                    // row.Frozen | .Visible | .ReadOnly changing
                    int rowIndex = ((dataGridViewRow.Index > -1) ? dataGridViewRow.Index : index); 
                    switch (elementState)
                    { 
                        case DataGridViewElementStates.Frozen: 
                        case DataGridViewElementStates.Visible:
                            if (elementState == DataGridViewElementStates.Visible && this.ptCurrentCell.Y == rowIndex) 
                            {
                                Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0);
                                // Row of the current cell is made invisible.
                                if (this.DataSource != null) 
                                {
                                    Debug.Assert(this.dataConnection != null); 
                                    Debug.Assert(this.dataConnection.CurrencyManager != null); 
                                    Debug.Assert(this.dataConnection.CurrencyManager.Position == this.ptCurrentCell.Y);
                                    // the row associated with the currency manager's position cannot be made invisble. 
                                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CurrencyManagerRowCannotBeInvisible));
                                }
                                // Trying to reset the current cell. May throw an exception.
                                ResetCurrentCell(); 
                                // [....]: Should the current cell be set to some cell after the operation?
                            } 
                            CorrectRowFrozenStates(dataGridViewRow, rowIndex, elementState == DataGridViewElementStates.Frozen); 
                            break;
 
                        case DataGridViewElementStates.ReadOnly:
                            if (this.ptCurrentCell.Y == rowIndex &&
                                (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.ReadOnly) == 0 &&
                                !this.ReadOnly && 
                                this.IsCurrentCellInEditMode &&
                                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
                            { 
                                // Row becomes read-only. Exit editing mode.
                                if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, 
                                            DataGridViewValidateCellInternal.Always /*validateCell*/,
                                            false /*fireCellLeave*/,
                                            false /*fireCellEnter*/,
                                            false /*fireRowLeave*/, 
                                            false /*fireRowEnter*/,
                                            false /*fireLeave*/, 
                                            true /*keepFocus*/, 
                                            false /*resetCurrentCell*/,
                                            false /*resetAnchorCell*/)) 
                                {
                                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation));
                                }
                            } 
                            break;
 
                        default: 
                            Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging");
                            break; 
                    }
                }
                else
                { 
                    DataGridViewCell dataGridViewCell = element as DataGridViewCell;
                    if (dataGridViewCell != null) 
                    { 
                        // cell.ReadOnly changing
                        switch (elementState) 
                        {
                            case DataGridViewElementStates.ReadOnly:
                                if (this.ptCurrentCell.X == dataGridViewCell.ColumnIndex &&
                                    this.ptCurrentCell.Y == dataGridViewCell.RowIndex && 
                                    this.IsCurrentCellInEditMode &&
                                    !dataGridViewCell.ReadOnly && 
                                    !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
                                {
                                    Debug.Assert(!this.Columns[dataGridViewCell.ColumnIndex].ReadOnly); 
                                    Debug.Assert(!this.Rows[dataGridViewCell.RowIndex].ReadOnly);
                                    Debug.Assert(!this.ReadOnly);
                                    // Current cell becomes read-only. Exit editing mode.
                                    if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, 
                                                DataGridViewValidateCellInternal.Always /*validateCell*/,
                                                false /*fireCellLeave*/, 
                                                false /*fireCellEnter*/, 
                                                false /*fireRowLeave*/,
                                                false /*fireRowEnter*/, 
                                                false /*fireLeave*/,
                                                true /*keepFocus*/,
                                                false /*resetCurrentCell*/,
                                                false /*resetAnchorCell*/)) 
                                    {
                                        throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation)); 
                                    } 
                                }
                                break; 

                            default:
                                Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging");
                                break; 
                        }
                    } 
                    else 
                    {
                        Debug.Fail("Unexpected DataGridViewElement type in DataGridView.OnDataGridViewElementStateChanging"); 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnDataMemberChanged(EventArgs e) 
        {
            RefreshColumnsAndRows(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATAMEMBERCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
 
            if (this.dataConnection != null && this.dataConnection.CurrencyManager != null)
            { 
                OnDataBindingComplete(ListChangedType.Reset);
            }
        }
 
        /// 
        protected virtual void OnDataSourceChanged(EventArgs e) 
        { 
            RefreshColumnsAndRows();
            InvalidateRowHeights(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATASOURCECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
 
            if (this.dataConnection != null && this.dataConnection.CurrencyManager != null)
            { 
                OnDataBindingComplete(ListChangedType.Reset);
            }
        }
 
        /// 
        protected virtual void OnDefaultCellStyleChanged(EventArgs e) 
        { 
            DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
            if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize) 
            {
                Invalidate();
            }
            else 
            {
                OnGlobalAutoSize(); 
                if (this.editingControl != null) 
                {
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); 
                }
            }

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected virtual void OnDefaultValuesNeeded(DataGridViewRowEventArgs e)
        { 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDEFAULTVALUESNEEDED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected override void OnDoubleClick(EventArgs e) 
        {
            base.OnDoubleClick(e); 
 
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                MouseEventArgs me = e as MouseEventArgs;
                if (me != null)
                {
                    HitTestInfo hti = HitTest(me.X, me.Y); 
                    if (hti.Type != DataGridViewHitTestType.None &&
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar && 
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar && 
                        me.Button == MouseButtons.Left)
                    { 
                        OnCellDoubleClick(new DataGridViewCellEventArgs(hti.col, hti.row));
                    }
                }
            } 
        }
 
        ///  
        protected virtual void OnEditingControlShowing(DataGridViewEditingControlShowingEventArgs e)
        { 
            DataGridViewEditingControlShowingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWEDITINGCONTROLSHOWING] as DataGridViewEditingControlShowingEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnEditModeChanged(EventArgs e) 
        {
            if (this.Focused &&
                this.EditMode == DataGridViewEditMode.EditOnEnter &&
                this.ptCurrentCell.X > -1 && 
                !this.IsCurrentCellInEditMode)
            { 
                // New edit mode is EditOnEnter and there is an editable current cell, try to go to edit mode. 
                BeginEditInternal(true /*selectAll*/);
            } 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWEDITMODECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        ///  
        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);
            if (GetAnyDisposingInHierarchy()) 
            {
                return; 
            } 

            if (this.IsHandleCreated && this.Enabled) 
            {
                if (this.vertScrollBar != null && this.vertScrollBar.Visible)
                {
                    this.vertScrollBar.Enabled = true; 
                }
                if (this.horizScrollBar != null && this.horizScrollBar.Visible) 
                { 
                    this.horizScrollBar.Enabled = true;
                } 
            }
        }

        ///  
        protected override void OnEnter(EventArgs e)
        { 
            if (this.editingControl != null && this.editingControl.ContainsFocus) 
            {
                return; 
            }

            base.OnEnter(e);
 
            // vsw 453314: there are cases when a control is on the designer and it still receives the OnEnter event.
            // Guard against this. 
            if (this.DesignMode) 
            {
                return; 
            }

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey] = false;
 
            if (this.ptCurrentCell.X > -1)
            { 
                DataGridViewCell dataGridViewCell = null; 
                // We're re-entering a row we already entered earlier. The first time we entered the row,
                // the DataGridView didn't have focus. This time it does. We don't want to recreate the new row a second time. 
                OnRowEnter(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*canCreateNewRow*/, false /*validationFailureOccurred*/);
                if (this.ptCurrentCell.X == -1)
                {
                    return; 
                }
                OnCellEnter(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); 
            } 
            else if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown])
            { 
                // Focus is given to the DataGridView control via a the TAB key.
                MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/);
            }
 
            if (this.ptCurrentCell.X > -1 &&
                !this.IsCurrentCellInEditMode) 
            { 
                if (this.EditMode == DataGridViewEditMode.EditOnEnter ||
                   (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)) 
                {
                    BeginEditInternal(true /*selectAll*/);
                    if (this.ptCurrentCell.X > -1 && this.CurrentCellInternal.EditType == null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown])
                    { 
                        // The current cell does not have an edit type so the data grid view did not put an edit control on top.
                        // We should invalidate the current cell so that the dataGridView repaints the focus around the current cell. 
                        // But do that only if the dataGridView did not get the focus via mouse. 
                        InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/);
                    } 
                }
                else if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown])
                {
                    // When the focus is given to the DataGridView control via mouse 
                    // the dataGridView changes selection so it invalidates the current cell anyway
                    // 
                    // In any other case Invalidate the current cell so the dataGridView repaints the focus around the current cell 
                    InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/);
                } 
            }
        }

        ///  
        protected override void OnFontChanged(EventArgs e)
        { 
            base.OnFontChanged(e); 

            if (GetAnyDisposingInHierarchy ()) 
            {
                return;
            }
 
            // Change may be due to an ambient font change.
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] && 
                this.ColumnHeadersDefaultCellStyle.Font != base.Font) 
            {
                this.ColumnHeadersDefaultCellStyle.Font = base.Font; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true;
                OnColumnHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] && 
                this.RowHeadersDefaultCellStyle.Font != base.Font) 
            {
                this.RowHeadersDefaultCellStyle.Font = base.Font; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true;
                OnRowHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 

            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] && 
                this.DefaultCellStyle.Font != base.Font) 
            {
                this.DefaultCellStyle.Font = base.Font; 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true;
                OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs);
            } 
        }
 
        ///  
        protected override void OnForeColorChanged(EventArgs e)
        { 
            base.OnForeColorChanged(e);
            if (GetAnyDisposingInHierarchy())
            {
                return; 
            }
 
            // Change may be due to an ambient forecolor change. 
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] && this.DefaultCellStyle.ForeColor != base.ForeColor)
            { 
                this.DefaultCellStyle.ForeColor = base.ForeColor;
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] = true;
                this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = false;
                OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs); 
            }
        } 
 
        private void OnGlobalAutoSize()
        { 
            Invalidate();

            if (this.noAutoSizeCount > 0)
            { 
                return;
            } 
 
            bool autoSizeRowHeaders = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                                      this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            if (autoSizeRowHeaders)
            {
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode,
                                          this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize /*fixedColumnHeadersHeight*/, 
                                          this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None /*fixedRowsHeight*/);
            } 
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, false /*fixedColumnsWidth*/); 
            }
            if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/); 
            }
            AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/); 
 
            if (autoSizeRowHeaders &&
                (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize || this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)) 
            {
                // Second round of row headers autosizing
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            } 
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
            { 
                // Second round of column headers autosizing 
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            } 
            if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)
            {
                // Second round of rows autosizing
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
        } 
 
        /// 
        protected override void OnGotFocus(EventArgs e) 
        {
            base.OnGotFocus(e);
            if (this.ptCurrentCell.X != -1)
            { 
                InvalidateCell(this.ptCurrentCell.X, this.ptCurrentCell.Y);
            } 
 
            // Inform Accessibility that our current cell contains the focus.
            if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] && 
                (!this.dataGridViewOper[DATAGRIDVIEWOPER_inEndEdit] || this.EditMode != DataGridViewEditMode.EditOnEnter) &&
                (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] || this.EditMode != DataGridViewEditMode.EditOnEnter) &&
                this.ptCurrentCell.X > -1)
            { 
                // The name is misleading ( the current cell did not change ).
                // However, AccessibilityNotifyCurrentCellChanged is now a public method so we can't change its name 
                // to better reflect its purpose. 
                AccessibilityNotifyCurrentCellChanged(this.ptCurrentCell);
            } 
        }

        /// 
        protected virtual void OnGridColorChanged(EventArgs e) 
        {
            InvalidateInside(); 
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWGRIDCOLORCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
        } 

        ///  
        protected override void OnHandleCreated(EventArgs e) 
        {
            base.OnHandleCreated(e); 
            DisposeCachedGraphics();

            if (this.layout.dirty)
            { 
                PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
            } 
            if (this.ptCurrentCell.X == -1) 
            {
                MakeFirstDisplayedCellCurrentCell(false /*includeNewRow*/); 
            }
            else
            {
                ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*forCurrentCellChange*/); 
            }
 
            // do the AutoSize work that was skipped during initialization 
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle])
            { 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = false;
                OnGlobalAutoSize();
            }
            SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(this.OnUserPreferenceChanged); 
        }
 
        ///  
        protected override void OnHandleDestroyed(EventArgs e)
        { 
            SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(this.OnUserPreferenceChanged);
            base.OnHandleDestroyed(e);
        }
 
        internal void OnInsertedColumn_PreNotification(DataGridViewColumn dataGridViewColumn)
        { 
            // Fix the OldFirstDisplayedScrollingCol 
            this.displayedBandsInfo.CorrectColumnIndexAfterInsertion(dataGridViewColumn.Index, 1);
 
            // Fix the Index of all following columns
            CorrectColumnIndexesAfterInsertion(dataGridViewColumn, 1);

            // Same effect as appending a column 
            OnAddedColumn(dataGridViewColumn);
        } 
 
        internal void OnInsertedColumn_PostNotification(Point newCurrentCell)
        { 
            // Update current cell if needed
            if (newCurrentCell.X != -1)
            {
                Debug.Assert(this.ptCurrentCell.X == -1); 
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X,
                                                              newCurrentCell.Y, 
                                                              true, 
                                                              false,
                                                              false, 
                                                              false /*clearSelection*/,
                                                              this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 1 /*forceCurrentCellSelection*/);
                Debug.Assert(success);
            } 
        }
 
        internal void OnInsertedRow_PreNotification(int rowIndex, int insertionCount) 
        {
            Debug.Assert(rowIndex >= 0); 
            Debug.Assert(insertionCount > 0);

            // Fix the OldFirstDisplayedScrollingRow
            this.displayedBandsInfo.CorrectRowIndexAfterInsertion(rowIndex, insertionCount); 

            // Fix the Index of all following rows 
            CorrectRowIndexesAfterInsertion(rowIndex, insertionCount); 

            // Next, same effect as adding a row 
            OnAddedRow_PreNotification(rowIndex);
        }

        internal void OnInsertedRow_PostNotification(int rowIndex, Point newCurrentCell, bool lastInsertion) 
        {
            Debug.Assert(rowIndex >= 0); 
 
            // Same effect as adding a row
            OnAddedRow_PostNotification(rowIndex); 

            // Update current cell if needed
            if (lastInsertion && newCurrentCell.Y != -1)
            { 
                Debug.Assert(this.ptCurrentCell.X == -1);
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, 
                                                              newCurrentCell.Y, 
                                                              true,
                                                              false, 
                                                              false,
                                                              false /*clearSelection*/,
                                                              this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 1 /*forceCurrentCellSelection*/);
                Debug.Assert(success); 
            }
        } 
 
        internal void OnInsertedRows_PreNotification(int rowIndex, DataGridViewRow[] dataGridViewRows)
        { 
            Debug.Assert(rowIndex >= 0);
            Debug.Assert(dataGridViewRows != null);
            Debug.Assert(dataGridViewRows.Length > 0);
 
            // Fix the OldFirstDisplayedScrollingRow
            this.displayedBandsInfo.CorrectRowIndexAfterInsertion(rowIndex, dataGridViewRows.Length); 
 
            // Fix the Index of all following rows
            CorrectRowIndexesAfterInsertion(rowIndex, dataGridViewRows.Length); 

            // Next, same effect as adding the rows
            OnAddedRows_PreNotification(dataGridViewRows);
        } 

        internal void OnInsertedRows_PostNotification(DataGridViewRow[] dataGridViewRows, Point newCurrentCell) 
        { 
            Debug.Assert(dataGridViewRows != null);
            Debug.Assert(dataGridViewRows.Length > 0); 

            // Same effect as adding the rows
            OnAddedRows_PostNotification(dataGridViewRows);
 
            // Update current cell if needed
            if (newCurrentCell.Y != -1) 
            { 
                Debug.Assert(this.ptCurrentCell.X == -1);
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, newCurrentCell.Y, true, false, false, false /*clearSelection*/, false /*forceCurrentCellSelection*/); 
                Debug.Assert(success);
            }
        }
 
        internal void OnInsertingColumn(int columnIndexInserted, DataGridViewColumn dataGridViewColumn, out Point newCurrentCell)
        { 
            Debug.Assert(dataGridViewColumn != null); 

            if (dataGridViewColumn.DataGridView != null) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView));
            }
 
            if (!this.InInitialization &&
                dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && 
                (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || 
                 this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect))
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString()));
            }

            if (dataGridViewColumn.Visible) 
            {
                // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used 
 
                // Make sure the column does not autosize based only on header while column headers are invisible
                if (!this.ColumnHeadersVisible && 
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader)))
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn));
                } 

                // Make sure the column is not frozen and auto fills 
                if (dataGridViewColumn.Frozen && 
                    (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill)))
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn));
                }
            }
 
            // check for correctness of frozen state - throws exception if state is incorrect.
            CorrectColumnFrozenState(dataGridViewColumn, columnIndexInserted); 
 
            // Reset current cell if there is one, no matter the relative position of the columns involved
            if (this.ptCurrentCell.X != -1) 
            {
                newCurrentCell = new Point(columnIndexInserted <= this.ptCurrentCell.X ? this.ptCurrentCell.X + 1 : this.ptCurrentCell.X,
                     this.ptCurrentCell.Y);
                ResetCurrentCell(); 
            }
            else 
            { 
                newCurrentCell = new Point(-1, -1);
            } 

            // prepare the existing rows by inserting cells of correct type
            if (this.Rows.Count > 0)
            { 
                // Only require a default cell type when there are rows to fill
                if (dataGridViewColumn.CellType == null) 
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn));
                } 

                if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1)
                {
                    // New row needs to be unshared before addition of new cell with a Value != null 
                    DataGridViewRow newRow = this.Rows[this.newRowIndex];
                } 
 
                int newColumnCount = this.Columns.Count + 1;
 
                try
                {
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
                    { 
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                        if (dataGridViewRow.Cells.Count < newColumnCount) 
                        { 
                            DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone();
                            dataGridViewRow.Cells.InsertInternal(columnIndexInserted, dataGridViewCellNew); 
                            if (rowIndex == this.newRowIndex)
                            {
                                dataGridViewCellNew.Value = dataGridViewCellNew.DefaultNewRowValue;
                            } 
                            dataGridViewCellNew.DataGridViewInternal = this;
                            dataGridViewCellNew.OwningRowInternal = dataGridViewRow; 
                            dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn; 
                        }
                    } 
                }
                catch
                {
                    // An error occurred while inserting the cells. Revert all the insertions. 
                    for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
                    { 
                        DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); 
                        if (dataGridViewRow.Cells.Count == newColumnCount)
                        { 
                            dataGridViewRow.Cells.RemoveAtInternal(columnIndexInserted);
                        }
                        else
                        { 
                            Debug.Assert(dataGridViewRow.Cells.Count < newColumnCount);
                            break; 
                        } 
                    }
                    throw; 
                }
            }

            // Update the indexes of selected columns to compensate for the insertion of this column 
            switch (this.SelectionMode)
            { 
                case DataGridViewSelectionMode.FullColumnSelect: 
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                    int columnEntries = this.selectedBandIndexes.Count; 
                    int columnEntry = 0;
                    while (columnEntry < columnEntries)
                    {
                        int columnIndex = this.selectedBandIndexes[columnEntry]; 
                        if (columnIndexInserted <= columnIndex)
                        { 
                            this.selectedBandIndexes[columnEntry] = columnIndex + 1; 
                        }
                        columnEntry++; 
                    }
                    if (this.selectedBandSnapshotIndexes != null)
                    {
                        columnEntries = this.selectedBandSnapshotIndexes.Count; 
                        columnEntry = 0;
                        while (columnEntry < columnEntries) 
                        { 
                            int columnIndex = this.selectedBandSnapshotIndexes[columnEntry];
                            if (columnIndexInserted <= columnIndex) 
                            {
                                this.selectedBandSnapshotIndexes[columnEntry] = columnIndex + 1;
                            }
                            columnEntry++; 
                        }
                    } 
                    break; 
            }
        } 

        internal void OnInsertingRow(int rowIndexInserted,
                                     DataGridViewRow dataGridViewRow,
                                     DataGridViewElementStates rowState, 
                                     ref Point newCurrentCell,
                                     bool firstInsertion, 
                                     int insertionCount, 
                                     bool force)
        { 
            // Reset the current cell's address if it's after the inserted row.
            if (firstInsertion)
            {
                if (this.ptCurrentCell.Y != -1 && rowIndexInserted <= this.ptCurrentCell.Y) 
                {
                    newCurrentCell = new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y + insertionCount); 
                    if (force) 
                    {
                        // When force is true, the underlying data was already added, therefore we need to avoid accessing any back-end data 
                        // since we might be off by 1 row.
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true;
                        bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false);
                        Debug.Assert(success); 
                    }
                    else 
                    { 
                        ResetCurrentCell();
                    } 
                }
                else
                {
                    newCurrentCell = new Point(-1, -1); 
                }
            } 
            else 
            {
                if (newCurrentCell.Y != -1) 
                {
                    newCurrentCell.Y += insertionCount;
                }
            } 

            // For now same checks as for OnAddingRow 
            OnAddingRow(dataGridViewRow, rowState, false /*checkFrozenState*/); 

            // check for correctness of frozen state - throws exception if state is incorrect. 
            CorrectRowFrozenState(dataGridViewRow, rowState, rowIndexInserted);

            // Update the indexes of selected rows to compensate for the insertion of this row
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.FullRowSelect: 
                case DataGridViewSelectionMode.RowHeaderSelect: 
                    int rowEntries = this.selectedBandIndexes.Count;
                    int rowEntry = 0; 
                    while (rowEntry < rowEntries)
                    {
                        int rowIndex = this.selectedBandIndexes[rowEntry];
                        if (rowIndexInserted <= rowIndex) 
                        {
                            this.selectedBandIndexes[rowEntry] = rowIndex + insertionCount; 
                        } 
                        rowEntry++;
                    } 
                    if (this.selectedBandSnapshotIndexes != null)
                    {
                        rowEntries = this.selectedBandSnapshotIndexes.Count;
                        rowEntry = 0; 
                        while (rowEntry < rowEntries)
                        { 
                            int rowIndex = this.selectedBandSnapshotIndexes[rowEntry]; 
                            if (rowIndexInserted <= rowIndex)
                            { 
                                this.selectedBandSnapshotIndexes[rowEntry] = rowIndex + insertionCount;
                            }
                            rowEntry++;
                        } 
                    }
                    break; 
            } 
        }
 
        internal void OnInsertingRows(int rowIndexInserted, DataGridViewRow[] dataGridViewRows, ref Point newCurrentCell)
        {
            Debug.Assert(dataGridViewRows != null);
 
            // Reset the current cell's address if it's after the inserted row.
            if (this.ptCurrentCell.Y != -1 && rowIndexInserted <= this.ptCurrentCell.Y) 
            { 
                newCurrentCell = new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y + dataGridViewRows.Length);
                ResetCurrentCell(); 
            }
            else
            {
                newCurrentCell = new Point(-1, -1); 
            }
 
            // For now almost same checks as for OnAddingRows 
            // OnAddingRows checks for Selected status of rows.
            OnAddingRows(dataGridViewRows, false /*checkFrozenStates*/); 

            // Check for Frozen state correctness
            CorrectRowFrozenStates(dataGridViewRows, rowIndexInserted);
 
            // Update the indexes of selected rows to compensate for the insertion of this row
            switch (this.SelectionMode) 
            { 
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect: 
                    int rowEntries = this.selectedBandIndexes.Count;
                    int rowEntry = 0;
                    while (rowEntry < rowEntries)
                    { 
                        int rowIndex = this.selectedBandIndexes[rowEntry];
                        if (rowIndexInserted <= rowIndex) 
                        { 
                            this.selectedBandIndexes[rowEntry] = rowIndex + dataGridViewRows.Length;
                        } 
                        rowEntry++;
                    }
                    if (this.selectedBandSnapshotIndexes != null)
                    { 
                        rowEntries = this.selectedBandSnapshotIndexes.Count;
                        rowEntry = 0; 
                        while (rowEntry < rowEntries) 
                        {
                            int rowIndex = this.selectedBandSnapshotIndexes[rowEntry]; 
                            if (rowIndexInserted <= rowIndex)
                            {
                                this.selectedBandSnapshotIndexes[rowEntry] = rowIndex + dataGridViewRows.Length;
                            } 
                            rowEntry++;
                        } 
                    } 
                    break;
            } 
        }

        /// 
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override void OnKeyDown(KeyEventArgs e)
        { 
            base.OnKeyDown(e); 
            if (e.Handled)
            { 
                return;
            }

            // Forward key down to current cell if any 
            if (this.ptCurrentCell.X != -1)
            { 
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal; 
                Debug.Assert(dataGridViewCell != null);
                if (dataGridViewCell.KeyDownUnsharesRowInternal(e, this.ptCurrentCell.Y)) 
                {
                    DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y];
                    this.CurrentCellInternal.OnKeyDownInternal(e, this.ptCurrentCell.Y);
                } 
                else
                { 
                    dataGridViewCell.OnKeyDownInternal(e, this.ptCurrentCell.Y); 
                }
            } 

            if (!e.Handled)
            {
                switch (e.KeyData & Keys.KeyCode) 
                {
                    case Keys.A: 
                    case Keys.C: 
                    case Keys.D0:
                    case Keys.NumPad0: 
                    case Keys.Delete:
                    case Keys.Down:
                    case Keys.F2:
                    case Keys.End: 
                    case Keys.Enter:
                    case Keys.Escape: 
                    case Keys.Home: 
                    case Keys.Insert:
                    case Keys.Left: 
                    case Keys.Next:
                    case Keys.Prior:
                    case Keys.Right:
                    case Keys.Space: 
                    case Keys.Tab:
                    case Keys.Up: 
                    { 
                        e.Handled = ProcessDataGridViewKey(e);
                        break; 
                    }
                }
            }
        } 

        ///  
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override void OnKeyPress(KeyPressEventArgs e)
        { 
            base.OnKeyPress(e);
            if (e.Handled)
            {
                return; 
            }
 
            // Forward key press to current cell if any 
            if (this.ptCurrentCell.X != -1)
            { 
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                Debug.Assert(dataGridViewCell != null);
                if (dataGridViewCell.KeyPressUnsharesRowInternal(e, this.ptCurrentCell.Y))
                { 
                    DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y];
                    this.CurrentCellInternal.OnKeyPressInternal(e, this.ptCurrentCell.Y); 
                } 
                else
                { 
                    dataGridViewCell.OnKeyPressInternal(e, this.ptCurrentCell.Y);
                }
            }
        } 

        ///  
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override void OnKeyUp(KeyEventArgs e)
        { 
            base.OnKeyUp(e);
            if (e.Handled)
            {
                return; 
            }
 
            // Forward key up to current cell if any 
            if (this.ptCurrentCell.X != -1)
            { 
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                Debug.Assert(dataGridViewCell != null);
                if (dataGridViewCell.KeyUpUnsharesRowInternal(e, this.ptCurrentCell.Y))
                { 
                    DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y];
                    this.CurrentCellInternal.OnKeyUpInternal(e, this.ptCurrentCell.Y); 
                } 
                else
                { 
                    dataGridViewCell.OnKeyUpInternal(e, this.ptCurrentCell.Y);
                }
            }
        } 

        ///  
        protected override void OnLayout(LayoutEventArgs e) 
        {
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging]) 
            {
                return;
            }
 
            base.OnLayout(e);
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
            if (this.RightToLeftInternal) 
            {
                Invalidate(); 
            }
            if (this.editingControl != null)
            {
                PositionEditingControl(true, true, false); 
            }
        } 
 
        /// 
        protected override void OnLeave(EventArgs e) 
        {
            if (this.ptCurrentCell.X > -1 && !this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey])
            {
                DataGridViewCell dataGridViewCell = null; 
                OnCellLeave(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                if (this.ptCurrentCell.X == -1) 
                { 
                    return;
                } 
                OnRowLeave(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y);
            }

            if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey]) 
            {
                base.OnLeave(e); 
 
                // 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*/);
                }
            } 
        }
 
        ///  
        protected override void OnLostFocus(EventArgs e)
        { 
            base.OnLostFocus(e);
            if (this.ptCurrentCell.X != -1)
            {
                InvalidateCell(this.ptCurrentCell.X, this.ptCurrentCell.Y); 
            }
        } 
 
        /// 
        protected override void OnMouseClick(MouseEventArgs e) 
        {
            bool mouseClickRaised = false;

            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
            {
                HitTestInfo hti = HitTest(e.X, e.Y);

                if (this.ptMouseDownCell.X == hti.col && 
                    this.ptMouseDownCell.Y == hti.row &&
                    (e.Button != MouseButtons.Left || 
                     this.ptMouseDownCell.X == -1 || 
                     this.ptMouseDownCell.Y == -1 ||
                     (this.ptMouseDownCell.X == this.ptCurrentCell.X && 
                      this.ptMouseDownCell.Y == this.ptCurrentCell.Y)))
                {
                    DataGridViewCellMouseEventArgs dgvcme = null;
                    if (hti.Type != DataGridViewHitTestType.None && 
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
                    { 
                        int mouseX = e.X - hti.ColumnX;
                        if (this.RightToLeftInternal) 
                        {
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness);
                        }
                        dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e); 
                        RecordCellMouseClick(dgvcme);
                        if (e.Button == MouseButtons.Left) 
                        { 
                            OnCellClick(new DataGridViewCellEventArgs(hti.col, hti.row));
                        } 
                        base.OnMouseClick(e);
                        mouseClickRaised = true;
                        if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                        { 
                            OnCellMouseClick(dgvcme);
                        } 
                    } 
                    else
                    { 
                        base.OnMouseClick(e);
                        mouseClickRaised = true;
                    }
 
                    if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation])
                    { 
                        switch (hti.typeInternal) 
                        {
                            case DataGridViewHitTestTypeInternal.ColumnHeader: 
                            case DataGridViewHitTestTypeInternal.ColumnHeaderLeft:
                            case DataGridViewHitTestTypeInternal.ColumnHeaderRight:
                            case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft:
                            { 
                                Debug.Assert(dgvcme != null);
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) 
                                { 
                                    OnColumnHeaderMouseClick(dgvcme);
                                } 
                                break;
                            }

                            case DataGridViewHitTestTypeInternal.RowHeader: 
                            {
                                Debug.Assert(dgvcme != null); 
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) 
                                {
                                    OnRowHeaderMouseClick(dgvcme); 
                                }
                                break;
                            }
                        } 
                    }
                } 
            } 
            if (!mouseClickRaised)
            { 
                base.OnMouseClick(e);
            }
        }
 
        /// 
        protected override void OnMouseDoubleClick(MouseEventArgs e) 
        { 
            base.OnMouseDoubleClick(e);
 
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize])
            { 
                HitTestInfo hti = HitTest(e.X, e.Y); 

                if (this.ptMouseDownCell.X == hti.col && this.ptMouseDownCell.Y == hti.row) 
                {
                    DataGridViewCellMouseEventArgs dgvcme = null;
                    if (hti.Type != DataGridViewHitTestType.None &&
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar && 
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar)
                    { 
                        int mouseX = e.X - hti.ColumnX; 
                        if (this.RightToLeftInternal)
                        { 
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness);
                        }
                        dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e);
                        OnCellMouseDoubleClick(dgvcme); 
                    }
 
                    if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) 
                    {
                        switch (hti.typeInternal) 
                        {
                            case DataGridViewHitTestTypeInternal.ColumnHeader:
                            case DataGridViewHitTestTypeInternal.ColumnHeaderLeft:
                            case DataGridViewHitTestTypeInternal.ColumnHeaderRight: 
                            case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft:
                            { 
                                Debug.Assert(dgvcme != null); 
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                                { 
                                    OnColumnHeaderMouseDoubleClick(dgvcme);
                                }
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.ColumnResizeLeft: 
                            case DataGridViewHitTestTypeInternal.ColumnResizeRight: 
                            {
                                int columnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight) ? hti.col : hti.adjacentCol; 
                                if (columnIndex < this.Columns.Count)
                                {
                                    HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/);
                                    DataGridViewColumnDividerDoubleClickEventArgs dgvcddce = new DataGridViewColumnDividerDoubleClickEventArgs(columnIndex, hme); 
                                    Debug.Assert(this.Columns[columnIndex].Resizable == DataGridViewTriState.True);
                                    OnColumnDividerDoubleClick(dgvcddce); 
                                } 
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop:
                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom:
                            case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: 
                            case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom:
                            { 
                                HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); 
                                DataGridViewRowDividerDoubleClickEventArgs dgvrddce = new DataGridViewRowDividerDoubleClickEventArgs(-1, hme);
                                Debug.Assert(this.columnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing); 
                                OnRowDividerDoubleClick(dgvrddce);
                                break;
                            }
 
                            case DataGridViewHitTestTypeInternal.RowHeader:
                            { 
                                Debug.Assert(dgvcme != null); 
                                if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                                { 
                                    OnRowHeaderMouseDoubleClick(dgvcme);
                                }
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.RowResizeBottom: 
                            case DataGridViewHitTestTypeInternal.RowResizeTop: 
                            {
                                int rowIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom) ? hti.row : hti.adjacentRow; 
                                if (rowIndex < this.Rows.Count)
                                {
                                    HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/);
                                    DataGridViewRowDividerDoubleClickEventArgs dgvrddce = new DataGridViewRowDividerDoubleClickEventArgs(rowIndex, hme); 
                                    Debug.Assert(this.Rows[rowIndex].Resizable == DataGridViewTriState.True);
                                    OnRowDividerDoubleClick(dgvrddce); 
                                } 
                                break;
                            } 

                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft:
                            case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight:
                            case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft: 
                            case DataGridViewHitTestTypeInternal.RowHeadersResizeRight:
                            { 
                                HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); 
                                DataGridViewColumnDividerDoubleClickEventArgs dgvcddce = new DataGridViewColumnDividerDoubleClickEventArgs(-1, hme);
                                Debug.Assert(this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing); 
                                OnColumnDividerDoubleClick(dgvcddce);
                                break;
                            }
                        } 
                    }
                } 
            } 
        }
 
        /// 
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]) 
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves] = true; 
            } 

            base.OnMouseDown(e); 

            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls])
            {
                return; 
            }
 
            if (this.ptMouseDownCell.X != -2) 
            {
                // Happens when user pushes the mouse wheel down while the left mouse button is already down 
                Debug.Assert(this.ptMouseDownCell.Y != -2);
                return;
            }
 
            HitTestInfo hti = HitTest(e.X, e.Y);
 
            if (hti.Type != DataGridViewHitTestType.None && 
                hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
            {
                this.ptMouseDownCell.X = hti.col;
                this.ptMouseDownCell.Y = hti.row;
                this.ptMouseDownGridCoord = new Point(e.X, e.Y); 
                int mouseX = e.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, e.Y - hti.RowY, e);
                OnCellMouseDown(dgvcme);
            }
        } 

        ///  
        protected override void OnMouseEnter(EventArgs e) 
        {
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] && 
                !this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] &&
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] &&
                !this.toolTipControl.Activated)
            { 
                base.OnMouseEnter(e);
            } 
 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] = false;
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] = false; 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] = false;
        }

        ///  
        protected override void OnMouseLeave(EventArgs e)
        { 
            // when the mouse leaves the dataGridView control, reset the cursor to the previously cached one 
            if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet])
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false;
                this.CursorInternal = this.oldCursor;
            }
 
            bool mouseOverEditingControl = this.MouseOverEditingControl;
            bool mouseOverEditingPanel = this.MouseOverEditingPanel; 
            bool mouseOverToolTipControl = this.toolTipControl.Activated && this.ClientRectangle.Contains(PointToClient(Control.MousePosition)); 

            if (!mouseOverEditingPanel && !mouseOverEditingControl && !mouseOverToolTipControl && this.ptMouseEnteredCell.X != -2) 
            {
                if (this.ptMouseEnteredCell.X >= -1 && this.ptMouseEnteredCell.X < this.Columns.Count &&
                    this.ptMouseEnteredCell.Y >= -1 && this.ptMouseEnteredCell.Y < this.Rows.Count)
                { 
                    DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(this.ptMouseEnteredCell.X, this.ptMouseEnteredCell.Y);
                    OnCellMouseLeave(dgvce); 
                } 
                else
                { 
                    this.ptMouseEnteredCell.X = this.ptMouseEnteredCell.Y = -2;
                }
            }
 
            ResetTrackingState();
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves] = false; 
 
            if (!mouseOverEditingPanel && !mouseOverEditingControl && !mouseOverToolTipControl && !this.MouseOverScrollBar)
            { 
                this.toolTipControl.Activate(false /*activate*/);
                base.OnMouseLeave(e);
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] = true;
            } 
        }
 
        ///  
        protected override void OnMouseMove(MouseEventArgs e)
        { 
            base.OnMouseMove(e);

            HitTestInfo hti = HitTest(e.X, e.Y);
 
            UpdateMouseEnteredCell(hti, e);
 
            // We need to give UI feedback when the user is resizing a column 
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize])
            { 
                MoveRowHeadersOrColumnResize(e);
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize])
            { 
                MoveColumnHeadersOrRowResize(e);
            } 
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) 
            {
                MoveColumnRelocation(e, hti); 
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize])
            {
                MoveColumnHeadersOrRowResize(e); 
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
            { 
                MoveRowHeadersOrColumnResize(e);
            } 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] ||
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] ||
                ((hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.RowHeadersResizeLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.RowHeadersResizeRight) && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]))
            { 
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) 
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; 
                    this.oldCursor = this.Cursor;
                }
                this.CursorInternal = Cursors.SizeWE;
                return; 
            }
            else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] || 
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || 
                ((hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeTop ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom) && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && 
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])) 
            {
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet])
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; 
                    this.oldCursor = this.Cursor;
                } 
                this.CursorInternal = Cursors.SizeNS; 
                return;
            } 
            /* Whidbey bug 156884 - no longer show hand cursor
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderLeft ||
                hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderRight || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft || 
                hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight))
            { 
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet])
                {
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true;
                    this.oldCursor = this.Cursor; 
                }
                this.CursorInternal = Cursors.Hand; 
                return; 
            }*/
            else if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false;
                this.CursorInternal = this.oldCursor;
            } 

            if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] || 
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] || 
                this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])
            { 
                int xOffset, yOffset, mouseX = e.X, mouseY = e.Y;
                if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset))
                {
                    if (xOffset == 0) 
                    {
                        if (this.horizScrollTimer != null && this.horizScrollTimer.Enabled) 
                        { 
                            // Mouse's X came in-bound - need to stop the horizontal scroll timer
                            this.horizScrollTimer.Enabled = false; 
                        }
                    }
                    else if (this.horizScrollTimer == null || !this.horizScrollTimer.Enabled)
                    { 
                        // Need to start delayed horizontal scroll
                        this.HorizScrollTimer.Interval = GetColumnScrollRate(Math.Abs(xOffset)); 
                        this.HorizScrollTimer.Enabled = true; 
                    }
 
                    if (yOffset == 0)
                    {
                        if (this.vertScrollTimer != null && this.vertScrollTimer.Enabled)
                        { 
                            // Mouse's Y came in-bound - need to stop the vertical scroll timer
                            this.vertScrollTimer.Enabled = false; 
                        } 
                    }
                    else if (this.vertScrollTimer == null || !this.vertScrollTimer.Enabled) 
                    {
                        // Need to start delayed vertical scroll
                        this.VertScrollTimer.Interval = GetRowScrollRate(Math.Abs(yOffset));
                        this.VertScrollTimer.Enabled = true; 
                    }
 
                    if (this.HorizScrollTimer.Enabled || this.VertScrollTimer.Enabled) 
                    {
                        return; 
                    }

                    if (/*!this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] && */
                        hti.Type != DataGridViewHitTestType.None && 
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
                    { 
                        if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && hti.col >= 0)
                        { 
                            OnColumnSelectMouseMove(hti);
                        }
                        else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && hti.row >= 0)
                        { 
                            OnRowSelectMouseMove(hti);
                        } 
                        else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) 
                        {
                            OnCellSelectMouseMove(hti); 
                        }
                    }
                }
            } 
#if DEBUG
            else 
            { 
                Debug.Assert(this.vertScrollTimer == null || !this.vertScrollTimer.Enabled);
                Debug.Assert(this.horizScrollTimer == null || !this.horizScrollTimer.Enabled); 
            }
#endif
            if (!this.toolTipControl.Activated)
            { 
                //
                // After processing the MouseMove event, the tool tip is still not activated. 
                // Reset the tool tip cell. 
                this.ptToolTipCell = new Point(-1, -1);
            } 
        }

        /// 
        protected override void OnMouseUp(MouseEventArgs e) 
        {
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]) 
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] = false;
 
                HitTestInfo hti = HitTest(e.X, e.Y);

                if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] &&
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && 
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] &&
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && 
                    !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
                {
                    if (hti.Type != DataGridViewHitTestType.None && 
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar)
                    {
                        int mouseX = e.X - hti.ColumnX; 
                        if (this.RightToLeftInternal)
                        { 
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); 
                        }
                        DataGridViewCellMouseEventArgs dgvcme; 
                        if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble])
                        {
                            MouseEventArgs meTmp = new MouseEventArgs(e.Button, 2, e.X, e.Y, e.Delta);
                            dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, meTmp); 
                        }
                        else 
                        { 
                            dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e);
                        } 
                        if (hti.col >= 0 && this.ptMouseDownCell.X == hti.col &&
                            hti.row >= 0 && this.ptMouseDownCell.Y == hti.row &&
                            this.EditMode == DataGridViewEditMode.EditOnEnter &&
                            this.editingControl != null) 
                        {
                            OnClick(e); 
                            OnMouseClick(e); 
                        }
 
                        CorrectFocus(true /*onlyIfGridHasFocus*/);

                        if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count)
                        { 
                            OnCellMouseUp(dgvcme);
                        } 
                    } 
                    else if (hti.Type == DataGridViewHitTestType.None)
                    { 
                        // VS Whidbey bug 469429
                        CorrectFocus(true /*onlyIfGridHasFocus*/);
                    }
                } 
                else
                { 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize]) 
                    {
                        EndColumnResize(e); 
                    }

                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize])
                    { 
                        EndRowResize(e);
                    } 
 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation])
                    { 
                        EndColumnRelocation(e, hti);
                    }

                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize]) 
                    {
                        EndColumnHeadersResize(e); 
                    } 

                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) 
                    {
                        EndRowHeadersResize(e);
                    }
 
                    // VS Whidbey bug 256893
                    CorrectFocus(true /*onlyIfGridHasFocus*/); 
 
                    // Updating the hit test info since the EndXXX operation above may have invalidated the previously
                    // determined hti. 
                    hti = HitTest(e.X, e.Y);
                    if (hti.Type != DataGridViewHitTestType.None &&
                        hti.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                        hti.Type != DataGridViewHitTestType.VerticalScrollBar) 
                    {
                        int mouseX = e.X - hti.ColumnX; 
                        if (this.RightToLeftInternal) 
                        {
                            mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); 
                        }
                        OnCellMouseUp(new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e));
                    }
                } 

                ResetTrackingState(); 
            } 
            base.OnMouseUp(e);
        } 

        /// 
        protected override void OnMouseWheel(MouseEventArgs e)
        { 
            base.OnMouseWheel(e);
 
            HandledMouseEventArgs hme = e as HandledMouseEventArgs; 
            if (hme != null && hme.Handled)
            { 
                // The application event handler handled the scrolling - don't do anything more.
                return;
            }
 
            if ((ModifierKeys & (Keys.Shift | Keys.Alt)) != 0 || MouseButtons != MouseButtons.None)
            { 
                return; // Do not scroll when Shift or Alt key is down, or when a mouse button is down. 
            }
 
            bool verticalScroll = ((ModifierKeys & Keys.Control) == 0);

            ScrollBar sb = (verticalScroll ? (ScrollBar) this.vertScrollBar : (ScrollBar) this.horizScrollBar);
 
            if (!sb.Visible || !sb.Enabled)
            { 
                return; // Do not scroll when the corresponding scrollbar is invisible or disabled 
            }
 
            if (hme != null)
            {
                hme.Handled = true;
            } 

            int wheelScrollLines = SystemInformation.MouseWheelScrollLines; 
            if (wheelScrollLines == 0) 
            {
                return; // Do not scroll when the user system setting is 0 lines per notch 
            }

            Debug.Assert(this.cumulativeVerticalWheelDelta > -NativeMethods.WHEEL_DELTA);
            Debug.Assert(this.cumulativeVerticalWheelDelta < NativeMethods.WHEEL_DELTA); 
            Debug.Assert(this.cumulativeHorizontalWheelDelta > -NativeMethods.WHEEL_DELTA);
            Debug.Assert(this.cumulativeHorizontalWheelDelta < NativeMethods.WHEEL_DELTA); 
 
            float partialNotches;
 
            if (verticalScroll)
            {
                this.cumulativeVerticalWheelDelta += e.Delta;
                partialNotches = (float) this.cumulativeVerticalWheelDelta / (float) NativeMethods.WHEEL_DELTA; 
            }
            else 
            { 
                this.cumulativeHorizontalWheelDelta += e.Delta;
                partialNotches = (float) this.cumulativeHorizontalWheelDelta / (float) NativeMethods.WHEEL_DELTA; 
            }

            int fullNotches = (int) partialNotches;
 
            if (wheelScrollLines == -1)
            { 
                // Equivalent to large change scrolls 
                if (fullNotches != 0)
                { 
                    if (this.ptCurrentCell.X >= 0 &&
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    false /*forCurrentCellChange*/, false /*forCurrentRowChange*/))
                    { 
                        // Could not commit edited cell value
                        return; 
                    } 
                    if (verticalScroll)
                    { 
                        int originalVerticalOffset = this.VerticalOffset;
                        this.VerticalOffset -= fullNotches * this.vertScrollBar.LargeChange;
                        if (Math.Abs(this.VerticalOffset - originalVerticalOffset) >= Math.Abs(fullNotches * this.vertScrollBar.LargeChange))
                        { 
                            this.cumulativeVerticalWheelDelta -= fullNotches * NativeMethods.WHEEL_DELTA;
                        } 
                        else 
                        {
                            this.cumulativeVerticalWheelDelta = 0; 
                        }
                    }
                    else
                    { 
                        int originalHorizontalOffset = this.HorizontalOffset;
                        this.HorizontalOffset -= fullNotches * this.horizScrollBar.LargeChange; 
                        if (Math.Abs(this.HorizontalOffset - originalHorizontalOffset) >= Math.Abs(fullNotches * this.horizScrollBar.LargeChange)) 
                        {
                            this.cumulativeHorizontalWheelDelta -= fullNotches * NativeMethods.WHEEL_DELTA; 
                        }
                        else
                        {
                            this.cumulativeHorizontalWheelDelta = 0; 
                        }
                    } 
                } 
            }
            else 
            {
                // Evaluate number of bands to scroll
                int scrollBands = (int) ((float) wheelScrollLines * partialNotches);
                if (scrollBands != 0) 
                {
                    if (this.ptCurrentCell.X >= 0 && 
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                    false /*forCurrentCellChange*/, false /*forCurrentRowChange*/))
                    { 
                        // Could not commit edited cell value
                        return;
                    }
                    int absScrollBands; 
                    if (verticalScroll)
                    { 
                        if (scrollBands > 0) 
                        {
                            absScrollBands = scrollBands; 
                            while (this.vertScrollBar.Value != this.vertScrollBar.Minimum && absScrollBands > 0)
                            {
                                ScrollRowsByCount(-1, ScrollEventType.SmallDecrement);
                                absScrollBands--; 
                            }
                            if (this.vertScrollBar.Value == this.vertScrollBar.Minimum) 
                            { 
                                this.cumulativeVerticalWheelDelta = 0;
                            } 
                            else
                            {
                                this.cumulativeVerticalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines));
                            } 
                        }
                        else 
                        { 
                            absScrollBands = -scrollBands;
                            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
                            int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                            while (absScrollBands > 0 &&
                                   this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <=
                                   this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) 
                            {
                                ScrollRowsByCount(1, ScrollEventType.SmallIncrement); 
                                // Assuming totalVisibleFrozenHeight is unchanged by scrolling operation 
                                Debug.Assert(totalVisibleFrozenHeight == this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen));
                                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
                                absScrollBands--;
                            }
                            if (this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) >
                                this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) 
                            {
                                this.cumulativeVerticalWheelDelta = 0; 
                            } 
                            else
                            { 
                                this.cumulativeVerticalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines));
                            }
                        }
                    } 
                    else
                    { 
                        int extremeScrollBarValue, scrollBand; 
                        if (scrollBands > 0)
                        { 
                            extremeScrollBarValue = this.horizScrollBar.Minimum;
                            scrollBand = -1;
                        }
                        else 
                        {
                            extremeScrollBarValue = this.horizScrollBar.Maximum; 
                            scrollBand = 1; 
                        }
                        absScrollBands = Math.Abs(scrollBands); 
                        while (this.horizScrollBar.Value != extremeScrollBarValue && absScrollBands > 0)
                        {
                            ScrollColumns(scrollBand);
                            absScrollBands--; 
                        }
                        if (this.horizScrollBar.Value == extremeScrollBarValue) 
                        { 
                            this.cumulativeHorizontalWheelDelta = 0;
                        } 
                        else
                        {
                            this.cumulativeHorizontalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines));
                        } 
                    }
                } 
            } 
        }
 
        internal void OnMouseWheelInternal(MouseEventArgs e)
        {
            // Notification forwarded from editing control
            OnMouseWheel(e); 
        }
 
        ///  
        protected virtual void OnMultiSelectChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWMULTISELECTCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnNewRowNeeded(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            }
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWNEWROWNEEDED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected override void OnPaint(PaintEventArgs e)
        { 
            try 
            {
                if (this.layout.dirty) 
                {
                    PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
                }
 
                Graphics g = e.Graphics;
                bool singleVerticalBorderAdded = false, singleHorizontalBorderAdded = false; 
                Rectangle clipRect = e.ClipRectangle; 
                Rectangle gridRect = this.layout.Data;
                if (this.layout.RowHeadersVisible) 
                {
                    gridRect = Rectangle.Union(gridRect, this.layout.RowHeaders);
                }
                else if (this.SingleVerticalBorderAdded) 
                {
                    singleVerticalBorderAdded = true; 
                    if (!this.RightToLeftInternal) 
                    {
                        gridRect.X--; 
                    }
                    gridRect.Width++;
                }
 
                if (this.layout.ColumnHeadersVisible)
                { 
                    gridRect = Rectangle.Union(gridRect, this.layout.ColumnHeaders); 
                }
                else if (this.SingleHorizontalBorderAdded) 
                {
                    singleHorizontalBorderAdded = true;
                    if (gridRect.Y == this.layout.Data.Y)
                    { 
                        gridRect.Y--;
                        gridRect.Height++; 
                    } 
                }
 
                if (this.currentRowSplitBar != -1)
                {
                    clipRect = Rectangle.Union(clipRect, CalcRowResizeFeedbackRect(this.currentRowSplitBar));
                } 
                else if (this.currentColSplitBar != -1)
                { 
                    clipRect = Rectangle.Union(clipRect, CalcColResizeFeedbackRect(this.currentColSplitBar)); 
                }
 
                if (clipRect.IntersectsWith(gridRect))
                {
                    using (Region clipRegion = g.Clip)
                    { 
                        g.SetClip(gridRect);
                        PaintBackground(g, clipRect, gridRect); 
                        PaintGrid(g, gridRect, clipRect, singleVerticalBorderAdded, singleHorizontalBorderAdded); 
                        g.Clip = clipRegion;
                    } 
                }

                PaintBorder(g, clipRect, this.layout.ClientRectangle);
                if (clipRect.IntersectsWith(this.layout.ResizeBoxRect)) 
                {
                    g.FillRectangle(SystemBrushes.Control, this.layout.ResizeBoxRect); 
                } 

                base.OnPaint(e); // raise paint event 
            }
            catch (Exception ex)
            {
                #if DEBUG 
                    Debug.Fail("DataGridView.OnPaint exception: " + ex.Message + " stack trace " + ex.StackTrace);
                #endif 
                if (ClientUtils.IsCriticalException(ex)) 
                {
                    throw; 
                }
            }
        }
 
        // See VSWhidbey 527459 & 526373.
        internal override void OnParentBecameInvisible() 
        { 
            base.OnParentBecameInvisible();
            if (GetState(STATE_VISIBLE)) 
            {
                // This control became invisible too - Update the Displayed properties of the bands.
                OnVisibleChangedPrivate();
            } 
        }
 
        ///  
        protected virtual void OnReadOnlyChanged(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWREADONLYCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
 
            VerifyImeRestrictedModeChanged(); 

            if (!this.ReadOnly && 
                this.ptCurrentCell.X != -1 &&
                ColumnEditable(this.ptCurrentCell.X) &&
                !this.IsCurrentCellInEditMode &&
                (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                 (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)) &&
                !this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X].ReadOnly) // Unshares the row 
            { 
                // Current cell becomes read/write. Enter editing mode.
                BeginEditInternal(true /*selectAll*/); 
            }
        }

        internal void OnRemovedColumn_PreNotification(DataGridViewColumn dataGridViewColumn) 
        {
            Debug.Assert(dataGridViewColumn.Index >= 0); 
            Debug.Assert(dataGridViewColumn.DataGridView == null); 

            // Clear the potential header sort glyph 
            if (dataGridViewColumn.HasHeaderCell)
            {
                dataGridViewColumn.HeaderCell.SortGlyphDirectionInternal = SortOrder.None;
            } 
            // Intentionally keep the DisplayIndex intact after detaching the column.
            CorrectColumnIndexesAfterDeletion(dataGridViewColumn); 
 
            CorrectColumnDisplayIndexesAfterDeletion(dataGridViewColumn);
 
            // Fix the OldFirstDisplayedScrollingCol
            this.displayedBandsInfo.CorrectRowIndexAfterDeletion(dataGridViewColumn.Index);

            // Raise the ColumnRemoved event 
            OnColumnRemoved(dataGridViewColumn);
        } 
 
        internal void OnRemovedColumn_PostNotification(DataGridViewColumn dataGridViewColumn, Point newCurrentCell)
        { 
            // Update current cell if needed
            if (newCurrentCell.X != -1)
            {
                Debug.Assert(this.ptCurrentCell.X == -1); 
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X,
                                                              newCurrentCell.Y, 
                                                              true, 
                                                              false,
                                                              false, 
                                                              false /*clearSelection*/,
                                                              false /*forceCurrentCellSelection*/);
                Debug.Assert(success);
            } 

            // Raise SelectionChanged event if needed 
            FlushSelectionChanged(); 

            // Raise ColumnStateChanged event for Displayed state of deleted column 
            OnColumnHidden(dataGridViewColumn);

            // Columns that are removed from the collection take their non-autosized width
            // Note that in some edge cases, the dev could have changed: 
            //     - the grid's AutoSizeColumnsMode
            //     - the column's Width or AutoSizeMode 
            // in a ColumnRemoved event handler for example, in which case using the CachedThickness may be wrong. 
            // At least we make sure the column is not sized smaller than its minimum width.
            DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.GetInheritedAutoSizeMode(this); 
            Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet);
            if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None &&
                autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill &&
                dataGridViewColumn.ThicknessInternal != dataGridViewColumn.CachedThickness) 
            {
                dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness); 
            } 

            // Autosize rows if needed 
            AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
        }

        internal void OnRemovedRow_PreNotification(int rowIndexDeleted) 
        {
            // Fix the OldFirstDisplayedScrollingRow 
            this.displayedBandsInfo.CorrectRowIndexAfterDeletion(rowIndexDeleted); 

            CorrectRowIndexesAfterDeletion(rowIndexDeleted); 
            ComputeVisibleRows();
        }

        internal void OnRemovedRow_PostNotification(DataGridViewRow dataGridViewRow, Point newCurrentCell) 
        {
            // Update current cell if needed 
            if (newCurrentCell.Y != -1) 
            {
                Debug.Assert(this.ptCurrentCell.X == -1); 
                bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X,
                                                              newCurrentCell.Y,
                                                              true /*setAnchorCellAddress*/,
                                                              false /*validateCurrentCell*/, 
                                                              false /*throughMouseClick*/,
                                                              false /*clearSelection*/, 
                                                              false /*forceCurrentCellSelection*/); 
                Debug.Assert(success);
            } 

            // Raise SelectionChange event if needed
            FlushSelectionChanged();
 
            bool rowDisplayed = dataGridViewRow.DataGridView == null && dataGridViewRow.Displayed;
 
            // Raise RowStateChanged event for Displayed state of deleted row 
            if (rowDisplayed)
            { 
                dataGridViewRow.DisplayedInternal = false;
                DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, DataGridViewElementStates.Displayed);
                OnRowStateChanged(-1 /*rowIndex*/, dgvrsce);
            } 

            // Rows that are removed from the collection take their non-autosized height 
            // Note that in some edge cases, the dev could have changed: 
            //     - the grid's AutoSizeRowsMode
            //     - the row's Height 
            // in a RowsRemoved event handler for example, in which case using the CachedThickness may be wrong.
            // At least we make sure the row is not sized smaller than its minimum height.
            if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None && dataGridViewRow.ThicknessInternal != dataGridViewRow.CachedThickness)
            { 
                dataGridViewRow.ThicknessInternal = Math.Max(dataGridViewRow.MinimumHeight, dataGridViewRow.CachedThickness);
            } 
 
            // Auto size columms also if needed
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; 
            if (rowDisplayed)
            {
                autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows;
            } 
            bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/);
            bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize; 
            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || 
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing;
 
            if (fixedRowHeadersWidth && !columnAutoSized)
            {
                // No need to autosize the column headers when the row headers and columns don't change.
                fixedColumnHeadersHeight = true; 
            }
 
            // Auto size column headers 
            if (!fixedColumnHeadersHeight)
            { 
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/);
            }

            // Auto size row headers 
            if (!fixedRowHeadersWidth)
            { 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); 
            }
 
            if (!fixedColumnHeadersHeight && !fixedRowHeadersWidth)
            {
                // Second round of column headers autosizing
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); 
            }
        } 
 
        internal void OnRemovingColumn(DataGridViewColumn dataGridViewColumn, out Point newCurrentCell, bool force)
        { 
            Debug.Assert(dataGridViewColumn != null);
            Debug.Assert(dataGridViewColumn.Index >= 0 && dataGridViewColumn.Index < this.Columns.Count);

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false; 
            int columnIndex = dataGridViewColumn.Index;
 
            // Reset the current cell's address if there is one. 
            if (this.ptCurrentCell.X != -1)
            { 
                int newX = this.ptCurrentCell.X;
                if (columnIndex == this.ptCurrentCell.X)
                {
                    DataGridViewColumn dataGridViewColumnNext = this.Columns.GetNextColumn( 
                        this.Columns[columnIndex],
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.None); 
                    if (dataGridViewColumnNext != null)
                    { 
                        if (dataGridViewColumnNext.Index > columnIndex)
                        {
                            newX = dataGridViewColumnNext.Index - 1;
                        } 
                        else
                        { 
                            newX = dataGridViewColumnNext.Index; 
                        }
                    } 
                    else
                    {
                        DataGridViewColumn dataGridViewColumnPrevious = this.Columns.GetPreviousColumn(
                            this.Columns[columnIndex], 
                            DataGridViewElementStates.Visible,
                            DataGridViewElementStates.None); 
                        if (dataGridViewColumnPrevious != null) 
                        {
                            if (dataGridViewColumnPrevious.Index > columnIndex) 
                            {
                                newX = dataGridViewColumnPrevious.Index - 1;
                            }
                            else 
                            {
                                newX = dataGridViewColumnPrevious.Index; 
                            } 
                        }
                        else 
                        {
                            newX = -1;
                        }
                    } 
                }
                else if (columnIndex < this.ptCurrentCell.X) 
                { 
                    newX = this.ptCurrentCell.X - 1;
                } 
                newCurrentCell = new Point(newX, (newX == -1) ? -1 : this.ptCurrentCell.Y);
                if (columnIndex == this.ptCurrentCell.X)
                {
                    // Left cell is not validated since cancelling validation wouldn't have any effect anyways. 
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false);
                    Debug.Assert(success); 
                } 
                else if (force)
                { 
                    // Underlying data of deleted column is gone. It cannot be accessed anymore.
                    // Do not end editing mode so that CellValidation doesn't get raised, since that event needs the current formatted value.
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true;
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); 
                    Debug.Assert(success);
                } 
                else 
                {
                    // Quit editing mode and set the current cell to its new location once everything is in [....] again. 
                    ResetCurrentCell();
                }
            }
            else 
            {
                newCurrentCell = new Point(-1, -1); 
            } 

            // If the last column is removed, delete all the rows first. 
            if (this.Columns.Count == 1)
            {
                Debug.Assert(columnIndex == 0);
                this.Rows.ClearInternal(false /*recreateNewRow*/); 
            }
 
            // Prepare the existing rows by removing cells at correct index 
            int newColumnCount = this.Columns.Count - 1;
 
            for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++)
            {
                DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                if (dataGridViewRow.Cells.Count > newColumnCount) 
                {
                    dataGridViewRow.Cells.RemoveAtInternal(columnIndex); 
                } 
            }
 
            // Detach column header cell
            if (dataGridViewColumn.HasHeaderCell)
            {
                dataGridViewColumn.HeaderCell.DataGridViewInternal = null; 
            }
 
            // Reset sort related variables. 
            if (dataGridViewColumn == this.sortedColumn)
            { 
                this.sortedColumn = null;
                this.sortOrder = SortOrder.None;

                if (dataGridViewColumn.IsDataBound) 
                {
                    // If the column being removed is the sorted column and it is also the dataBound column 
                    // then see if there is another dataBound column which has the same property name as the sorted column. 
                    // If so, then make that dataGridViewColumn the sorted column in the data grid view.
                    for (int i = 0; i < this.Columns.Count; i ++) 
                    {
                        if (dataGridViewColumn != this.Columns[i] &&
                            this.Columns[i].SortMode != DataGridViewColumnSortMode.NotSortable &&
                            String.Compare(dataGridViewColumn.DataPropertyName, 
                                           this.Columns[i].DataPropertyName,
                                           true /*ignoreCase*/, 
                                           CultureInfo.InvariantCulture) == 0) 
                        {
                            Debug.Assert(this.Columns[i].IsDataBound, "two columns w/ the same DataPropertyName should be DataBound at the same time"); 
                            Debug.Assert(this.Columns[i].HeaderCell.SortGlyphDirection == dataGridViewColumn.HeaderCell.SortGlyphDirection, "DataBound columns should have the same SortGlyphDirection as the one on the DataGridView");
                            this.sortedColumn = this.Columns[i];
                            this.sortOrder = this.Columns[i].HeaderCell.SortGlyphDirection;
                            break; 
                        }
                    } 
                } 
            }
 
            // Is deleted column scrolled off screen?
            if (dataGridViewColumn.Visible &&
                !dataGridViewColumn.Frozen &&
                this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) 
            {
                // Deleted column is part of scrolling columns. 
                if (this.displayedBandsInfo.FirstDisplayedScrollingCol == dataGridViewColumn.Index) 
                {
                    // Deleted column is first scrolling column 
                    this.horizontalOffset -= this.negOffset;
                    this.negOffset = 0;
                }
                else if (this.Columns.DisplayInOrder(this.displayedBandsInfo.FirstDisplayedScrollingCol, dataGridViewColumn.Index)) 
                {
                    // Deleted column is displayed after first scrolling column 
                    if (this.horizScrollBar.Enabled) 
                    {
                        int newHorizontalOffset = this.horizScrollBar.Maximum - this.horizScrollBar.LargeChange - dataGridViewColumn.Thickness; 
                        if (newHorizontalOffset >= 0 && newHorizontalOffset < this.horizScrollBar.Value)
                        {
                            this.horizontalOffset = newHorizontalOffset;
                            this.negOffset = GetNegOffsetFromHorizontalOffset(this.horizontalOffset); 
                        }
                    } 
                    else 
                    {
                        this.horizontalOffset = this.negOffset = 0; 
                    }
                }
                else
                { 
                    // Deleted column is displayed before first scrolling column
                    Debug.Assert(this.horizontalOffset >= dataGridViewColumn.Thickness); 
                    this.horizontalOffset -= dataGridViewColumn.Thickness; 
                }
 
                if (this.horizScrollBar.Enabled)
                {
                    this.horizScrollBar.Value = this.horizontalOffset;
                } 
            }
 
            bool raiseSelectionChanged = false; 

            // Update the indexes of selected columns or individual cells to compensate for the removal of this column 
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.FullColumnSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    int columnEntries = this.selectedBandIndexes.Count;
                    int columnEntry = 0; 
                    while (columnEntry < columnEntries) 
                    {
                        int columnIndexSelected = this.selectedBandIndexes[columnEntry]; 
                        if (columnIndex == columnIndexSelected)
                        {
                            this.selectedBandIndexes.RemoveAt(columnEntry);
                            columnEntries--; 
                            raiseSelectionChanged = true;
                        } 
                        else 
                        {
                            if (columnIndex < columnIndexSelected) 
                            {
                                this.selectedBandIndexes[columnEntry] = columnIndexSelected - 1;
                            }
                            columnEntry++; 
                        }
                    } 
                    break; 
            }
 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] |= this.individualSelectedCells.RemoveAllCellsAtBand(true /*column*/, columnIndex) > 0 ||
                                                                                 raiseSelectionChanged;
            this.individualReadOnlyCells.RemoveAllCellsAtBand(true /*column*/, columnIndex);
        } 

        internal void OnRemovingRow(int rowIndexDeleted, out Point newCurrentCell, bool force) 
        { 
            // if force is true, the row needs to be deleted no matter what. The underlying data row was already deleted.
 
            Debug.Assert(rowIndexDeleted >= 0 && rowIndexDeleted < this.Rows.Count);

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false;
            newCurrentCell = new Point(-1, -1); 

            // Reset the current cell's address if it's on the deleted row, or after it. 
            if (this.ptCurrentCell.Y != -1 && rowIndexDeleted <= this.ptCurrentCell.Y) 
            {
                int newY; 
                if (rowIndexDeleted == this.ptCurrentCell.Y)
                {
                    int rowIndexPrevious = this.Rows.GetPreviousRow(rowIndexDeleted, DataGridViewElementStates.Visible);
                    int rowIndexNext = this.Rows.GetNextRow(rowIndexDeleted, DataGridViewElementStates.Visible); 
                    if (rowIndexPrevious > -1 && this.AllowUserToAddRowsInternal)
                    { 
                        Debug.Assert(this.newRowIndex != -1); 
                        Debug.Assert(this.newRowIndex == this.Rows.Count-1);
                        if (rowIndexNext > -1 && rowIndexNext < this.Rows.Count - 1) 
                        {
                            newY = rowIndexNext - 1;
                        }
                        else 
                        {
                            newY = rowIndexPrevious; 
                        } 
                    }
                    else 
                    {
                        if (rowIndexNext > -1)
                        {
                            newY = rowIndexNext - 1; 
                        }
                        else 
                        { 
                            newY = rowIndexPrevious;
                        } 
                    }
                    // Since the current row is deleted, the dirty states need to be reset
                    this.IsCurrentCellDirtyInternal = false;
                    this.IsCurrentRowDirtyInternal = false; 
                }
                else 
                { 
                    Debug.Assert(rowIndexDeleted < this.ptCurrentCell.Y);
                    newY = this.ptCurrentCell.Y - 1; 
                }
                newCurrentCell = new Point(this.ptCurrentCell.X, newY);
                if (rowIndexDeleted == this.ptCurrentCell.Y)
                { 
                    // Left cell is not validated since cancelling validation wouldn't have any effect anyways.
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); 
                    Debug.Assert(success); 
                }
                else if (force) 
                {
                    // Underlying data of deleted row is gone. It cannot be accessed anymore.
                    // Do not end editing mode so that CellValidation doesn't get raised, since that event needs the current formatted value.
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true; 
                    bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false);
                    Debug.Assert(success); 
                } 
                else
                { 
                    // Quit editing mode and set the current cell to its new location once everything is in [....] again.
                    ResetCurrentCell();
                }
            } 

            bool raiseSelectionChanged = false; 
 
            // Update the indexes of selected rows to compensate for the removal of this row
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect:
                    int rowEntries = this.selectedBandIndexes.Count; 
                    int rowEntry = 0;
                    while (rowEntry < rowEntries) 
                    { 
                        int rowIndex = this.selectedBandIndexes[rowEntry];
                        if (rowIndexDeleted == rowIndex) 
                        {
                            raiseSelectionChanged = true;
                            this.selectedBandIndexes.RemoveAt(rowEntry);
                            rowEntries--; 
                        }
                        else 
                        { 
                            if (rowIndexDeleted < rowIndex)
                            { 
                                this.selectedBandIndexes[rowEntry] = rowIndex - 1;
                            }
                            rowEntry++;
                        } 
                    }
                    if (this.selectedBandSnapshotIndexes != null) 
                    { 
                        rowEntries = this.selectedBandSnapshotIndexes.Count;
                        rowEntry = 0; 
                        while (rowEntry < rowEntries)
                        {
                            int rowIndex = this.selectedBandSnapshotIndexes[rowEntry];
                            if (rowIndexDeleted == rowIndex) 
                            {
                                this.selectedBandSnapshotIndexes.RemoveAt(rowEntry); 
                                rowEntries--; 
                            }
                            else 
                            {
                                if (rowIndexDeleted < rowIndex)
                                {
                                    this.selectedBandSnapshotIndexes[rowEntry] = rowIndex - 1; 
                                }
                                rowEntry++; 
                            } 
                        }
                    } 
                    break;
            }

            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] |= this.individualSelectedCells.RemoveAllCellsAtBand(false /*column*/, rowIndexDeleted) > 0 || 
                                                                                 raiseSelectionChanged;
            this.individualReadOnlyCells.RemoveAllCellsAtBand(false /*column*/, rowIndexDeleted); 
        } 

        internal void OnReplacedCell(DataGridViewRow dataGridViewRow, int columnIndex) 
        {
            DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex];
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected])
            { 
                this.individualSelectedCells.Add(dataGridViewCell);
            } 
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly]) 
            {
                this.individualReadOnlyCells.Add(dataGridViewCell); 
            }

            // AutoSize column and row if needed
            OnCellCommonChange(columnIndex, dataGridViewRow.Index); 

            if (this.ptCurrentCellCache.X != -1) 
            { 
                if (!IsInnerCellOutOfBounds(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y))
                { 
                    SetCurrentCellAddressCore(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y, false, false, false);
                }
                this.ptCurrentCellCache.X = -1;
                this.ptCurrentCellCache.Y = -1; 
            }
        } 
 
        internal void OnReplacingCell(DataGridViewRow dataGridViewRow, int columnIndex)
        { 
            if (this.ptCurrentCell.X == dataGridViewRow.Index &&
                this.ptCurrentCell.Y == columnIndex)
            {
                // Trying to replace the current cell. Exiting editing mode first (if needed). 
                // Remember to reset the current cell in OnReplacedCell notification
                this.ptCurrentCellCache.X = this.ptCurrentCell.X; 
                this.ptCurrentCellCache.Y = this.ptCurrentCell.Y; 
                // This may fail and throw an exception
                ResetCurrentCell(); 
            }
            else
            {
                this.ptCurrentCellCache.X = -1; 
                this.ptCurrentCellCache.Y = -1;
            } 
            DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex]; 
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected] = this.individualSelectedCells.Contains(dataGridViewCell);
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected]) 
            {
                this.individualSelectedCells.Remove(dataGridViewCell);
            }
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly] = this.individualReadOnlyCells.Contains(dataGridViewCell); 
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly])
            { 
                this.individualReadOnlyCells.Remove(dataGridViewCell); 
            }
        } 

        /// 
        protected override void OnResize(EventArgs e)
        { 
            int borderWidth = this.BorderWidth;
            Rectangle right; 
            Rectangle bottom; 
            Rectangle oldClientRectangle = this.layout.ClientRectangle;
 
            right = new Rectangle(oldClientRectangle.X + oldClientRectangle.Width - borderWidth,
                oldClientRectangle.Y,
                borderWidth,
                oldClientRectangle.Height); 
            bottom = new Rectangle(oldClientRectangle.X,
                oldClientRectangle.Y + oldClientRectangle.Height - borderWidth, 
                oldClientRectangle.Width, 
                borderWidth);
 
            if (!this.IsMinimized)
            {
                // When owning form is minimized, act as if it had a normal size
                this.normalClientRectangle = this.ClientRectangle; 
            }
 
            Rectangle newClientRectangle = this.normalClientRectangle; 
            if (newClientRectangle.Width != oldClientRectangle.Width)
            { 
                Invalidate(right);
                right = new Rectangle(newClientRectangle.X + newClientRectangle.Width - borderWidth,
                    newClientRectangle.Y,
                    borderWidth, 
                    newClientRectangle.Height);
                Invalidate(right); 
            } 
            if (newClientRectangle.Height != oldClientRectangle.Height)
            { 
                Invalidate(bottom);
                bottom = new Rectangle(newClientRectangle.X,
                    newClientRectangle.Y + newClientRectangle.Height - borderWidth,
                    newClientRectangle.Width, 
                    borderWidth);
                Invalidate(bottom); 
            } 

            //also, invalidate the ResizeBoxRect 
            if (!this.layout.ResizeBoxRect.IsEmpty)
            {
                Invalidate(this.layout.ResizeBoxRect);
            } 
            this.layout.ClientRectangle = newClientRectangle;
 
            int oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
            base.OnResize(e);
            if (oldfirstDisplayedScrollingRow != this.displayedBandsInfo.FirstDisplayedScrollingRow) 
            {
                Invalidate();
            }
        } 

        ///  
        protected override void OnRightToLeftChanged(EventArgs e) 
        {
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_rightToLeftValid] = false; 
            base.OnRightToLeftChanged(e);
            CorrectFocus(true /*onlyIfGridHasFocus*/);
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/);
        } 

        internal void OnRowCollectionChanged_PostNotification(bool recreateNewRow, 
                                                              bool allowSettingCurrentCell, 
                                                              CollectionChangeAction cca,
                                                              DataGridViewRow dataGridViewRow, 
                                                              int rowIndex)
        {
            if (recreateNewRow &&
                cca == CollectionChangeAction.Refresh && 
                this.Columns.Count != 0 &&
                this.Rows.Count == 0 && 
                this.AllowUserToAddRowsInternal) 
            {
                AddNewRow(false); 
            }

            if (cca == CollectionChangeAction.Refresh)
            { 
                FlushSelectionChanged();
            } 
 
            if ((cca == CollectionChangeAction.Refresh || cca == CollectionChangeAction.Add) &&
                this.ptCurrentCell.X == -1 && allowSettingCurrentCell && !this.InSortOperation) 
            {
                MakeFirstDisplayedCellCurrentCell(false /*includeNewRow*/);
            }
 
            if (this.AutoSize)
            { 
                bool invalidatePreferredSizeCache = true; 
                switch (cca)
                { 
                    case CollectionChangeAction.Add:
                        Debug.Assert(rowIndex >= 0);
                        DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
                        invalidatePreferredSizeCache = ((rowState & DataGridViewElementStates.Visible) != 0); 
                        break;
                    case CollectionChangeAction.Remove: 
                        invalidatePreferredSizeCache = dataGridViewRow.DataGridView == null && dataGridViewRow.Visible; 
                        break;
                    // case CollectionChangeAction.Refresh: invalidatePreferredSizeCache stays true 
                }
                if (invalidatePreferredSizeCache)
                {
                    LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows); 
                }
            } 
        } 

        ///  
        protected virtual void OnRowContextMenuStripChanged(DataGridViewRowEventArgs e)
        {
            if (e.Row.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            } 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWCONTEXTMENUSTRIPCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal ContextMenuStrip OnRowContextMenuStripNeeded(int rowIndex, ContextMenuStrip contextMenuStrip)
        { 
            DataGridViewRowContextMenuStripNeededEventArgs dgvrcmsne = new DataGridViewRowContextMenuStripNeededEventArgs(rowIndex, contextMenuStrip); 
            OnRowContextMenuStripNeeded(dgvrcmsne);
            return dgvrcmsne.ContextMenuStrip; 
        }

        /// 
        protected virtual void OnRowContextMenuStripNeeded(DataGridViewRowContextMenuStripNeededEventArgs e) 
        {
            DataGridViewRowContextMenuStripNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWCONTEXTMENUSTRIPNEEDED] as DataGridViewRowContextMenuStripNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnRowDefaultCellStyleChanged(DataGridViewRowEventArgs e)
        { 
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            }

            OnRowGlobalAutoSize(e.Row.Index);
 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDEFAULTCELLSTYLECHANGED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnRowDirtyStateNeeded(QuestionEventArgs e) 
        {
            QuestionEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIRTYSTATENEEDED] as QuestionEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnRowDividerDoubleClick(DataGridViewRowDividerDoubleClickEventArgs e)
        { 
            DataGridViewRowDividerDoubleClickEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIVIDERDOUBLECLICK] as DataGridViewRowDividerDoubleClickEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }

            if (!e.Handled && e.Button == MouseButtons.Left && e.RowIndex < this.Rows.Count) 
            {
                if (e.RowIndex == -1) 
                { 
                    AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
                } 
                else
                {
                    if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
                    { 
                        AutoResizeRowInternal(e.RowIndex, DataGridViewAutoSizeRowMode.AllCells, true /*fixedWidth*/, true /*internalAutosizing*/);
                    } 
                    else 
                    {
                        AutoResizeRowInternal(e.RowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnRowDividerHeightChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            }
 
            OnRowGlobalAutoSize(e.Row.Index);
 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIVIDERHEIGHTCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        private void OnRowEnter(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, bool canCreateNewRow, bool validationFailureOccurred)
        { 
            Debug.Assert(columnIndex >= 0 && rowIndex >= 0); 

            if (!validationFailureOccurred) 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] = false;
            }
            if (rowIndex < this.Rows.Count && 
                columnIndex < this.Columns.Count)
            { 
                bool calledAddNewOnTheDataConnection = false; 
                if (!validationFailureOccurred && this.AllowUserToAddRowsInternal && this.newRowIndex == rowIndex)
                { 
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] = true;

                    if (canCreateNewRow)
                    { 
                        DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(this.Rows[this.newRowIndex]);
                        if (this.VirtualMode || this.DataSource != null) 
                        { 
                            if (this.dataConnection != null && this.dataConnection.InterestedInRowEvents)
                            { 
                                this.dataConnection.OnNewRowNeeded();
                                calledAddNewOnTheDataConnection = true;
                            }
                            if (this.VirtualMode) 
                            {
                                OnNewRowNeeded(dgvre); 
                            } 
                        }
 
                        // vsWhidbey 329429: AllowUserToAddRowsInternal can become FALSE while adding a row.
                        // NOTE: we don't need to invalidate if AllowUserToAddRowsInternal changed to FALSE.
                        //
                        if (this.AllowUserToAddRowsInternal) 
                        {
                            OnDefaultValuesNeeded(dgvre); 
                            InvalidateRowPrivate(this.newRowIndex); 
                        }
                        #if DEBUG 
                        else
                        {
                            Debug.Assert(this.newRowIndex == -1, "newRowIndex and AllowUserToAddRowsInternal became out of [....]");
                        } 
                        #endif //
                    } 
                } 

                if (calledAddNewOnTheDataConnection && rowIndex > this.Rows.Count - 1) 
                {
                    // Calling AddNew on the DataConnection can result in the entire list being wiped out.
                    //
                    rowIndex = Math.Min(rowIndex, this.Rows.Count - 1); 
                }
 
                DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); 
                OnRowEnter(dgvce);
                if (this.dataConnection != null && 
                    this.dataConnection.InterestedInRowEvents &&
                    !this.dataConnection.PositionChangingOutsideDataGridView &&
                    !this.dataConnection.ListWasReset &&
                    (!calledAddNewOnTheDataConnection || this.dataConnection.List.Count > 0)) 
                {
                    this.dataConnection.OnRowEnter(dgvce); 
                } 

                if (dataGridViewCell != null) 
                {
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                    {
                        dataGridViewCell = null; 
                    }
                    else 
                    { 
                        Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                        dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; 
                    }
                }
            }
        } 

        ///  
        protected virtual void OnRowEnter(DataGridViewCellEventArgs e) 
        {
            try 
            {
                this.noDimensionChangeCount++;

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWENTER] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            }
            finally
            {
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
            } 
        } 

        internal void OnRowErrorTextChanged(DataGridViewRow dataGridViewRow) 
        {
            DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
            OnRowErrorTextChanged(dgvre);
        } 

        ///  
        protected virtual void OnRowErrorTextChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            }
            UpdateRowErrorText(e.Row.Index); 

            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWERRORTEXTCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal string OnRowErrorTextNeeded(int rowIndex, string errorText) 
        {
            Debug.Assert(rowIndex >= 0); 
            DataGridViewRowErrorTextNeededEventArgs dgvretne = new DataGridViewRowErrorTextNeededEventArgs(rowIndex, errorText); 
            OnRowErrorTextNeeded(dgvretne);
            return dgvretne.ErrorText; 
        }

        /// 
        protected virtual void OnRowErrorTextNeeded(DataGridViewRowErrorTextNeededEventArgs e) 
        {
            DataGridViewRowErrorTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWERRORTEXTNEEDED] as DataGridViewRowErrorTextNeededEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        private void OnRowGlobalAutoSize(int rowIndex) 
        {
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if ((rowState & DataGridViewElementStates.Visible) == 0) 
            {
                return; 
            }

            InvalidateRowPrivate(rowIndex);
 
            if (this.noAutoSizeCount > 0)
            { 
                return; 
            }
 
            DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode;
            bool autoSizeRow = false;
            bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0;
            if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None && 
                !((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed))
            { 
                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/); 
                autoSizeRow = true;
            } 

            // Auto size columms also if needed
            DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows;
            if (rowDisplayed) 
            {
                autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; 
            } 
            AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/);
 
            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing ||
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing;
            // Auto size column headers
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
            {
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/); 
            } 

            // Auto size row headers 
            if (!fixedRowHeadersWidth)
            {
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            } 

            if (autoSizeRow) 
            { 
                // Second round of row autosizing
                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
            }

            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize && !fixedRowHeadersWidth)
            { 
                // Second round of column headers autosizing
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); 
            } 
        }
 
        /// 
        protected virtual void OnRowHeaderCellChanged(DataGridViewRowEventArgs e)
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            } 

            OnRowHeaderGlobalAutoSize(e.Row.Index); 

            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERCELLCHANGED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            } 
        } 

        private void OnRowHeaderGlobalAutoSize(int rowIndex) 
        {
            if (!this.RowHeadersVisible)
            {
                return; 
            }
 
            InvalidateCellPrivate(-1, rowIndex); 

            if (this.noAutoSizeCount > 0) 
            {
                return;
            }
 
            bool rowDisplayed = false;
            if (rowIndex != -1) 
            { 
                rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0;
            } 

            bool fixedColumnHeadersHeight = rowIndex != -1 || this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            bool fixedRowHeight = rowIndex == -1 ||
                                  ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) == 0) || 
                                  ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && rowIndex != -1 && !rowDisplayed);
 
            bool autoSizeRowHeaders = false; 
            if (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders ||
                (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders && rowIndex != -1 && rowDisplayed) || 
                (this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing && rowIndex == -1) ||
                (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader && rowIndex != -1 && rowIndex == this.Rows.GetFirstRow(DataGridViewElementStates.Visible)))
            {
                AutoResizeRowHeadersWidth(rowIndex, 
                                          this.rowHeadersWidthSizeMode,
                                          fixedColumnHeadersHeight, 
                                          fixedRowHeight); 
                autoSizeRowHeaders = true;
            } 
            if (!fixedColumnHeadersHeight)
            {
                AutoResizeColumnHeadersHeight(-1, true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/);
            } 
            if (!fixedRowHeight)
            { 
                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
 
            if (autoSizeRowHeaders && (!fixedColumnHeadersHeight || !fixedRowHeight))
            {
                // Second round of row headers autosizing
                AutoResizeRowHeadersWidth(rowIndex, 
                                          this.rowHeadersWidthSizeMode,
                                          true /*fixedColumnHeadersHeight*/, 
                                          true /*fixedRowHeight*/); 
            }
        } 

        /// 
        protected virtual void OnRowHeaderMouseClick(DataGridViewCellMouseEventArgs e)
        { 
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERMOUSECLICK] as DataGridViewCellMouseEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnRowHeaderMouseDoubleClick(DataGridViewCellMouseEventArgs e) 
        {
            DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        private void OnRowHeaderMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown) 
        {
            Debug.Assert(hti.Type == DataGridViewHitTestType.RowHeader); 
            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.FullColumnSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        break; 
 
                    case DataGridViewSelectionMode.FullRowSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                    {
                        bool select = true;
                        if (isControlDown &&
                            ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)) 
                        {
                            select = false; 
                        } 
                        if (select)
                        { 
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
                            if (dataGridViewColumn != null && hti.row != this.ptCurrentCell.Y)
                            {
                                int oldCurrentCellX = this.ptCurrentCell.X; 
                                int oldCurrentCellY = this.ptCurrentCell.Y;
                                // Make sure we will be able to scroll into view 
                                if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange, 
                                    DataGridViewValidateCellInternal.Always /*validateCell*/,
                                    true /*fireCellLeave*/, 
                                    true /*fireCellEnter*/,
                                    hti.row != this.ptCurrentCell.Y /*fireRowLeave*/,
                                    hti.row != this.ptCurrentCell.Y /*fireRowEnter*/,
                                    false /*fireLeave*/, 
                                    this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/,
                                    true /*resetCurrentCell*/, 
                                    false /*resetAnchorCell*/)) 
                                {
                                    // Just cancel operation silently instead of throwing InvalidOperationException 
                                    return;
                                }
                                if (oldCurrentCellY != -1)
                                { 
                                    DataGridViewCell dataGridViewCellTmp = null;
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    { 
                                        return;
                                    } 
                                    if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY))
                                    {
                                        // Row validation was cancelled
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                        {
                                            return; 
                                        } 
                                        OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/);
                                        if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                        {
                                            return;
                                        }
                                        OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                        return;
                                    } 
                                    if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        return; 
                                    }
                                    OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);

                                    // Row validation was not cancelled, but operation needs to be re-evaluated. 
                                    if (hti.row >= this.Rows.Count)
                                    { 
                                        int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); 
                                        if (this.ptCurrentCell.X == -1 && lastVisibleRowIndex != -1)
                                        { 
                                            // CurrentCell was reset because commit deleted row(s).
                                            // Since the user wants to select a row, 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'. 
                                            if (IsColumnOutOfBounds(oldCurrentCellX))
                                            { 
                                                return; 
                                            }
                                            bool success = SetAndSelectCurrentCellAddress(oldCurrentCellX, 
                                                                                          lastVisibleRowIndex,
                                                                                          true,
                                                                                          false,
                                                                                          false, 
                                                                                          false /*clearSelection*/,
                                                                                          false /*forceCurrentCellSelection*/); 
                                            Debug.Assert(success); 
                                        }
                                        return; 
                                    }
                                    else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Visible) == 0)
                                    {
                                        return; 
                                    }
                                } 
                            } 
                            bool selectRowRange = false;
                            this.trackRow = hti.row; 
                            this.trackRowEdge = -1;
                            if (this.MultiSelect &&
                                isShiftDown &&
                                this.ptAnchorCell.Y > -1 && 
                                (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Selected) != 0)
                            { 
                                selectRowRange = true; 
                            }
                            if (!this.MultiSelect || !isControlDown || isShiftDown) 
                            {
                                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1);
                                int bandIndex = 0;
                                bool switchedToBulkPaint = false; 
                                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                                { 
                                    this.inBulkPaintCount++; 
                                    switchedToBulkPaint = true;
                                } 
                                try
                                {
                                    while (bandIndex < this.selectedBandIndexes.Count)
                                    { 
                                        if (this.selectedBandIndexes[bandIndex] != hti.row)
                                        { 
                                            // deselect currently selected row 
                                            SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false);
                                        } 
                                        else
                                        {
                                            bandIndex++;
                                        } 
                                    }
 
                                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) 
                                    {
                                        RemoveIndividuallySelectedCells(); 
                                    }
                                    else
                                    {
                                        Debug.Assert(this.individualSelectedCells.Count == 0); 
                                    }
                                } 
                                finally 
                                {
                                    if (switchedToBulkPaint) 
                                    {
                                        ExitBulkPaint(-1, -1);
                                    }
                                } 
                            }
                            if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) 
                            { 
                                this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = true;
                            } 
                            if (selectRowRange)
                            {
                                if (hti.row >= this.ptAnchorCell.Y)
                                { 
                                    SelectRowRange(this.ptAnchorCell.Y, hti.row, true);
                                } 
                                else 
                                {
                                    SelectRowRange(hti.row, this.ptAnchorCell.Y, true); 
                                }
                            }
                            else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) == 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(hti.row) ==
                                             ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)); 
                                SetSelectedRowCore(hti.row, true); 
                            }
                            if (dataGridViewColumn != null) 
                            {
                                if (hti.row != this.ptCurrentCell.Y)
                                {
                                    if (IsInnerCellOutOfBounds(dataGridViewColumn.Index, hti.row)) 
                                    {
                                        return; 
                                    } 
                                    // set current cell to the left most visible cell in the row
                                    bool success = ScrollIntoView(dataGridViewColumn.Index, hti.row, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(dataGridViewColumn.Index, hti.row))
                                    {
                                        return; 
                                    }
                                    success = SetCurrentCellAddressCore(dataGridViewColumn.Index, hti.row, !selectRowRange, false, true); 
                                    Debug.Assert(success); 
                                }
                                else if (-1 != this.ptCurrentCell.Y) 
                                {
                                    // Potentially have to give focus back to the current edited cell.
                                    bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y,
                                                                            false /*setAnchorCellAddress*/, 
                                                                            false /*validateCurrentCell*/,
                                                                            false /*throughMouseClick*/); 
                                    Debug.Assert(success); 
                                }
                            } 
                            else
                            {
                                Debug.Assert(this.CurrentCellAddress == new Point(-1, -1));
                            } 
                        }
                        else 
                        { 
                            Debug.Assert(this.selectedBandIndexes.Contains(hti.row));
                            SetSelectedRowCore(hti.row, false); 
                        }
                        break;
                    }
                } 
            }
            finally 
            { 
                this.NoSelectionChangeCount--;
            } 
        }

        /// 
        protected virtual void OnRowHeadersBorderStyleChanged(EventArgs e) 
        {
            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); 
            Invalidate(); 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSBORDERSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        ///  
        protected virtual void OnRowHeadersDefaultCellStyleChanged(EventArgs e)
        { 
            if (this.RowHeadersVisible)
            {
                Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.RowHeaders));
 
                DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs;
                if (dgvcsce == null || dgvcsce.ChangeAffectsPreferredSize) 
                { 
                    OnRowHeadersGlobalAutoSize(false /*expandingRows*/);
                    if (this.editingControl != null) 
                    {
                        PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                    }
                } 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        private void OnRowHeadersGlobalAutoSize(bool expandingRows)
        { 
            if (this.noAutoSizeCount > 0) 
            {
                return; 
            }

            bool fixedRowsHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) == 0 ||
                                   !this.RowHeadersVisible; 
            bool autoSizeRowHeaders = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                                      this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            if (autoSizeRowHeaders) 
            {
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, fixedRowsHeight); 
            }

            if (!fixedRowsHeight)
            { 
                if (expandingRows)
                { 
                    AdjustExpandingRows(-1, true /*fixedWidth*/); 
                }
                else 
                {
                    AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/);
                }
 
                if (autoSizeRowHeaders)
                { 
                    // Second round of row headers autosizing 
                    AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
                } 
            }
        }

        ///  
        protected virtual void OnRowHeadersWidthChanged(EventArgs e)
        { 
            if (this.RowHeadersVisible) 
            {
                if (this.editingControl != null) 
                {
                    PositionEditingControl(true, false, false);
                }
 
                UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
 
                OnRowHeadersGlobalAutoSize(false /*expandingRows*/); 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSWIDTHCHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnRowHeadersWidthSizeModeChanged(DataGridViewAutoSizeModeEventArgs e) 
        {
            if (this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing &&
                this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing)
            { 
                if (!e.PreviousModeAutoSized)
                { 
                    // Save current row headers width for later reuse 
                    this.cachedRowHeadersWidth = this.RowHeadersWidth;
                } 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode,
                                          true /*fixedColumnHeadersHeight*/,
                                          true /*fixedRowsHeight*/);
            } 
            else if (e.PreviousModeAutoSized)
            { 
                this.RowHeadersWidth = this.cachedRowHeadersWidth; 
            }
 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSWIDTHSIZEMODECHANGED] as EventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        /// 
        protected virtual void OnRowHeightChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); 
            }
            UpdateRowHeightInfoPrivate(e.Row.Index, false, false /*invalidInAdjustFillingColumns*/); 
 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTCHANGED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e);
            }
 
            OnRowGlobalAutoSize(e.Row.Index);
        } 
 
        internal DataGridViewRowHeightInfoNeededEventArgs OnRowHeightInfoNeeded(int rowIndex, int height, int minimumHeight)
        { 
            DataGridViewRowHeightInfoNeededEventArgs dgvrhine = this.RowHeightInfoNeededEventArgs;
            dgvrhine.SetProperties(rowIndex, height, minimumHeight);
            OnRowHeightInfoNeeded(dgvrhine);
            return dgvrhine; 
        }
 
        ///  
        protected virtual void OnRowHeightInfoNeeded(DataGridViewRowHeightInfoNeededEventArgs e)
        { 
            DataGridViewRowHeightInfoNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTINFONEEDED] as DataGridViewRowHeightInfoNeededEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        private bool OnRowHeightInfoPushed(int rowIndex, int height, int minimumHeight)
        { 
            Debug.Assert(rowIndex != -1);
            Debug.Assert(this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None);
            if (this.VirtualMode || this.DataSource != null)
            { 
                DataGridViewRowHeightInfoPushedEventArgs dgvrhipe = new DataGridViewRowHeightInfoPushedEventArgs(rowIndex, height, minimumHeight);
                OnRowHeightInfoPushed(dgvrhipe); 
                if (dgvrhipe.Handled) 
                {
                    UpdateRowHeightInfoPrivate(rowIndex, false, true /*invalidInAdjustFillingColumns*/); 
                    return true;
                }
            }
            return false; 
        }
 
        ///  
        protected virtual void OnRowHeightInfoPushed(DataGridViewRowHeightInfoPushedEventArgs e)
        { 
            DataGridViewRowHeightInfoPushedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTINFOPUSHED] as DataGridViewRowHeightInfoPushedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e); 
            }
        } 
 
        private void OnRowLeave(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        { 
            Debug.Assert(columnIndex >= 0 && rowIndex >= 0);
            if (rowIndex < this.Rows.Count && columnIndex < this.Columns.Count)
            {
                DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); 
                OnRowLeave(dgvce);
                if (dataGridViewCell != null) 
                { 
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                    { 
                        dataGridViewCell = null;
                    }
                    else
                    { 
                        Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                        dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; 
                    } 
                }
            } 
        }

        /// 
        protected virtual void OnRowLeave(DataGridViewCellEventArgs e) 
        {
            try 
            { 
                this.noDimensionChangeCount++;
 
                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWLEAVE] as DataGridViewCellEventHandler;
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                {
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            } 
            finally
            { 
                this.noDimensionChangeCount--;
                Debug.Assert(this.noDimensionChangeCount >= 0);
            }
        } 

        ///  
        protected virtual void OnRowMinimumHeightChanged(DataGridViewRowEventArgs e) 
        {
            if (e.Row.DataGridView != this) 
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            }
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWMINIMUMHEIGHTCHANGED] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e); 
            }
        } 

        /// 
        protected internal virtual void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
        { 
            DataGridViewRowPostPaintEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWPOSTPAINT] as DataGridViewRowPostPaintEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected internal virtual void OnRowPrePaint(DataGridViewRowPrePaintEventArgs e) 
        {
            DataGridViewRowPrePaintEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWPREPAINT] as DataGridViewRowPrePaintEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal void OnRowsAddedInternal(int rowIndex, int rowCount) 
        {
            OnRowsAdded(new DataGridViewRowsAddedEventArgs(rowIndex, rowCount)); 
        } 

        ///  
        protected virtual void OnRowsAdded(DataGridViewRowsAddedEventArgs e)
        {
            DataGridViewRowsAddedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSADDED] as DataGridViewRowsAddedEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnRowsDefaultCellStyleChanged(EventArgs e)
        {
            DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs; 
            if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize)
            { 
                InvalidateData(); 
            }
            else 
            {
                OnRowsGlobalAutoSize();
                if (this.editingControl != null)
                { 
                    PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                } 
            } 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSDEFAULTCELLSTYLECHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            {
                eh(this, e);
            } 
        }
 
        private void OnRowSelectMouseMove(HitTestInfo hti) 
        {
            Debug.Assert(hti.row >= 0); 
            Debug.Assert(this.MultiSelect);

            if (this.ptCurrentCell.Y != -1 &&
                hti.row != this.ptCurrentCell.Y && 
                !CommitEditForOperation(this.ptCurrentCell.X, hti.row, true))
            { 
                // Return silently if validating/commit/abort failed 
                return;
            } 
            if (IsRowOutOfBounds(hti.row))
            {
                return;
            } 

            this.noSelectionChangeCount++; 
            try 
            {
                if (this.trackRowEdge >= this.trackRow && hti.row > this.trackRowEdge && this.trackRowEdge >= 0) 
                {
                    SelectRowRange(this.Rows.GetNextRow(this.trackRowEdge, DataGridViewElementStates.Visible),
                        hti.row, true);
                    this.trackRowEdge = hti.row; 
                }
                else if (this.trackRowEdge > this.trackRow && hti.row < this.trackRowEdge && hti.row >= this.trackRow && this.trackRowEdge >= 0) 
                { 
                    SelectRowRange(this.Rows.GetNextRow(hti.row, DataGridViewElementStates.Visible),
                        this.trackRowEdge, false); 
                    this.trackRowEdge = hti.row;
                }
                else if (hti.row > this.trackRow && this.trackRowEdge == -1)
                { 
                    SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible),
                        hti.row, true); 
                    this.trackRowEdge = hti.row; 
                }
                else if (this.trackRowEdge <= this.trackRow && hti.row < this.trackRowEdge && this.trackRowEdge >= 0) 
                {
                    SelectRowRange(hti.row,
                        this.Rows.GetPreviousRow(this.trackRowEdge, DataGridViewElementStates.Visible),
                        true); 
                    this.trackRowEdge = hti.row;
                } 
                else if (this.trackRowEdge < this.trackRow && hti.row > this.trackRowEdge && hti.row <= this.trackRow && this.trackRowEdge >= 0) 
                {
                    SelectRowRange(this.trackRowEdge, 
                        this.Rows.GetPreviousRow(hti.row, DataGridViewElementStates.Visible),
                        false);
                    this.trackRowEdge = hti.row;
                } 
                else if (hti.row < this.trackRow && this.trackRowEdge == -1)
                { 
                    SelectRowRange(hti.row, 
                        this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible),
                        true); 
                    this.trackRowEdge = hti.row;
                }
                else if (this.trackRowEdge > this.trackRow && hti.row < this.trackRow)
                { 
                    SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible),
                        this.trackRowEdge, false); 
                    SelectRowRange(hti.row, 
                        this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible),
                        true); 
                    this.trackRowEdge = hti.row;
                }
                else if (hti.row > this.trackRow && this.trackRowEdge < this.trackRow && this.trackRowEdge >= 0)
                { 
                    SelectRowRange(this.trackRowEdge,
                        this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible), 
                        false); 
                    SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible),
                        hti.row, true); 
                    this.trackRowEdge = hti.row;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 

            if (this.ptCurrentCell.Y != -1 && hti.row != this.ptCurrentCell.Y) 
            {
                if (IsRowOutOfBounds(hti.row))
                {
                    return; 
                }
                bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, 
                    hti.row, 
                    false /*setAnchorCellAddress*/,
                    false /*validateCurrentCell*/, 
                    false /*throughMouseClick*/);
                Debug.Assert(success);
            }
        } 

        private void OnRowsGlobalAutoSize() 
        { 
            InvalidateData();
 
            if (this.noAutoSizeCount > 0)
            {
                return;
            } 

            // Autosize rows if needed 
            if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) 
            {
                AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/); 
            }

            // Auto size columms also if needed
            AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | 
                                                DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows,
                                                true /*fixedHeight*/); 
 
            bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing ||
                                        this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; 
            // Auto size column headers
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize)
            {
                AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/); 
            }
 
            // Auto size row headers 
            if (!fixedRowHeadersWidth)
            { 
                AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/);
            }

            // Second round of rows autosizing 
            if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
            { 
                AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
            }
 
            // Second round of column headers autosizing
            if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize && !fixedRowHeadersWidth)
            {
                AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); 
            }
        } 
 
        internal void OnRowsRemovedInternal(int rowIndex, int rowCount)
        { 
            OnRowsRemoved(new DataGridViewRowsRemovedEventArgs(rowIndex, rowCount));
        }

        ///  
        protected virtual void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e)
        { 
            DataGridViewRowsRemovedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSREMOVED] as DataGridViewRowsRemovedEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        /// 
        protected virtual void OnRowStateChanged(int rowIndex, DataGridViewRowStateChangedEventArgs e) 
        { 
            Debug.Assert(rowIndex >= -1);
 
            // If row.Frozen changed, we need to update the vertical scroll bar
            // A hidden row may become visible and vice-versa, we'd better repaint the whole control
            DataGridViewRow dataGridViewRow = e.Row;
            DataGridViewElementStates newState = DataGridViewElementStates.None; 
            bool rowVisible = false;
            if (rowIndex >= 0) 
            { 
                newState = this.Rows.GetRowState(rowIndex);
                rowVisible = ((newState & DataGridViewElementStates.Visible) != 0); 
            }
            switch (e.StateChanged)
            {
                // At this point we assume that only the Selected state has an influence on the rendering of the row. 
                // If there is a customer scenario where another state has an influence, the dev will have to invalidate the row by hand.
                // case DataGridViewElementStates.ReadOnly: 
                // case DataGridViewElementStates.Resizable: 

                case DataGridViewElementStates.Selected: 
                    if (rowVisible && this.inBulkPaintCount == 0)
                    {
                        InvalidateRowPrivate(rowIndex);
                    } 
                    break;
 
                case DataGridViewElementStates.Frozen: 
                    if (rowVisible)
                    { 
                        if ((newState & DataGridViewElementStates.Frozen) == 0)
                        {
                            // row was unfrozen - make it the first visible scrolling row if there is room
                            FirstVisibleScrollingRowTempted(rowIndex); 
                        }
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); 
                        Invalidate(); 
                    }
                    break; 

                case DataGridViewElementStates.Visible:
                {
                    if (!rowVisible && (newState & DataGridViewElementStates.Displayed) != 0) 
                    {
                        // Displayed row becomes invisible. Turns off the Displayed state. 
                        this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Displayed, false); 
                    }
 
                    PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/);
                    Invalidate();

                    bool rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0; 
                    DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode;
 
                    bool autoSizeRow = false; 

                    if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None) 
                    {
                        int height = dataGridViewRow.ThicknessInternal;
                        if (rowVisible)
                        { 
                            // Cache row's height before potential autosizing occurs
                            // Valid operation even for shared rows 
                            dataGridViewRow.CachedThickness = height; 
                            if (!((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed))
                            { 
                                AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/);
                                autoSizeRow = true;
                            }
                        } 
                        else if (height != dataGridViewRow.CachedThickness)
                        { 
                            // Rows that are made invisible in the collection take their non-autosized height 
                            // Not calling OnRowHeightInfoPushed(...) because rows are autosized
                            // Make sure the affected row is unshared 
                            if (dataGridViewRow.Index == -1)
                            {
                                dataGridViewRow = this.Rows[rowIndex];
                            } 
                            dataGridViewRow.ThicknessInternal = Math.Max(dataGridViewRow.MinimumHeight, dataGridViewRow.CachedThickness);
                        } 
                    } 

                    // Auto size columms also if needed 
                    DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows;
                    if (rowDisplayed)
                    {
                        autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; 
                    }
                    if (rowVisible && this.Rows.GetRowCount(DataGridViewElementStates.Visible) > 1) 
                    { 
                        // Columns can only expand, and not collapse.
                        AdjustExpandingColumns(autoSizeColumnCriteriaFilter, rowIndex); 
                    }
                    else
                    {
                        AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/); 
                    }
 
                    if (autoSizeRow) 
                    {
                        // Second round of row autosizing 
                        AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/);
                    }
                    break;
                } 
            }
 
            DataGridViewRowStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSTATECHANGED] as DataGridViewRowStateChangedEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }

            if (e.StateChanged == DataGridViewElementStates.ReadOnly && 
                rowIndex == this.ptCurrentCell.Y &&
                !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) 
            { 
                VerifyImeRestrictedModeChanged();
 
                if ((newState & DataGridViewElementStates.ReadOnly) == 0 &&
                    !this.ReadOnly &&
                    !this.Columns[this.ptCurrentCell.X].ReadOnly &&
                    ColumnEditable(this.ptCurrentCell.X) && 
                    !this.IsCurrentCellInEditMode &&
                    (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                    (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))) 
                {
                    // Current row becomes read/write. Enter editing mode. 
                    BeginEditInternal(true /*selectAll*/);
                }
            }
        } 

        internal void OnRowUnshared(DataGridViewRow dataGridViewRow) 
        { 
            if (-1 != this.ptCurrentCell.X && dataGridViewRow.Index == this.ptCurrentCell.Y && this.editingControl != null)
            { 
                this.CurrentCellInternal.CacheEditingControl();
            }
            DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
            OnRowUnshared(dgvre); 
        }
 
        ///  
        protected virtual void OnRowUnshared(DataGridViewRowEventArgs e)
        { 
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            } 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWUNSHARED] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        private bool OnRowValidating(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex)
        { 
            DataGridViewCellCancelEventArgs dgvcce = new DataGridViewCellCancelEventArgs(columnIndex, rowIndex);
            OnRowValidating(dgvcce); 
            if (!dgvcce.Cancel) 
            {
                if (this.dataConnection != null && 
                    this.dataConnection.InterestedInRowEvents &&
                    !this.dataConnection.PositionChangingOutsideDataGridView &&
                    !this.dataConnection.ListWasReset)
                { 
                    this.dataConnection.OnRowValidating(dgvcce);
                } 
            } 
            if (dataGridViewCell != null && rowIndex < this.Rows.Count && columnIndex < this.Columns.Count)
            { 
                dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
            }
            return dgvcce.Cancel;
        } 

        ///  
        protected virtual void OnRowValidating(DataGridViewCellCancelEventArgs e) 
        {
            try 
            {
                this.noDimensionChangeCount++;

                DataGridViewCellCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWVALIDATING] as DataGridViewCellCancelEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
                { 
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                } 
            }
            finally
            {
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0);
            } 
        } 

        private void OnRowValidated(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) 
        {
            this.IsCurrentRowDirtyInternal = false;
            this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowCreatedByEditing] = false;
            if (rowIndex == this.newRowIndex) 
            {
                // Stop displaying the default cell values on the 'new row'. 
                InvalidateRowPrivate(rowIndex); 
            }
 
            DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex);
            OnRowValidated(dgvce);
            if (dataGridViewCell != null)
            { 
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    dataGridViewCell = null; 
                }
                else 
                {
                    Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count);
                    dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex];
                } 
            }
        } 
 
        /// 
        protected virtual void OnRowValidated(DataGridViewCellEventArgs e) 
        {
            try
            {
                this.noDimensionChangeCount++; 

                DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWVALIDATED] as DataGridViewCellEventHandler; 
                if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
                {
                    eh(this, e); 
                    CorrectFocus(true /*onlyIfGridHasFocus*/);
                }
            }
            finally 
            {
                this.noDimensionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0); 
            }
        } 

        private void OnScroll(ScrollEventType scrollEventType, int oldValue, int newValue, ScrollOrientation orientation)
        {
            ScrollEventArgs se = new ScrollEventArgs(scrollEventType, oldValue, newValue, orientation); 
            OnScroll(se);
            if (ScrollOrientation.VerticalScroll == orientation) 
            { 
                if (se.NewValue != newValue)
                { 
                    try
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll] = true;
                        int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                        int rowIndexPrevious = rowIndex;
                        newValue = se.NewValue; 
                        while (rowIndex != -1 && newValue > 0) 
                        {
                            rowIndexPrevious = rowIndex; 
                            rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible);
                            newValue--;
                        }
                        if (rowIndex != -1) 
                        {
                            rowIndexPrevious = rowIndex; 
                        } 
                        if (rowIndexPrevious != -1)
                        { 
                            this.FirstDisplayedScrollingRowIndex = rowIndexPrevious;
                        }
                    }
                    finally 
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll] = false; 
                    } 
                }
            } 
            else
            {
                if (se.NewValue != newValue)
                { 
                    try
                    { 
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingHorizontalScroll] = true; 
                        this.HorizontalOffset = se.NewValue;
                    } 
                    finally
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingHorizontalScroll] = false;
                    } 
                }
            } 
        } 

        ///  
        protected virtual void OnScroll(ScrollEventArgs e)
        {
            ScrollEventHandler eh = this.Events[EVENT_DATAGRIDVIEWSCROLL] as ScrollEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            } 
        }
 
        /// 
        protected virtual void OnSelectionChanged(EventArgs e)
        {
            this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = false; 

            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWSELECTIONCHANGED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        internal bool OnSortCompare(DataGridViewColumn dataGridViewSortedColumn, object value1, object value2, int rowIndex1, int rowIndex2, out int sortResult) 
        {
            DataGridViewSortCompareEventArgs dgvsce = new DataGridViewSortCompareEventArgs(dataGridViewSortedColumn, value1, value2, rowIndex1, rowIndex2); 
            OnSortCompare(dgvsce); 
            sortResult = dgvsce.SortResult;
            return dgvsce.Handled; 
        }

        /// 
        protected virtual void OnSortCompare(DataGridViewSortCompareEventArgs e) 
        {
            DataGridViewSortCompareEventHandler eh = this.Events[EVENT_DATAGRIDVIEWSORTCOMPARE] as DataGridViewSortCompareEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnSorted(EventArgs e)
        { 
            EventHandler eh = this.Events[EVENT_DATAGRIDVIEWSORTED] as EventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        internal void OnSortGlyphDirectionChanged(DataGridViewColumnHeaderCell dataGridViewColumnHeaderCell)
        { 
            Debug.Assert(dataGridViewColumnHeaderCell != null); 

            if (dataGridViewColumnHeaderCell.OwningColumn == this.SortedColumn) 
            {
                if (dataGridViewColumnHeaderCell.SortGlyphDirection == SortOrder.None)
                {
                    this.sortedColumn = null; 
                    DataGridViewColumn dataGridViewColumn = dataGridViewColumnHeaderCell.OwningColumn;
 
                    if (dataGridViewColumn.IsDataBound) 
                    {
                        // If the column whose SortGlyphChanges is the sorted column and it is also the dataBound column 
                        // then see if there is another dataBound column which has the same property name as the sorted column.
                        // If so, then make that dataGridViewColumn the sorted column in the data grid view.
                        for (int i = 0; i < this.Columns.Count; i ++)
                        { 
                            if (dataGridViewColumn != this.Columns[i] &&
                                this.Columns[i].SortMode != DataGridViewColumnSortMode.NotSortable && 
                                String.Compare(dataGridViewColumn.DataPropertyName, 
                                               this.Columns[i].DataPropertyName,
                                               true /*ignoreCase*/, 
                                               CultureInfo.InvariantCulture) == 0)
                            {
                                Debug.Assert(this.Columns[i].IsDataBound, "two columns w/ the same DataPropertyName should be DataBound at the same time");
                                this.sortedColumn = this.Columns[i]; 
                                break;
                            } 
                        } 
                    }
                } 

                this.sortOrder = this.sortedColumn != null ? this.sortedColumn.HeaderCell.SortGlyphDirection : SortOrder.None;
            }
 
            InvalidateCellPrivate(dataGridViewColumnHeaderCell);
        } 
 
        private void OnTopLeftHeaderMouseDown()
        { 
            if (this.MultiSelect)
            {
                SelectAll();
                if (-1 != this.ptCurrentCell.X) 
                {
                    // Potentially have to give focus back to the current edited cell. 
                    bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, 
                                                             false /*setAnchorCellAddress*/,
                                                             false /*validateCurrentCell*/, 
                                                             false /*throughMouseClick*/);
                    Debug.Assert(success);
                }
            } 
        }
 
        ///  
        protected virtual void OnUserAddedRow(DataGridViewRowEventArgs e)
        { 
            if (e.Row.DataGridView != this)
            {
                throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row");
            } 
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERADDEDROW] as DataGridViewRowEventHandler;
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            { 
                eh(this, e);
            } 
        }

        /// 
        protected virtual void OnUserDeletedRow(DataGridViewRowEventArgs e) 
        {
            DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERDELETEDROW] as DataGridViewRowEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) 
            {
                eh(this, e); 
            }
        }

        ///  
        protected virtual void OnUserDeletingRow(DataGridViewRowCancelEventArgs e)
        { 
            DataGridViewRowCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERDELETINGROW] as DataGridViewRowCancelEventHandler; 
            if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed)
            { 
                eh(this, e);
            }
        }
 
        private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
        { 
            if (e.Category == UserPreferenceCategory.Color || 
                e.Category == UserPreferenceCategory.Locale ||
                e.Category == UserPreferenceCategory.General || 
                e.Category == UserPreferenceCategory.Window ||
                e.Category == UserPreferenceCategory.VisualStyle)
            {
                OnGlobalAutoSize(); 
                if (e.Category == UserPreferenceCategory.Window)
                { 
                    this.cachedEditingControl = null; 
                    if (this.editingControl != null)
                    { 
                        // The editing control may not adapt well to the new system rendering,
                        // so instead of caching it into the this.cachedEditingControl variable
                        // next time editing mode is exited, simply discard the control.
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_discardEditingControl] = true; 
                    }
                    PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); 
                } 
            }
        } 

        /// 
        protected override void OnValidating(CancelEventArgs e)
        { 
            // VSWhidbey 481170. Avoid Cell/Row Validation events when the grid or its editing control gets the focus
            if (!this.BecomingActiveControl && (this.editingControl == null || !this.editingControl.BecomingActiveControl)) 
            { 
                if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey])
                { 
                    if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.LeaveControl,
                                 DataGridViewValidateCellInternal.Always,
                                 false /*fireCellLeave*/,
                                 false /*fireCellEnter*/, 
                                 false /*fireRowLeave*/,
                                 false /*fireRowEnter*/, 
                                 false /*fireLeave*/, 
                                 false /*keepFocus*/,
                                 false /*resetCurrentCell*/, 
                                 false /*resetAnchorCell unused here*/))
                    {
                        e.Cancel = true;
                        return; 
                    }
                } 
 
                if (this.ptCurrentCell.X >= 0)
                { 
                    DataGridViewCell dataGridViewCellTmp = null;
                    if (OnRowValidating(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y))
                    {
                        // Row validation was cancelled 
                        e.Cancel = true;
                        return; 
                    } 
                    if (this.ptCurrentCell.X == -1)
                    { 
                        return;
                    }
                    OnRowValidated(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                    // Row validation was not cancelled, but does operation need to be re-evaluated. 
                    if (this.DataSource != null &&
                        this.ptCurrentCell.X >= 0 && 
                        this.AllowUserToAddRowsInternal && 
                        this.newRowIndex == this.ptCurrentCell.Y)
                    { 
                        // Current cell needs to be moved to the row just above the 'new row' if possible.
                        int rowIndex = this.Rows.GetPreviousRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
                        if (rowIndex > -1)
                        { 
                            bool success = SetAndSelectCurrentCellAddress(this.ptCurrentCell.X, rowIndex,
                                true /*setAnchorCellAddress*/, 
                                false /*validateCurrentCell*/, 
                                false /*throughMouseClick*/,
                                false /*clearSelection*/, 
                                false /*forceCurrentCellSelection*/);
                            Debug.Assert(success);
                        }
                        else 
                        {
                            bool success = SetCurrentCellAddressCore(-1, -1, 
                                true /*setAnchorCellAddress*/, 
                                false /*validateCurrentCell*/,
                                false /*throughMouseClick*/); 
                            Debug.Assert(success);
                        }
                    }
                } 
            }
            base.OnValidating(e); 
        } 

        protected override void OnVisibleChanged(EventArgs e) 
        {
            base.OnVisibleChanged(e);
            OnVisibleChangedPrivate();
        } 

        private void OnVisibleChangedPrivate() 
        { 
            // Debug.Assert(!this.displayedBandsInfo.Dirty);   Not valid because EnsureDirtyState can potentially be called
            //                                                 for example when RowHeadersVisible is changed while the control is invisible. 
            int rowIndexTmp;

            if (this.Visible)
            { 
                // Make sure all displayed bands get the Displayed state: 1 & 2 for rows
 
                // 1. Make sure all displayed frozen rows have their Displayed state set to true 
                int numDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedFrozenRows;
                if (numDisplayedFrozenRows > 0) 
                {
                    rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                    while (numDisplayedFrozenRows > 0)
                    { 
                        Debug.Assert(rowIndexTmp != -1);
                        if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) 
                        { 
#if DEBUG
                            int numDisplayedFrozenRowsDbg = numDisplayedFrozenRows; 
                            while (numDisplayedFrozenRowsDbg > 0)
                            {
                                Debug.Assert(rowIndexTmp != -1);
                                Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0); 
                                rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                                numDisplayedFrozenRowsDbg--; 
                            } 
#endif
                            return; // rows' Displayed states are already up-to-date. OnHandleCreated already did the job. 
                        }
                        else
                        {
                            this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true); 
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                            numDisplayedFrozenRows--; 
                        } 
                    }
                } 

                // 2. Make sure all displayed scrolling rows have their Displayed state set to true
                rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                if (rowIndexTmp > -1) 
                {
                    Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Visible) != 0); 
                    int numDisplayedScrollingRows = this.displayedBandsInfo.NumDisplayedScrollingRows; 
                    Debug.Assert(numDisplayedScrollingRows > 0);
                    while (numDisplayedScrollingRows > 0) 
                    {
                        Debug.Assert(rowIndexTmp != -1);
                        if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0)
                        { 
#if DEBUG
                            int numDisplayedScrollingRowsDbg = numDisplayedScrollingRows; 
                            while (numDisplayedScrollingRowsDbg > 0) 
                            {
                                Debug.Assert(rowIndexTmp != -1); 
                                Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0);
                                rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                                numDisplayedScrollingRowsDbg--;
                            } 
#endif
                            return; // rows' Displayed states are already up-to-date. OnHandleCreated already did the job. 
                        } 
                        else
                        { 
                            this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true);
                            rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible);
                            numDisplayedScrollingRows--;
                        } 
                    }
                } 
            } 
            else
            { 
                // Make sure all displayed bands lose the Displayed state
                UpdateRowsDisplayedState(false /*displayed*/);
            }
 
            UpdateColumnsDisplayedState(this.Visible /*displayed*/);
        } 
 
        /// 
        protected virtual void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds) 
        {
            // Paint potential block below rows
            Rectangle rcBelowRows = gridBounds;
            int visibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); 
            if (this.layout.ColumnHeadersVisible)
            { 
                rcBelowRows.Y += this.layout.ColumnHeaders.Height; 
                rcBelowRows.Height -= this.layout.ColumnHeaders.Height;
            } 
            else if (this.SingleHorizontalBorderAdded && visibleRowsHeight > 0)
            {
                rcBelowRows.Y++;
                rcBelowRows.Height--; 
            }
            int rowsHeight = visibleRowsHeight - this.verticalOffset; 
            rcBelowRows.Y += rowsHeight; 
            rcBelowRows.Height -= rowsHeight;
            if (rcBelowRows.Width > 0 && rcBelowRows.Height > 0) 
            {
                graphics.FillRectangle(this.backgroundBrush, rcBelowRows);
            }
 
            // Paint potential block next to column headers and rows
            int visibleColumnsWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible); 
            Rectangle rcNextRows = gridBounds; 
            if (this.Columns.Count > 0)
            { 
                if (this.layout.RowHeadersVisible)
                {
                    if (!this.RightToLeftInternal)
                    { 
                        rcNextRows.X += this.layout.RowHeaders.Width;
                    } 
                    rcNextRows.Width -= this.layout.RowHeaders.Width; 
                }
                else if (this.SingleVerticalBorderAdded && visibleColumnsWidth > 0) 
                {
                    if (!this.RightToLeftInternal)
                    {
                        rcNextRows.X++; 
                    }
                    rcNextRows.Width--; 
                } 
            }
            int rowsWidth = visibleColumnsWidth - this.horizontalOffset; 
            if (!this.RightToLeftInternal)
            {
                rcNextRows.X += rowsWidth;
            } 
            rcNextRows.Width -= rowsWidth;
            rcNextRows.Height = gridBounds.Height - rcBelowRows.Height; 
            if (rcNextRows.Width > 0 && rcNextRows.Height > 0) 
            {
                graphics.FillRectangle(this.backgroundBrush, rcNextRows); 
            }
        }

        private void PaintBorder(Graphics g, Rectangle clipRect, Rectangle bounds) 
        {
            Debug.Assert(bounds.Left == 0); 
            Debug.Assert(bounds.Top == 0); 
            if (this.BorderStyle == BorderStyle.None)
            { 
                return;
            }
            bool paintingNeeded = false;
            int borderWidth = this.BorderWidth; 
            // Does the clipRect intersect with the top edge?
            Rectangle edge = new Rectangle(0, 0, bounds.Width, borderWidth); 
            paintingNeeded = clipRect.IntersectsWith(edge); 
            if (!paintingNeeded)
            { 
                // Does the clipRect intersect with the bottom edge?
                edge.Y = bounds.Height - borderWidth;
                paintingNeeded = clipRect.IntersectsWith(edge);
                if (!paintingNeeded) 
                {
                    // Does the clipRect intersect with the left edge? 
                    edge.Y = 0; 
                    edge.Height = bounds.Height;
                    edge.Width = borderWidth; 
                    paintingNeeded = clipRect.IntersectsWith(edge);
                    if (!paintingNeeded)
                    {
                        // Does the clipRect intersect with the right edge? 
                        edge.X = bounds.Width - borderWidth;
                        paintingNeeded = clipRect.IntersectsWith(edge); 
                    } 
                }
            } 

            if (paintingNeeded)
            {
                if (this.BorderStyle == BorderStyle.Fixed3D) 
                {
                    if (Application.RenderWithVisualStyles) 
                    { 
                        Pen pen = GetCachedPen(VisualStyleInformation.TextControlBorder);
                        g.DrawRectangle(pen, new Rectangle(0, 0, bounds.Width - 1, bounds.Height - 1)); 
                    }
                    else
                    {
                        ControlPaint.DrawBorder3D(g, bounds, Border3DStyle.Sunken); 
                    }
                } 
                else if (this.BorderStyle == BorderStyle.FixedSingle) 
                {
                    Pen pen = GetCachedPen(SystemColors.ControlText); 
                    g.DrawRectangle(pen, new Rectangle(0, 0, bounds.Width - 1, bounds.Height - 1));
                }
                else
                { 
                    Debug.Fail("DataGridView.PaintBorder - Unexpected BorderStyle value.");
                } 
            } 
        }
 
        private void PaintColumnHeaders(Graphics g, Rectangle clipBounds, bool singleBorderAdded)
        {
            if (g.IsVisible(this.layout.ColumnHeaders))
            { 
                Rectangle bandBounds, cellBounds;
                bandBounds = cellBounds = this.layout.ColumnHeaders; 
                bandBounds.Height = cellBounds.Height = this.columnHeadersHeight; 
                int cx = 0;
                bool isFirstDisplayedColumn = true, isLastVisibleColumn = false; 
                DataGridViewCell cell;
                DataGridViewCellStyle inheritedCellStyle = new DataGridViewCellStyle();
                DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder = new DataGridViewAdvancedBorderStyle(), dgvabsEffective;
                DataGridViewColumn dataGridViewColumnNext = null; 

                // first paint the visible frozen columns 
                DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                while (dataGridViewColumn != null)
                { 
                    cell = dataGridViewColumn.HeaderCell;
                    cellBounds.Width = dataGridViewColumn.Thickness;
                    if (singleBorderAdded && isFirstDisplayedColumn)
                    { 
                        cellBounds.Width++;
                    } 
                    Debug.Assert(cellBounds.Width > 0); 
                    if (this.RightToLeftInternal)
                    { 
                        cellBounds.X = bandBounds.Right - cx - cellBounds.Width;
                    }
                    else
                    { 
                        cellBounds.X = bandBounds.X + cx;
                    } 
 
                    BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell);
 
                    dataGridViewColumnNext = this.Columns.GetNextColumn(dataGridViewColumn,
                        DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen,
                        DataGridViewElementStates.None);
                    if (dataGridViewColumnNext == null) 
                    {
                        isLastVisibleColumn = (this.displayedBandsInfo.FirstDisplayedScrollingCol < 0); 
                    } 

                    dgvabsEffective = AdjustColumnHeaderBorderStyle(this.AdvancedColumnHeadersBorderStyle, dataGridViewAdvancedBorderStylePlaceholder, 
                                                                    isFirstDisplayedColumn, isLastVisibleColumn);

                    // [....]: should paintSelectionBackground be dev-settable?
                    cell.PaintWork(g, 
                                   clipBounds,
                                   cellBounds, 
                                   -1, 
                                   dataGridViewColumn.State,
                                   inheritedCellStyle, 
                                   dgvabsEffective,
                                   DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground);

                    cx += cellBounds.Width; 
                    if (cx >= bandBounds.Width)
                    { 
                        break; 
                    }
 
                    dataGridViewColumn = dataGridViewColumnNext;
                    isFirstDisplayedColumn = false;
                }
 
                // then paint the visible scrolling ones
                Rectangle scrollingBounds = bandBounds; 
                if (!this.RightToLeftInternal) 
                {
                    scrollingBounds.X -= this.negOffset; 
                }
                scrollingBounds.Width += this.negOffset;

                if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && cx < scrollingBounds.Width) 
                {
                    Region clipRegion = null; 
                    if (this.negOffset > 0) 
                    {
                        clipRegion = g.Clip; 
                        Rectangle rowRect = bandBounds;
                        if (!this.RightToLeftInternal)
                        {
                            rowRect.X += cx; 
                        }
                        rowRect.Width -= cx; 
                        g.SetClip(rowRect); 
                    }
 
                    dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                    while (dataGridViewColumn != null)
                    {
                        Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); 

                        cell = dataGridViewColumn.HeaderCell; 
                        cellBounds.Width = dataGridViewColumn.Thickness; 
                        if (singleBorderAdded && isFirstDisplayedColumn)
                        { 
                            cellBounds.Width++;
                        }
                        Debug.Assert(cellBounds.Width > 0);
                        if (this.RightToLeftInternal) 
                        {
                            cellBounds.X = scrollingBounds.Right - cx - cellBounds.Width; 
                        } 
                        else
                        { 
                            cellBounds.X = scrollingBounds.X + cx;
                        }

                        BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell); 

                        dataGridViewColumnNext = this.Columns.GetNextColumn(dataGridViewColumn, 
                            DataGridViewElementStates.Visible, 
                            DataGridViewElementStates.None);
                        isLastVisibleColumn = (dataGridViewColumnNext == null); 

                        dgvabsEffective = AdjustColumnHeaderBorderStyle(this.AdvancedColumnHeadersBorderStyle, dataGridViewAdvancedBorderStylePlaceholder,
                                                                        isFirstDisplayedColumn, isLastVisibleColumn);
 
                        cell.PaintWork(g,
                                       clipBounds, 
                                       cellBounds, 
                                       -1,
                                       dataGridViewColumn.State, 
                                       inheritedCellStyle,
                                       dgvabsEffective,
                                       DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground);
 
                        cx += cellBounds.Width;
                        if (cx >= scrollingBounds.Width) 
                        { 
                            break;
                        } 

                        dataGridViewColumn = dataGridViewColumnNext;
                        isFirstDisplayedColumn = false;
                    } 

                    if (this.negOffset > 0) 
                    { 
                        Debug.Assert(clipRegion != null);
                        g.Clip = clipRegion; 
                        clipRegion.Dispose();
                    }
                }
            } 
        }
 
        private void PaintGrid(Graphics g, 
            Rectangle gridBounds,
            Rectangle clipRect, 
            bool singleVerticalBorderAdded,
            bool singleHorizontalBorderAdded)
        {
            Rectangle rc = gridBounds; 

            if (this.layout.TopLeftHeader.Width > 0 && 
                (clipRect.IntersectsWith(this.layout.TopLeftHeader) || this.lastHeaderShadow != -1)) 
            {
                if (this.Columns.Count > 0 || this.Rows.Count > 0) 
                {
                    using (Region clipRegion = g.Clip)
                    {
                        g.SetClip(this.layout.TopLeftHeader); 
                        PaintTopLeftHeaderCell(g);
                        g.Clip = clipRegion; 
                    } 
                }
            } 

            if (this.layout.ColumnHeadersVisible)
            {
                Rectangle columnHeadersClip = new Rectangle(); 
                columnHeadersClip = this.layout.ColumnHeaders;
                if (singleVerticalBorderAdded) 
                { 
                    columnHeadersClip.Width++;
                } 
                if (clipRect.IntersectsWith(columnHeadersClip) || this.lastHeaderShadow != -1)
                {
                    using (Region clipRegion = g.Clip)
                    { 
                        g.SetClip(columnHeadersClip);
                        PaintColumnHeaders(g, columnHeadersClip, singleVerticalBorderAdded); 
                        g.Clip = clipRegion; 
                    }
                } 
                int columnHeadersHeight = this.layout.ColumnHeaders.Height;
                rc.Y += columnHeadersHeight;
                rc.Height -= columnHeadersHeight;
 
                if (this.lastHeaderShadow != -1)
                { 
                    DrawColHeaderShadow(g, this.lastHeaderShadow); 
                }
            } 

            if (rc.Height > 0)
            {
                PaintRows(g, rc, clipRect, /*singleVerticalBorderAdded, */ singleHorizontalBorderAdded); 
            }
 
            if (this.currentRowSplitBar != -1) 
            {
                Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize]); 
                DrawRowSplitBar(this.currentRowSplitBar);
            }
            else if (this.currentColSplitBar != -1)
            { 
                Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize]);
                DrawColSplitBar(this.currentColSplitBar); 
            } 
        }
 
        private void PaintRows(Graphics g,
            Rectangle boundingRect,
            Rectangle clipRect,
            /*bool singleVerticalBorderAdded,*/ 
            bool singleHorizontalBorderAdded)
        { 
            int cy = 0; 
            Rectangle rowBounds;
            DataGridViewRow dataGridViewRow; 
            bool isFirstDisplayedRow = true;
            int indexTmp, indexTmpNext;

            // paint visible none-scrolling rows 
            indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            while (indexTmp != -1) 
            { 
                rowBounds = boundingRect;
                rowBounds.Height = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); 
                if (isFirstDisplayedRow && singleHorizontalBorderAdded)
                {
                    rowBounds.Height++;
                } 
                rowBounds.Y = boundingRect.Y + cy;
 
                indexTmpNext = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 

                if (clipRect.IntersectsWith(rowBounds)) 
                {
                    dataGridViewRow = this.Rows.SharedRow(indexTmp);
                    dataGridViewRow.Paint(g,
                        clipRect, 
                        rowBounds,
                        indexTmp, 
                        this.Rows.GetRowState(indexTmp), 
                        isFirstDisplayedRow,
                        (indexTmpNext == -1) && (this.displayedBandsInfo.FirstDisplayedScrollingRow == -1)); 
                }
                cy += rowBounds.Height;
                if (cy >= boundingRect.Height)
                { 
                    break;
                } 
                indexTmp = indexTmpNext; 
                isFirstDisplayedRow = false;
            } 

            // paint scrolling rows
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0 && cy < boundingRect.Height)
            { 
                indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0); 
                Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0); 
                while (indexTmp != -1)
                { 
                    rowBounds = boundingRect;
                    rowBounds.Height = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp);
                    if (isFirstDisplayedRow && singleHorizontalBorderAdded)
                    { 
                        rowBounds.Height++;
                    } 
                    rowBounds.Y = boundingRect.Y + cy; 

                    indexTmpNext = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); 

                    if (clipRect.IntersectsWith(rowBounds))
                    {
                        dataGridViewRow = this.Rows.SharedRow(indexTmp); 
                        dataGridViewRow.Paint(g,
                            clipRect, 
                            rowBounds, 
                            indexTmp,
                            this.Rows.GetRowState(indexTmp), 
                            isFirstDisplayedRow,
                            indexTmpNext == -1);
                    }
                    cy += rowBounds.Height; 
                    if (cy >= boundingRect.Height)
                    { 
                        break; 
                    }
                    indexTmp = indexTmpNext; 
                    isFirstDisplayedRow = false;
                }
            }
        } 

        private void PaintTopLeftHeaderCell(Graphics g) 
        { 
            if (g.IsVisible(this.layout.TopLeftHeader))
            { 
                DataGridViewCell cell = this.TopLeftHeaderCell;
                DataGridViewCellStyle inheritedCellStyle = new DataGridViewCellStyle();
                BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell);
                Rectangle cellBounds = this.layout.TopLeftHeader; 
                cellBounds.Width = this.rowHeadersWidth;
                cellBounds.Height = this.columnHeadersHeight; 
                // [....]: Should paintSelectionBackground be dev-settable? 
                cell.PaintWork(g,
                               this.layout.TopLeftHeader, 
                               cellBounds,
                               -1,
                               cell.State,
                               inheritedCellStyle, 
                               this.AdjustedTopLeftHeaderBorderStyle,
                               DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground); 
            } 
        }
 
        private void PerformLayoutPrivate(bool useRowShortcut,
                                          bool computeVisibleRows,
                                          bool invalidInAdjustFillingColumns,
                                          bool repositionEditingControl) 
        {
            this.inPerformLayoutCount++; 
            try 
            {
                if (invalidInAdjustFillingColumns && this.InAdjustFillingColumns) 
                {
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter));
                }
 
                if (this.IsHandleCreated)
                { 
                    bool columnsAdjusted = false; 
                    if (useRowShortcut)
                    { 
                        ComputeLayoutShortcut(computeVisibleRows);
                    }
                    else
                    { 
                        columnsAdjusted = ComputeLayout();
                    } 
                    FlushDisplayedChanged(); 
                    if (columnsAdjusted && this.inPerformLayoutCount < 3)
                    { 
                        // Some columns were auto-filled, the rows and column headers may need to be autosized.
                        if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0)
                        {
                            AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); 
                        }
                        if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) 
                        { 
                            AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/);
                        } 
                    }
                    if (repositionEditingControl && this.editingControl != null)
                    {
                        PositionEditingControl(true /*setLocation*/, false /*setSize*/, false /*setFocus*/); 
                    }
                } 
                else 
                {
                    this.displayedBandsInfo.FirstDisplayedFrozenCol = -1; 
                    this.displayedBandsInfo.FirstDisplayedFrozenRow = -1;
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = -1;
                    this.displayedBandsInfo.FirstDisplayedScrollingCol = -1;
                    this.displayedBandsInfo.NumDisplayedFrozenRows = 0; 
                    this.displayedBandsInfo.NumDisplayedFrozenCols = 0;
                    this.displayedBandsInfo.NumDisplayedScrollingRows = 0; 
                    this.displayedBandsInfo.NumDisplayedScrollingCols = 0; 
                    this.displayedBandsInfo.NumTotallyDisplayedFrozenRows = 0;
                    this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = 0; 
                    this.displayedBandsInfo.LastDisplayedScrollingRow = -1;
                    this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1;
                    if (this.layout != null)
                    { 
                        this.layout.dirty = true;
                    } 
                } 
            }
            finally 
            {
                this.inPerformLayoutCount--;
                Debug.Assert(this.inPerformLayoutCount >= 0);
            } 
        }
 
        [ 
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ] 
        private void PopulateNewRowWithDefaultValues()
        {
            if (this.newRowIndex != -1)
            { 
                DataGridViewRow newRow = this.Rows.SharedRow(this.newRowIndex);
                DataGridViewCellCollection newRowCells = newRow.Cells; 
                foreach (DataGridViewCell dataGridViewCell in newRowCells) 
                {
                    if (dataGridViewCell.DefaultNewRowValue != null) 
                    {
                        newRow = this.Rows[this.newRowIndex]; // unshare the 'new row'.
                        newRowCells = newRow.Cells;
                        break; 
                    }
                } 
                foreach (DataGridViewCell dataGridViewCell in newRowCells) 
                {
                    dataGridViewCell.SetValueInternal(this.newRowIndex, dataGridViewCell.DefaultNewRowValue); 
                }
            }
        }
 
        private void PositionEditingControl(bool setLocation, bool setSize, bool setFocus)
        { 
            Debug.Assert(this.editingControl != null); 

            if (!this.IsHandleCreated) 
            {
                return;
            }
 
            #if DEBUG
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal; 
                Debug.Assert(dataGridViewCell != null); 
                Debug.Assert(dataGridViewCell.ColumnIndex == this.ptCurrentCell.X);
                Debug.Assert(dataGridViewCell.RowIndex == this.ptCurrentCell.Y || dataGridViewCell.RowIndex == -1); 
            #endif

            Rectangle editingZone = this.layout.Data;
            if (editingZone.Width == 0 || editingZone.Height == 0) 
            {
                return; 
            } 

            this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true; 

            try
            {
                int leftEdge = GetColumnXFromIndex(this.ptCurrentCell.X); 
                if (this.RightToLeftInternal)
                { 
                    leftEdge -= this.Columns[this.ptCurrentCell.X].Width-1; 
                }
                Rectangle cellBounds = new Rectangle(leftEdge, GetRowYFromIndex(this.ptCurrentCell.Y), 
                                                     this.Columns[this.ptCurrentCell.X].Width, this.Rows.SharedRow(this.ptCurrentCell.Y).GetHeight(this.ptCurrentCell.Y));
                Rectangle cellClip = cellBounds;
                // Need to clip the zones of the frozen columns and rows and headers.
                if (!this.Columns[this.ptCurrentCell.X].Frozen) 
                {
                    int totalVisibleFrozenWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    if (!this.RightToLeftInternal) 
                    {
                        editingZone.X += totalVisibleFrozenWidth; 
                    }
                    editingZone.Width = Math.Max(0, editingZone.Width - totalVisibleFrozenWidth);
                }
                if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Frozen) == 0) 
                {
                    int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    editingZone.Y += totalVisibleFrozenHeight; 
                }
                cellClip.Intersect(editingZone); 

                if (cellClip.Width == 0 || cellClip.Height == 0)
                {
                    // we cannot simply make the control invisible because we want it to keep the focus. 
                    // (and Control::CanFocus returns false if the control is not visible).
                    // So we place the editing control to the right of the DataGridView. 
                    Debug.Assert(this.editingControl != null); 
                    this.editingPanel.Location = new Point(this.Width + 1, 0);
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] = true; 
                }
                else
                {
                    bool singleVerticalBorderAdded = this.SingleVerticalBorderAdded; 
                    bool singleHorizontalBorderAdded = this.SingleHorizontalBorderAdded;
                    bool isFirstDisplayedColumn = this.FirstDisplayedColumnIndex == this.ptCurrentCell.X; 
                    bool isFirstDisplayedRow = this.FirstDisplayedRowIndex == this.ptCurrentCell.Y; 

                    if (singleVerticalBorderAdded && isFirstDisplayedColumn) 
                    {
                        if (!this.RightToLeftInternal)
                        {
                            cellBounds.X--; 
                            cellClip.X--;
                        } 
                        cellBounds.Width++; 
                        cellClip.Width++;
                    } 
                    if (singleHorizontalBorderAdded && isFirstDisplayedRow)
                    {
                        cellBounds.Y--;
                        cellClip.Y--; 
                        cellBounds.Height++;
                        cellClip.Height++; 
                    } 

                    this.CurrentCellInternal.PositionEditingControl( 
                        setLocation || this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden],
                        setSize || this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden],
                        cellBounds, cellClip, this.InheritedEditingCellStyle,
                        singleVerticalBorderAdded, singleHorizontalBorderAdded, 
                        isFirstDisplayedColumn, isFirstDisplayedRow);
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] = false; 
                } 
                this.editingPanel.Visible = true;
                if (setFocus) 
                {
                    CorrectFocus(false /*onlyIfGridHasFocus*/);
                }
            } 
            finally
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = false; 
            }
        } 

        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessAKey(Keys keyData) 
        { 
            if ((keyData & (Keys.Shift | Keys.Control | Keys.Alt)) == Keys.Control &&
                this.MultiSelect) 
            {
                SelectAll();
                return true;
            } 
            return false;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
            SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters") // Derived controls may need keyData.
        ]
        protected bool ProcessDeleteKey(Keys keyData) 
        {
            if (this.AllowUserToDeleteRowsInternal) 
            { 
                if (this.editingControl != null)
                { 
                    // editing control gets a chance to handle the Delete key first
                    return false;
                }
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.FullRowSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        int remainingSelectedRows = 0;
                        try 
                        {
                            this.selectedBandSnapshotIndexes = new DataGridViewIntLinkedList(this.selectedBandIndexes);
                            while (this.selectedBandSnapshotIndexes.Count > remainingSelectedRows)
                            { 
                                int rowIndex = this.selectedBandSnapshotIndexes[remainingSelectedRows];
                                Debug.Assert(rowIndex >= 0); 
                                if (rowIndex == this.newRowIndex || rowIndex >= this.Rows.Count) 
                                {
                                    remainingSelectedRows++; 
                                }
                                else
                                {
                                    DataGridViewRowCancelEventArgs dgvrce = new DataGridViewRowCancelEventArgs(this.Rows[rowIndex]); 
                                    OnUserDeletingRow(dgvrce);
                                    if (!dgvrce.Cancel) 
                                    { 
                                        DataGridViewRow dataGridViewRow = this.Rows[rowIndex];
                                        if (this.DataSource != null) 
                                        {
                                            int rowCount = this.dataConnection.CurrencyManager.List.Count;
#if DEBUG
                                        int dataGridViewRowsCount = this.Rows.Count;           // the number of rows in the dataGridView row collection not counting the AddNewRow 
                                        if (this.AllowUserToAddRowsInternal )
                                        { 
                                            if (this.newRowIndex < rowCount) 
                                            {
                                                // the user did not type inside the 'add new row' 
                                                Debug.Assert(rowCount == dataGridViewRowsCount, "out of [....] in AddNewTransaction when the user did not type in the 'add new row'");
                                            }
                                            else
                                            { 
                                                dataGridViewRowsCount --;
                                            } 
                                        } 

                                        Debug.Assert(rowCount == dataGridViewRowsCount, "out of [....]"); 
#endif
                                            DataGridViewDataErrorEventArgs dgvdee = null;
                                            try
                                            { 
                                                this.DataConnection.DeleteRow(rowIndex);
                                            } 
                                            catch (Exception exception) 
                                            {
                                                if (ClientUtils.IsCriticalException(exception)) 
                                                {
                                                    throw;
                                                }
                                                // this is tricky. 
                                                // the back-end threw an exception. At that stage, we did not delete the dataGridView row
                                                // from our collection of dataGridView rows. 
                                                // So all we do is to throw the exception if the user wants. Otherwise we don't do anything. 
                                                dgvdee = new DataGridViewDataErrorEventArgs(exception,
                                                                                            -1, 
                                                                                            rowIndex,
                                                                                            // null,
                                                                                            // null,
                                                                                            DataGridViewDataErrorContexts.RowDeletion); 
                                                OnDataErrorInternal(dgvdee);
 
                                                if (dgvdee.ThrowException) 
                                                {
                                                    throw dgvdee.Exception; 
                                                }
                                                else
                                                {
                                                    remainingSelectedRows++; 
                                                }
                                            } 
                                            catch 
                                            {
                                                throw; 
                                            }
                                            if (rowCount != this.dataConnection.CurrencyManager.List.Count)
                                            {
                                                Debug.Assert(dataGridViewRow.Index == -1); 
                                                DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
                                                OnUserDeletedRow(dgvre); 
                                            } 
                                            else if (dgvdee == null)
                                            { 
                                                remainingSelectedRows++;
                                            }
                                        }
                                        else 
                                        {
                                            this.Rows.RemoveAtInternal(rowIndex, false /*force*/); 
                                            Debug.Assert(dataGridViewRow.Index == -1); 
                                            DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow);
                                            OnUserDeletedRow(dgvre); 
                                        }
                                    }
                                    else
                                    { 
                                        remainingSelectedRows++;
                                    } 
                                } 
                            }
                        } 
                        finally
                        {
                            this.selectedBandSnapshotIndexes = null;
                        } 
                        return true;
                } 
            } 
            return false;
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets a value that indicates whether a key should be processed
        ///       further. 
        ///     
        /// 
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)] 
        protected override bool ProcessDialogKey(Keys keyData)
        {
            Keys key = (keyData & Keys.KeyCode);
 
            if (key == Keys.Enter)
            { 
                if (ProcessEnterKey(keyData)) 
                {
                    return true; 
                }
            }
            else if (key == Keys.Escape)
            { 
                bool keyEffective = this.IsEscapeKeyEffective;
                bool ret = base.ProcessDialogKey(keyData); 
                if (!keyEffective) 
                {
                    // This call may perform Click of Cancel button of form. 
                    if (this.Focused)
                    {
                        // Make sure the current cell is in editing mode if needed.
                        if (this.ptCurrentCell.X > -1 && 
                            !this.IsCurrentCellInEditMode &&
                            (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                            (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))) 
                        {
                            BeginEditInternal(true /*selectAll*/); 
                        }
                    }
                }
                return ret; 
            }
            else if (key == Keys.D0 || key == Keys.NumPad0) 
            { 
                if (ProcessZeroKey(keyData))
                { 
                    return true;
                }
            }
            else if (key == Keys.C || key == Keys.Insert) 
            {
                if (ProcessInsertKey(keyData)) 
                { 
                    return true;
                } 
            }
            else if (key == Keys.Tab)
            {
                IntSecurity.AllWindows.Demand(); 
                if (ProcessTabKey(keyData))
                { 
                    return true; 
                }
                else 
                {
                    if (this.editingControl != null)
                    {
                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey] = true; 
                        if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.LeaveControl,
                                     DataGridViewValidateCellInternal.Always, 
                                     true /*fireCellLeave*/, 
                                     true /*fireCellEnter*/,
                                     true /*fireRowLeave*/, 
                                     true /*fireRowEnter*/,
                                     true /*fireLeave*/,
                                     false /*keepFocus*/,
                                     false /*resetCurrentCell*/, 
                                     false /*resetAnchorCell unused here*/))
                        { 
                            return true; 
                        }
                    } 

                    keyData &= ~Keys.Control;
                    bool ret = false;
 
                    // SECREVIEW : ProcessDialogKey can generate a call to ContainerControl.SetActiveControl which demands ModifyFocus permission,
                    //             we need to assert it here; the assert is safe, setting the active control does not expose any sec vulnerability 
                    //             indirectly. 
                    //
                    IntSecurity.ModifyFocus.Assert(); 
                    try
                    {
                        ret = base.ProcessDialogKey(keyData);
                    } 
                    finally
                    { 
                        CodeAccessPermission.RevertAssert(); 
                    }
 
                    if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey] && this.Focused)
                    {
                        // There was no other control to tab to. The CellLeave, RowLeave, Leave events were raised.
                        // Since the DataGridView control still has the focus, Enter, RowEnter, CellEnter events need to be raised. 
                        OnEnter(EventArgs.Empty);
                    } 
 
                    return ret;
                } 
            }
            return base.ProcessDialogKey(keyData);
        }
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessDownKey(Keys keyData) 
        {
            bool moved;
            return ProcessDownKeyInternal(keyData, out moved);
        } 

        private bool ProcessDownKeyInternal(Keys keyData, out bool moved) 
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || lastVisibleRowIndex == -1)
            { 
                moved = false;
                return false; 
            } 
            int nextVisibleRowIndex = -1;
            if (this.ptCurrentCell.Y != -1) 
            {
                nextVisibleRowIndex = this.Rows.GetNextRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
            }
            moved = true; 

            this.noSelectionChangeCount++; 
            try 
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                    { 
                                        moved = false; 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    {
                                        // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell 
                                        // the list under the DataGridView changes.
                                        // In this case set moved to false so the users that call ProcessDownKey 
                                        // will commit the data. 
                                        // See vsWhidbey: 325296.
                                        moved = false; 
                                    }
                                }
                                else
                                { 
                                    if (this.MultiSelect)
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                        {
                                            return true; 
                                        }
                                        //ClearSelection();
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        //SelectCellRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptCurrentCell.X == -1 || this.ptAnchorCell.X == -1 || 
                                            IsRowOutOfBounds(lastVisibleRowIndex))
                                        { 
                                            moved = false;
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex);
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, false, false, false); 
                                        if (!success) 
                                        {
                                            moved = false; 
                                        }
                                    }
                                    else
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                        { 
                                            return true; 
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                        {
                                            moved = false;
                                            return true;
                                        } 
                                        //SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                        if (!success) 
                                        {
                                            moved = false;
                                        }
                                    } 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                    {
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex))
                                    { 
                                        moved = false; 
                                        return true;
                                    } 
                                    ClearSelection();
                                    SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    {
                                        moved = false; 
                                    } 
                                }
                            } 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                    { 
                                        moved = false;
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    {
                                        moved = false;
                                    }
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1) 
                                    {
                                        moved = false; 
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true))
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true;
                                    }
                                    if (this.MultiSelect)
                                    { 
                                        //SelectCellUnorderedRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            moved = false;
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextVisibleRowIndex);
                                    } 
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, !this.MultiSelect, false, false);
                                    if (!success) 
                                    {
                                        moved = false; 
                                    } 
                                }
                            } 
                            else
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (nextVisibleRowIndex == -1) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true /*forCurrentCellChange*/)) 
                                    {
                                        return true;
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X,
                                        nextVisibleRowIndex,
                                        true  /*setAnchorCellAddress*/, 
                                        false /*validateCurrentCell*/,
                                        false /*throughMouseClick*/); 
                                    if (!success) 
                                    {
                                        moved = false; 
                                    }
                                }
                            }
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (this.MultiSelect) 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptAnchorCell.Y == -1 || this.ptCurrentCell.X == -1 ||
                                            IsRowOutOfBounds(lastVisibleRowIndex))
                                        {
                                            moved = false; 
                                            return true;
                                        } 
                                        ClearSelection(); 
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        SelectRowRange(this.ptAnchorCell.Y, lastVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, false, false, false);
                                        if (!success)
                                        {
                                            moved = false; 
                                        }
                                    } 
                                    else 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                        {
                                            return true;
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                        {
                                            moved = false; 
                                            return true; 
                                        }
                                        SetSelectedRowCore(this.ptCurrentCell.Y, false); 
                                        SetSelectedRowCore(lastVisibleRowIndex, true);
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                        if (!success)
                                        { 
                                            moved = false;
                                        } 
                                    } 
                                }
                            } 
                            else
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex))
                                    { 
                                        moved = false;
                                        return true;
                                    }
                                    ClearSelection(); 
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false); 
                                    if (!success) 
                                    {
                                        moved = false; 
                                    }
                                }
                            }
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1)
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex))
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    if (this.MultiSelect) 
                                    {
                                        if (this.ptAnchorCell.X == -1) 
                                        {
                                            moved = false;
                                            return true;
                                        } 
                                        if (nextVisibleRowIndex >= this.ptAnchorCell.Y)
                                        { 
                                            SelectRowRange(this.ptAnchorCell.Y, nextVisibleRowIndex, true); 
                                        }
                                        else 
                                        {
                                            SelectRowRange(nextVisibleRowIndex, this.ptAnchorCell.Y, true);
                                        }
                                    } 
                                    else
                                    { 
                                        SetSelectedRowCore(nextVisibleRowIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, !this.MultiSelect, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1)
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex))
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedRowCore(nextVisibleRowIndex, true); 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    {
                                        moved = false;
                                    }
                                } 
                            }
                        } 
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                    {
                                        moved = false; 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    { 
                                        moved = false;
                                    }
                                }
                                else 
                                {
                                    if (this.MultiSelect) 
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                        { 
                                            return true;
                                        }
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        if (this.ptAnchorCell.Y == -1 || this.ptCurrentCell.Y == -1 || 
                                            IsRowOutOfBounds(lastVisibleRowIndex))
                                        { 
                                            moved = false; 
                                            return true;
                                        } 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                        {
                                            ClearSelection();
                                            SelectRowRange(this.ptAnchorCell.Y, lastVisibleRowIndex, true); 
                                        }
                                        else 
                                        { 
                                            //ClearSelection();
                                            //SelectCellRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex); 
                                        }
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, false, false, false); 
                                        if (!success) 
                                        {
                                            moved = false; 
                                        }
                                    }
                                    else
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                        { 
                                            return true; 
                                        }
                                        if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                        {
                                            moved = false;
                                            return true;
                                        } 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                        { 
                                            SetSelectedRowCore(this.ptCurrentCell.Y, false); 
                                            SetSelectedRowCore(lastVisibleRowIndex, true);
                                        } 
                                        else
                                        {
                                            SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                            SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                        }
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false); 
                                        if (!success) 
                                        {
                                            moved = false; 
                                        }
                                    }
                                }
                            } 
                            else
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                                else 
                                { 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(lastVisibleRowIndex))
                                    { 
                                        moved = false;
                                        return true; 
                                    } 
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    { 
                                        ClearSelection();
                                        SetSelectedRowCore(lastVisibleRowIndex, true);
                                    }
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, lastVisibleRowIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                            } 
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    {
                                        moved = false;
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success) 
                                    { 
                                        moved = false;
                                    } 
                                }
                                else
                                {
                                    if (nextVisibleRowIndex == -1) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    {
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                    {
                                        moved = false; 
                                        return true; 
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection();
                                        if (this.MultiSelect)
                                        { 
                                            if (this.ptAnchorCell.Y == -1)
                                            { 
                                                moved = false; 
                                                return true;
                                            } 
                                            if (nextVisibleRowIndex >= this.ptAnchorCell.Y)
                                            {
                                                SelectRowRange(this.ptAnchorCell.Y, nextVisibleRowIndex, true);
                                            } 
                                            else
                                            { 
                                                SelectRowRange(nextVisibleRowIndex, this.ptAnchorCell.Y, true); 
                                            }
                                        } 
                                        else
                                        {
                                            SetSelectedRowCore(nextVisibleRowIndex, true);
                                        } 
                                    }
                                    else 
                                    { 
                                        if (this.MultiSelect)
                                        { 
                                            //SelectCellUnorderedRange(this.ptCurrentCell.X, this.ptAnchorCell.Y, this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            if (this.ptAnchorCell.X == -1) 
                                            {
                                                moved = false; 
                                                return true; 
                                            }
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextVisibleRowIndex);
                                        }
                                        else
                                        { 
                                            ClearSelection();
                                            SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true); 
                                        } 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, !this.MultiSelect, false, false); 
                                    if (!success)
                                    {
                                        moved = false;
                                    } 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, lastVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                    { 
                                        moved = false;
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                    if (!success)
                                    { 
                                        moved = false;
                                    } 
                                } 
                                else
                                { 
                                    if (nextVisibleRowIndex == -1)
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.Y == -1 || IsRowOutOfBounds(nextVisibleRowIndex))
                                    {
                                        moved = false;
                                        return true; 
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    { 
                                        ClearSelection();
                                        SetSelectedRowCore(nextVisibleRowIndex, true); 
                                    }
                                    else
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, nextVisibleRowIndex, true);
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, true, false, false); 
                                    if (!success)
                                    { 
                                        moved = false;
                                    }
                                }
                            } 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection(); 
                                SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex))
                                { 
                                    moved = false;
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false); 
                                if (!success)
                                { 
                                    moved = false; 
                                }
                            } 
                            else
                            {
                                if (!ScrollIntoView(this.ptCurrentCell.X, lastVisibleRowIndex, true))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(lastVisibleRowIndex)) 
                                {
                                    moved = false; 
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, lastVisibleRowIndex, true, false, false);
                                if (!success) 
                                {
                                    moved = false; 
                                } 
                            }
                        } 
                        else
                        {
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, lastVisibleRowIndex, false); 
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, lastVisibleRowIndex)) 
                                {
                                    moved = false;
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                if (!success) 
                                { 
                                    moved = false;
                                } 
                            }
                            else
                            {
                                if (nextVisibleRowIndex == -1) 
                                {
                                    moved = false; 
                                    return true; 
                                }
                                if (!ScrollIntoView(this.ptCurrentCell.X, nextVisibleRowIndex, true)) 
                                {
                                    return true;
                                }
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextVisibleRowIndex)) 
                                {
                                    moved = false; 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextVisibleRowIndex, true, false, false); 
                                if (!success)
                                {
                                    moved = false;
                                } 
                            }
                        } 
                        return true; 
                }
            } 
            finally
            {
                this.NoSelectionChangeCount--;
            } 
            return true;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ]
        protected bool ProcessEndKey(Keys keyData)
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, 
                DataGridViewElementStates.None); 
            int lastVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
            int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
            if (lastVisibleColumnIndex == -1 || firstVisibleRowIndex == -1)
            {
                return false; 
            }
 
            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex); 
                        } 
                        else
                        { 
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                            {
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex))
                            { 
                                return true; 
                            }
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0)
                                {
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex); 
                                }
                                else 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false);
                            } 
                            else 
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            }
                            // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                            // DataGridView changes.
                            // See vsWhidbey: 325296. 
                            // Debug.Assert(success); 
                        }
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == 0)
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else 
                        {
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true)) 
                            {
                                return true;
                            }
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex)) 
                            {
                                return true; 
                            } 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0)
                                {
                                    if (this.ptCurrentCell.Y > -1 &&
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection(); 
                                        SelectRowRange(this.ptCurrentCell.Y, lastVisibleRowIndex, true); 
                                    }
                                    else 
                                    {
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex);
                                    } 
                                } 
                                else
                                { 
                                    if (this.ptCurrentCell.Y > -1 &&
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(lastVisibleRowIndex, true);
                                    } 
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                    }
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false); 
                            }
                            else 
                            { 
                                if (this.ptCurrentCell.Y > -1 &&
                                    (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                {
                                    ClearSelection();
                                    SetSelectedRowCore(lastVisibleRowIndex, true);
                                } 
                                else
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true);
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            }
                            // Debug.Assert(success);
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if ((keyData & Keys.Control) == 0)
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else
                        { 
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                            { 
                                return true; 
                            }
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex)) 
                            {
                                return true;
                            }
                            ClearSelection(); 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptCurrentCell.X >= 0) 
                                {
                                    SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false); 
                            } 
                            else
                            { 
                                SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            }
                            // Debug.Assert(success); 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    if (this.MultiSelect)
                                    {
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        } 
                                        SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true); 
                                    }
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    if (this.MultiSelect && this.ptCurrentCell.X >= 0) 
                                    {
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, lastVisibleRowIndex); 
                                    }
                                    else 
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true); 
                                    }
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false);
                                // Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                }
                                else
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, lastVisibleRowIndex, true); 
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                                // Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == 0) 
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else
                        {
                            if (!ScrollIntoView(lastVisibleColumnIndex, lastVisibleRowIndex, true))
                            { 
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, lastVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            ClearSelection();
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptCurrentCell.Y >= 0)
                                { 
                                    if (this.ptAnchorCell.Y == -1) 
                                    {
                                        return true; 
                                    }
                                    SelectRowRange(this.ptAnchorCell.Y, lastVisibleRowIndex, true);
                                }
                                else 
                                {
                                    SetSelectedRowCore(lastVisibleRowIndex, true); 
                                } 

                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, !this.MultiSelect, false, false); 
                            }
                            else
                            {
                                SetSelectedRowCore(lastVisibleRowIndex, true); 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, lastVisibleRowIndex, true, false, false);
                            } 
                            // Debug.Assert(success); 
                        }
                        return true; 
                }
            }
            finally
            { 
                this.NoSelectionChangeCount--;
            } 
            return true; 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessEnterKey(Keys keyData)
        { 
            bool moved = false, ret = true, commitRow = true; 
            if ((keyData & Keys.Control) == 0)
            { 
                // Enter behaves like down arrow - it commits the potential editing and goes down one cell.
                commitRow = false;
                keyData &= ~Keys.Shift;
                ret = ProcessDownKeyInternal(keyData, out moved); 
            }
 
            if (!moved) 
            {
                DataGridViewCell dataGridViewCurrentCell = null; 
                // Try to commit the potential editing
                if (this.EditMode == DataGridViewEditMode.EditOnEnter)
                {
                    if (this.ptCurrentCell.X != -1) 
                    {
                        dataGridViewCurrentCell = this.CurrentCellInternal; 
                        DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, 
                            DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit,
                            DataGridViewValidateCellInternal.WhenChanged, 
                            false /*fireCellLeave*/,
                            false /*fireCellEnter*/,
                            false /*fireRowLeave*/,
                            false /*fireRowEnter*/, 
                            false /*fireLeave*/);
                        if (null != dgvdee) 
                        { 
                            if (dgvdee.ThrowException)
                            { 
                                throw dgvdee.Exception;
                            }
                        }
                    } 
                }
                else 
                { 
                    EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit,
                        DataGridViewValidateCellInternal.WhenChanged /*validateCell*/, 
                        false /*fireCellLeave*/,
                        false /*fireCellEnter*/,
                        false /*fireRowLeave*/,
                        false /*fireRowEnter*/, 
                        false /*fireLeave*/,
                        true /*keepFocus*/, 
                        true /*resetCurrentCell unused here*/, 
                        true /*resetAnchorCell unused here*/);
                } 
                if (commitRow && this.IsCurrentRowDirty)
                {
                    dataGridViewCurrentCell = null;
                    int columnIndex = this.ptCurrentCell.X; 
                    int rowIndex = this.ptCurrentCell.Y;
                    if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                    { 
                        return ret;
                    } 
                    if (!OnRowValidating(ref dataGridViewCurrentCell, columnIndex, rowIndex))
                    {
                        if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                        { 
                            return ret;
                        } 
                        OnRowValidated(ref dataGridViewCurrentCell, columnIndex, rowIndex); 
                    }
                } 
            }
            return ret;
        }
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode), 
            SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters") // Derived controls may need keyData.
        ] 
        protected bool ProcessEscapeKey(Keys keyData)
        {
            if (this.IsEscapeKeyEffective)
            { 
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] ||
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] || 
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || 
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] ||
                    this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) 
                {
                    ResetTrackingState();
                }
                else 
                {
                    CancelEdit(true /*endEdit, DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.InitialValueRestoration*/); 
                } 
                return true;
            } 
            return false;
        }

        ///  
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode), 
            SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters") // Derived controls may need keyData. 
        ]
        protected bool ProcessF2Key(Keys keyData) 
        {
            if (this.ptCurrentCell.X != -1 &&
                !this.IsCurrentCellInEditMode &&
                ModifierKeys == 0) 
            {
                Debug.Assert(this.ptCurrentCell.Y != -1); 
                Debug.Assert(this.CurrentCellInternal != null); 
                Debug.Assert(this.EditMode != DataGridViewEditMode.EditOnEnter ||
                    (IsSharedCellReadOnly(this.CurrentCellInternal, this.ptCurrentCell.Y) || !ColumnEditable(this.ptCurrentCell.X))); 
                if (ColumnEditable(this.ptCurrentCell.X) &&
                    !IsSharedCellReadOnly(this.CurrentCellInternal, this.ptCurrentCell.Y) &&
                    (this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2 ||
                     this.EditMode == DataGridViewEditMode.EditOnF2)) 
                {
                    bool success = ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                    Debug.Assert(success); 
                    BeginEditInternal(this.EditMode == DataGridViewEditMode.EditOnF2 /*selectAll*/);
                    return true; 
                }
            }
            return false;
        } 

        ///  
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessHomeKey(Keys keyData)
        {
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            {
                return false; 
            }

            this.noSelectionChangeCount++;
            try 
            {
                switch (this.SelectionMode) 
                { 
                    case DataGridViewSelectionMode.CellSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true)) 
                            { 
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            {
                                return true;
                            } 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0) 
                                {
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                } 
                                else
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false);
                            }
                            else
                            { 
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            }
                            // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                            // DataGridView changes.
                            // See vsWhidbey: 325296.
                            // Debug.Assert(success);
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        if ((keyData & Keys.Control) == 0)
                        { 
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else
                        { 
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                            { 
                                return true; 
                            }
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                            {
                                return true;
                            }
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.MultiSelect && this.ptAnchorCell.X >= 0) 
                                { 
                                    if (this.ptCurrentCell.Y > -1 &&
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection();
                                        SelectRowRange(firstVisibleRowIndex, this.ptAnchorCell.Y, true);
                                    } 
                                    else
                                    { 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                    }
                                }
                                else 
                                {
                                    if (this.ptCurrentCell.Y > -1 && 
                                        (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(firstVisibleRowIndex, true);
                                    }
                                    else
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    } 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false); 
                            }
                            else
                            {
                                if (this.ptCurrentCell.Y > -1 && 
                                    (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                { 
                                    ClearSelection(); 
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                } 
                                else
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            } 
                            // Debug.Assert(success);
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        } 
                        else
                        { 
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                            {
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            { 
                                return true; 
                            }
                            ClearSelection(); 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.MultiSelect && this.ptCurrentCell.X >= 0)
                                { 
                                    if (this.ptAnchorCell.X == -1)
                                    { 
                                        return true; 
                                    }
                                    SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                }
                                else
                                {
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false); 
                            } 
                            else
                            { 
                                SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                            }
                            // Debug.Assert(success); 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == 0) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    if (this.MultiSelect)
                                    {
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        } 
                                        SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                    }
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    if (this.MultiSelect && this.ptCurrentCell.X >= 0) 
                                    {
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1)
                                        { 
                                            return true;
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex); 
                                    }
                                    else 
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    }
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, !this.MultiSelect, false, false);
                                // Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                                { 
                                    return true;
                                }
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X >= 0 && this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                }
                                else
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                // Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == 0) 
                        { 
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else
                        {
                            if (!ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, true))
                            { 
                                return true;
                            } 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            ClearSelection();
                            SetSelectedRowCore(firstVisibleRowIndex, true);
                            success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            // Debug.Assert(success);
                        } 
                        return true; 
                }
            } 
            finally
            {
                this.NoSelectionChangeCount--;
            } 
            return true;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ]
        protected bool ProcessInsertKey(Keys keyData)
        { 
            if (((keyData & (Keys.Shift | Keys.Control | Keys.Alt)) == Keys.Control ||
                 ((keyData & (Keys.Shift | Keys.Control | Keys.Alt)) == (Keys.Control | Keys.Shift) && (keyData & Keys.KeyCode) == Keys.C)) && 
                this.ClipboardCopyMode != DataGridViewClipboardCopyMode.Disable) 
            {
                DataObject dataObject = GetClipboardContent(); 
                if (dataObject != null)
                {
                    Clipboard.SetDataObject(dataObject);
                    return true; 
                }
            } 
            return false; 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
        ] 
        protected override bool ProcessKeyEventArgs(ref Message m)
        { 
            if (m.Msg == NativeMethods.WM_SYSKEYDOWN || m.Msg == NativeMethods.WM_KEYDOWN) 
            {
                if (this.ptCurrentCell.X != -1) 
                {
                    DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                    Debug.Assert(dataGridViewCell != null);
 
                    if (!this.IsCurrentCellInEditMode &&
                        ColumnEditable(this.ptCurrentCell.X) && 
                        !IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) && 
                        (this.EditMode == DataGridViewEditMode.EditOnKeystroke || this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2))
                    { 
                        KeyEventArgs ke = new KeyEventArgs((Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys);
                        if (ke.KeyCode != Keys.ProcessKey || (int) m.LParam != 0x01) // Changing IME context does not trigger editing mode
                        {
                            Type editControlType = dataGridViewCell.EditType; 
                            Type editingCellInterface = null;
                            if (editControlType == null) 
                            { 
                                // Current cell does not have an editing control. Does it implement IDataGridViewEditingCell?
                                editingCellInterface = dataGridViewCell.GetType().GetInterface("System.Windows.Forms.IDataGridViewEditingCell"); 
                            }

                            if ((editControlType != null || editingCellInterface == null) &&
                                dataGridViewCell.KeyEntersEditMode(ke)) 
                            {
                                // Cell wants to go to edit mode 
                                bool success = ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                Debug.Assert(success);
                                if (BeginEditInternal(!(ke.KeyCode == Keys.F2 && ModifierKeys == 0 && this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2) /*selectAll*/)) 
                                {
                                    // Forward the key message to the editing control if any
                                    if (this.editingControl != null)
                                    { 
                                        this.editingControl.SendMessage(m.Msg, m.WParam, m.LParam);
                                        this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] = true; 
                                        return true; 
                                    }
                                } 
                            }
                        }
                    }
                } 
            }
            else if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] && 
                     (m.Msg == NativeMethods.WM_SYSCHAR || m.Msg == NativeMethods.WM_CHAR  || m.Msg == NativeMethods.WM_IME_CHAR)) 
            {
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] = false; 
                if (this.editingControl != null)
                {
                    this.editingControl.SendMessage(m.Msg, m.WParam, m.LParam);
                    return true; 
                }
            } 
            return base.ProcessKeyEventArgs(ref m); 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected override bool ProcessKeyPreview(ref Message m)
        { 
            bool dataGridViewWantsInputKey; 
            KeyEventArgs ke = new KeyEventArgs((Keys)((int)m.WParam) | ModifierKeys);
            switch (ke.KeyCode) 
            {
                case Keys.Delete:
                case Keys.Down:
                case Keys.End: 
                case Keys.Enter:
                case Keys.Escape: 
                case Keys.F2: 
                case Keys.Home:
                case Keys.Left: 
                case Keys.Next:
                case Keys.Prior:
                case Keys.Right:
                case Keys.Space: 
                case Keys.Tab:
                case Keys.Up: 
                    dataGridViewWantsInputKey = true; 
                    break;
 
                default:
                    dataGridViewWantsInputKey = false;
                    break;
            } 

            if (this.editingControl != null && (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN)) 
            { 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_currentCellWantsInputKey] = ((IDataGridViewEditingControl)this.editingControl).EditingControlWantsInputKey(ke.KeyData, dataGridViewWantsInputKey);
            } 

            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_currentCellWantsInputKey])
            {
                return base.ProcessKeyPreview(ref m); 
            }
 
            if (dataGridViewWantsInputKey) 
            {
                if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN) 
                {
                    if (ProcessDataGridViewKey(ke))
                    {
                        return true; 
                        // Ctrl-Tab will be sent as a tab paired w/ a control on the KeyUp message
                    } 
                    else 
                    {
                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_currentCellWantsInputKey] = true; 
                    }
                }
                else
                { 
                    return true;
                } 
            } 
            return base.ProcessKeyPreview(ref m);
        } 

        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessLeftKey(Keys keyData) 
        { 
            if (this.RightToLeftInternal)
            { 
                return ProcessRightKeyPrivate(keyData);
            }
            else
            { 
                return ProcessLeftKeyPrivate(keyData);
            } 
        } 

        private bool ProcessLeftKeyPrivate(Keys keyData) 
        {
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            { 
                return false;
            } 
            int previousVisibleColumnIndex = -1;
            if (this.ptCurrentCell.X != -1)
            {
                dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.ptCurrentCell.X], 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None); 
                if (dataGridViewColumn != null) 
                {
                    previousVisibleColumnIndex = dataGridViewColumn.Index; 
                }
            }

            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control)
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else 
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success);
                                } 
                                else
                                { 
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.MultiSelect)
                                    {
                                        Debug.Assert(this.ptAnchorCell.X >= 0);
                                        //SelectCellUnorderedRange(previousVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        if (this.ptAnchorCell.X == -1) 
                                        {
                                            return true; 
                                        }
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, previousVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    } 
                                    else
                                    { 
                                        ClearSelection(); 
                                        SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    } 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                            else
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    ClearSelection(); 
                                    SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                }
                            }
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    ClearSelection(); 
                                    if (this.MultiSelect)
                                    { 
                                        if (this.ptAnchorCell.X == -1)
                                        {
                                            return true;
                                        } 
                                        if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, previousVisibleColumnIndex))
                                        { 
                                            SelectColumnRange(this.ptAnchorCell.X, previousVisibleColumnIndex, true); 
                                        }
                                        else 
                                        {
                                            SelectColumnRange(previousVisibleColumnIndex, this.ptAnchorCell.X, true);
                                        }
                                    } 
                                    else
                                    { 
                                        SetSelectedColumnCore(previousVisibleColumnIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false); 
                                    Debug.Assert(success);
                                }
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (previousVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedColumnCore(previousVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (previousVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected) 
                                    { 
                                        ClearSelection();
                                        if (this.MultiSelect) 
                                        {
                                            if (this.ptAnchorCell.X == -1)
                                            {
                                                return true; 
                                            }
                                            if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, previousVisibleColumnIndex)) 
                                            { 
                                                SelectColumnRange(this.ptAnchorCell.X, previousVisibleColumnIndex, true);
                                            } 
                                            else
                                            {
                                                SelectColumnRange(previousVisibleColumnIndex, this.ptAnchorCell.X, true);
                                            } 
                                        }
                                        SetSelectedColumnCore(previousVisibleColumnIndex, true); 
                                    } 
                                    else
                                    { 
                                        if (this.MultiSelect)
                                        {
                                            //SelectCellUnorderedRange(previousVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true);
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            if (this.ptAnchorCell.X == -1) 
                                            { 
                                                return true;
                                            } 
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, previousVisibleColumnIndex,
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                        }
                                        else 
                                        {
                                            ClearSelection(); 
                                            SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                        }
                                    } 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                            else
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (previousVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    } 
                                    if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    if (this.Columns[this.ptCurrentCell.X].Selected) 
                                    {
                                        ClearSelection(); 
                                        SetSelectedColumnCore(previousVisibleColumnIndex, true);
                                    }
                                    else
                                    { 
                                        ClearSelection();
                                        SetSelectedCellCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    } 
                                    success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.FullRowSelect: 
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessLeftMost((keyData & Keys.Shift) == Keys.Shift, firstVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else
                        {
                            if (this.ptCurrentCell.X == -1) 
                            {
                                ClearSelection(); 
                                SetSelectedRowCore(firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                {
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success); 
                            } 
                            else
                            { 
                                if (previousVisibleColumnIndex == -1)
                                {
                                    return true;
                                } 
                                if (!ScrollIntoView(previousVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(previousVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(previousVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success);
                            } 
                        } 
                        return true;
                } 
            }
            finally
            {
                this.NoSelectionChangeCount--; 
            }
            return true; 
        } 

        // Ctrl Left <==> Home 
        // Shift Ctrl Left <==> Shift Home
        private bool ProcessLeftMost(bool shift, int firstVisibleColumnIndex, int firstVisibleRowIndex)
        {
            bool success; 

            this.noSelectionChangeCount++; 
            try 
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if (shift) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else
                            {
                                if (this.MultiSelect)
                                { 
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true; 
                                    }
                                    //ClearSelection(); 
                                    Debug.Assert(this.ptAnchorCell.X >= 0);
                                    //SelectCellRange(firstVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true);
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                    if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 ||
                                        IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                                    { 
                                        return true;
                                    } 
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false);
                                    Debug.Assert(success); 
                                }
                                else 
                                { 
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true;
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    { 
                                        return true;
                                    } 
                                    //SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                        }
                        else 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            }
                            else
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y  == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                ClearSelection(); 
                                SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success); 
                            }
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if (shift) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else
                            {
                                if (this.MultiSelect)
                                { 
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    { 
                                        return true; 
                                    }
                                    if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.Y == -1 || 
                                        IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    {
                                        return true;
                                    } 
                                    ClearSelection();
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false);
                                    Debug.Assert(success); 
                                }
                                else
                                {
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    { 
                                        return true;
                                    }
                                    SetSelectedColumnCore(this.ptCurrentCell.X, false);
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                } 
                            }
                        } 
                        else
                        {
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else 
                            {
                                if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true;
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                                {
                                    return true; 
                                } 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                Debug.Assert(success);
                            }
                        } 
                        return true;
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (shift)
                        { 
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            } 
                            else
                            { 
                                if (this.MultiSelect) 
                                {
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true;
                                    }
                                    if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 || 
                                        IsColumnOutOfBounds(firstVisibleColumnIndex))
                                    { 
                                        return true; 
                                    }
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    {
                                        ClearSelection();
                                        SelectColumnRange(firstVisibleColumnIndex, this.ptAnchorCell.X, true); 
                                    }
                                    else 
                                    { 
                                        //ClearSelection();
                                        //SelectCellRange(firstVisibleColumnIndex, this.ptCurrentCell.Y, this.ptAnchorCell.X, this.ptCurrentCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, firstVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex); 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || 
                                        IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    {
                                        SetSelectedColumnCore(this.ptCurrentCell.X, false); 
                                        SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                    } 
                                    else 
                                    {
                                        SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                        SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection();
                                SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            } 
                            else
                            { 
                                if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true; 
                                }
                                if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex))
                                {
                                    return true; 
                                }
                                if (this.Columns[this.ptCurrentCell.X].Selected) 
                                { 
                                    ClearSelection();
                                    SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                }
                                else
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success);
                            } 
                        }
                        return true;

                    case DataGridViewSelectionMode.FullRowSelect: 
                        if (this.ptCurrentCell.X == -1)
                        { 
                            ClearSelection(); 
                            SetSelectedRowCore(firstVisibleRowIndex, true);
                            success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                            Debug.Assert(success);
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            {
                                return true; 
                            }
                            success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            Debug.Assert(success); 
                        }
                        else 
                        {
                            if (!ScrollIntoView(firstVisibleColumnIndex, this.ptCurrentCell.Y, true))
                            {
                                return true; 
                            }
                            if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                            { 
                                return true;
                            } 
                            success = SetCurrentCellAddressCore(firstVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                            Debug.Assert(success);
                        }
                        return true; 
                }
            } 
            finally 
            {
                this.NoSelectionChangeCount--; 
            }
            return true;
        }
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessNextKey(Keys keyData) 
        {
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            if (firstVisibleColumnIndex == -1)
            { 
                return false; 
            }
            int nextScreenVisibleRowIndexTmp, nextScreenVisibleRowIndex = -1, jumpRows = 0; 
            if (this.ptCurrentCell.Y == -1)
            {
                nextScreenVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                if (nextScreenVisibleRowIndex == -1) 
                {
                    return false; 
                } 
            }
            else 
            {
                nextScreenVisibleRowIndex = this.ptCurrentCell.Y;
            }
 
            if ((this.Rows.GetRowState(nextScreenVisibleRowIndex) & DataGridViewElementStates.Frozen) != 0)
            { 
                if (this.displayedBandsInfo.FirstDisplayedScrollingRow > 0) 
                {
                    int firstDisplayedScrollingRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                    Debug.Assert(firstDisplayedScrollingRowIndex != -1);
                    if (!ScrollIntoView(this.ptCurrentCell.X == -1 ? firstVisibleColumnIndex : this.ptCurrentCell.X,
                        firstDisplayedScrollingRowIndex, true))
                    { 
                        return true;
                    } 
                    jumpRows = this.Rows.GetRowCount(DataGridViewElementStates.Visible, 
                        this.ptCurrentCell.Y,
                        firstDisplayedScrollingRowIndex)-1; 
                }
                else
                {
                    jumpRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows; 
                }
            } 
            jumpRows += this.displayedBandsInfo.NumTotallyDisplayedScrollingRows; 

            nextScreenVisibleRowIndexTmp = nextScreenVisibleRowIndex; 
            Debug.Assert(nextScreenVisibleRowIndexTmp != -1);
            if (jumpRows == 0)
            {
                jumpRows = 1; 
            }
            while (jumpRows > 0 && nextScreenVisibleRowIndexTmp != -1) 
            { 
                nextScreenVisibleRowIndexTmp = this.Rows.GetNextRow(nextScreenVisibleRowIndex, DataGridViewElementStates.Visible);
                if (nextScreenVisibleRowIndexTmp != -1) 
                {
                    nextScreenVisibleRowIndex = nextScreenVisibleRowIndexTmp;
                    jumpRows--;
                } 
            }
 
            this.noSelectionChangeCount++; 
            try
            { 
                if (this.ptCurrentCell.X == -1)
                {
                    ClearSelection();
                    switch (this.SelectionMode) 
                    {
                        case DataGridViewSelectionMode.CellSelect: 
                        case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        case DataGridViewSelectionMode.RowHeaderSelect:
                            SetSelectedCellCore(firstVisibleColumnIndex, nextScreenVisibleRowIndex, true); 
                            break;
                        case DataGridViewSelectionMode.FullRowSelect:
                            SetSelectedRowCore(nextScreenVisibleRowIndex, true);
                            break; 
                        case DataGridViewSelectionMode.FullColumnSelect:
                            SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                            break; 
                    }
                    success = ScrollIntoView(firstVisibleColumnIndex, nextScreenVisibleRowIndex, false); 
                    Debug.Assert(success);
                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, nextScreenVisibleRowIndex))
                    {
                        return true; 
                    }
                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, nextScreenVisibleRowIndex, true, false, false); 
                    // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                    // DataGridView changes.
                    // See vsWhidbey: 325296. 
                    // Debug.Assert(success);
                    return true;
                }
 
                switch (this.SelectionMode)
                { 
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true)) 
                        {
                            return true;
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex)) 
                        {
                            return true; 
                        } 
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                            if (this.ptAnchorCell.Y == -1) 
                            {
                                return true; 
                            } 
                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextScreenVisibleRowIndex); 
                        }
                        else
                        {
                            ClearSelection(); 
                            SetSelectedCellCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true);
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, false, false, false); 
                        Debug.Assert(success);
                        return true; 

                    case DataGridViewSelectionMode.FullRowSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true))
                        { 
                            return true;
                        } 
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex)) 
                        {
                            return true; 
                        }
                        ClearSelection();
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            if (this.ptAnchorCell.Y == -1) 
                            { 
                                return true;
                            } 
                            if (this.ptAnchorCell.Y < nextScreenVisibleRowIndex)
                            {
                                SelectRowRange(this.ptAnchorCell.Y, nextScreenVisibleRowIndex, true);
                            } 
                            else
                            { 
                                SelectRowRange(nextScreenVisibleRowIndex, this.ptAnchorCell.Y, true); 
                            }
                        } 
                        else
                        {
                            SetSelectedRowCore(nextScreenVisibleRowIndex, true);
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, false, false, false);
                        // Debug.Assert(success); 
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true))
                        {
                            return true;
                        } 
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex))
                        { 
                            return true; 
                        }
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect) 
                        {
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            if (this.ptAnchorCell.Y == -1)
                            { 
                                return true;
                            } 
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                            {
                                ClearSelection(); 
                                if (this.ptAnchorCell.Y < nextScreenVisibleRowIndex)
                                {
                                    SelectRowRange(this.ptAnchorCell.Y, nextScreenVisibleRowIndex, true);
                                } 
                                else
                                { 
                                    SelectRowRange(nextScreenVisibleRowIndex, this.ptAnchorCell.Y, true); 
                                }
                            } 
                            else
                            {
                                int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                    this.ptAnchorCell.Y, ref oldEdgeRowIndex, nextScreenVisibleRowIndex); 
                            } 
                        }
                        else 
                        {
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                            {
                                ClearSelection(); 
                                SetSelectedRowCore(nextScreenVisibleRowIndex, true);
                            } 
                            else 
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true);
                            }
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, !this.MultiSelect, false, false); 
                        // Debug.Assert(success);
                        return true; 
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true)) 
                        {
                            return true;
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(nextScreenVisibleRowIndex)) 
                        {
                            return true; 
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, nextScreenVisibleRowIndex, true, false, false);
                        // Debug.Assert(success); 
                        return true;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 
            return true;
        } 

        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected bool ProcessPriorKey(Keys keyData) 
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            if (firstVisibleColumnIndex == -1)
            {
                return false; 
            }
            int previousScreenVisibleRowIndexTmp, previousScreenVisibleRowIndex = -1; 
            if (this.ptCurrentCell.Y == -1) 
            {
                previousScreenVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                if (previousScreenVisibleRowIndex == -1)
                {
                    return false;
                } 
            }
            else 
            { 
                previousScreenVisibleRowIndex = this.ptCurrentCell.Y;
            } 

            int jumpRows;
            if ((this.Rows.GetRowState(previousScreenVisibleRowIndex) & DataGridViewElementStates.Frozen) != 0)
            { 
                jumpRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows;
            } 
            else 
            {
                jumpRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows; 
            }
            if (jumpRows == 0)
            {
                jumpRows = 1; 
            }
            previousScreenVisibleRowIndexTmp = previousScreenVisibleRowIndex; 
            Debug.Assert(previousScreenVisibleRowIndexTmp != -1); 
            while (jumpRows > 0 && previousScreenVisibleRowIndexTmp != -1)
            { 
                previousScreenVisibleRowIndexTmp = this.Rows.GetPreviousRow(previousScreenVisibleRowIndex, DataGridViewElementStates.Visible);
                if (previousScreenVisibleRowIndexTmp != -1)
                {
                    previousScreenVisibleRowIndex = previousScreenVisibleRowIndexTmp; 
                }
                jumpRows--; 
            } 

            if ((this.Rows.GetRowState(previousScreenVisibleRowIndex) & DataGridViewElementStates.Frozen) != 0) 
            {
                // Make sure the first scrolling row is visible if any
                int firstDisplayedScrollingRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen);
                if (firstDisplayedScrollingRowIndex != -1 && 
                    !ScrollIntoView(this.ptCurrentCell.X == -1 ? firstVisibleColumnIndex : this.ptCurrentCell.X,
                    firstDisplayedScrollingRowIndex, true)) 
                { 
                    return true;
                } 
                // Also, first visible frozen row should become current one - there is no reason to jump to another frozen row.
                previousScreenVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
            }
            Debug.Assert(previousScreenVisibleRowIndex != -1); 

            this.noSelectionChangeCount++; 
            try 
            {
                if (this.ptCurrentCell.X == -1) 
                {
                    ClearSelection();
                    switch (this.SelectionMode)
                    { 
                        case DataGridViewSelectionMode.CellSelect:
                        case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        case DataGridViewSelectionMode.RowHeaderSelect: 
                            SetSelectedCellCore(firstVisibleColumnIndex, previousScreenVisibleRowIndex, true);
                            break; 
                        case DataGridViewSelectionMode.FullRowSelect:
                            SetSelectedRowCore(previousScreenVisibleRowIndex, true);
                            break;
                        case DataGridViewSelectionMode.FullColumnSelect: 
                            SetSelectedColumnCore(firstVisibleColumnIndex, true);
                            break; 
                    } 
                    success = ScrollIntoView(firstVisibleColumnIndex, previousScreenVisibleRowIndex, false);
                    Debug.Assert(success); 
                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, previousScreenVisibleRowIndex))
                    {
                        return true;
                    } 
                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, previousScreenVisibleRowIndex, true, false, false);
                    // Debug.Assert(success); 
                    return true; 
                }
 
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true))
                        { 
                            return true; 
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex)) 
                        {
                            return true;
                        }
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect) 
                        {
                            Debug.Assert(this.ptAnchorCell.Y >= 0); 
                            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                            if (this.ptAnchorCell.X == -1) 
                            {
                                return true;
                            }
                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousScreenVisibleRowIndex);
                        } 
                        else 
                        {
                            ClearSelection(); 
                            SetSelectedCellCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true);
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, false, false, false);
                        // Debug.Assert(success); 
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true))
                        { 
                            return true;
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex))
                        { 
                            return true;
                        } 
                        ClearSelection(); 
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0);
                            if (this.ptAnchorCell.Y == -1)
                            {
                                return true; 
                            }
                            if (this.ptAnchorCell.Y < previousScreenVisibleRowIndex) 
                            { 
                                SelectRowRange(this.ptAnchorCell.Y, previousScreenVisibleRowIndex, true);
                            } 
                            else
                            {
                                SelectRowRange(previousScreenVisibleRowIndex, this.ptAnchorCell.Y, true);
                            } 
                        }
                        else 
                        { 
                            SetSelectedRowCore(previousScreenVisibleRowIndex, true);
                        } 
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, false, false, false);
                        // Debug.Assert(success);
                        return true;
 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true)) 
                        { 
                            return true;
                        } 
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex))
                        {
                            return true;
                        } 
                        if ((keyData & Keys.Shift) == Keys.Shift && this.MultiSelect)
                        { 
                            Debug.Assert(this.ptAnchorCell.Y >= 0); 
                            if (this.ptAnchorCell.Y == -1)
                            { 
                                return true;
                            }
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                            { 
                                ClearSelection();
                                if (this.ptAnchorCell.Y < previousScreenVisibleRowIndex) 
                                { 
                                    SelectRowRange(this.ptAnchorCell.Y, previousScreenVisibleRowIndex, true);
                                } 
                                else
                                {
                                    SelectRowRange(previousScreenVisibleRowIndex, this.ptAnchorCell.Y, true);
                                } 
                            }
                            else 
                            { 
                                int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                    this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousScreenVisibleRowIndex);
                            }
                        } 
                        else
                        { 
                            if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                            {
                                ClearSelection(); 
                                SetSelectedRowCore(previousScreenVisibleRowIndex, true);
                            }
                            else
                            { 
                                ClearSelection();
                                SetSelectedCellCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true); 
                            } 
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, !this.MultiSelect, false, false); 
                        // Debug.Assert(success);
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if (!ScrollIntoView(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true))
                        { 
                            return true; 
                        }
                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousScreenVisibleRowIndex)) 
                        {
                            return true;
                        }
                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousScreenVisibleRowIndex, true, false, false); 
                        // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the
                        // DataGridView changes. 
                        // See vsWhidbey: 325296. 
                        // Debug.Assert(success);
                        return true; 
                }
            }
            finally
            { 
                this.NoSelectionChangeCount--;
            } 
            return true; 
        }
 
        /// 
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessRightKey(Keys keyData)
        { 
            if (this.RightToLeftInternal) 
            {
                return ProcessLeftKeyPrivate(keyData); 
            }
            else
            {
                return ProcessRightKeyPrivate(keyData); 
            }
        } 
 
        private bool ProcessRightKeyPrivate(Keys keyData)
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible,
                DataGridViewElementStates.None);
            int lastVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (lastVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            { 
                return false;
            } 
            int nextVisibleColumnIndex = -1;
            if (this.ptCurrentCell.X != -1)
            {
                dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.ptCurrentCell.X], 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None); 
                if (dataGridViewColumn != null) 
                {
                    nextVisibleColumnIndex = dataGridViewColumn.Index; 
                }
            }

            this.noSelectionChangeCount++; 
            try
            { 
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control)
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else 
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success);
                                } 
                                else
                                { 
                                    if (nextVisibleColumnIndex == -1) 
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.MultiSelect)
                                    {
                                        //SelectCellUnorderedRange(this.ptAnchorCell.X, this.ptCurrentCell.Y, nextVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        if (this.ptAnchorCell.X == -1) 
                                        { 
                                            return true;
                                        } 
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, nextVisibleColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    }
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    }
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false); 
                                    Debug.Assert(success);
                                }
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex); 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true; 
                                    }
                                    ClearSelection(); 
                                    if (this.MultiSelect) 
                                    {
                                        if (this.ptAnchorCell.X == -1) 
                                        {
                                            return true;
                                        }
                                        if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, nextVisibleColumnIndex)) 
                                        {
                                            SelectColumnRange(this.ptAnchorCell.X, nextVisibleColumnIndex, true); 
                                        } 
                                        else
                                        { 
                                            SelectColumnRange(nextVisibleColumnIndex, this.ptAnchorCell.X, true);
                                        }
                                    }
                                    else 
                                    {
                                        SetSelectedColumnCore(nextVisibleColumnIndex, true); 
                                    } 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success); 
                                }
                            }
                            else
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true;
                                    } 
                                    ClearSelection();
                                    SetSelectedColumnCore(nextVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                } 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        { 
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        } 
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (nextVisibleColumnIndex == -1)
                                    {
                                        return true; 
                                    }
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    {
                                        return true;
                                    } 
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    { 
                                        ClearSelection(); 
                                        if (this.MultiSelect)
                                        { 
                                            if (this.ptAnchorCell.X == -1)
                                            {
                                                return true;
                                            } 
                                            if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, nextVisibleColumnIndex))
                                            { 
                                                SelectColumnRange(this.ptAnchorCell.X, nextVisibleColumnIndex, true); 
                                            }
                                            else 
                                            {
                                                SelectColumnRange(nextVisibleColumnIndex, this.ptAnchorCell.X, true);
                                            }
                                        } 
                                        else
                                        { 
                                            SetSelectedColumnCore(nextVisibleColumnIndex, true); 
                                        }
                                    } 
                                    else
                                    {
                                        if (this.MultiSelect)
                                        { 
                                            if (this.ptAnchorCell.X == -1)
                                            { 
                                                return true; 
                                            }
                                            //SelectCellUnorderedRange(this.ptAnchorCell.X, this.ptCurrentCell.Y, nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, nextVisibleColumnIndex,
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex); 
                                        }
                                        else 
                                        { 
                                            ClearSelection();
                                            SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                        }
                                    }
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, !this.MultiSelect, false, false);
                                    Debug.Assert(success); 
                                }
                            } 
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    Debug.Assert(success);
                                }
                                else 
                                {
                                    if (nextVisibleColumnIndex == -1) 
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                    {
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                    { 
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected) 
                                    {
                                        ClearSelection();
                                        SetSelectedColumnCore(nextVisibleColumnIndex, true);
                                    } 
                                    else
                                    { 
                                        ClearSelection(); 
                                        SetSelectedCellCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    } 
                                    success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success);
                                }
                            } 
                        }
                        return true; 
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            return ProcessRightMost((keyData & Keys.Shift) == Keys.Shift, lastVisibleColumnIndex, firstVisibleRowIndex);
                        }
                        else 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedRowCore(firstVisibleRowIndex, true); 
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            } 
                            else
                            {
                                if (nextVisibleColumnIndex == -1)
                                { 
                                    return true;
                                } 
                                if (!ScrollIntoView(nextVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(nextVisibleColumnIndex))
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(nextVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success); 
                            }
                        } 
                        return true;
                }
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 
            return true;
        } 

        // Ctrl Right <==> End
        // Shift Ctrl Right <==> Shift End
        private bool ProcessRightMost(bool shift, int lastVisibleColumnIndex, int firstVisibleRowIndex) 
        {
            bool success; 
 
            this.noSelectionChangeCount++;
            try 
            {
                switch (this.SelectionMode)
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if (shift) 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            }
                            else
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                if (this.MultiSelect) 
                                {
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return true; 
                                    }
                                    int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                    int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                    UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                        this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false); 
                                    Debug.Assert(success); 
                                }
                                else 
                                {
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                } 
                            } 
                        }
                        else 
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true;
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                { 
                                    return true;
                                } 
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                Debug.Assert(success);
                            }
                        }
                        return true; 

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if (shift) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            {
                                ClearSelection();
                                SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            }
                            else 
                            {
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                {
                                    return true;
                                } 
                                if (this.MultiSelect)
                                { 
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return true; 
                                    }
                                    ClearSelection();
                                    Debug.Assert(this.ptAnchorCell.X >= 0);
                                    SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true); 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false);
                                    Debug.Assert(success); 
                                } 
                                else
                                { 
                                    SetSelectedColumnCore(this.ptCurrentCell.X, false);
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                    Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection();
                                SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success);
                            } 
                            else
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true)) 
                                {
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                {
                                    return true; 
                                }
                                ClearSelection(); 
                                SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect:
                        if (shift) 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                Debug.Assert(success);
                            }
                            else
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true; 
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex)) 
                                {
                                    return true;
                                }
                                if (this.MultiSelect) 
                                {
                                    Debug.Assert(this.ptAnchorCell.X >= 0); 
                                    if (this.ptAnchorCell.X == -1) 
                                    {
                                        return true; 
                                    }
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    {
                                        ClearSelection(); 
                                        SelectColumnRange(this.ptAnchorCell.X, lastVisibleColumnIndex, true);
                                    } 
                                    else 
                                    {
                                        //ClearSelection(); 
                                        //SelectCellRange(this.ptAnchorCell.X, this.ptCurrentCell.Y, lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, lastVisibleColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, oldEdgeRowIndex);
                                    } 
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, false, false, false); 
                                    Debug.Assert(success);
                                } 
                                else
                                {
                                    if (this.Columns[this.ptCurrentCell.X].Selected)
                                    { 
                                        SetSelectedColumnCore(this.ptCurrentCell.X, false);
                                        SetSelectedColumnCore(lastVisibleColumnIndex, true); 
                                    } 
                                    else
                                    { 
                                        SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                        SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true);
                                    }
                                    success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false); 
                                    Debug.Assert(success);
                                } 
                            } 
                        }
                        else 
                        {
                            if (this.ptCurrentCell.X == -1)
                            {
                                ClearSelection(); 
                                SetSelectedCellCore(lastVisibleColumnIndex, firstVisibleRowIndex, true);
                                success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false); 
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                }
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                Debug.Assert(success); 
                            }
                            else 
                            { 
                                if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                                { 
                                    return true;
                                }
                                if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex))
                                { 
                                    return true;
                                } 
                                if (this.Columns[this.ptCurrentCell.X].Selected) 
                                {
                                    ClearSelection(); 
                                    SetSelectedColumnCore(lastVisibleColumnIndex, true);
                                }
                                else
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true); 
                                } 
                                success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                                Debug.Assert(success); 
                            }
                        }
                        return true;
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if (this.ptCurrentCell.X == -1) 
                        { 
                            ClearSelection();
                            SetSelectedRowCore(firstVisibleRowIndex, true); 
                            success = ScrollIntoView(lastVisibleColumnIndex, firstVisibleRowIndex, false);
                            Debug.Assert(success);
                            if (IsInnerCellOutOfBounds(lastVisibleColumnIndex, firstVisibleRowIndex))
                            { 
                                return true;
                            } 
                            success = SetCurrentCellAddressCore(lastVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                            Debug.Assert(success);
                        } 
                        else
                        {
                            if (!ScrollIntoView(lastVisibleColumnIndex, this.ptCurrentCell.Y, true))
                            { 
                                return true;
                            } 
                            if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(lastVisibleColumnIndex)) 
                            {
                                return true; 
                            }
                            success = SetCurrentCellAddressCore(lastVisibleColumnIndex, this.ptCurrentCell.Y, true, false, false);
                            Debug.Assert(success);
                        } 
                        return true;
                } 
            } 
            finally
            { 
                this.NoSelectionChangeCount--;
            }
            return true;
        } 

        ///  
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)
        ] 
        protected bool ProcessSpaceKey(Keys keyData)
        {
            if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Shift &&
                this.ptCurrentCell.X != -1) 
            {
                this.noSelectionChangeCount++; 
                bool switchedToBulkPaint = false; 
                if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold)
                { 
                    this.inBulkPaintCount++;
                    switchedToBulkPaint = true;
                }
                try 
                {
                    if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) 
                    { 
                        // Same as clicking the column header cell
                        Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                        int bandIndex = 0;
                        while (bandIndex < this.selectedBandIndexes.Count)
                        {
                            if (this.selectedBandIndexes[bandIndex] != this.ptCurrentCell.X) 
                            {
                                // deselect currently selected column 
                                SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false); 
                            }
                            else 
                            {
                                bandIndex++;
                            }
                        } 
                        RemoveIndividuallySelectedCells();
                        if (!this.Columns[this.ptCurrentCell.X].Selected) 
                        { 
                            Debug.Assert(!this.selectedBandIndexes.Contains(this.ptCurrentCell.X));
                            SetSelectedColumnCore(this.ptCurrentCell.X, true); 
                        }
                        return true;
                    }
                    else if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) 
                    {
                        // Same as clicking the row header cell 
                        Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                        int bandIndex = 0;
                        while (bandIndex < this.selectedBandIndexes.Count) 
                        {
                            if (this.selectedBandIndexes[bandIndex] != this.ptCurrentCell.Y)
                            {
                                // deselect currently selected row 
                                SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false);
                            } 
                            else 
                            {
                                bandIndex++; 
                            }
                        }
                        RemoveIndividuallySelectedCells();
                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) == 0) 
                        {
                            Debug.Assert(!this.selectedBandIndexes.Contains(this.ptCurrentCell.Y)); 
                            SetSelectedRowCore(this.ptCurrentCell.Y, true); 
                        }
                        return true; 
                    }
                }
                finally
                { 
                    this.NoSelectionChangeCount--;
                    if (switchedToBulkPaint) 
                    { 
                        ExitBulkPaint(-1, -1);
                    } 
                }
            }
            return false;
        } 

        ///  
        ///  
        ///    
        ///       Gets a value indicating whether the Tab key should be processed. 
        ///    
        /// 
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        protected bool ProcessTabKey(Keys keyData) 
        {
            if (this.StandardTab) 
            { 
                if ((keyData & Keys.Control) == Keys.Control)
                { 
                    if ((keyData & Keys.Shift) == Keys.Shift)
                    {
                        if (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell)
                        { 
                            // Goto previous control
                            return false; 
                        } 
                        else
                        { 
                            // Goto previous cell
                            return TabToPreviousCell();
                        }
                    } 
                    else
                    { 
                        if (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell) 
                        {
                            // Goto next control 
                            return false;
                        }
                        else
                        { 
                            // Goto next cell
                            return TabToNextCell(); 
                        } 
                    }
                } 
                else
                {
                    /*
                    if ((keyData & Keys.Shift) == Keys.Shift) 
                    {
                        // Goto previous control 
                    } 
                    else
                    { 
                        // Goto next control
                    }
                    */
                    return false; 
                }
            } 
            else 
            {
                if ((keyData & Keys.Control) == Keys.Control) 
                {
                    /*
                    if ((keyData & Keys.Shift) == Keys.Shift)
                    { 
                        // Goto previous control
                    } 
                    else 
                    {
                        // Goto next control 
                    }
                    */
                    return false;
                } 
                else
                { 
                    if ((keyData & Keys.Shift) == Keys.Shift) 
                    {
                        if (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell) 
                        {
                            // Goto previous control
                            return false;
                        } 
                        else
                        { 
                            // Goto previous cell 
                            return TabToPreviousCell();
                        } 
                    }
                    else
                    {
                        if (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell) 
                        {
                            // Goto next control 
                            return false; 
                        }
                        else 
                        {
                            // Goto next cell
                            return TabToNextCell();
                        } 
                    }
                } 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Processes keys for dataGridView navigation. 
        ///    
        ///  
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
            SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers") 
        ]
        protected virtual bool ProcessDataGridViewKey(KeyEventArgs e)
        {
            switch (e.KeyCode) 
            {
                case Keys.Tab: 
                { 
                    return ProcessTabKey(e.KeyData);
                } 
                case Keys.Up:
                {
                    return ProcessUpKey(e.KeyData);
                } 
                case Keys.Down:
                { 
                    return ProcessDownKey(e.KeyData); 
                }
                case Keys.Next: 
                {
                    return ProcessNextKey(e.KeyData);
                }
                case Keys.Prior: 
                {
                    return ProcessPriorKey(e.KeyData); 
                } 
                case Keys.Left:
                { 
                    return ProcessLeftKey(e.KeyData);
                }
                case Keys.Right:
                { 
                    return ProcessRightKey(e.KeyData);
                } 
                case Keys.F2: 
                {
                    return ProcessF2Key(e.KeyData); 
                }
                case Keys.Home:
                {
                    return ProcessHomeKey(e.KeyData); 
                }
                case Keys.D0: 
                case Keys.NumPad0: 
                {
                    return ProcessZeroKey(e.KeyData); 
                }
                case Keys.Delete:
                {
                    return ProcessDeleteKey(e.KeyData); 
                }
                case Keys.End: 
                { 
                    return ProcessEndKey(e.KeyData);
                } 
                case Keys.Enter:
                {
                    return ProcessEnterKey(e.KeyData);
                } 
                case Keys.Escape:
                { 
                    return ProcessEscapeKey(e.KeyData); 
                }
                case Keys.A: 
                {
                    return ProcessAKey(e.KeyData);
                }
                case Keys.C: 
                case Keys.Insert:
                { 
                    return ProcessInsertKey(e.KeyData); 
                }
                case Keys.Space: 
                {
                    return ProcessSpaceKey(e.KeyData);
                }
            } 
            return false;
        } 
 
        /// 
        [ 
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
        ]
        protected bool ProcessUpKey(Keys keyData)
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            {
                return false;
            }
            int previousVisibleRowIndex = -1; 
            if (this.ptCurrentCell.Y != -1)
            { 
                previousVisibleRowIndex = this.Rows.GetPreviousRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible); 
            }
 
            this.noSelectionChangeCount++;
            try
            {
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the
                                    // DataGridView changes. 
                                    // See vsWhidbey: 325296. 
                                    // Debug.Assert(success);
                                } 
                                else
                                {
                                    if (this.MultiSelect)
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                        { 
                                            return true; 
                                        }
                                        if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 || 
                                            IsRowOutOfBounds(firstVisibleRowIndex))
                                        {
                                            return true;
                                        } 
                                        //ClearSelection();
                                        Debug.Assert(this.ptAnchorCell.Y >= 0); 
                                        //SelectCellRange(this.ptCurrentCell.X, firstVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex,
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, false, false, false);
                                        // Debug.Assert(success); 
                                    }
                                    else 
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                        { 
                                            return true;
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex))
                                        { 
                                            return true;
                                        } 
                                        //SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false); 
                                        ClearSelection();
                                        SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                        // Debug.Assert(success);
                                    }
                                } 
                            }
                            else 
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                }
                                else
                                { 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                    { 
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    ClearSelection(); 
                                    SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success); 
                                }
                            } 
                        }
                        else
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else
                                {
                                    if (previousVisibleRowIndex == -1)
                                    { 
                                        return true;
                                    } 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    if (this.MultiSelect) 
                                    { 
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        if (this.ptAnchorCell.Y == -1) 
                                        {
                                            return true;
                                        }
                                        //SelectCellUnorderedRange(this.ptCurrentCell.X, previousVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                        int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                        int oldEdgeRowIndex = this.ptCurrentCell.Y; 
                                        UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                            this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousVisibleRowIndex);
                                    } 
                                    else
                                    {
                                        ClearSelection();
                                        SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true); 
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, !this.MultiSelect, false, false); 
                                    // Debug.Assert(success); 
                                }
                            } 
                            else
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else 
                                {
                                    if (previousVisibleRowIndex == -1) 
                                    {
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    ClearSelection();
                                    SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true); 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                } 
                            }
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullRowSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if ((keyData & Keys.Shift) == Keys.Shift) 
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                }
                                else
                                { 
                                    if (this.MultiSelect)
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true)) 
                                        {
                                            return true; 
                                        }
                                        if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 ||
                                            IsRowOutOfBounds(firstVisibleRowIndex))
                                        { 
                                            return true;
                                        } 
                                        ClearSelection(); 
                                        Debug.Assert(this.ptAnchorCell.Y >= 0);
                                        SelectRowRange(firstVisibleRowIndex, this.ptAnchorCell.Y, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, false, false, false);
                                        // Debug.Assert(success);
                                    }
                                    else 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true)) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex))
                                        {
                                            return true;
                                        } 
                                        SetSelectedRowCore(this.ptCurrentCell.Y, false);
                                        SetSelectedRowCore(firstVisibleRowIndex, true); 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false); 
                                        // Debug.Assert(success);
                                    } 
                                }
                            }
                            else
                            { 
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection(); 
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true; 
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success); 
                                }
                                else 
                                {
                                    if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                    {
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                    { 
                                        return true;
                                    } 
                                    ClearSelection();
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedRowCore(firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else 
                                {
                                    if (previousVisibleRowIndex == -1) 
                                    {
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    ClearSelection();
                                    if (this.MultiSelect) 
                                    {
                                        if (this.ptAnchorCell.Y == -1) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptAnchorCell.Y >= previousVisibleRowIndex)
                                        {
                                            SelectRowRange(previousVisibleRowIndex, this.ptAnchorCell.Y, true);
                                        } 
                                        else
                                        { 
                                            SelectRowRange(this.ptAnchorCell.Y, previousVisibleRowIndex, true); 
                                        }
                                    } 
                                    else
                                    {
                                        SetSelectedRowCore(previousVisibleRowIndex, true);
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, !this.MultiSelect, false, false);
                                    // Debug.Assert(success); 
                                } 
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1)
                                {
                                    ClearSelection(); 
                                    SetSelectedRowCore(firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                                else 
                                { 
                                    if (previousVisibleRowIndex == -1)
                                    { 
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true))
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    ClearSelection();
                                    SetSelectedRowCore(previousVisibleRowIndex, true);
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                            } 
                        }
                        return true; 

                    case DataGridViewSelectionMode.RowHeaderSelect:
                        if ((keyData & Keys.Control) == Keys.Control)
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            { 
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                                else
                                {
                                    if (this.MultiSelect) 
                                    {
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true)) 
                                        { 
                                            return true;
                                        } 
                                        if (this.ptAnchorCell.X == -1 || this.ptCurrentCell.X == -1 ||
                                            IsRowOutOfBounds(firstVisibleRowIndex))
                                        {
                                            return true; 
                                        }
                                        Debug.Assert(this.ptAnchorCell.Y >= 0); 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                        {
                                            ClearSelection(); 
                                            SelectRowRange(firstVisibleRowIndex, this.ptAnchorCell.Y, true);
                                        }
                                        else
                                        { 
                                            //ClearSelection();
                                            //SelectCellRange(this.ptCurrentCell.X, firstVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X; 
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, firstVisibleRowIndex);
                                        }
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, false, false, false);
                                        // Debug.Assert(success); 
                                    }
                                    else 
                                    { 
                                        if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                        { 
                                            return true;
                                        }
                                        if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex))
                                        { 
                                            return true;
                                        } 
                                        if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                        {
                                            SetSelectedRowCore(this.ptCurrentCell.Y, false); 
                                            SetSelectedRowCore(firstVisibleRowIndex, true);
                                        }
                                        else
                                        { 
                                            SetSelectedCellCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                                            SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true); 
                                        } 
                                        success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                        // Debug.Assert(success); 
                                    }
                                }
                            }
                            else 
                            {
                                if (this.ptCurrentCell.X == -1) 
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    { 
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else
                                {
                                    if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                    { 
                                        return true;
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                    {
                                        return true; 
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(firstVisibleRowIndex, true);
                                    } 
                                    else 
                                    {
                                        ClearSelection(); 
                                        SetSelectedCellCore(this.ptCurrentCell.X, firstVisibleRowIndex, true);
                                    }
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                }
                            } 
                        } 
                        else
                        { 
                            if ((keyData & Keys.Shift) == Keys.Shift)
                            {
                                if (this.ptCurrentCell.X == -1)
                                { 
                                    ClearSelection();
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false); 
                                    Debug.Assert(success);
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                    // Debug.Assert(success);
                                } 
                                else 
                                {
                                    if (previousVisibleRowIndex == -1) 
                                    {
                                        return true;
                                    }
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                    {
                                        return true; 
                                    } 
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex))
                                    { 
                                        return true;
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0)
                                    { 
                                        ClearSelection();
                                        if (this.MultiSelect) 
                                        { 
                                            if (this.ptAnchorCell.Y == -1)
                                            { 
                                                return true;
                                            }
                                            if (this.ptAnchorCell.Y >= previousVisibleRowIndex)
                                            { 
                                                SelectRowRange(previousVisibleRowIndex, this.ptAnchorCell.Y, true);
                                            } 
                                            else 
                                            {
                                                SelectRowRange(this.ptAnchorCell.Y, previousVisibleRowIndex, true); 
                                            }
                                        }
                                        SetSelectedRowCore(previousVisibleRowIndex, true);
                                    } 
                                    else
                                    { 
                                        if (this.MultiSelect) 
                                        {
                                            //SelectCellUnorderedRange(this.ptCurrentCell.X, previousVisibleRowIndex, this.ptCurrentCell.X, this.ptAnchorCell.Y, true); 
                                            int oldEdgeColumnIndex = this.ptCurrentCell.X;
                                            int oldEdgeRowIndex = this.ptCurrentCell.Y;
                                            if (this.ptAnchorCell.Y == -1)
                                            { 
                                                return true;
                                            } 
                                            UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, oldEdgeColumnIndex, 
                                                this.ptAnchorCell.Y, ref oldEdgeRowIndex, previousVisibleRowIndex);
                                        } 
                                        else
                                        {
                                            ClearSelection();
                                            SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true); 
                                        }
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, !this.MultiSelect, false, false); 
                                    // Debug.Assert(success);
                                } 
                            }
                            else
                            {
                                if (this.ptCurrentCell.X == -1) 
                                {
                                    ClearSelection(); 
                                    SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                                    success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                    Debug.Assert(success); 
                                    if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                    {
                                        return true;
                                    } 
                                    success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                } 
                                else
                                { 
                                    if (previousVisibleRowIndex == -1)
                                    {
                                        return true;
                                    } 
                                    if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true))
                                    { 
                                        return true; 
                                    }
                                    if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex)) 
                                    {
                                        return true;
                                    }
                                    if ((this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Selected) != 0) 
                                    {
                                        ClearSelection(); 
                                        SetSelectedRowCore(previousVisibleRowIndex, true); 
                                    }
                                    else 
                                    {
                                        ClearSelection();
                                        SetSelectedCellCore(this.ptCurrentCell.X, previousVisibleRowIndex, true);
                                    } 
                                    success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false);
                                    // Debug.Assert(success); 
                                } 
                            }
                        } 
                        return true;

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if ((keyData & Keys.Control) == Keys.Control) 
                        {
                            if (this.ptCurrentCell.X == -1) 
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success);
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true;
                                } 
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                // Debug.Assert(success);
                            } 
                            else
                            {
                                if (!ScrollIntoView(this.ptCurrentCell.X, firstVisibleRowIndex, true))
                                { 
                                    return true;
                                } 
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(firstVisibleRowIndex)) 
                                {
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, firstVisibleRowIndex, true, false, false);
                                // Debug.Assert(success);
                            } 
                        }
                        else 
                        { 
                            if (this.ptCurrentCell.X == -1)
                            { 
                                ClearSelection();
                                SetSelectedColumnCore(firstVisibleColumnIndex, true);
                                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                                Debug.Assert(success); 
                                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                                { 
                                    return true; 
                                }
                                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                                // Debug.Assert(success);
                            }
                            else
                            { 
                                if (previousVisibleRowIndex == -1)
                                { 
                                    return true; 
                                }
                                if (!ScrollIntoView(this.ptCurrentCell.X, previousVisibleRowIndex, true)) 
                                {
                                    return true;
                                }
                                if (this.ptCurrentCell.X == -1 || IsRowOutOfBounds(previousVisibleRowIndex)) 
                                {
                                    return true; 
                                } 
                                success = SetCurrentCellAddressCore(this.ptCurrentCell.X, previousVisibleRowIndex, true, false, false);
                                // Debug.Assert(success); 
                            }
                        }
                        return true;
                } 
            }
            finally 
            { 
                this.NoSelectionChangeCount--;
            } 
            return true;
        }

        ///  
        [
            SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ] 
        protected bool ProcessZeroKey(Keys keyData)
        { 
            if (this.ptCurrentCell.X != -1 && !this.IsCurrentCellInEditMode && ColumnEditable(this.ptCurrentCell.X))
            {
                DataGridViewCell dataGridViewCell = this.CurrentCellInternal;
                Debug.Assert(dataGridViewCell != null); 

                if (!IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) && 
                    (this.EditMode == DataGridViewEditMode.EditOnKeystroke || this.EditMode == DataGridViewEditMode.EditOnKeystrokeOrF2) && 
                    dataGridViewCell.EditType != null)
                { 
                    bool success = ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false);
                    Debug.Assert(success);
                    if (!BeginEditInternal(false /*selectAll*/))
                    { 
                        return false;
                    } 
                } 
            }
 
            if ((keyData & (Keys.Alt | Keys.Shift | Keys.Control)) == Keys.Control &&
                this.IsCurrentCellInEditMode)
            {
                DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal; 
                Debug.Assert(dataGridViewCurrentCell != null);
                object nullValue = dataGridViewCurrentCell.GetInheritedStyle(null, this.ptCurrentCell.Y, false).NullValue; 
                if (nullValue == null || 
                    (dataGridViewCurrentCell.FormattedValueType != null && dataGridViewCurrentCell.FormattedValueType.IsAssignableFrom(nullValue.GetType())))
                { 
                    if (this.editingControl != null)
                    {
                        ((IDataGridViewEditingControl) this.editingControl).EditingControlFormattedValue = nullValue;
                        ((IDataGridViewEditingControl) this.editingControl).EditingControlValueChanged = true; 
                        ((IDataGridViewEditingControl) this.editingControl).PrepareEditingControlForEdit(true /*selectAll*/);
                    } 
                    else 
                    {
                        Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); 
                        IDataGridViewEditingCell dataGridViewEditingCell = dataGridViewCurrentCell as IDataGridViewEditingCell;
                        Debug.Assert(dataGridViewEditingCell != null);
                        dataGridViewEditingCell.EditingCellFormattedValue = nullValue;
                        dataGridViewEditingCell.EditingCellValueChanged = true; 
                        dataGridViewEditingCell.PrepareEditingCellForEdit(true /*selectAll*/);
                        InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); 
                    } 
                    NotifyCurrentCellDirty(true);
                    return true; 
                }
                return false;
            }
            return false; 
        }
 
        private void PushAllowUserToAddRows() 
        {
            if (this.AllowUserToAddRowsInternal) 
            {
                if (this.Columns.Count > 0 && this.newRowIndex == -1)
                {
                    AddNewRow(false); 
                }
            } 
            else if (this.newRowIndex != -1) 
            {
                // Delete the 'new' row 
                Debug.Assert(this.newRowIndex == this.Rows.Count - 1);
                this.Rows.RemoveAtInternal(this.newRowIndex, false /*force*/);
            }
        } 

        private bool PushFormattedValue(ref DataGridViewCell dataGridViewCurrentCell, object formattedValue, out Exception exception) 
        { 
            Debug.Assert(this.IsCurrentCellInEditMode);
 
            exception = null;

            DataGridViewCellStyle cellStyle = this.InheritedEditingCellStyle;
 
            DataGridViewCellParsingEventArgs dgvcpe = OnCellParsing(this.ptCurrentCell.Y,
                                                                    this.ptCurrentCell.X, 
                                                                    formattedValue, 
                                                                    dataGridViewCurrentCell.ValueType,
                                                                    cellStyle); 
            if (dgvcpe.ParsingApplied &&
                dgvcpe.Value != null &&
                dataGridViewCurrentCell.ValueType != null &&
                dataGridViewCurrentCell.ValueType.IsAssignableFrom(dgvcpe.Value.GetType())) 
            {
                if (dataGridViewCurrentCell.RowIndex == -1) 
                { 
                    dataGridViewCurrentCell = this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X]; // unsharing the row before pushing the new value
                } 
                return dataGridViewCurrentCell.SetValueInternal(this.ptCurrentCell.Y, dgvcpe.Value);
            }

            object val; 
            try
            { 
                val = dataGridViewCurrentCell.ParseFormattedValue(formattedValue, dgvcpe.InheritedCellStyle, null, null); 
            }
            catch (Exception e) 
            {
                if (ClientUtils.IsCriticalException(e))
                {
                    throw; 
                }
                exception = e; 
                return false; 
            }
            if (dataGridViewCurrentCell.RowIndex == -1) 
            {
                dataGridViewCurrentCell = this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X]; // unsharing the row before pushing the new value
            }
            return dataGridViewCurrentCell.SetValueInternal(this.ptCurrentCell.Y, val); 
        }
 
        private void RecordCellMouseClick(DataGridViewCellMouseEventArgs dgvcme) 
        {
            Debug.Assert(dgvcme.Clicks == 1); 
            this.lastMouseClickInfo.button = dgvcme.Button;
            this.lastMouseClickInfo.timeStamp = DateTime.Now.Ticks;
            this.lastMouseClickInfo.x = dgvcme.X;
            this.lastMouseClickInfo.y = dgvcme.Y; 
            this.lastMouseClickInfo.col = dgvcme.ColumnIndex;
            this.lastMouseClickInfo.row = dgvcme.RowIndex; 
        } 

        private void RefreshColumnsAndRows() 
        {
            this.Rows.ClearInternal(false /*recreateNewRow*/);
            RefreshColumns();
            RefreshRows(true /*scrollIntoView*/); 
        }
 
        private void RefreshColumns() 
        {
            // if AutoGenerateColumns == true then: 
            // 1. remove the columns which were previously bound
            // 2. add new columns based on data source
            //
 
            bool startUpdateInternal = this.Visible;
            if (startUpdateInternal) 
            { 
                BeginUpdateInternal();
            } 

            this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns] = true;
            try
            { 
                DataGridViewColumnCollection dataGridViewCols = this.Columns;
                DataGridViewColumn[] boundColumns = null; 
 
                if (this.dataConnection != null)
                { 
                    boundColumns = this.dataConnection.GetCollectionOfBoundDataGridViewColumns();
                }

                if (this.AutoGenerateColumns) 
                {
                    AutoGenerateDataBoundColumns(boundColumns); 
                } 
                else
                { 
                    for (int j = 0; j < dataGridViewCols.Count; j ++)
                    {
                        // when we refresh the columns, always clear whatever binding information we had on the columns
                        dataGridViewCols[j].IsDataBoundInternal = false; 
                        dataGridViewCols[j].BoundColumnIndex = -1;
                        dataGridViewCols[j].BoundColumnConverter = null; 
                        // set up the columns which have DataPropertyName set to something 
                        if (this.DataSource != null && dataGridViewCols[j].DataPropertyName.Length != 0)
                        { 
                            MapDataGridViewColumnToDataBoundField(dataGridViewCols[j]);
                        }
                    }
                } 

                if (this.DataSource != null) 
                { 
                    this.dataConnection.ApplySortingInformationFromBackEnd();
                } 
            }
            finally
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns] = false; 

                if (startUpdateInternal) 
                { 
                    EndUpdateInternal(false);
                    Invalidate(true); 
                }
            }
        }
 
        /// 
        //  Returns true for success, and false if an OnDataError event was raised and cancelled the operation (e.Cancel = true). 
        public bool RefreshEdit() 
        {
            if (this.ptCurrentCell.X != -1 && this.IsCurrentCellInEditMode) 
            {
                Debug.Assert(this.ptCurrentCell.Y != -1);
                DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal;
                DataGridViewCellStyle dataGridViewCellStyle = dataGridViewCurrentCell.GetInheritedStyle(null, this.ptCurrentCell.Y, true); 
                if (this.editingControl != null)
                { 
                    if (InitializeEditingControlValue(ref dataGridViewCellStyle, dataGridViewCurrentCell)) 
                    {
                        if (((IDataGridViewEditingControl) this.editingControl).RepositionEditingControlOnValueChange) 
                        {
                            PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                        }
                        ((IDataGridViewEditingControl) this.editingControl).PrepareEditingControlForEdit(true /*selectAll*/); 
                        ((IDataGridViewEditingControl) this.editingControl).EditingControlValueChanged = false;
                        this.IsCurrentCellDirtyInternal = false; 
                        return true; 
                    }
                    return false; 
                }
                else
                {
                    Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); 
                    if (InitializeEditingCellValue(ref dataGridViewCellStyle, ref dataGridViewCurrentCell))
                    { 
                        IDataGridViewEditingCell dataGridViewEditingCell = dataGridViewCurrentCell as IDataGridViewEditingCell; 
                        Debug.Assert(dataGridViewEditingCell != null);
                        dataGridViewEditingCell.PrepareEditingCellForEdit(true /*selectAll*/); 
                        dataGridViewEditingCell.EditingCellValueChanged = false;
                        this.IsCurrentCellDirtyInternal = false;
                        return true;
                    } 
                    return false;
                } 
            } 
            return true;
        } 

        private void RefreshRows(bool scrollIntoView)
        {
            bool startBeginUpdate = this.Visible; 
            if (startBeginUpdate)
            { 
                BeginUpdateInternal(); 
            }
 
            try
            {
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange])
                { 
                    this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] = true;
                } 
 
                // Clear existing rows
                this.Rows.ClearInternal(true /*recreateNewRow*/); 

                // Add a row for each object in the data source
                if (this.dataConnection != null && this.Columns.Count > 0)
                { 
                    IList list = this.dataConnection.List;
                    if (list != null && list.Count > 0) 
                    { 
                        int rowsCount = list.Count;
                        bool oldDoNotChangePositionInTheCurrencyManager = this.dataConnection.DoNotChangePositionInTheCurrencyManager; 

                        // scroll into view when we have a non-empty list
                        // and the layout is not dirty and we are not in a sort operation.
                        bool matchPositionInCurrencyManagerAfterRecreatingRows = !this.layout.dirty && !this.InSortOperation; 

                        if (matchPositionInCurrencyManagerAfterRecreatingRows) 
                        { 
                            // Prevent the data connection from changing position in the currency manager.
                            // But only if the data grid view will set the position in the currency manager after recreating the rows collection. 
                            this.dataConnection.DoNotChangePositionInTheCurrencyManager = true;
                        }
                        try
                        { 
                            this.Rows.AddInternal(this.RowTemplateClone);
                            Debug.Assert(list.Count == rowsCount); 
                            if (rowsCount > 1) 
                            {
                                this.Rows.AddCopiesInternal(0, rowsCount-1); 
                            }
                        }
                        finally
                        { 
                            this.dataConnection.DoNotChangePositionInTheCurrencyManager = oldDoNotChangePositionInTheCurrencyManager;
                        } 
 
                        if (matchPositionInCurrencyManagerAfterRecreatingRows)
                        { 
                            dataConnection.MatchCurrencyManagerPosition(scrollIntoView, true /*clearSelection*/);
                        }
                    }
                } 
            }
            finally 
            { 
                if (startBeginUpdate)
                { 
                    EndUpdateInternal(false);
                    Invalidate(true);
                }
            } 
        }
 
        private void RealeaseMouse() 
        {
            Cursor.ClipInternal = Rectangle.Empty; 
            this.CaptureInternal = false;
        }

        private void RemoveIndividualReadOnlyCellsInColumn(int columnIndex) 
        {
            int cellIndex = 0; 
            while (cellIndex < this.individualReadOnlyCells.Count) 
            {
                DataGridViewCell dataGridViewCell = this.individualReadOnlyCells[cellIndex]; 
                if (dataGridViewCell.ColumnIndex == columnIndex)
                {
                    SetReadOnlyCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                } 
                else
                { 
                    cellIndex++; 
                }
            } 
        }

        private void RemoveIndividualReadOnlyCellsInRow(int rowIndex)
        { 
            int cellIndex = 0;
            while (cellIndex < this.individualReadOnlyCells.Count) 
            { 
                DataGridViewCell dataGridViewCell = this.individualReadOnlyCells[cellIndex];
                if (dataGridViewCell.RowIndex == rowIndex) 
                {
                    SetReadOnlyCellCore(dataGridViewCell.ColumnIndex, rowIndex, false);
                }
                else 
                {
                    cellIndex++; 
                } 
            }
        } 

        private void RemoveIndividuallySelectedCells()
        {
            Debug.Assert(this.noSelectionChangeCount > 0); 
            bool switchedToBulkPaint = false;
            if (this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold) 
            { 
                this.inBulkPaintCount++;
                switchedToBulkPaint = true; 
            }
            try
            {
                while (this.individualSelectedCells.Count > 0) 
                {
                    DataGridViewCell dataGridViewCell = this.individualSelectedCells.HeadCell; 
                    SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false); 
                }
            } 
            finally
            {
                if (switchedToBulkPaint)
                { 
                    ExitBulkPaint(-1, -1);
                } 
            } 
        }
 
        private void RemoveIndividuallySelectedCells(int columnIndexException, int rowIndexException)
        {
            Debug.Assert(this.noSelectionChangeCount > 0);
            bool switchedToBulkPaint = false; 
            if (this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold)
            { 
                this.inBulkPaintCount++; 
                switchedToBulkPaint = true;
            } 
            try
            {
                while (this.individualSelectedCells.Count > 0)
                { 
                    DataGridViewCell dataGridViewCell = this.individualSelectedCells.HeadCell;
                    if (dataGridViewCell.ColumnIndex != columnIndexException || dataGridViewCell.RowIndex != rowIndexException) 
                    { 
                        SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                    } 
                    else
                    {
                        while (this.individualSelectedCells.Count > 1)
                        { 
                            dataGridViewCell = this.individualSelectedCells[1];
                            Debug.Assert(dataGridViewCell.ColumnIndex != columnIndexException || dataGridViewCell.RowIndex != rowIndexException); 
                            SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false); 
                        }
                        break; 
                    }
                }
            }
            finally 
            {
                if (switchedToBulkPaint) 
                { 
                    ExitBulkPaint(-1, -1);
                } 
            }
        }

        private void RemoveIndividuallySelectedCellsInColumn(int columnIndex) 
        {
            Debug.Assert(this.noSelectionChangeCount > 0); 
            int cellIndex = 0; 
            int cellCountInColumn = 0;
            bool switchToBulkOperation = false; 
            DataGridViewCell dataGridViewCell;

            while (cellIndex < this.individualSelectedCells.Count)
            { 
                dataGridViewCell = this.individualSelectedCells[cellIndex];
                if (dataGridViewCell.ColumnIndex == columnIndex) 
                { 
                    SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                    cellCountInColumn++; 
                    if (cellCountInColumn > DATAGRIDVIEW_bulkPaintThreshold)
                    {
                        switchToBulkOperation = true;
                        break; 
                    }
                } 
                else 
                {
                    cellIndex++; 
                }
            }

            if (switchToBulkOperation) 
            {
                this.inBulkPaintCount++; 
                try 
                {
                    while (cellIndex < this.individualSelectedCells.Count) 
                    {
                        dataGridViewCell = this.individualSelectedCells[cellIndex];
                        if (dataGridViewCell.ColumnIndex == columnIndex)
                        { 
                            SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false);
                        } 
                        else 
                        {
                            cellIndex++; 
                        }
                    }
                }
                finally 
                {
                    ExitBulkPaint(columnIndex, -1); 
                } 
            }
        } 

        private void RemoveIndividuallySelectedCellsInRow(int rowIndex)
        {
            Debug.Assert(this.noSelectionChangeCount > 0); 
            // Since there are typically not many columns in a row, we don't try to switch into a bulk operation
            // as we do in RemoveIndividuallySelectedCellsInColumn. 
            int cellIndex = 0; 
            while (cellIndex < this.individualSelectedCells.Count)
            { 
                DataGridViewCell dataGridViewCell = this.individualSelectedCells[cellIndex];
                if (dataGridViewCell.RowIndex == rowIndex)
                {
                    SetSelectedCellCore(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, false); 
                }
                else 
                { 
                    cellIndex++;
                } 
            }
        }

        // required by the Designer 
        private void ResetBackgroundColor()
        { 
            this.BackgroundColor = DefaultBackgroundBrush.Color; 
        }
 
        // required by the Designer
        private void ResetGridColor()
        {
            this.GridColor = DefaultGridColor; 
        }
 
        ///  
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override void ResetText() 
        {
            base.ResetText();
        }
 
        /// 
        ///      Re-initializes all tracking related state. 
        ///  
        private void ResetTrackingState()
        { 
            if (this.horizScrollTimer != null && this.horizScrollTimer.Enabled)
            {
                this.horizScrollTimer.Enabled = false;
            } 
            if (this.vertScrollTimer != null && this.vertScrollTimer.Enabled)
            { 
                this.vertScrollTimer.Enabled = false; 
            }
 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] = false; 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] = false;
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = false; 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = false; 
            this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = false;
            this.trackColumn = -1; 
            this.trackRow = -1;
            this.ptMouseDownCell.X = -2;
            this.ptMouseDownCell.Y = -2;
 
            if (this.currentRowSplitBar != -1)
            { 
                Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar), true); 
                this.lastRowSplitBar = this.currentRowSplitBar = -1;
            } 
            if (this.currentColSplitBar != -1)
            {
                Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar), true);
                this.lastColSplitBar = this.currentColSplitBar = -1; 
            }
            if (this.lastHeaderShadow != -1) 
            { 
                this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = false;
                this.trackColumnEdge = -1; 
                this.lastHeaderShadow = -1;
                Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders));
            }
            RealeaseMouse(); 
        }
 
        ///  
        ///      Re-initializes all UI related state.
        ///  
        internal void ResetUIState(bool useRowShortcut, bool computeVisibleRows)
        {
            PerformLayoutPrivate(useRowShortcut, computeVisibleRows, true /*invalidInAdjustFillingColumns*/, !useRowShortcut /*repositionEditingControl*/);
            if (!useRowShortcut) 
            {
                Invalidate(); 
                InvalidateScrollBars(); 
            }
        } 

        private void RestoreRowsCachedThickness()
        {
            // Switch to batch operation 
            this.inBulkPaintCount++;
            this.inBulkLayoutCount++; 
            try 
            {
                // Only height of visible rows are restored since invisible rows are not autosized. 
                for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
                    rowIndex != -1;
                    rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible))
                { 
                    DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
                    int height, minimumHeight; 
                    dataGridViewRow.GetHeightInfo(rowIndex, out height, out minimumHeight); 
                    if (height != dataGridViewRow.CachedThickness &&
                        !OnRowHeightInfoPushed(rowIndex, dataGridViewRow.CachedThickness, minimumHeight)) 
                    {
                        dataGridViewRow.ThicknessInternal = dataGridViewRow.CachedThickness;
                    }
                } 
            }
            finally 
            { 
                ExitBulkLayout(true /*invalidInAdjustFillingColumns*/);
                ExitBulkPaint(-1, -1); 
            }
        }

        // we need to access the GetRowState, otherwise we would unshare the row 
        private bool RowIsResizable(int rowIndex)
        { 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if ((rowState & DataGridViewElementStates.ResizableSet) == DataGridViewElementStates.ResizableSet)
            { 
                return (rowState & DataGridViewElementStates.Resizable) == DataGridViewElementStates.Resizable;
            }
            else
            { 
                return this.AllowUserToResizeRows;
            } 
        } 

        private bool RowNeedsDisplayedState(int rowIndex, int lastDisplayedFrozenRowIndex, int lastDisplayedScrollingRowIndex) 
        {
            Debug.Assert(rowIndex >= 0);
            Debug.Assert(rowIndex < this.Rows.Count);
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
 
            if ((rowState & DataGridViewElementStates.Visible) == 0) 
            {
                return false; 
            }

            if ((rowState & DataGridViewElementStates.Frozen) != 0)
            { 
                return rowIndex <= lastDisplayedFrozenRowIndex;
            } 
            else if (this.displayedBandsInfo.FirstDisplayedScrollingRow != -1 && 
                     rowIndex >= this.displayedBandsInfo.FirstDisplayedScrollingRow &&
                     rowIndex <= lastDisplayedScrollingRowIndex) 
            {
                return true;
            }
            return false; 
        }
 
        private void ScrollBar_MouseEnter(object sender, System.EventArgs e) 
        {
            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected]) 
            {
                OnMouseEnter(EventArgs.Empty);
            }
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 
        }
 
        private void ScrollBar_MouseLeave(object sender, System.EventArgs e) 
        {
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 
            Point ptMouse = PointToClient(Control.MousePosition);
            if (!this.ClientRectangle.Contains(ptMouse))
            {
                OnMouseLeave(EventArgs.Empty); 
            }
        } 
 
        private bool ScrollColumnIntoView(int columnIndex, int rowIndex, bool committed, bool forCurrentCellChange)
        { 
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count);

            if (this.displayedBandsInfo.FirstDisplayedScrollingCol != -1 &&
                !this.Columns[columnIndex].Frozen && 
                (columnIndex != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.negOffset > 0))
            { 
                int columnsToScroll; 
                if (this.Columns.DisplayInOrder(columnIndex, this.displayedBandsInfo.FirstDisplayedScrollingCol))
                { 
                    if (!committed && this.ptCurrentCell.X >= 0 &&
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex),
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/)) 
                    {
                        return false; 
                    } 

                    columnsToScroll = this.Columns.GetColumnCount(DataGridViewElementStates.Visible, columnIndex, this.displayedBandsInfo.FirstDisplayedScrollingCol); 
                    if (this.negOffset > 0)
                    {
                        columnsToScroll++;
                    } 
                    ScrollColumns(-columnsToScroll);
                } 
                else if (columnIndex == this.displayedBandsInfo.FirstDisplayedScrollingCol && this.negOffset > 0) 
                {
                    if (!committed && this.ptCurrentCell.X >= 0 && 
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex),
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/))
                    { 
                        return false;
                    } 
                    ScrollColumns(-1); 
                }
                else if (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol == -1 || 
                         (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol != columnIndex &&
                          this.Columns.DisplayInOrder(this.displayedBandsInfo.LastTotallyDisplayedScrollingCol, columnIndex)))
                {
                    if (!committed && this.ptCurrentCell.X >= 0 && 
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex), 
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/)) 
                    {
                        return false; 
                    }

                    columnsToScroll = 0;
                    int firstDisplayedScrollingColumn = this.displayedBandsInfo.FirstDisplayedScrollingCol; 
                    int xColumnRightEdge;
 
                    if (this.RightToLeftInternal) 
                    {
                        xColumnRightEdge = GetColumnXFromIndex(columnIndex) - this.Columns[columnIndex].Width; 
                        while (xColumnRightEdge < this.layout.Data.X && this.Columns.DisplayInOrder(firstDisplayedScrollingColumn, columnIndex))
                        {
                            xColumnRightEdge += this.Columns[firstDisplayedScrollingColumn].Width;
                            if (firstDisplayedScrollingColumn == this.displayedBandsInfo.FirstDisplayedScrollingCol) 
                            {
                                xColumnRightEdge -= this.negOffset; 
                            } 
                            columnsToScroll++;
                            if (xColumnRightEdge < this.layout.Data.X) 
                            {
                                firstDisplayedScrollingColumn = this.Columns.GetNextColumn(this.Columns[firstDisplayedScrollingColumn],
                                                                                           DataGridViewElementStates.Visible,
                                                                                           DataGridViewElementStates.None).Index; 
                            }
                        } 
                    } 
                    else
                    { 
                        xColumnRightEdge = GetColumnXFromIndex(columnIndex) + this.Columns[columnIndex].Width;
                        while (xColumnRightEdge > this.layout.Data.Right && this.Columns.DisplayInOrder(firstDisplayedScrollingColumn, columnIndex))
                        {
                            xColumnRightEdge -= this.Columns[firstDisplayedScrollingColumn].Width; 
                            if (firstDisplayedScrollingColumn == this.displayedBandsInfo.FirstDisplayedScrollingCol)
                            { 
                                xColumnRightEdge += this.negOffset; 
                            }
                            columnsToScroll++; 
                            if (xColumnRightEdge > this.layout.Data.Right)
                            {
                                firstDisplayedScrollingColumn = this.Columns.GetNextColumn(this.Columns[firstDisplayedScrollingColumn],
                                                                                           DataGridViewElementStates.Visible, 
                                                                                           DataGridViewElementStates.None).Index;
                            } 
                        } 
                    }
                    if (columnsToScroll != 0) 
                    {
                        ScrollColumns(columnsToScroll);
                    }
                } 
            }
            return true; 
        } 

        private void ScrollColumns(int columns) 
        {
            DataGridViewColumn newFirstVisibleScrollingCol = null;
            DataGridViewColumn dataGridViewColumnTmp;
            int colCount = 0; 
            //ScrollEventType scrollEventType;
            if (columns > 0) 
            { 
                //scrollEventType = columns > 1 ? ScrollEventType.LargeIncrement : ScrollEventType.SmallIncrement;
                if (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0) 
                {
                    dataGridViewColumnTmp = this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol];
                    while (colCount < columns && dataGridViewColumnTmp != null)
                    { 
                        dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp,
                            DataGridViewElementStates.Visible, 
                            DataGridViewElementStates.None); 
                        colCount++;
                    } 

                    if (dataGridViewColumnTmp == null)
                    {
                        // no more column to display on the right of the last totally seen column 
                        return;
                    } 
                } 
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0);
                dataGridViewColumnTmp = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
                colCount = 0;
                while (colCount < columns && dataGridViewColumnTmp != null)
                {
                    dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, 
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.None); 
                    colCount++; 
                }
                newFirstVisibleScrollingCol = dataGridViewColumnTmp; 
            }

            if (columns < 0)
            { 
                //scrollEventType = columns < -1 ? ScrollEventType.LargeDecrement : ScrollEventType.SmallDecrement;
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0); 
                dataGridViewColumnTmp = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; 
                if (this.negOffset > 0)
                { 
                    colCount++;
                }
                while (colCount < -columns && dataGridViewColumnTmp != null)
                { 
                    dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp,
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.Frozen); 
                    colCount++;
                } 
                newFirstVisibleScrollingCol = dataGridViewColumnTmp;
                if (newFirstVisibleScrollingCol == null)
                {
                    if (this.negOffset == 0) 
                    {
                        // no more column to display on the left of the first seen column 
                        FlushDisplayedChanged(); 
                        return;
                    } 
                    else
                    {
                        newFirstVisibleScrollingCol = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol];
                    } 
                }
            } 
 
            int newColOffset = 0;
            for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, 
                     DataGridViewElementStates.Frozen);
                dataGridViewColumn != newFirstVisibleScrollingCol;
                dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn,
                DataGridViewElementStates.Visible, 
                DataGridViewElementStates.None))
            { 
                newColOffset += dataGridViewColumn.Thickness; 
            }
 
            this.HorizontalOffset = newColOffset;
        }

        private bool ScrollIntoView(int columnIndex, int rowIndex, bool forCurrentCellChange) 
        {
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= -1 && this.displayedBandsInfo.FirstDisplayedScrollingCol < this.Columns.Count); 
            Debug.Assert(this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= -1 && this.displayedBandsInfo.LastTotallyDisplayedScrollingCol < this.Columns.Count);
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); 
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= -1 && this.displayedBandsInfo.FirstDisplayedScrollingRow < this.Rows.Count);
            Debug.Assert(this.Columns[columnIndex].Visible);
            Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0);
 
            bool committed = false;
            if (this.ptCurrentCell.X >= 0 && 
                (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex)) 
            {
                if (!CommitEditForOperation(columnIndex, rowIndex, forCurrentCellChange)) 
                {
                    return false;
                }
                committed = true; 
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    return false; 
                }
            } 

            //scroll horizontally
            if (!ScrollColumnIntoView(columnIndex, rowIndex, committed, forCurrentCellChange))
            { 
                return false;
            } 
 
            if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
            { 
                return false;
            }

            //scroll vertically 
            return ScrollRowIntoView(columnIndex, rowIndex, committed, forCurrentCellChange);
        } 
 
        private void ScrollRectangles(NativeMethods.RECT[] rects, int change)
        { 
            if (rects != null)
            {
                if (MouseButtons != MouseButtons.None)
                { 
                    this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] = true;
                } 
 
                NativeMethods.RECT scroll;
                for (int r = 0; r < rects.Length; r++) 
                {
                    scroll = rects[r];
                    SafeNativeMethods.ScrollWindow(new HandleRef(this, this.Handle),
                        change, 
                        0,
                        ref scroll, 
                        ref scroll); 
                }
            } 
        }

        private bool ScrollRowIntoView(int columnIndex, int rowIndex, bool committed, bool forCurrentCellChange)
        { 
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
 
            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) == 0) 
            {
                int rowsToScroll; 
                if (rowIndex < this.displayedBandsInfo.FirstDisplayedScrollingRow)
                {
                    if (!committed && this.ptCurrentCell.X >= 0 &&
                        !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                    forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex),
                                    this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/)) 
                    { 
                        return false;
                    } 

                    rowsToScroll = this.Rows.GetRowCount(DataGridViewElementStates.Visible, rowIndex, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                    ScrollRowsByCount(-rowsToScroll, rowsToScroll > 1 ? ScrollEventType.LargeDecrement : ScrollEventType.SmallDecrement);
                } 
                else if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0 &&
                         rowIndex > this.displayedBandsInfo.FirstDisplayedScrollingRow) 
                { 
                    rowsToScroll = 0;
                    int firstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
                    int yRowBottomEdge = GetRowYFromIndex(rowIndex) + this.Rows.SharedRow(rowIndex).GetHeight(rowIndex);
                    while (yRowBottomEdge > this.layout.Data.Bottom && rowIndex > firstDisplayedScrollingRow)
                    {
                        yRowBottomEdge -= this.Rows.SharedRow(firstDisplayedScrollingRow).GetHeight(firstDisplayedScrollingRow); 
                        rowsToScroll++;
                        if (yRowBottomEdge > this.layout.Data.Bottom) 
                        { 
                            firstDisplayedScrollingRow = this.Rows.GetNextRow(firstDisplayedScrollingRow, DataGridViewElementStates.Visible);
                            Debug.Assert(firstDisplayedScrollingRow != -1); 
                        }
                    }
                    if (rowsToScroll != 0)
                    { 
                        if (!committed && this.ptCurrentCell.X >= 0 &&
                            !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                        forCurrentCellChange && (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex), 
                                        this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/))
                        { 
                            return false;
                        }
                        ScrollRowsByCount(rowsToScroll, rowsToScroll > 1 ? ScrollEventType.LargeIncrement : ScrollEventType.SmallIncrement);
                    } 
                }
            } 
            return true; 
        }
 
        private void ScrollRows(int rowCount, int deltaY, ScrollEventType scrollEventType)
        {
            bool invalidateTopOfRowHeaders = false;
            Debug.Assert(rowCount != 0); 
            Debug.Assert(deltaY != 0);
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen)); 
            this.verticalOffset -= deltaY; 
            if (this.vertScrollBar.Enabled)
            { 
                this.vertScrollBar.Value = this.verticalOffset;
            }
            ClearRegionCache();
            int frozenRowsThickness = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            Rectangle rowsRect = this.layout.Data;
            if (this.layout.RowHeadersVisible) 
            { 
                rowsRect = Rectangle.Union(rowsRect, this.layout.RowHeaders);
                if (this.SingleHorizontalBorderAdded) 
                {
                    rowsRect.Y++;
                    rowsRect.Height--;
                    invalidateTopOfRowHeaders = true; 
                }
            } 
            else if (this.SingleVerticalBorderAdded) 
            {
                Debug.Assert(rowsRect.X > 0); 
                rowsRect.X--;
                rowsRect.Width++;
            }
            rowsRect.Y += frozenRowsThickness; 
            rowsRect.Height -= frozenRowsThickness;
            Debug.Assert(rowsRect.Height >= 0); 
 
            if (this.editingControl != null &&
                (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Frozen) == 0) 
            {
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow > -1);
                PositionEditingControl(true /*setLocation*/, false /*setSize*/, false /*setFocus*/);
            } 

            if (MouseButtons != MouseButtons.None) 
            { 
                this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] = true;
            } 

            // The mouse probably is not over the same cell after the scroll.
            UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/);
 
            NativeMethods.RECT scrollArea = NativeMethods.RECT.FromXYWH(rowsRect.X, rowsRect.Y, rowsRect.Width, rowsRect.Height);
            SafeNativeMethods.ScrollWindow(new HandleRef(this, this.Handle), 0, deltaY, ref scrollArea, ref scrollArea); 
            if (invalidateTopOfRowHeaders) 
            {
                rowsRect.X = this.layout.Inside.X; 
                rowsRect.Y = this.layout.Inside.Y;
                rowsRect.Width = this.layout.RowHeaders.Width;
                rowsRect.Height = 1;
                Invalidate(rowsRect); 
            }
            if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll]) 
            { 
                Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                int firstVisibleScrollingRow = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); 
                Debug.Assert(firstVisibleScrollingRow != -1);
                int newScrolledOffRowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible, firstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                Debug.Assert(newScrolledOffRowCount >= rowCount);
                OnScroll(scrollEventType, newScrolledOffRowCount - rowCount, newScrolledOffRowCount, ScrollOrientation.VerticalScroll); 
            }
        } 
 
        private void ScrollRowsByCount(int rows, ScrollEventType scrollEventType)
        { 
            Debug.Assert(rows != 0);
            Debug.Assert((rows > 0 && (scrollEventType == ScrollEventType.SmallIncrement || scrollEventType == ScrollEventType.LargeIncrement)) ||
                         (rows < 0 && (scrollEventType == ScrollEventType.SmallDecrement || scrollEventType == ScrollEventType.LargeDecrement)));
 
            int deltaY = 0;
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); 
            int newFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
            if (rows > 0)
            { 
                for (int rowCount = rows; rowCount > 0; rowCount--)
                {
                    deltaY -= this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                    newFirstVisibleScrollingRow = this.Rows.GetNextRow(newFirstVisibleScrollingRow, 
                        DataGridViewElementStates.Visible);
 
                    Debug.Assert(newFirstVisibleScrollingRow != -1); 
                }
                if (newFirstVisibleScrollingRow != -1) 
                {
                    int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                    // Tentative target value for this.displayedBandsInfo.FirstDisplayedScrollingRow.
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = newFirstVisibleScrollingRow; 
                    // This sets the actual value of this.displayedBandsInfo.FirstDisplayedScrollingRow
                    ComputeVisibleRows(); 
                    // Compute the actual deltaY given the new this.displayedBandsInfo.FirstDisplayedScrollingRow 
                    if (this.displayedBandsInfo.FirstDisplayedScrollingRow > oldFirstVisibleScrollingRow)
                    { 
                        deltaY = -this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                        rows = this.Rows.GetRowCount(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                    }
                    else 
                    {
                        Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow == oldFirstVisibleScrollingRow); 
                        rows = 0; 
                    }
                } 
            }
            else
            {
                for (int rowCount = rows; rowCount < 0; rowCount++) 
                {
                    newFirstVisibleScrollingRow = this.Rows.GetPreviousRow(newFirstVisibleScrollingRow, 
                        DataGridViewElementStates.Visible, 
                        DataGridViewElementStates.Frozen);
                    if (newFirstVisibleScrollingRow != -1) 
                    {
                        deltaY += this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                    }
                } 
                if (newFirstVisibleScrollingRow != -1)
                { 
                    this.displayedBandsInfo.FirstDisplayedScrollingRow = newFirstVisibleScrollingRow; 
                    ComputeVisibleRows();
                    Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow == newFirstVisibleScrollingRow); 
                }
            }

            if (newFirstVisibleScrollingRow != -1 && rows != 0) 
            {
                ScrollRows(rows, deltaY, scrollEventType); 
            } 

            FlushDisplayedChanged(); 
        }

        private void ScrollRowsByHeight(int height)
        { 
            Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
            int deltaY, scrollHeight = 0; 
            int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 
            int newFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
            if (height > 0) 
            {
                deltaY = this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                while (deltaY <= height)
                { 
                    newFirstVisibleScrollingRow = this.Rows.GetNextRow(newFirstVisibleScrollingRow, DataGridViewElementStates.Visible);
                    if (newFirstVisibleScrollingRow == -1) 
                    { 
                        throw new InvalidOperationException(); // Occurs in case of VSWhidbey 533407
                    } 
                    else
                    {
                        deltaY += this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow);
                    } 
                }
            } 
            else 
            {
                newFirstVisibleScrollingRow = this.Rows.GetPreviousRow(newFirstVisibleScrollingRow, 
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.Frozen);
                Debug.Assert(newFirstVisibleScrollingRow != -1);
                deltaY = -this.Rows.SharedRow(newFirstVisibleScrollingRow).GetHeight(newFirstVisibleScrollingRow); 
                while (deltaY >= height)
                { 
                    int scrollingRowTmp = this.Rows.GetPreviousRow(newFirstVisibleScrollingRow, 
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.Frozen); 
                    if (scrollingRowTmp != -1)
                    {
                        deltaY -= this.Rows.SharedRow(scrollingRowTmp).GetHeight(scrollingRowTmp);
                        if (deltaY >= height) 
                        {
                            newFirstVisibleScrollingRow = scrollingRowTmp; 
                        } 
                    }
                    else 
                    {
                        break;
                    }
                } 
            }
 
            // Tentative target value for this.displayedBandsInfo.FirstDisplayedScrollingRow. 
            this.displayedBandsInfo.FirstDisplayedScrollingRow = newFirstVisibleScrollingRow;
            // This sets the actual value of this.displayedBandsInfo.FirstDisplayedScrollingRow 
            ComputeVisibleRows();
            ScrollEventType scrollEventType = ScrollEventType.EndScroll;
            int rowCount = 0;
            // Compute the scrollHeight given the new this.displayedBandsInfo.FirstDisplayedScrollingRow 
            if (this.displayedBandsInfo.FirstDisplayedScrollingRow > oldFirstVisibleScrollingRow)
            { 
                scrollHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow); 
                rowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible, oldFirstVisibleScrollingRow, this.displayedBandsInfo.FirstDisplayedScrollingRow);
                scrollEventType = rowCount > 1 ? ScrollEventType.LargeIncrement : ScrollEventType.SmallIncrement; 
            }
            else if (this.displayedBandsInfo.FirstDisplayedScrollingRow < oldFirstVisibleScrollingRow)
            {
                scrollHeight = -this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, oldFirstVisibleScrollingRow); 
                rowCount = -this.Rows.GetRowCount(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, oldFirstVisibleScrollingRow);
                scrollEventType = rowCount < -1 ? ScrollEventType.LargeDecrement : ScrollEventType.SmallDecrement; 
            } 
            if (scrollHeight != 0)
            { 
                ScrollRows(rowCount, -scrollHeight, scrollEventType);
            }

            FlushDisplayedChanged(); 
        }
 
        ///  
        // Does not seem to be a valid fxcop violation report. Contacting fxcop team to double-check.
        [SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops")] 
        public void SelectAll()
        {
            if (!this.MultiSelect)
            { 
                return;
            } 
            this.inBulkPaintCount++; 
            this.noDimensionChangeCount++;
            this.noSelectionChangeCount++; 
            try
            {
                DataGridViewRow dataGridViewRow = null;
                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect: 
                    { 
                        // Bonjour the scalability issues! We select each cell, one at the time.
                        int maxColumnIndex = this.Columns.Count; 
                        int rowIndex = 0, maxRowIndex = this.Rows.Count;
                        while (rowIndex < maxRowIndex)
                        {
                            dataGridViewRow = this.Rows[rowIndex];  //unsharing each row! 
                            int columnIndex = 0;
                            while (columnIndex < maxColumnIndex) 
                            { 
                                SetSelectedCellCore(columnIndex, rowIndex, true);
                                columnIndex++; 
                            }
                            rowIndex++;
                        }
                        break; 
                    }
 
                    case DataGridViewSelectionMode.FullRowSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    { 
                        int rowIndex = 0, maxRowIndex = this.Rows.Count;
                        while (rowIndex < maxRowIndex)
                        {
                            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
                            if ((rowState & DataGridViewElementStates.Selected) == 0)
                            { 
                                SetSelectedRowCore(rowIndex, true); 
                            }
                            rowIndex++; 
                        }
                        break;
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    { 
                        int columnIndex = 0, maxColumnIndex = this.Columns.Count;
                        while (columnIndex < maxColumnIndex) 
                        {
                            if (!this.Columns[columnIndex].Selected)
                            {
                                SetSelectedColumnCore(columnIndex, true); 
                            }
                            columnIndex++; 
                        } 
                        break;
                    } 
                }
            }
            finally
            { 
                this.noDimensionChangeCount--;
                this.noSelectionChangeCount--; 
                Debug.Assert(this.noDimensionChangeCount >= 0); 
                Debug.Assert(this.noSelectionChangeCount >= 0);
                ExitBulkPaint(-1, -1); 
            }

            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
            if (dataGridViewColumn != null && firstVisibleRowIndex != -1)
            { 
                // This is the only place in the code outside of SetCurrentCellAddressCore where this.ptAnchorCell gets changed. 
                // There is no way in SetCurrentCellAddressCore to just change the anchor cell.
                this.ptAnchorCell.X = dataGridViewColumn.Index; 
                this.ptAnchorCell.Y = firstVisibleRowIndex;
            }
            else
            { 
                this.ptAnchorCell.X = -1;
                this.ptAnchorCell.Y = -1; 
            } 

            if (this.noSelectionChangeCount == 0) 
            {
                FlushSelectionChanged();
            }
        } 

        private DataGridViewCell SelectedCell(int index) 
        { 
            Debug.Assert(index >= 0);
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.CellSelect:
                {
                    if (index < this.individualSelectedCells.Count) 
                    {
                        return this.individualSelectedCells[index]; 
                    } 
                    break;
                } 
                case DataGridViewSelectionMode.FullColumnSelect:
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                {
                    int selectedBand = 0, selectedBands = this.selectedBandIndexes.Count; 
                    while (selectedBand < selectedBands && index >= 0)
                    { 
                        if (index >= this.Rows.Count) 
                        {
                            index -= this.Rows.Count; 
                            selectedBand++;
                        }
                        else
                        { 
                            int columnIndex = this.selectedBandIndexes[selectedBand];
                            return this.Rows.SharedRow(index).Cells[columnIndex]; 
                        } 
                    }
 
                    if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect &&
                        index < this.individualSelectedCells.Count)
                    {
                        return this.individualSelectedCells[index]; 
                    }
                    break; 
                } 
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect: 
                {
                    int selectedBand = 0, selectedBands = this.selectedBandIndexes.Count;
                    while (selectedBand < selectedBands && index >= 0)
                    { 
                        if (index >= this.Columns.Count)
                        { 
                            index -= this.Columns.Count; 
                            selectedBand++;
                        } 
                        else
                        {
                            int rowIndex = this.selectedBandIndexes[selectedBand];
                            return this.Rows.SharedRow(rowIndex).Cells[index]; 
                        }
                    } 
 
                    if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect &&
                        index < this.individualSelectedCells.Count) 
                    {
                        return this.individualSelectedCells[index];
                    }
                    break; 
                }
            } 
            return null; 
        }
 
        private void SetColumnHeadersHeightInternal(int columnHeadersHeight, bool invalidInAdjustFillingColumns)
        {
            using (LayoutTransaction.CreateTransactionIf(this.AutoSize, this.ParentInternal, this, PropertyNames.ColumnHeadersHeight))
            { 
                Debug.Assert(this.columnHeadersHeight != columnHeadersHeight);
                Debug.Assert(columnHeadersHeight >= minimumColumnHeadersHeight); 
                Debug.Assert(columnHeadersHeight <= maxHeadersThickness); 
                this.columnHeadersHeight = columnHeadersHeight;
                if (this.AutoSize) 
                {
                    InvalidateInside();
                }
                else 
                {
                    if (this.layout.ColumnHeadersVisible) 
                    { 
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, true /*repositionEditingControl*/);
                        InvalidateInside(); 
                    }
                }
                OnColumnHeadersHeightChanged(EventArgs.Empty);
            } 
        }
 
        ///  
        protected virtual bool SetCurrentCellAddressCore(int columnIndex,
            int rowIndex, 
            bool setAnchorCellAddress,
            bool validateCurrentCell,
            bool throughMouseClick)
        { 
            if (columnIndex < -1 ||
                (columnIndex >= 0 && rowIndex == -1) || 
                columnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("columnIndex"); 
            }
            if (rowIndex < -1 ||
                (columnIndex == -1 && rowIndex >= 0) ||
                rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            } 

            if (columnIndex > -1 && 
                rowIndex > -1 &&
                !IsSharedCellVisible(this.Rows.SharedRow(rowIndex).Cells[columnIndex], rowIndex))
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CurrentCellCannotBeInvisible)); 
            }
 
            if (this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] &&                      // Allow the code to be re-entrant only as a result of 
                (this.dataConnection == null || !this.dataConnection.ProcessingListChangedEvent))   // underlying data changing.
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_SetCurrentCellAddressCoreNotReentrant));
            }

            this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] = true; 
            try
            { 
                DataGridViewCell dataGridViewCellTmp = null; 

                if (columnIndex > -1) 
                {
                    Debug.Assert(rowIndex >= 0 &&
                        columnIndex < this.Columns.Count &&
                        rowIndex < this.Rows.Count); 

                    if (this.ptCurrentCell.X != columnIndex || this.ptCurrentCell.Y != rowIndex) 
                    { 
                        if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell])
                        { 
                            this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false;
                            this.ptCurrentCell.X = columnIndex;
                            this.ptCurrentCell.Y = rowIndex;
                            if (this.cachedEditingControl != null) 
                            {
                                this.editingControl = this.cachedEditingControl; 
                                ((IDataGridViewEditingControl)this.editingControl).EditingControlRowIndex = rowIndex; 
                                this.cachedEditingControl = null;
                                PositionEditingControl(true, true, false); 
                            }
                            OnCurrentCellChanged(EventArgs.Empty);
                            return true;
                        } 

                        DataGridViewCell currentCell; 
                        int oldCurrentCellX = this.ptCurrentCell.X; 
                        int oldCurrentCellY = this.ptCurrentCell.Y;
                        if (oldCurrentCellX >= 0) 
                        {
                            currentCell = this.CurrentCellInternal;
                            if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange,
                                        validateCurrentCell ? DataGridViewValidateCellInternal.Always : DataGridViewValidateCellInternal.Never /*validateCell*/, 
                                        validateCurrentCell /*fireCellLeave*/,
                                        false /*fireCellEnter*/, 
                                        validateCurrentCell && oldCurrentCellY != rowIndex /*fireRowLeave*/, 
                                        false /*fireRowEnter*/,
                                        false /*fireLeave*/, 
                                        this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/,
                                        false /*resetCurrentCell*/,
                                        false /*resetAnchorCell unused here*/))
                            { 
                                return false;
                            } 
                            if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                            {
                                currentCell = this.Rows.SharedRow(oldCurrentCellY).Cells[oldCurrentCellX]; 
                                if (currentCell.LeaveUnsharesRowInternal(oldCurrentCellY, throughMouseClick))
                                {
                                    currentCell = this.Rows[oldCurrentCellY].Cells[oldCurrentCellX]; // unsharing the current row
                                } 
                                currentCell.OnLeaveInternal(oldCurrentCellY, throughMouseClick);
                            } 
                            if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                            {
                                return false; 
                            }
                            if (oldCurrentCellY != rowIndex)
                            {
                                if (validateCurrentCell) 
                                {
                                    if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY)) 
                                    { 
                                        if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                        { 
                                            // Row validation was cancelled
                                            Debug.Assert(oldCurrentCellX == this.ptCurrentCell.X);
                                            Debug.Assert(oldCurrentCellY == this.ptCurrentCell.Y);
                                            OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); 
                                            if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                                            { 
                                                currentCell.OnEnterInternal(oldCurrentCellY, throughMouseClick); 
                                                OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);
                                            } 
                                        }
                                        return false;
                                    }
                                    if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                    } 
                                }
                            } 
                        }

                        this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] = false;
 
                        try
                        { 
                            if (oldCurrentCellY != rowIndex) 
                            {
                                //Tentatively commenting out for bug #321924 
                                //this.ptCurrentCell.X = -1;
                                //this.ptCurrentCell.Y = -1;
                                //OnCurrentCellChanged(EventArgs.Empty);
                                if (!IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
                                {
                                    OnRowEnter(ref dataGridViewCellTmp, columnIndex, rowIndex, true /*canCreateNewRow*/, false /*validationFailureOccurred*/); 
                                } 
                            }
 
                            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell])
                            {
                                //
                                // The rows collection was cleared while processing OnRowEnter. 
                                // If the new list is too small for rowIndex, fail the call to SetCurrentCellAddressCore.
                                // 
                                if (rowIndex >= this.Rows.Count) 
                                {
                                    return false; 
                                }
                                // rowIndex = Math.Min(rowIndex, this.Rows.GetRowCount(DataGridViewElementStates.Visible) - 1);
                            }
 
                            if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                            { 
                                return false; 
                            }
 
                            this.ptCurrentCell.X = columnIndex;
                            this.ptCurrentCell.Y = rowIndex;
                            if (this.editingControl != null)
                            { 
                                ((IDataGridViewEditingControl)this.editingControl).EditingControlRowIndex = rowIndex;
                            } 
                            OnCurrentCellChanged(EventArgs.Empty); 
                            if (setAnchorCellAddress)
                            { 
                                this.ptAnchorCell.X = columnIndex;
                                this.ptAnchorCell.Y = rowIndex;
                            }
 
                            #if FALSE
                            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell]) 
                            { 
                                // DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell bit will be cleared while executing the
                                // "finally" block. 
                                return true;
                            }
                            #endif
 
                            currentCell = this.CurrentCellInternal;
                            if (currentCell.EnterUnsharesRowInternal(rowIndex, throughMouseClick)) 
                            { 
                                currentCell = this.Rows[rowIndex].Cells[columnIndex]; // unsharing the row
                            } 
                            currentCell.OnEnterInternal(rowIndex, throughMouseClick);
                            OnCellEnter(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y);
                            if (oldCurrentCellX >= 0)
                            { 
                                Debug.Assert(oldCurrentCellY >= 0);
                                if (oldCurrentCellX < this.Columns.Count && oldCurrentCellY < this.Rows.Count) 
                                { 
                                    InvalidateCellPrivate(oldCurrentCellX, oldCurrentCellY);
                                } 
                                if (oldCurrentCellY != this.ptCurrentCell.Y && this.RowHeadersVisible && oldCurrentCellY < this.Rows.Count)
                                {
                                    InvalidateCellPrivate(-1, oldCurrentCellY);
                                } 
                            }
                            InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); 
                            if (this.RowHeadersVisible && oldCurrentCellY != this.ptCurrentCell.Y) 
                            {
                                InvalidateCellPrivate(-1, this.ptCurrentCell.Y); 
                            }
                            if (this.Focused &&
                                this.ptCurrentCell.X != -1 &&
                                !this.IsCurrentCellInEditMode && 
                                !this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] &&      // don't edit if the rows collection changed
                                (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                                (this.EditMode != DataGridViewEditMode.EditProgrammatically && currentCell.EditType == null))) 
                            {
                                BeginEditInternal(true /*selectAll*/); 
                            }
                        }
                        finally
                        { 
                            this.dataGridViewState2[DATAGRIDVIEWSTATE2_rowsCollectionClearedInSetCell] = false;
                        } 
 
                        // Accessibility
                        if (this.ptCurrentCell.X != -1) 
                        {
                            AccessibilityNotifyCurrentCellChanged(new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y));
                        }
                    } 
                    else
                    { 
                        // this.ptCurrentCell.X == columnIndex && this.ptCurrentCell.Y == rowIndex 
                        // Not trying to change the current cell, but may need to edit it.
                        if (setAnchorCellAddress) 
                        {
                            this.ptAnchorCell.X = columnIndex;
                            this.ptAnchorCell.Y = rowIndex;
                        } 
                        if (this.Focused &&
                            (!this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter || 
                            (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)))) 
                        {
                            BeginEditInternal(true /*selectAll*/); 
                        }
                        else
                        {
                            CorrectFocus(false /*onlyIfGridHasFocus*/); 
                        }
                    } 
                } 
                else
                { 
                    int oldCurrentCellX = this.ptCurrentCell.X;
                    int oldCurrentCellY = this.ptCurrentCell.Y;
                    if (oldCurrentCellX >= 0 &&
                        !this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] && 
                        !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose])
                    { 
                        DataGridViewCell currentCell = this.CurrentCellInternal; 
                        if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange,
                                    validateCurrentCell ? DataGridViewValidateCellInternal.Always : DataGridViewValidateCellInternal.Never, 
                                    validateCurrentCell /*fireCellLeave*/,
                                    false /*fireCellEnter*/,
                                    validateCurrentCell /*fireRowLeave*/,
                                    false /*fireRowEnter*/, 
                                    false /*fireLeave*/,
                                    this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/, 
                                    false /*resetCurrentCell*/, 
                                    false /*resetAnchorCell unused here*/))
                        { 
                            return false;
                        }
                        if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                        { 
                            currentCell = this.Rows.SharedRow(oldCurrentCellY).Cells[oldCurrentCellX];
                            if (currentCell.LeaveUnsharesRowInternal(oldCurrentCellY, throughMouseClick)) 
                            { 
                                currentCell = this.Rows[oldCurrentCellY].Cells[oldCurrentCellX]; // unsharing the current row
                            } 
                            currentCell.OnLeaveInternal(oldCurrentCellY, throughMouseClick);
                        }
                        if (validateCurrentCell)
                        { 
                            if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY))
                            { 
                                if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                {
                                    // Row validation was cancelled 
                                    Debug.Assert(oldCurrentCellX == this.ptCurrentCell.X);
                                    Debug.Assert(oldCurrentCellY == this.ptCurrentCell.Y);
                                    OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/);
                                    if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) 
                                    {
                                        currentCell.OnEnterInternal(oldCurrentCellY, throughMouseClick); 
                                        OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); 
                                    }
                                } 
                                return false;
                            }
                            if (!IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY))
                            { 
                                OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY);
                            } 
                        } 
                    }
                    if (this.ptCurrentCell.X != -1) 
                    {
                        this.ptCurrentCell.X = -1;
                        this.ptCurrentCell.Y = -1;
                        OnCurrentCellChanged(EventArgs.Empty); 
                    }
                    if (setAnchorCellAddress) 
                    { 
                        this.ptAnchorCell.X = -1;
                        this.ptAnchorCell.Y = -1; 
                    }
                    if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell])
                    {
                        if (this.editingControl != null) 
                        {
                            if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_discardEditingControl]) 
                            { 
                                this.dataGridViewState2[DATAGRIDVIEWSTATE2_discardEditingControl] = false;
                            } 
                            else
                            {
                                this.cachedEditingControl = this.editingControl;
                            } 
                            this.editingControl = null;
                        } 
                    } 
                    else if (oldCurrentCellX >= 0 && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose])
                    { 
                        Debug.Assert(oldCurrentCellY >= 0);
                        if (oldCurrentCellX < this.Columns.Count && oldCurrentCellY < this.Rows.Count)
                        {
                            InvalidateCellPrivate(oldCurrentCellX, oldCurrentCellY); 
                        }
                        if (this.RowHeadersVisible && oldCurrentCellY < this.Rows.Count) 
                        { 
                            InvalidateCellPrivate(-1, oldCurrentCellY);
                        } 
                    }
                }
            }
            finally 
            {
                this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] = false; 
            } 
            return true;
        } 

        internal void SetCurrentCellAddressCoreInternal(int columnIndex,
            int rowIndex,
            bool setAnchorCellAddress, 
            bool validateCurrentCell,
            bool throughMouseClick) 
        { 
            SetCurrentCellAddressCore(columnIndex, rowIndex, setAnchorCellAddress, validateCurrentCell, throughMouseClick);
        } 

        private void SelectCellRange(int columnIndexFrom, int rowIndexFrom, int columnIndexTo, int rowIndexTo, bool select)
        {
            Debug.Assert(columnIndexFrom >= 0 && columnIndexTo >= 0); 
            Debug.Assert((this.Columns[columnIndexFrom]).DisplayIndex <= (this.Columns[columnIndexTo]).DisplayIndex);
            Debug.Assert(rowIndexFrom >= 0 && rowIndexTo >= 0); 
            Debug.Assert(rowIndexFrom <= rowIndexTo); 
            Debug.Assert(this.noSelectionChangeCount > 0);
 
            bool switchedToBulkPaint = false;
            if (rowIndexTo - rowIndexFrom > DATAGRIDVIEW_bulkPaintThreshold)
            {
                // Switch to batch operation 
                this.inBulkPaintCount++;
                switchedToBulkPaint = true; 
            } 
            try
            { 
                // Selection and deselection are done in reverse order for perf. reasons.
                if (select)
                {
                    int columnIndex = columnIndexFrom; 
                    do
                    { 
                        for (int rowIndex = rowIndexFrom; rowIndex <= rowIndexTo; rowIndex++) 
                        {
                            SetSelectedCellCore(columnIndex, rowIndex, true); 
                        }
                        if (columnIndex != columnIndexTo)
                        {
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[columnIndex], 
                                DataGridViewElementStates.Visible,
                                DataGridViewElementStates.None); 
                            Debug.Assert(dataGridViewColumn != null); 
                            columnIndex = dataGridViewColumn.Index;
                        } 
                    }
                    while (columnIndex != columnIndexTo);

                    if (columnIndexFrom != columnIndexTo) 
                    {
                        for (int rowIndex = rowIndexFrom; rowIndex <= rowIndexTo; rowIndex++) 
                        { 
                            SetSelectedCellCore(columnIndex, rowIndex, true);
                        } 
                    }
                }
                else
                { 
                    int columnIndex = columnIndexTo;
                    do 
                    { 
                        for (int rowIndex = rowIndexTo; rowIndex >= rowIndexFrom; rowIndex--)
                        { 
                            SetSelectedCellCore(columnIndex, rowIndex, false);
                        }
                        if (columnIndex != columnIndexFrom)
                        { 
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[columnIndex],
                                DataGridViewElementStates.Visible, 
                                DataGridViewElementStates.None); 
                            Debug.Assert(dataGridViewColumn != null);
                            columnIndex = dataGridViewColumn.Index; 
                        }
                    }
                    while (columnIndex != columnIndexFrom);
 
                    if (columnIndexFrom != columnIndexTo)
                    { 
                        for (int rowIndex = rowIndexTo; rowIndex >= rowIndexFrom; rowIndex--) 
                        {
                            SetSelectedCellCore(columnIndex, rowIndex, false); 
                        }
                    }
                }
            } 
            finally
            { 
                if (switchedToBulkPaint) 
                {
                    ExitBulkPaint(-1, -1); 
                }
            }
        }
 
        private void SelectCellUnorderedRange(int columnIndexFrom, int rowIndexFrom, int columnIndexTo, int rowIndexTo, bool select)
        { 
            Debug.Assert(this.noSelectionChangeCount > 0); 
            int columnIndexFromTmp, rowIndexFromTmp, columnIndexToTmp, rowIndexToTmp;
 
            if (this.Columns.DisplayInOrder(columnIndexFrom, columnIndexTo))
            {
                columnIndexFromTmp = columnIndexFrom;
                columnIndexToTmp = columnIndexTo; 
            }
            else 
            { 
                columnIndexFromTmp = columnIndexTo;
                columnIndexToTmp = columnIndexFrom; 
            }

            if (rowIndexFrom < rowIndexTo)
            { 
                rowIndexFromTmp = rowIndexFrom;
                rowIndexToTmp = rowIndexTo; 
            } 
            else
            { 
                rowIndexFromTmp = rowIndexTo;
                rowIndexToTmp = rowIndexFrom;
            }
 
            SelectCellRange(columnIndexFromTmp, rowIndexFromTmp, columnIndexToTmp, rowIndexToTmp, select);
        } 
 
        private void SelectColumnRange(int columnIndexFrom, int columnIndexTo, bool select)
        { 
            Debug.Assert(columnIndexFrom >= 0 && columnIndexTo >= 0);
            Debug.Assert((this.Columns[columnIndexFrom]).DisplayIndex <= (this.Columns[columnIndexTo]).DisplayIndex);
            Debug.Assert(this.noSelectionChangeCount > 0);
 
            int columnIndex = columnIndexFrom;
            do 
            { 
                if (select)
                { 
                    if (!this.selectedBandIndexes.Contains(columnIndex))
                    {
                        SetSelectedColumnCore(columnIndex, true);
                    } 
                }
                else 
                { 
                    Debug.Assert(this.selectedBandIndexes.Contains(columnIndex));
                    SetSelectedColumnCore(columnIndex, false); 
                }
                if (columnIndex != columnIndexTo)
                {
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[columnIndex], 
                        DataGridViewElementStates.Visible,
                        DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null); 
                    columnIndex = dataGridViewColumn.Index;
                } 
            }
            while (columnIndex != columnIndexTo);

            if (columnIndexFrom != columnIndexTo) 
            {
                if (select) 
                { 
                    if (!this.selectedBandIndexes.Contains(columnIndexTo))
                    { 
                        SetSelectedColumnCore(columnIndexTo, true);
                    }
                }
                else 
                {
                    Debug.Assert(this.selectedBandIndexes.Contains(columnIndexTo)); 
                    SetSelectedColumnCore(columnIndexTo, false); 
                }
            } 
        }

        private void SelectRowRange(int rowIndexFrom, int rowIndexTo, bool select)
        { 
            Debug.Assert(rowIndexFrom >= 0 && rowIndexTo >= 0);
            Debug.Assert(rowIndexFrom <= rowIndexTo); 
            Debug.Assert(this.noSelectionChangeCount > 0); 

            bool switchedToBulkPaint = false; 
            if (rowIndexTo - rowIndexFrom > DATAGRIDVIEW_bulkPaintThreshold)
            {
                // Switch to batch operation
                this.inBulkPaintCount++; 
                switchedToBulkPaint = true;
            } 
            try 
            {
                // Selecting and deselecting rows in reverse order for perf. reasons 
                if (select)
                {
                    for (int rowIndex = rowIndexFrom; rowIndex <= rowIndexTo; rowIndex++)
                    { 
                        if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) == 0)
                        { 
                            Debug.Assert(!this.selectedBandIndexes.Contains(rowIndex)); 
                            SetSelectedRowCore(rowIndex, true);
                        } 
                    }
                }
                else
                { 
                    for (int rowIndex = rowIndexTo; rowIndex >= rowIndexFrom; rowIndex--)
                    { 
                        Debug.Assert(this.selectedBandIndexes.Contains(rowIndex)); 
                        SetSelectedRowCore(rowIndex, false);
                    } 
                }
            }
            finally
            { 
                if (switchedToBulkPaint)
                { 
                    ExitBulkPaint(-1, -1); 
                }
            } 
        }

        private bool SetAndSelectCurrentCellAddress(int columnIndex,
            int rowIndex, 
            bool setAnchorCellAddress,
            bool validateCurrentCell, 
            bool throughMouseClick, 
            bool clearSelection,
            bool forceCurrentCellSelection) 
        {
            if (!SetCurrentCellAddressCore(columnIndex, rowIndex, setAnchorCellAddress, validateCurrentCell, throughMouseClick))
            {
                return false; 
            }
            if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) 
            { 
                return false;
            } 
            if (clearSelection)
            {
                ClearSelection(columnIndex, rowIndex, true /*selectException*/);    // we always select the new current cell when clearSelection is true
            } 
            else
            { 
                if (forceCurrentCellSelection) 
                {
                    SetSelectedElementCore(columnIndex, rowIndex, true); 
                }
                else
                {
                    if (this.MultiSelect && (this.individualSelectedCells.Count + this.selectedBandIndexes.Count) > 1) 
                    {
                        return true;   // Do not discard the multi-selection 
                    } 
                    if (this.individualSelectedCells.Count == 1)
                    { 
                        DataGridViewCell dataGridViewCell = this.individualSelectedCells.HeadCell;
                        if (dataGridViewCell.ColumnIndex != columnIndex || dataGridViewCell.RowIndex != rowIndex)
                        {
                            return true; 
                        }
                    } 
                    else if (this.selectedBandIndexes.Count == 1) 
                    {
                        switch (this.SelectionMode) 
                        {
                            case DataGridViewSelectionMode.FullColumnSelect:
                            case DataGridViewSelectionMode.ColumnHeaderSelect:
                            { 
                                if (this.selectedBandIndexes.HeadInt != columnIndex)
                                { 
                                    return true;  // Do not change a single selection that does not match the new current cell 
                                }
                                break; 
                            }
                            case DataGridViewSelectionMode.FullRowSelect:
                            case DataGridViewSelectionMode.RowHeaderSelect:
                            { 
                                if (this.selectedBandIndexes.HeadInt != rowIndex)
                                { 
                                    return true;  // Do not change a single selection that does not match the new current cell 
                                }
                                break; 
                            }
                        }
                    }
                    SetSelectedElementCore(columnIndex, rowIndex, true); 
                }
            } 
            return true; 
        }
 
        /// 
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        {
            if ((specified & BoundsSpecified.Width) == BoundsSpecified.Width && width > upperSize) { 
                throw new ArgumentOutOfRangeException("width", width, SR.GetString(SR.DataGridView_SizeTooLarge, (upperSize).ToString(CultureInfo.CurrentCulture)));
            } 
            if ((specified & BoundsSpecified.Height) == BoundsSpecified.Height && height > upperSize) { 
                throw new ArgumentOutOfRangeException("height", height, SR.GetString(SR.DataGridView_SizeTooLarge, (upperSize).ToString(CultureInfo.CurrentCulture)));
            } 
            base.SetBoundsCore(x, y, width, height, specified);
        }

        [ 
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ] 
        internal void SetReadOnlyCellCore(int columnIndex, int rowIndex, bool readOnly) 
        {
            Debug.Assert(columnIndex >= 0 && rowIndex >= 0 && 
                columnIndex < this.Columns.Count &&
                rowIndex < this.Rows.Count);

            // cell's readonly state changes 
            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if (IsSharedCellReadOnly(dataGridViewRow.Cells[columnIndex], rowIndex) != readOnly) 
            {
                DataGridViewCell dataGridViewCell = this.Rows[rowIndex].Cells[columnIndex]; 
                if (readOnly)
                {
                    if ((rowState & DataGridViewElementStates.ReadOnly) == 0 &&
                        !this.Columns[columnIndex].ReadOnly) 
                    {
                        this.individualReadOnlyCells.Add(dataGridViewCell); 
                        dataGridViewCell.ReadOnlyInternal = true; 
                    }
                } 
                else
                {
                    if (this.individualReadOnlyCells.Contains(dataGridViewCell))
                    { 
                        this.individualReadOnlyCells.Remove(dataGridViewCell);
                    } 
                    else 
                    {
                        DataGridViewCell dataGridViewCellTmp; 
                        if (this.Columns[columnIndex].ReadOnly)
                        {
                            this.Columns[columnIndex].ReadOnlyInternal = false;
                            // Perf Issue: this unshares all rows! 
                            for (int row = 0; row < rowIndex; row++)
                            { 
                                dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                dataGridViewCellTmp.ReadOnlyInternal = true;
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            }
                            for (int row = rowIndex+1; row < this.Rows.Count; row++)
                            {
                                dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                dataGridViewCellTmp.ReadOnlyInternal = true;
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            } 
                        }
                        if ((rowState & DataGridViewElementStates.ReadOnly) != 0) 
                        {
                            this.Rows.SetRowState(rowIndex, DataGridViewElementStates.ReadOnly, false);
                            for (int column = 0; column < columnIndex; column++)
                            { 
                                dataGridViewCellTmp = this.Rows[rowIndex].Cells[column];
                                dataGridViewCellTmp.ReadOnlyInternal = true; 
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            }
                            for (int column = columnIndex+1; column < this.Columns.Count; column++) 
                            {
                                dataGridViewCellTmp = this.Rows[rowIndex].Cells[column];
                                dataGridViewCellTmp.ReadOnlyInternal = true;
                                this.individualReadOnlyCells.Add(dataGridViewCellTmp); 
                            }
                        } 
                    } 
                    if (dataGridViewCell.ReadOnly)
                    { 
                        dataGridViewCell.ReadOnlyInternal = false;
                    }
                }
            } 
        }
 
        internal void SetReadOnlyColumnCore(int columnIndex, bool readOnly) 
        {
            Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); 

            if (this.Columns[columnIndex].ReadOnly != readOnly)
            {
                // ReadOnly state of entire column changes 
                if (readOnly)
                { 
                    // column is made read-only 
                    // remove individual read-only cells of this column
                    try 
                    {
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = true;
                        RemoveIndividualReadOnlyCellsInColumn(columnIndex);
                    } 
                    finally
                    { 
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = false; 
                    }
                    this.Columns[columnIndex].ReadOnlyInternal = true; 
                }
                else
                {
                    // column is made read-write 
                    this.Columns[columnIndex].ReadOnlyInternal = false;
                } 
            } 
            else if (!readOnly)
            { 
                // remove any potentially individual read-only cells in the column
                RemoveIndividualReadOnlyCellsInColumn(columnIndex);
            }
        } 

        internal void SetReadOnlyRowCore(int rowIndex, bool readOnly) 
        { 
            Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count);
 
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
            if (((rowState & DataGridViewElementStates.ReadOnly) != 0) != readOnly)
            {
                // ReadOnly state of entire row changes 
                if (readOnly)
                { 
                    // row is made read-only 
                    // first remove individual read-only cells of this row
                    try 
                    {
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = true;
                        RemoveIndividualReadOnlyCellsInRow(rowIndex);
                    } 
                    finally
                    { 
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange] = false; 
                    }
                    this.Rows.SetRowState(rowIndex, DataGridViewElementStates.ReadOnly, true); 
                }
                else
                {
                    // row is made read-write 
                    this.Rows.SetRowState(rowIndex, DataGridViewElementStates.ReadOnly, false);
                } 
            } 
            else if (!readOnly)
            { 
                // remove any potentially individual read-only cells in the row
                RemoveIndividualReadOnlyCellsInRow(rowIndex);
            }
        } 

        ///  
        [ 
            SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report.
        ] 
        protected virtual void SetSelectedCellCore(int columnIndex, int rowIndex, bool selected)
        {
            if (columnIndex < 0 || columnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("columnIndex");
            } 
 
            if (rowIndex < 0 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex");
            }

            // cell selection changes 
            DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex);
            DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); 
            if (IsSharedCellSelected(dataGridViewRow.Cells[columnIndex], rowIndex) != selected) 
            {
                DataGridViewCell dataGridViewCell = this.Rows[rowIndex].Cells[columnIndex]; 
                if (selected)
                {
                    if ((rowState & DataGridViewElementStates.Selected) == 0 &&
                        !this.Columns[columnIndex].Selected) 
                    {
                        this.individualSelectedCells.Add(dataGridViewCell); 
                        dataGridViewCell.SelectedInternal = true; 
                    }
                } 
                else
                {
                    if ((dataGridViewCell.State & DataGridViewElementStates.Selected) != 0)
                    { 
                        Debug.Assert(this.individualSelectedCells.Contains(dataGridViewCell));
                        this.individualSelectedCells.Remove(dataGridViewCell); 
                    } 
                    else
                    { 
                        DataGridViewCell dataGridViewCellTmp;
                        bool switchedToBulkPaint = false;
                        if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)
                        { 
                            if (this.Rows.Count > DATAGRIDVIEW_bulkPaintThreshold)
                            { 
                                this.inBulkPaintCount++; 
                                switchedToBulkPaint = true;
                            } 
                            try
                            {
                                Debug.Assert(this.selectedBandIndexes.Contains(columnIndex));
                                this.selectedBandIndexes.Remove(columnIndex); 
                                this.Columns[columnIndex].SelectedInternal = false;
                                // Perf Issue: this unshares all rows! 
                                for (int row = 0; row < rowIndex; row++) 
                                {
                                    dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                    dataGridViewCellTmp.SelectedInternal = true;
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                }
                                for (int row = rowIndex+1; row < this.Rows.Count; row++) 
                                {
                                    dataGridViewCellTmp = this.Rows[row].Cells[columnIndex]; 
                                    dataGridViewCellTmp.SelectedInternal = true; 
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                } 
                            }
                            finally
                            {
                                if (switchedToBulkPaint) 
                                {
                                    ExitBulkPaint(columnIndex, -1); 
                                } 
                            }
                        } 
                        else if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                        {
                            if (this.Columns.Count > DATAGRIDVIEW_bulkPaintThreshold)
                            { 
                                this.inBulkPaintCount++;
                                switchedToBulkPaint = true; 
                            } 
                            try
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(rowIndex));
                                this.selectedBandIndexes.Remove(rowIndex);
                                this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Selected, false);
                                for (int column = 0; column < columnIndex; column++) 
                                {
                                    dataGridViewCellTmp = this.Rows[rowIndex].Cells[column]; 
                                    dataGridViewCellTmp.SelectedInternal = true; 
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                } 
                                for (int column = columnIndex+1; column < this.Columns.Count; column++)
                                {
                                    dataGridViewCellTmp = this.Rows[rowIndex].Cells[column];
                                    dataGridViewCellTmp.SelectedInternal = true; 
                                    this.individualSelectedCells.Add(dataGridViewCellTmp);
                                } 
                            } 
                            finally
                            { 
                                if (switchedToBulkPaint)
                                {
                                    ExitBulkPaint(-1, rowIndex);
                                } 
                            }
                        } 
                    } 
                    if (dataGridViewCell.Selected)
                    { 
                        dataGridViewCell.SelectedInternal = false;
                    }
                }
            } 
        }
 
        internal void SetSelectedCellCoreInternal(int columnIndex, int rowIndex, bool selected) 
        {
            if (selected && !this.MultiSelect) 
            {
                if (!this.Columns[columnIndex].Visible ||
                    (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) == 0)
                { 
                    throw new InvalidOperationException(SR.GetString(SR.DataGridView_CurrentCellCannotBeInvisible));
                } 
 
                if (!ScrollIntoView(columnIndex, rowIndex, true))
                { 
                    return;
                }
                if (IsInnerCellOutOfBounds(columnIndex, rowIndex))
                { 
                    return;
                } 
            } 

            this.noSelectionChangeCount++; 
            try
            {
                switch (this.SelectionMode)
                { 
                    case DataGridViewSelectionMode.CellSelect:
                    { 
                        if (selected && !this.MultiSelect) 
                        {
                            Debug.Assert(this.individualSelectedCells.Count <= 1); 
                            RemoveIndividuallySelectedCells();
                        }
                        SetSelectedCellCore(columnIndex, rowIndex, selected);
                        break; 
                    }
 
                    case DataGridViewSelectionMode.FullColumnSelect: 
                    {
                        if (selected) 
                        {
                            if (!this.MultiSelect)
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1); 
                                int bandIndex = 0;
                                while (bandIndex < this.selectedBandIndexes.Count) 
                                { 
                                    if (this.selectedBandIndexes[bandIndex] != columnIndex)
                                    { 
                                        // deselect currently selected column
                                        SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false);
                                    }
                                    else 
                                    {
                                        bandIndex++; 
                                    } 
                                }
                            } 
                            if (!this.selectedBandIndexes.Contains(columnIndex))
                            {
                                SetSelectedColumnCore(columnIndex, true);
                            } 
                        }
                        else 
                        { 
                            if (this.selectedBandIndexes.Contains(columnIndex))
                            { 
                                SetSelectedColumnCore(columnIndex, false);
                            }
                        }
                        break; 
                    }
 
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                    {
                        if (selected) 
                        {
                            if (!this.MultiSelect)
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1); 
                                if (this.selectedBandIndexes.Count > 0)
                                { 
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); 
                                }
                                else 
                                {
                                    RemoveIndividuallySelectedCells();
                                }
                            } 
                            SetSelectedCellCore(columnIndex, rowIndex, true);
                        } 
                        else 
                        {
                            if (!this.MultiSelect) 
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0)
                                { 
                                    SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false);
                                } 
                                else 
                                {
                                    SetSelectedCellCore(columnIndex, rowIndex, false); 
                                }
                            }
                            else
                            { 
                                SetSelectedCellCore(columnIndex, rowIndex, false);
                            } 
                        } 
                        break;
                    } 

                    case DataGridViewSelectionMode.FullRowSelect:
                    {
                        if (selected) 
                        {
                            if (!this.MultiSelect) 
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                int bandIndex = 0; 
                                while (bandIndex < this.selectedBandIndexes.Count)
                                {
                                    if (this.selectedBandIndexes[bandIndex] != rowIndex)
                                    { 
                                        // deselect currently selected row
                                        SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false); 
                                    } 
                                    else
                                    { 
                                        bandIndex++;
                                    }
                                }
                            } 
                            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) == 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(rowIndex) == 
                                             ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0));
                                SetSelectedRowCore(rowIndex, true); 
                            }
                        }
                        else
                        { 
                            if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Contains(rowIndex) == 
                                             ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0));
                                SetSelectedRowCore(rowIndex, false); 
                            }
                        }
                        break;
                    } 

                    case DataGridViewSelectionMode.RowHeaderSelect: 
                    { 
                        if (selected)
                        { 
                            if (!this.MultiSelect)
                            {
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0) 
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); 
                                } 
                                else
                                { 
                                    RemoveIndividuallySelectedCells();
                                }
                            }
                            SetSelectedCellCore(columnIndex, rowIndex, true); 
                        }
                        else 
                        { 
                            if (!this.MultiSelect)
                            { 
                                Debug.Assert(this.selectedBandIndexes.Count <= 1);
                                if (this.selectedBandIndexes.Count > 0)
                                {
                                    SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); 
                                }
                                else 
                                { 
                                    SetSelectedCellCore(columnIndex, rowIndex, false);
                                } 
                            }
                            else
                            {
                                SetSelectedCellCore(columnIndex, rowIndex, false); 
                            }
                        } 
                        break; 
                    }
                } 
            }
            finally
            {
                this.NoSelectionChangeCount--; 
            }
 
            if (selected && !this.MultiSelect) 
            {
                bool success = SetCurrentCellAddressCore(columnIndex, rowIndex, true, false, true); 
                Debug.Assert(success);
            }
        }
 
        /// 
        protected virtual void SetSelectedColumnCore(int columnIndex, bool selected) 
        { 
            if (columnIndex < 0 || columnIndex >= this.Columns.Count)
            { 
                throw new ArgumentOutOfRangeException("columnIndex");
            }

            this.noSelectionChangeCount++; 
            try
            { 
                if (this.Columns[columnIndex].Selected != selected) 
                {
                    // selection of entire column changes 
                    if (selected)
                    {
                        // column is selected
                        // remove individually selected cells of this column 
                        RemoveIndividuallySelectedCellsInColumn(columnIndex);
                        this.Columns[columnIndex].SelectedInternal = true; 
                        Debug.Assert(!this.selectedBandIndexes.Contains(columnIndex)); 
                        this.selectedBandIndexes.Add(columnIndex);
                    } 
                    else
                    {
                        // column is deselected
                        Debug.Assert(this.selectedBandIndexes.Contains(columnIndex)); 
                        this.Columns[columnIndex].SelectedInternal = false;
                        this.selectedBandIndexes.Remove(columnIndex); 
                    } 
                }
                else if (!selected) 
                {
                    // remove any potentially individually selected cells in the column
                    RemoveIndividuallySelectedCellsInColumn(columnIndex);
                } 
            }
            finally 
            { 
                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1);
                this.NoSelectionChangeCount--; 
            }
        }

        internal void SetSelectedColumnCoreInternal(int columnIndex, bool selected) 
        {
            this.noSelectionChangeCount++; 
            try 
            {
                if (!this.MultiSelect) 
                {
                    Debug.Assert(this.selectedBandIndexes.Count <= 1);
                    if (this.selectedBandIndexes.Count > 0)
                    { 
                        int columnIndexSelected = this.selectedBandIndexes.HeadInt;
                        if (columnIndexSelected != columnIndex) 
                        { 
                            SetSelectedColumnCore(columnIndexSelected, false);
                        } 
                    }
                }
                SetSelectedColumnCore(columnIndex, selected);
            } 
            finally
            { 
                this.NoSelectionChangeCount--; 
            }
        } 

        private void SetSelectedElementCore(int columnIndex, int rowIndex, bool selected)
        {
            switch (this.SelectionMode) 
            {
                case DataGridViewSelectionMode.CellSelect: 
                { 
                    SetSelectedCellCore(columnIndex, rowIndex, selected);
                    break; 
                }
                case DataGridViewSelectionMode.RowHeaderSelect:
                {
                    if (columnIndex == -1) 
                    {
                        SetSelectedRowCore(rowIndex, selected); 
                    } 
                    else
                    { 
                        SetSelectedCellCore(columnIndex, rowIndex, selected);
                    }
                    break;
                } 
                case DataGridViewSelectionMode.ColumnHeaderSelect:
                { 
                    if (rowIndex == -1) 
                    {
                        SetSelectedColumnCore(columnIndex, selected); 
                    }
                    else
                    {
                        SetSelectedCellCore(columnIndex, rowIndex, selected); 
                    }
                    break; 
                } 
                case DataGridViewSelectionMode.FullRowSelect:
                { 
                    SetSelectedRowCore(rowIndex, selected);
                    break;
                }
                case DataGridViewSelectionMode.FullColumnSelect: 
                {
                    SetSelectedColumnCore(columnIndex, selected); 
                    break; 
                }
            } 
        }

        /// 
        protected virtual void SetSelectedRowCore(int rowIndex, bool selected) 
        {
            if (rowIndex < 0 || rowIndex >= this.Rows.Count) 
            { 
                throw new ArgumentOutOfRangeException("rowIndex");
            } 

            this.noSelectionChangeCount++;
            try
            { 
                DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex);
                if (((rowState & DataGridViewElementStates.Selected) != 0) != selected) 
                { 
                    // selection of entire row changes
                    if (selected) 
                    {
                        // row is selected
                        // first remove individually selected cells of this row
                        RemoveIndividuallySelectedCellsInRow(rowIndex); 
                        Debug.Assert(!this.selectedBandIndexes.Contains(rowIndex));
                        this.selectedBandIndexes.Add(rowIndex); 
                        this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Selected, true); 
                    }
                    else 
                    {
                        // row is deselected
                        Debug.Assert(this.selectedBandIndexes.Contains(rowIndex));
                        this.selectedBandIndexes.Remove(rowIndex); 
                        this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Selected, false);
                    } 
                } 
                else if (!selected)
                { 
                    // remove any potentially individually selected cells in the row
                    RemoveIndividuallySelectedCellsInRow(rowIndex);
                }
            } 
            finally
            { 
                Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); 
                this.NoSelectionChangeCount--;
            } 
        }

        internal void SetSelectedRowCoreInternal(int rowIndex, bool selected)
        { 
            this.noSelectionChangeCount++;
            try 
            { 
                if (!this.MultiSelect)
                { 
                    Debug.Assert(this.selectedBandIndexes.Count <= 1);
                    if (this.selectedBandIndexes.Count > 0)
                    {
                        int rowIndexSelected = this.selectedBandIndexes.HeadInt; 
                        if (rowIndexSelected != rowIndex)
                        { 
                            SetSelectedRowCore(rowIndexSelected, false); 
                        }
                    } 
                }
                SetSelectedRowCore(rowIndex, selected);
            }
            finally 
            {
                this.NoSelectionChangeCount--; 
            } 
        }
 
        private bool ShouldSerializeAlternatingRowsDefaultCellStyle()
        {
            DataGridViewCellStyle defaultStyle = new DataGridViewCellStyle();
            return !this.AlternatingRowsDefaultCellStyle.Equals(defaultStyle); 
        }
 
        private bool ShouldSerializeColumnHeadersDefaultCellStyle() 
        {
            return !this.ColumnHeadersDefaultCellStyle.Equals(this.DefaultColumnHeadersDefaultCellStyle); 
        }

        private bool ShouldSerializeDefaultCellStyle()
        { 
            return !this.DefaultCellStyle.Equals(this.DefaultDefaultCellStyle);
        } 
 
        private bool ShouldSerializeRowHeadersDefaultCellStyle()
        { 
            return !this.RowHeadersDefaultCellStyle.Equals(this.DefaultRowHeadersDefaultCellStyle);
        }

        private bool ShouldSerializeRowsDefaultCellStyle() 
        {
            DataGridViewCellStyle defaultStyle = new DataGridViewCellStyle(); 
            return !this.RowsDefaultCellStyle.Equals(defaultStyle); 
        }
 
        /// 
        public virtual void Sort(DataGridViewColumn dataGridViewColumn, ListSortDirection direction)
        {
            if (dataGridViewColumn == null) 
            {
                throw new ArgumentNullException("dataGridViewColumn"); 
            } 

            if (direction != ListSortDirection.Ascending && direction != ListSortDirection.Descending) 
            {
                throw new InvalidEnumArgumentException("direction", (int)direction, typeof(ListSortDirection));
            }
 
            if (dataGridViewColumn.DataGridView != this)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); 
            }
 
            if (this.VirtualMode && !dataGridViewColumn.IsDataBound)
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_OperationDisabledInVirtualMode));
            } 

            SortInternal(null, dataGridViewColumn, direction); 
        } 

        ///  
        public virtual void Sort(IComparer comparer)
        {
            if (comparer == null)
            { 
                throw new ArgumentNullException("comparer");
            } 
 
            if (this.VirtualMode)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_OperationDisabledInVirtualMode));
            }

            // can't sort a data bound dataGridView control using a comparer 
            if (this.DataSource != null)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotUseAComparerToSortDataGridViewWhenDataBound)); 
            }
 
            SortInternal(comparer, null, ListSortDirection.Ascending);
        }

        private void SortDataBoundDataGridView_PerformCheck(DataGridViewColumn dataGridViewColumn) 
        {
            IBindingList ibl = this.dataConnection.List as IBindingList; 
            if (ibl == null) 
            {
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotSortDataBoundDataGridViewBoundToNonIBindingList)); 
            }

            if (!ibl.SupportsSorting)
            { 
                throw new InvalidOperationException(SR.GetString(SR.DataGridView_IBindingListNeedsToSupportSorting));
            } 
 
            if (!dataGridViewColumn.IsDataBound)
            { 
                throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnNeedsToBeDataBoundWhenSortingDataBoundDataGridView), "dataGridViewColumn");
            }
        }
 
        private void SortInternal(IComparer comparer, DataGridViewColumn dataGridViewColumn, ListSortDirection direction)
        { 
            Debug.Assert(!(comparer != null && this.DataSource != null)); 
            Debug.Assert(direction == ListSortDirection.Ascending || direction == ListSortDirection.Descending);
 
            // Exit editing mode if needed
            this.ptCurrentCellCache.X = this.ptCurrentCell.X;
            this.ptCurrentCellCache.Y = this.ptCurrentCell.Y;
            this.dataGridViewOper[DATAGRIDVIEWOPER_inSort] = true; 
            try
            { 
                if (!SetCurrentCellAddressCore(-1, -1, true, true, false)) 
                {
                    // Just cancel operation silently instead of throwing InvalidOperationException 
                    // 'finally' below resets this.dataGridViewOper[DATAGRIDVIEWOPER_inSort] to false
                    return;
                }
 
                int firstDisplayedScrollingRowCache = this.displayedBandsInfo.FirstDisplayedScrollingRow;
                int visibleFrozenRows = this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                if (visibleFrozenRows > 0 && this.DataSource == null) 
                {
                    int rowVFIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    Debug.Assert(rowVFIndex != -1);
                    this.Rows.SetRowState(rowVFIndex, DataGridViewElementStates.Frozen, false);
                    Debug.Assert(0 == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen));
                } 

                if (this.sortedColumn != null && 
                    this.sortedColumn.SortMode == DataGridViewColumnSortMode.Automatic && 
                    this.sortedColumn.HasHeaderCell)
                { 
                    this.sortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
                }

                if (comparer == null) 
                {
                    Debug.Assert(dataGridViewColumn != null); 
                    this.sortedColumn = dataGridViewColumn; 
                    this.sortOrder = (direction == ListSortDirection.Ascending) ? SortOrder.Ascending : SortOrder.Descending;
                    if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && dataGridViewColumn.HasHeaderCell) 
                    {
                        dataGridViewColumn.HeaderCell.SortGlyphDirection = this.sortOrder;
                    }
                } 
                else
                { 
                    this.sortedColumn = null; 
                    this.sortOrder = SortOrder.None;
                } 

                if (this.DataSource == null)
                {
                    // Displayed rows may end up all spread out in the final layout. 
                    // So we simply reset their displayed state before the sort.
                    UpdateRowsDisplayedState(false /*displayed*/); 
                    this.Rows.Sort(comparer, direction == ListSortDirection.Ascending); 
                }
                else 
                {
                    SortDataBoundDataGridView_PerformCheck(dataGridViewColumn);
                    // the check passed, do the sorting
                    this.dataConnection.Sort(dataGridViewColumn, direction); 
                }
 
                if (this.ptCurrentCellCache.X != -1) 
                {
                    if (!IsInnerCellOutOfBounds(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y)) 
                    {
                        SetAndSelectCurrentCellAddress(this.ptCurrentCellCache.X,
                                                   this.ptCurrentCellCache.Y,
                                                   true, 
                                                   false,
                                                   false, 
                                                   false /*clearSelection*/, 
                                                   false /*forceCurrentCellSelection*/);
                    } 
                }
                if (visibleFrozenRows > 0)
                {
                    int rowVIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                    Debug.Assert(rowVIndex != -1);
                    while (visibleFrozenRows > 1) 
                    { 
                        rowVIndex = this.Rows.GetNextRow(rowVIndex, DataGridViewElementStates.Visible);
                        Debug.Assert(rowVIndex != -1); 
                        visibleFrozenRows--;
                    }
                    this.Rows.SetRowState(rowVIndex, DataGridViewElementStates.Frozen, true);
                } 
                this.displayedBandsInfo.FirstDisplayedScrollingRow = firstDisplayedScrollingRowCache;
            } 
            finally 
            {
                Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inSort]); 
                this.dataGridViewOper[DATAGRIDVIEWOPER_inSort] = false;
            }
            // Same effect as changing a top level cell style
            OnGlobalAutoSize(); 
            if (this.DataSource == null)
            { 
                // VSWhidbey 500898. Ensure that the Displayed states get set properly because they were wiped out by UpdateRowsDisplayedState above. 
                this.displayedBandsInfo.EnsureDirtyState();
            } 
            ResetUIState(false /*useRowShortcut*/, false /*computeVisibleRows*/);
            OnSorted(EventArgs.Empty);
        }
 
        internal void SwapSortedRows(int rowIndex1, int rowIndex2)
        { 
            Debug.Assert(rowIndex1 != this.newRowIndex); 
            Debug.Assert(rowIndex2 != this.newRowIndex);
            if (rowIndex1 == rowIndex2) 
            {
                return;
            }
 
            // Follow the move of the old current cell
            if (rowIndex1 == this.ptCurrentCellCache.Y) 
            { 
                this.ptCurrentCellCache.Y = rowIndex2;
            } 
            else if (rowIndex2 == this.ptCurrentCellCache.Y)
            {
                this.ptCurrentCellCache.Y = rowIndex1;
            } 

            switch (this.SelectionMode) 
            { 
                case DataGridViewSelectionMode.FullRowSelect:
                case DataGridViewSelectionMode.RowHeaderSelect: 
                    int row1Selected = this.selectedBandIndexes.IndexOf(rowIndex1);
                    int row2Selected = this.selectedBandIndexes.IndexOf(rowIndex2);
                    if (row1Selected != -1 && row2Selected == -1)
                    { 
                        this.selectedBandIndexes[row1Selected] = rowIndex2;
                    } 
                    else if (row1Selected == -1 && row2Selected != -1) 
                    {
                        this.selectedBandIndexes[row2Selected] = rowIndex1; 
                    }
                    if (this.selectedBandSnapshotIndexes != null)
                    {
                        row1Selected = this.selectedBandSnapshotIndexes.IndexOf(rowIndex1); 
                        row2Selected = this.selectedBandSnapshotIndexes.IndexOf(rowIndex2);
                        if (row1Selected != -1 && row2Selected == -1) 
                        { 
                            this.selectedBandSnapshotIndexes[row1Selected] = rowIndex2;
                        } 
                        else if (row1Selected == -1 && row2Selected != -1)
                        {
                            this.selectedBandSnapshotIndexes[row2Selected] = rowIndex1;
                        } 
                    }
                    break; 
            } 
        }
 
        private void DataGridViewHScrolled(object sender, ScrollEventArgs se)
        {
            if (!this.Enabled)
            { 
                return;
            } 
 
            /* VS Whidbey bug 262445 - no more commit on scroll
            if (this.ptCurrentCell.X >= 0) 
            {
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll])
                {
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition); 
                    se.NewValue = this.HorizontalOffset;
                    return; 
                } 
                this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition);
                this.horizScrollBar.Invalidate(); 
                if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll,
                                false /*forCurrentCellChange-/, false /*forCurrentRowChange-/))
                {
                    se.NewValue = this.HorizontalOffset; 
                    if (se.Type == ScrollEventType.SmallIncrement || se.Type == ScrollEventType.SmallDecrement)
                    { 
                        // Workaround for a pbm where the scrollbar ends up in a bad state after a validation failure dialog is displayed. 
                        this.horizScrollBar.RecreateScrollBarHandle();
                    } 
                    else
                    {
                        this.horizScrollBar.Invalidate();
                    } 
                    return;
                } 
                else 
                {
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinHScroll] = false; 
                }
            }
            */
 
            if (se.Type == ScrollEventType.SmallIncrement ||
                se.Type == ScrollEventType.SmallDecrement) 
            { 
                int dCols = (se.Type == ScrollEventType.SmallIncrement) ? 1 : -1;
                ScrollColumns(dCols); 
                se.NewValue = this.HorizontalOffset;
            }
            else if (se.Type != ScrollEventType.EndScroll)
            { 
                this.HorizontalOffset = se.NewValue;
            } 
        } 

        private void DataGridViewVScrolled(object sender, ScrollEventArgs se) 
        {
            if (!this.Enabled)
            {
                return; 
            }
 
            /* VS Whidbey bug 262445 - no more commit on scroll 
            if (this.ptCurrentCell.X >= 0)
            { 
                if (this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll])
                {
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition);
                    se.NewValue = this.VerticalOffset; 
                    return;
                } 
                this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll] = (se.Type == ScrollEventType.ThumbTrack || se.Type == ScrollEventType.ThumbPosition); 
                this.vertScrollBar.Invalidate();
                if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, 
                                false /*forCurrentCellChange-/, false /*forCurrentRowChange-/))
                {
                    se.NewValue = this.VerticalOffset;
                    if (se.Type == ScrollEventType.SmallIncrement || se.Type == ScrollEventType.SmallDecrement) 
                    {
                        // Workaround for a pbm where the scrollbar ends up in a bad state after a validation failure dialog is displayed. 
                        this.vertScrollBar.RecreateScrollBarHandle(); 
                    }
                    else 
                    {
                        this.vertScrollBar.Invalidate();
                    }
                    return; 
                }
                else 
                { 
                    this.dataGridViewOper[DATAGRIDVIEWOPER_cancelCommitWithinVScroll] = false;
                } 
            }
            */

            int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
            switch (se.Type)
            { 
                case ScrollEventType.SmallIncrement: 
                {
                    // Making sure that when the last visible scrolling row is taller than the data area, it does not get scrolled off screen 
                    Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                    if (this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <=
                        this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight))
                    { 
                        ScrollRowsByCount(1, ScrollEventType.SmallIncrement);
                    } 
                    se.NewValue = this.VerticalOffset; 
                    break;
                } 
                case ScrollEventType.SmallDecrement:
                {
                    if (this.vertScrollBar.Value != this.vertScrollBar.Minimum)
                    { 
                        ScrollRowsByCount(-1, ScrollEventType.SmallDecrement);
                    } 
                    se.NewValue = this.VerticalOffset; 
                    break;
                } 
                case ScrollEventType.LargeIncrement:
                {
                    Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0);
                    int firstDisplayedScrollingRowHeight = this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow); 
                    this.VerticalOffset += Math.Max(firstDisplayedScrollingRowHeight, this.vertScrollBar.LargeChange);
                    se.NewValue = this.VerticalOffset; 
                    break; 
                }
                case ScrollEventType.LargeDecrement: 
                {
                    this.VerticalOffset -= this.vertScrollBar.LargeChange;
                    se.NewValue = this.VerticalOffset;
                    break; 
                }
                case ScrollEventType.ThumbTrack: 
                case ScrollEventType.First: 
                case ScrollEventType.Last:
                { 
                    if (se.NewValue >= this.vertScrollBar.Maximum - this.vertScrollBar.LargeChange)
                    {
                        // Need to display the last scrolling row
                        this.VerticalOffset = this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight); 
                    }
                    else 
                    { 
                        this.VerticalOffset = se.NewValue;
                    } 
                    break;
                }
            }
        } 

        private bool TabToNextCell() 
        { 
            bool success;
            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index;
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1)
            { 
                return false;
            } 
            int nextVisibleColumnIndex = -1; 
            if (this.ptCurrentCell.X != -1)
            { 
                dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.ptCurrentCell.X],
                    DataGridViewElementStates.Visible,
                    DataGridViewElementStates.None);
                if (dataGridViewColumn != null) 
                {
                    nextVisibleColumnIndex = dataGridViewColumn.Index; 
                } 
            }
            int nextVisibleRowIndex = -1; 
            if (this.ptCurrentCell.Y != -1)
            {
                nextVisibleRowIndex = this.Rows.GetNextRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
            } 
            int targetRowIndex = -1, targetColumnIndex = -1;
 
            this.noSelectionChangeCount++; 
            try
            { 
                if (this.ptCurrentCell.X == -1)
                {
                    ClearSelection();
                } 
                else
                { 
                    if (nextVisibleColumnIndex == -1) 
                    {
                        targetRowIndex = (nextVisibleRowIndex == -1) ? firstVisibleRowIndex : nextVisibleRowIndex; 
                        targetColumnIndex = firstVisibleColumnIndex;
                    }
                    else
                    { 
                        targetRowIndex = this.ptCurrentCell.Y;
                        targetColumnIndex = nextVisibleColumnIndex; 
                    } 
                    if (!ScrollIntoView(targetColumnIndex, targetRowIndex, true))
                    { 
                        return true;
                    }
                }
 
                switch (this.SelectionMode)
                { 
                    case DataGridViewSelectionMode.CellSelect: 
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (this.ptCurrentCell.X == -1)
                        {
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                            { 
                                return true;
                            } 
                            SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true); 
                        }
                        else 
                        {
                            if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex))
                            {
                                return true; 
                            }
                            ClearSelection(); 
                            SetSelectedCellCore(targetColumnIndex, targetRowIndex, true); 
                        }
                        break; 

                    case DataGridViewSelectionMode.FullColumnSelect:
                        if (this.ptCurrentCell.X == -1)
                        { 
                            if (IsColumnOutOfBounds(firstVisibleColumnIndex))
                            { 
                                return true; 
                            }
                            SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                        }
                        else
                        {
                            if (IsColumnOutOfBounds(targetColumnIndex)) 
                            {
                                return true; 
                            } 
                            ClearSelection();
                            SetSelectedColumnCore(targetColumnIndex, true); 
                        }
                        break;

                    case DataGridViewSelectionMode.FullRowSelect: 
                        if (this.ptCurrentCell.X == -1)
                        { 
                            if (IsRowOutOfBounds(firstVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            SetSelectedRowCore(firstVisibleRowIndex, true);
                        }
                        else 
                        {
                            if (targetRowIndex != this.ptCurrentCell.Y || this.MultiSelect) 
                            { 
                                if (IsRowOutOfBounds(targetRowIndex))
                                { 
                                    return true;
                                }
                                ClearSelection();
                                SetSelectedRowCore(targetRowIndex, true); 
                            }
                        } 
                        break; 
                }
            } 
            finally
            {
                this.NoSelectionChangeCount--;
            } 

            if (this.ptCurrentCell.X == -1) 
            { 
                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                Debug.Assert(success); 
                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                {
                    return true;
                } 
                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false);
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                // DataGridView changes. 
                // See vsWhidbey: 325296.
                // Debug.Assert(success); 
            }
            else
            {
                if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex)) 
                {
                    return true; 
                } 
                success = SetCurrentCellAddressCore(targetColumnIndex, targetRowIndex, true, false, false);
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                // DataGridView changes.
                // See vsWhidbey: 325296.
                // Debug.Assert(success);
            } 
            return true;
        } 
 
        private bool TabToPreviousCell()
        { 
            bool success;

            DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            int firstVisibleColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; 
            int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible);
            if (firstVisibleColumnIndex == -1 || firstVisibleRowIndex == -1) 
            { 
                return false;
            } 

            int previousVisibleColumnIndex = -1;
            if (this.ptCurrentCell.X != -1)
            { 
                dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.ptCurrentCell.X],
                    DataGridViewElementStates.Visible, 
                    DataGridViewElementStates.None); 
                if (dataGridViewColumn != null)
                { 
                    previousVisibleColumnIndex = dataGridViewColumn.Index;
                }
            }
 
            int previousVisibleRowIndex = -1;
            if (this.ptCurrentCell.Y != -1) 
            { 
                previousVisibleRowIndex = this.Rows.GetPreviousRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible);
            } 

            dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible,
                DataGridViewElementStates.None);
            Debug.Assert(dataGridViewColumn != null); 
            int lastVisibleColumnIndex = dataGridViewColumn.Index;
            int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); 
            Debug.Assert(lastVisibleRowIndex != -1); 

            int targetRowIndex = -1, targetColumnIndex = -1; 

            this.noSelectionChangeCount++;
            try
            { 
                if (this.ptCurrentCell.X == -1)
                { 
                    ClearSelection(); 
                }
                else 
                {
                    if (previousVisibleColumnIndex == -1)
                    {
                        targetRowIndex = (previousVisibleRowIndex == -1) ? lastVisibleRowIndex : previousVisibleRowIndex; 
                        targetColumnIndex = lastVisibleColumnIndex;
                    } 
                    else 
                    {
                        targetRowIndex = this.ptCurrentCell.Y; 
                        targetColumnIndex = previousVisibleColumnIndex;
                    }
                    if (!ScrollIntoView(targetColumnIndex, targetRowIndex, true))
                    { 
                        return true;
                    } 
                } 

                switch (this.SelectionMode) 
                {
                    case DataGridViewSelectionMode.CellSelect:
                    case DataGridViewSelectionMode.RowHeaderSelect:
                    case DataGridViewSelectionMode.ColumnHeaderSelect: 
                        if (this.ptCurrentCell.X == -1)
                        { 
                            if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex)) 
                            {
                                return true; 
                            }
                            SetSelectedCellCore(firstVisibleColumnIndex, firstVisibleRowIndex, true);
                        }
                        else 
                        {
                            if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex)) 
                            { 
                                return true;
                            } 
                            ClearSelection();
                            SetSelectedCellCore(targetColumnIndex, targetRowIndex, true);
                        }
                        break; 

                    case DataGridViewSelectionMode.FullColumnSelect: 
                        if (this.ptCurrentCell.X == -1) 
                        {
                            if (IsColumnOutOfBounds(firstVisibleColumnIndex)) 
                            {
                                return true;
                            }
                            SetSelectedColumnCore(firstVisibleColumnIndex, true); 
                        }
                        else 
                        { 
                            if (IsColumnOutOfBounds(targetColumnIndex))
                            { 
                                return true;
                            }
                            ClearSelection();
                            SetSelectedColumnCore(targetColumnIndex, true); 
                        }
                        break; 
 
                    case DataGridViewSelectionMode.FullRowSelect:
                        if (this.ptCurrentCell.X == -1) 
                        {
                            if (IsRowOutOfBounds(firstVisibleRowIndex))
                            {
                                return true; 
                            }
                            SetSelectedRowCore(firstVisibleRowIndex, true); 
                        } 
                        else
                        { 
                            if (targetRowIndex != this.ptCurrentCell.Y || this.MultiSelect)
                            {
                                if (IsRowOutOfBounds(targetRowIndex))
                                { 
                                    return true;
                                } 
                                ClearSelection(); 
                                SetSelectedRowCore(targetRowIndex, true);
                            } 
                        }
                        break;
                }
            } 
            finally
            { 
                this.NoSelectionChangeCount--; 
            }
 
            if (this.ptCurrentCell.X == -1)
            {
                success = ScrollIntoView(firstVisibleColumnIndex, firstVisibleRowIndex, false);
                Debug.Assert(success); 
                if (IsInnerCellOutOfBounds(firstVisibleColumnIndex, firstVisibleRowIndex))
                { 
                    return true; 
                }
                success = SetCurrentCellAddressCore(firstVisibleColumnIndex, firstVisibleRowIndex, true, false, false); 
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the
                // DataGridView changes.
                // See vsWhidbey: 325296.
                // Debug.Assert(success); 
            }
            else 
            { 
                if (IsInnerCellOutOfBounds(targetColumnIndex, targetRowIndex))
                { 
                    return true;
                }
                success = SetCurrentCellAddressCore(targetColumnIndex, targetRowIndex, true, false, false);
                // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the 
                // DataGridView changes.
                // See vsWhidbey: 325296. 
                // Debug.Assert(success); 
            }
 
            return true;
        }

        private void UnwireEditingControlEvents() 
        {
            Debug.Assert(this.editingPanel != null); 
            this.editingPanel.Click -= new System.EventHandler(EditingControls_Click); 
            this.editingPanel.DoubleClick -= new System.EventHandler(EditingControls_DoubleClick);
            this.editingPanel.MouseClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick); 
            this.editingPanel.MouseDoubleClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick);
            this.editingPanel.MouseDown -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown);
            this.editingPanel.MouseEnter -= new System.EventHandler(EditingControls_MouseEnter);
            this.editingPanel.MouseLeave -= new System.EventHandler(EditingControls_MouseLeave); 
            this.editingPanel.MouseMove -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove);
            this.editingPanel.MouseUp -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp); 
 
            Debug.Assert(this.editingControl != null);
            this.editingControl.Click -= new System.EventHandler(EditingControls_Click); 
            this.editingControl.DoubleClick -= new System.EventHandler(EditingControls_DoubleClick);
            this.editingControl.MouseClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick);
            this.editingControl.MouseDoubleClick -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick);
            this.editingControl.MouseDown -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown); 
            this.editingControl.MouseEnter -= new System.EventHandler(EditingControls_MouseEnter);
            this.editingControl.MouseLeave -= new System.EventHandler(EditingControls_MouseLeave); 
            this.editingControl.MouseMove -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove); 
            this.editingControl.MouseUp -= new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp);
        } 

        private void UnwireScrollBarsEvents()
        {
            if (this.horizScrollBar != null) 
            {
                this.horizScrollBar.MouseEnter -= new System.EventHandler(ScrollBar_MouseEnter); 
                this.horizScrollBar.MouseLeave -= new System.EventHandler(ScrollBar_MouseLeave); 
            }
            if (this.vertScrollBar != null) 
            {
                this.vertScrollBar.MouseEnter -= new System.EventHandler(ScrollBar_MouseEnter);
                this.vertScrollBar.MouseLeave -= new System.EventHandler(ScrollBar_MouseLeave);
            } 
        }
 
        ///  
        public void UpdateCellErrorText(int columnIndex, int rowIndex)
        { 
            if (columnIndex < -1 || columnIndex >= this.Columns.Count)
            {
                throw new ArgumentOutOfRangeException("columnIndex");
            } 
            if (rowIndex < -1 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex"); 
            }
            if (this.IsHandleCreated) 
            {
                InvalidateCellPrivate(columnIndex, rowIndex);
            }
        } 

        ///  
        public void UpdateCellValue(int columnIndex, int rowIndex) 
        {
            if (columnIndex < 0 || columnIndex >= this.Columns.Count) 
            {
                throw new ArgumentOutOfRangeException("columnIndex");
            }
            if (rowIndex < 0 || rowIndex >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            } 
            if (this.IsHandleCreated)
            { 
                OnCellCommonChange(columnIndex, rowIndex);
            }
        }
 
        private void UpdateColumnsDisplayedState(bool displayed)
        { 
            // Make sure all displayed frozen columns have their Displayed state set to this.Visible 
            DataGridViewColumn dataGridViewColumnTmp;
            int numDisplayedFrozenCols = this.displayedBandsInfo.NumDisplayedFrozenCols; 
            if (numDisplayedFrozenCols > 0)
            {
                dataGridViewColumnTmp = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                while (numDisplayedFrozenCols > 0) 
                {
                    Debug.Assert(dataGridViewColumnTmp != null); 
                    if (dataGridViewColumnTmp.Displayed != displayed) 
                    {
                        dataGridViewColumnTmp.DisplayedInternal = displayed; 
                        Debug.Assert(ColumnNeedsDisplayedState(dataGridViewColumnTmp));
                    }
                    dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None);
                    numDisplayedFrozenCols--; 
                }
            } 
 
            // Make sure all displayed scrolling columns have the Displayed state set to this.Visible
            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 != displayed) 
                    {
                        dataGridViewColumnTmp.DisplayedInternal = displayed;
                        Debug.Assert(ColumnNeedsDisplayedState(dataGridViewColumnTmp));
                    } 
                    dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    numDisplayedScrollingCols--; 
                } 
            }
        } 

        /// 
        public void UpdateRowErrorText(int rowIndex)
        { 
            if (rowIndex < 0 || rowIndex >= this.Rows.Count)
            { 
                throw new ArgumentOutOfRangeException("rowIndex"); 
            }
            if (this.IsHandleCreated && this.layout.RowHeadersVisible) 
            {
                InvalidateCellPrivate(-1, rowIndex);
            }
        } 

        ///  
        public void UpdateRowErrorText(int rowIndexStart, int rowIndexEnd) 
        {
            if (rowIndexStart < 0 || rowIndexStart >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndexStart");
            }
            if (rowIndexEnd < 0 || rowIndexEnd >= this.Rows.Count) 
            {
                throw new ArgumentOutOfRangeException("rowIndexEnd"); 
            } 
            if (rowIndexEnd < rowIndexStart)
            { 
                throw new ArgumentOutOfRangeException("rowIndexEnd");
            }
            if (this.IsHandleCreated && this.layout.RowHeadersVisible)
            { 
                Rectangle rectUpper = GetCellAdjustedDisplayRectangle(-1, rowIndexStart, true);
                Rectangle rectLower = GetCellAdjustedDisplayRectangle(-1, rowIndexEnd, true); 
                if (rectUpper.IsEmpty || rectLower.IsEmpty) 
                {
                    if (!rectUpper.IsEmpty || !rectLower.IsEmpty) 
                    {
                        Invalidate(this.layout.RowHeaders);
                    }
                } 
                else
                { 
                    Invalidate(Rectangle.Union(rectUpper, rectLower)); 
                }
            } 
        }

        /// 
        public void UpdateRowHeightInfo(int rowIndex, bool updateToEnd) 
        {
            UpdateRowHeightInfoPrivate(rowIndex, updateToEnd, true /*invalidInAdjustFillingColumns*/); 
        } 

        private void UpdateRowHeightInfoPrivate(int rowIndex, bool updateToEnd, bool invalidInAdjustFillingColumns) 
        {
            if ((updateToEnd && rowIndex < 0) || (!updateToEnd && rowIndex < -1) || rowIndex >= this.Rows.Count)
            {
                throw new ArgumentOutOfRangeException("rowIndex"); 
            }
 
            this.Rows.InvalidateCachedRowsHeights(); 

            bool rowVisible = (rowIndex >= 0 && (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0); 

            // don't do any layout logic if the handled was not created already
            if (this.IsHandleCreated && (rowIndex == -1 || rowVisible))
            { 
                if (updateToEnd)
                { 
                    int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; 

                    if (this.AutoSize) 
                    {
                        LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows);
                    }
                    else 
                    {
                        PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/); 
                    } 

                    Rectangle bottomArea = this.layout.Data; 
                    if (this.layout.RowHeadersVisible)
                    {
                        bottomArea = Rectangle.Union(bottomArea, this.layout.RowHeaders);
                    } 
                    else if (this.SingleVerticalBorderAdded)
                    { 
                        if (!this.RightToLeftInternal) 
                        {
                            bottomArea.X--; 
                        }
                        bottomArea.Width++;
                    }
 
                    if (!rowVisible)
                    { 
                        rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); 
                    }
                    if (rowIndex != -1) 
                    {
                        int topEdge = GetRowYFromIndex(oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow ? rowIndex : this.displayedBandsInfo.FirstDisplayedScrollingRow);
                        bottomArea.Height -= bottomArea.Y - topEdge;
                        bottomArea.Y = topEdge; 
                        Invalidate(bottomArea);
                    } 
 
                    if (this.editingControl != null)
                    { 
                        PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/);
                    }
                }
                else 
                {
                    if (rowIndex == -1) 
                    { 
                        if (this.AutoSize)
                        { 
                            LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows);
                        }
                        else
                        { 
                            PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/);
                        } 
                        Invalidate(); 
                    }
                    else 
                    {
                        Debug.Assert(rowVisible);
                        int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow;
 
                        if (this.inBulkLayoutCount == 0)
                        { 
                            if (this.AutoSize) 
                            {
                                LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows); 
                            }
                            else
                            {
                                PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/); 
                            }
                        } 
 
                        if (this.inBulkPaintCount == 0)
                        { 
                            Rectangle bottomArea = this.layout.Data;
                            if (this.layout.RowHeadersVisible)
                            {
                                bottomArea = Rectangle.Union(bottomArea, this.layout.RowHeaders); 
                            }
                            else if (this.SingleVerticalBorderAdded) 
                            { 
                                if (!this.RightToLeftInternal)
                                { 
                                    bottomArea.X--;
                                }
                                bottomArea.Width++;
                            } 
                            int topEdge = GetRowYFromIndex(oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow ? rowIndex : this.displayedBandsInfo.FirstDisplayedScrollingRow);
                            bottomArea.Height -= bottomArea.Y - topEdge; 
                            bottomArea.Y = topEdge; 
                            Invalidate(bottomArea);
                        } 
                    }

                    if (this.editingControl != null)
                    { 
                        PositionEditingControl(rowIndex == -1 || this.ptCurrentCell.Y != rowIndex, true, false);
                    } 
                } 

                UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); 
            }
        }

        private void UpdateRowsDisplayedState(bool displayed) 
        {
            // Make sure all displayed frozen rows have their Displayed state set to 'displayed' 
            int rowIndexTmp, numDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedFrozenRows; 
            if (numDisplayedFrozenRows > 0)
            { 
                rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen);
                while (numDisplayedFrozenRows > 0)
                {
                    Debug.Assert(rowIndexTmp != -1); 
                    if (((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0) == displayed)
                    { 
                        this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, displayed); 
                    }
                    rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); 
                    numDisplayedFrozenRows--;
                }
            }
 
            // Make sure all displayed scrolling rows have their Displayed state set to 'displayed'
            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) == displayed)
                    { 
                        this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, displayed); 
                    }
                    rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); 
                    numDisplayedScrollingRows--;
                }
            }
        } 

        private void UpdateMouseEnteredCell(HitTestInfo hti, MouseEventArgs e) 
        { 
            Point ptMouse = PointToClient(Control.MousePosition);
            HitTestInfo htiToUse; 
            if (hti != null)
            {
                htiToUse = hti;
            } 
            else
            { 
                htiToUse = HitTest(ptMouse.X, ptMouse.Y); 
            }
 
            if (htiToUse.Type != DataGridViewHitTestType.None &&
                htiToUse.Type != DataGridViewHitTestType.HorizontalScrollBar &&
                htiToUse.Type != DataGridViewHitTestType.VerticalScrollBar)
            { 
                if (this.ptMouseEnteredCell.X != htiToUse.col || this.ptMouseEnteredCell.Y != htiToUse.row)
                { 
                    DataGridViewCellEventArgs dgvce; 
                    if (this.ptMouseEnteredCell.X >= -1 &&
                        this.ptMouseEnteredCell.X < this.Columns.Count && 
                        this.ptMouseEnteredCell.Y >= -1 &&
                        this.ptMouseEnteredCell.Y < this.Rows.Count)
                    {
                        dgvce = new DataGridViewCellEventArgs(this.ptMouseEnteredCell.X, this.ptMouseEnteredCell.Y); 
                        OnCellMouseLeave(dgvce);
                    } 
                    dgvce = new DataGridViewCellEventArgs(htiToUse.col, htiToUse.row); 
                    OnCellMouseEnter(dgvce);
                } 
                if (e != null)
                {
                    int mouseX = e.X - htiToUse.ColumnX;
                    if (this.RightToLeftInternal) 
                    {
                        mouseX += ((htiToUse.col == -1) ? this.RowHeadersWidth : this.Columns[htiToUse.col].Thickness); 
                    } 
                    DataGridViewCellMouseEventArgs dgvcme = new DataGridViewCellMouseEventArgs(htiToUse.col, htiToUse.row, mouseX, e.Y - htiToUse.RowY, e);
                    OnCellMouseMove(dgvcme); 
                }
            }
            else if (this.ptMouseEnteredCell.X != -2)
            { 
                if (this.ptMouseEnteredCell.X >= -1 &&
                    this.ptMouseEnteredCell.X < this.Columns.Count && 
                    this.ptMouseEnteredCell.Y >= -1 && 
                    this.ptMouseEnteredCell.Y < this.Rows.Count)
                { 
                    DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(this.ptMouseEnteredCell.X, this.ptMouseEnteredCell.Y);
                    OnCellMouseLeave(dgvce);
                }
                else 
                {
                    this.ptMouseEnteredCell.X = this.ptMouseEnteredCell.Y = -2; 
                } 
            }
        } 

        private void UpdateSelectedCellsBlock(int anchorColumnIndex, ref int oldEdgeColumnIndex, int newEdgeColumnIndex,
            int anchorRowIndex, ref int oldEdgeRowIndex, int newEdgeRowIndex)
        { 
            Debug.Assert(anchorColumnIndex >= 0);
            Debug.Assert(anchorRowIndex >= 0); 
            Debug.Assert(newEdgeColumnIndex >= 0); 
            Debug.Assert(newEdgeRowIndex >= 0);
            Debug.Assert(this.noSelectionChangeCount > 0); 
            if ((this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex) &&
                this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex)) ||
                (this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex) &&
                this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex)) || 
                (anchorRowIndex < oldEdgeRowIndex && newEdgeRowIndex < anchorRowIndex) ||
                (oldEdgeRowIndex < anchorRowIndex && anchorRowIndex < newEdgeRowIndex)) 
            { 
                // deselecting all selected block
                SelectCellUnorderedRange(anchorColumnIndex, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false); 
                // and reselecting new block
                SelectCellUnorderedRange(anchorColumnIndex, anchorRowIndex, newEdgeColumnIndex, newEdgeRowIndex, true);
                oldEdgeColumnIndex = newEdgeColumnIndex;
                oldEdgeRowIndex = newEdgeRowIndex; 
                return;
            } 
 
            if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex) &&
                (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex) || anchorColumnIndex == oldEdgeColumnIndex) && 
                oldEdgeRowIndex == newEdgeRowIndex)
            {
                // h1
                DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                Debug.Assert(dataGridViewColumn != null);
                if (anchorRowIndex <= newEdgeRowIndex) 
                { 
                    SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, newEdgeColumnIndex, newEdgeRowIndex, true);
                } 
                else
                {
                    // newEdgeRowIndex < anchorRowIndex
                    SelectCellRange(dataGridViewColumn.Index, newEdgeRowIndex, newEdgeColumnIndex, anchorRowIndex, true); 
                }
            } 
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex) && 
                (this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex) || oldEdgeColumnIndex == anchorColumnIndex) &&
                oldEdgeRowIndex == newEdgeRowIndex) 
            {
                // h2
                DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                Debug.Assert(dataGridViewColumn != null); 
                if (anchorRowIndex <= newEdgeRowIndex)
                { 
                    SelectCellRange(newEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, newEdgeRowIndex, true); 
                }
                else 
                {
                    // newEdgeRowIndex < anchorRowIndex
                    SelectCellRange(newEdgeColumnIndex, newEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, true);
                } 
            }
            else if (newEdgeRowIndex > oldEdgeRowIndex && 
                anchorRowIndex <= oldEdgeRowIndex && 
                newEdgeColumnIndex == oldEdgeColumnIndex)
            { 
                // h3
                if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || anchorColumnIndex == newEdgeColumnIndex)
                {
                    SelectCellRange(anchorColumnIndex, 
                        this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        newEdgeColumnIndex, 
                        newEdgeRowIndex, 
                        true);
                } 
                else
                {
                    // newEdgeColumnIndex before anchorColumnIndex
                    SelectCellRange(newEdgeColumnIndex, 
                        this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        anchorColumnIndex, 
                        newEdgeRowIndex, 
                        true);
                } 
            }
            else if (newEdgeRowIndex < oldEdgeRowIndex &&
                oldEdgeRowIndex <= anchorRowIndex &&
                newEdgeColumnIndex == oldEdgeColumnIndex) 
            {
                // h4 
                if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || anchorColumnIndex == newEdgeColumnIndex) 
                {
                    SelectCellRange(anchorColumnIndex, 
                        newEdgeRowIndex,
                        newEdgeColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        true); 
                }
                else 
                { 
                    // newEdgeColumnIndex before anchorColumnIndex
                    SelectCellRange(newEdgeColumnIndex, 
                        newEdgeRowIndex,
                        anchorColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        true); 
                }
            } 
            else if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex) && 
                !this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex) &&
                newEdgeRowIndex > oldEdgeRowIndex && anchorRowIndex <= oldEdgeRowIndex) 
            {
                // h5
                DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                Debug.Assert(dataGridViewColumn != null); 
                SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, newEdgeColumnIndex, oldEdgeRowIndex, true);
                SelectCellRange(anchorColumnIndex, 
                    this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible), 
                    newEdgeColumnIndex,
                    newEdgeRowIndex, 
                    true);
            }
            else if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex) &&
                newEdgeRowIndex < oldEdgeRowIndex && oldEdgeRowIndex <= anchorRowIndex) 
            {
                if (!this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex)) 
                { 
                    // h6
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                    Debug.Assert(dataGridViewColumn != null);
                    SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, newEdgeColumnIndex, anchorRowIndex, true);
                    SelectCellRange(anchorColumnIndex,
                        newEdgeRowIndex, 
                        newEdgeColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible), 
                        true); 
                }
                else 
                {
                    if (!this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex))
                    {
                        if (anchorRowIndex == oldEdgeRowIndex) 
                        {
                            // g2 
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, anchorColumnIndex, oldEdgeRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex, newEdgeRowIndex, anchorColumnIndex, anchorRowIndex, true);
                        } 
                        else
                        {
                            // b4
                            DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                            Debug.Assert(dataGridViewColumn != null);
                            Debug.Assert(oldEdgeRowIndex < anchorRowIndex); 
                            SelectCellRange(oldEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex,
                                newEdgeRowIndex, 
                                anchorColumnIndex,
                                this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                                true);
                        } 
                    }
                } 
            } 
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex) &&
                newEdgeRowIndex < oldEdgeRowIndex && anchorRowIndex >= oldEdgeRowIndex) 
            {
                if (!this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex))
                {
                    // h7 
                    DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                    Debug.Assert(dataGridViewColumn != null); 
                    SelectCellRange(newEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, true); 
                    SelectCellRange(newEdgeColumnIndex,
                        newEdgeRowIndex, 
                        anchorColumnIndex,
                        this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                        true);
                } 
                else
                { 
                    if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex)) 
                    {
                        // a4 
                        DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                        Debug.Assert(dataGridViewColumn != null);
                        Debug.Assert(oldEdgeRowIndex <= anchorRowIndex);
                        SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false); 
                        SelectCellRange(anchorColumnIndex,
                            newEdgeRowIndex, 
                            newEdgeColumnIndex, 
                            this.Rows.GetPreviousRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                            true); 
                    }
                    else
                    {
                        // g8 
                        SelectCellRange(anchorColumnIndex, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false);
                        SelectCellRange(newEdgeColumnIndex, newEdgeRowIndex, anchorColumnIndex, anchorRowIndex, true); 
                    } 
                }
            } 
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex) &&
                !this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex) &&
                newEdgeRowIndex > oldEdgeRowIndex && anchorRowIndex <= oldEdgeRowIndex)
            { 
                // h8
                DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                Debug.Assert(dataGridViewColumn != null); 
                SelectCellRange(newEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, true);
                SelectCellRange(newEdgeColumnIndex, 
                    this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                    anchorColumnIndex,
                    newEdgeRowIndex,
                    true); 
            }
            else if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex)) 
            { 
                DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                if (newEdgeRowIndex == oldEdgeRowIndex) 
                {
                    if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex))
                    {
                        // a1 
                        Debug.Assert(dataGridViewColumn != null);
                        if (oldEdgeRowIndex > anchorRowIndex) 
                        { 
                            SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false);
                        } 
                        else
                        {
                            SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false);
                        } 
                    }
                } 
                else if (newEdgeRowIndex < oldEdgeRowIndex) 
                {
                    if (oldEdgeRowIndex > anchorRowIndex) 
                    {
                        if (this.Columns.DisplayInOrder(newEdgeColumnIndex, oldEdgeColumnIndex))
                        {
                            if (anchorRowIndex <= newEdgeRowIndex) 
                            {
                                if (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex)) 
                                { 
                                    if (!this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex))
                                    { 
                                        // a2
                                        Debug.Assert(dataGridViewColumn != null);
                                        SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false);
                                        SelectCellRange(anchorColumnIndex, 
                                            this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                            newEdgeColumnIndex, 
                                            oldEdgeRowIndex, 
                                            false);
                                    } 
                                }
                                else
                                {
                                    // d3 
                                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    Debug.Assert(dataGridViewColumn != null); 
                                    SelectCellRange(oldEdgeColumnIndex, 
                                        this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        anchorColumnIndex, 
                                        oldEdgeRowIndex,
                                        false);
                                    SelectCellRange(newEdgeColumnIndex,
                                        anchorRowIndex, 
                                        dataGridViewColumn.Index,
                                        newEdgeRowIndex, 
                                        true); 
                                }
                            } 
                        }
                    }
                }
                else if (newEdgeRowIndex > oldEdgeRowIndex) 
                {
                    if (oldEdgeRowIndex < anchorRowIndex) 
                    { 
                        if ((this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex)) &&
                            newEdgeRowIndex <= anchorRowIndex) 
                        {
                            // a3
                            Debug.Assert(dataGridViewColumn != null);
                            SelectCellRange(dataGridViewColumn.Index, oldEdgeRowIndex, oldEdgeColumnIndex, anchorRowIndex, false); 
                            SelectCellRange(anchorColumnIndex,
                                oldEdgeRowIndex, 
                                newEdgeColumnIndex, 
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                false); 
                        }
                        else
                        {
                            if (!this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex)) 
                            {
                                if (newEdgeRowIndex <= anchorRowIndex) 
                                { 
                                    // c3
                                    dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
                                    Debug.Assert(dataGridViewColumn != null);
                                    SelectCellRange(oldEdgeColumnIndex,
                                        oldEdgeRowIndex,
                                        anchorColumnIndex, 
                                        this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        false); 
                                    SelectCellRange(newEdgeColumnIndex, 
                                        newEdgeRowIndex,
                                        dataGridViewColumn.Index, 
                                        anchorRowIndex,
                                        true);
                                }
                            } 
                        }
                    } 
                    else 
                    {
                        if (this.Columns.DisplayInOrder(anchorColumnIndex, newEdgeColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex)) 
                        {
                            // a5
                            Debug.Assert(oldEdgeRowIndex >= anchorRowIndex);
                            Debug.Assert(dataGridViewColumn != null); 
                            SelectCellRange(dataGridViewColumn.Index, anchorRowIndex, oldEdgeColumnIndex, oldEdgeRowIndex, false);
                            SelectCellRange(anchorColumnIndex, 
                                this.Rows.GetNextRow(anchorRowIndex, DataGridViewElementStates.Visible), 
                                newEdgeColumnIndex,
                                newEdgeRowIndex, 
                                true);
                        }
                    }
                } 
            }
            else if (this.Columns.DisplayInOrder(oldEdgeColumnIndex, newEdgeColumnIndex)) 
            { 
                DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[newEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                if (newEdgeRowIndex == oldEdgeRowIndex) 
                {
                    if (this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (newEdgeColumnIndex == anchorColumnIndex))
                    {
                        // b1 
                        Debug.Assert(dataGridViewColumn != null);
                        if (oldEdgeRowIndex > anchorRowIndex) 
                        { 
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, false);
                        } 
                        else
                        {
                            SelectCellRange(oldEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, false);
                        } 
                    }
                } 
                else if (newEdgeRowIndex < oldEdgeRowIndex) 
                {
                    if (oldEdgeRowIndex > anchorRowIndex) 
                    {
                        if ((this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (newEdgeColumnIndex == anchorColumnIndex)) &&
                            newEdgeRowIndex >= anchorRowIndex)
                        { 
                            // b2
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex, 
                                this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                anchorColumnIndex, 
                                oldEdgeRowIndex,
                                false);
                        }
                        else 
                        {
                            if (!this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex)) 
                            { 
                                if (newEdgeRowIndex >= anchorRowIndex)
                                { 
                                    // d2
                                    dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    Debug.Assert(dataGridViewColumn != null);
                                    SelectCellRange(anchorColumnIndex, 
                                        this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        oldEdgeColumnIndex, 
                                        oldEdgeRowIndex, 
                                        false);
                                    SelectCellRange(dataGridViewColumn.Index, 
                                        anchorRowIndex,
                                        newEdgeColumnIndex,
                                        newEdgeRowIndex,
                                        true); 
                                }
                            } 
                        } 
                    }
                } 
                else if (newEdgeRowIndex > oldEdgeRowIndex)
                {
                    if (oldEdgeRowIndex < anchorRowIndex)
                    { 
                        if ((this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex)) &&
                            newEdgeRowIndex <= anchorRowIndex) 
                        { 
                            // b3
                            SelectCellRange(oldEdgeColumnIndex, oldEdgeRowIndex, dataGridViewColumn.Index, anchorRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex,
                                oldEdgeRowIndex,
                                anchorColumnIndex,
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible), 
                                false);
                        } 
                        else 
                        {
                            if (!this.Columns.DisplayInOrder(oldEdgeColumnIndex, anchorColumnIndex)) 
                            {
                                if (newEdgeRowIndex <= anchorRowIndex)
                                {
                                    // c2 
                                    dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[oldEdgeColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None);
                                    Debug.Assert(dataGridViewColumn != null); 
                                    SelectCellRange(anchorColumnIndex, 
                                        oldEdgeRowIndex,
                                        oldEdgeColumnIndex, 
                                        this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                        false);
                                    SelectCellRange(dataGridViewColumn.Index,
                                        newEdgeRowIndex, 
                                        newEdgeColumnIndex,
                                        anchorRowIndex, 
                                        true); 
                                }
                            } 
                        }
                    }
                    else
                    { 
                        if (this.Columns.DisplayInOrder(newEdgeColumnIndex, anchorColumnIndex) || (anchorColumnIndex == newEdgeColumnIndex))
                        { 
                            // b5 
                            Debug.Assert(oldEdgeRowIndex >= anchorRowIndex);
                            SelectCellRange(oldEdgeColumnIndex, anchorRowIndex, dataGridViewColumn.Index, oldEdgeRowIndex, false); 
                            SelectCellRange(newEdgeColumnIndex,
                                this.Rows.GetNextRow(oldEdgeRowIndex, DataGridViewElementStates.Visible),
                                anchorColumnIndex,
                                newEdgeRowIndex, 
                                true);
                        } 
                    } 
                }
            } 
            else if (newEdgeRowIndex > oldEdgeRowIndex)
            {
                if (newEdgeColumnIndex == oldEdgeColumnIndex)
                { 
                    if (newEdgeRowIndex <= anchorRowIndex)
                    { 
                        // c1 
                        if (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex))
                        { 
                            SelectCellRange(anchorColumnIndex,
                                oldEdgeRowIndex,
                                oldEdgeColumnIndex,
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible), 
                                false);
                        } 
                        else 
                        {
                            SelectCellRange(oldEdgeColumnIndex, 
                                oldEdgeRowIndex,
                                anchorColumnIndex,
                                this.Rows.GetPreviousRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                false); 
                        }
                    } 
                } 
            }
            else if (newEdgeRowIndex < oldEdgeRowIndex) 
            {
                if (newEdgeColumnIndex == oldEdgeColumnIndex)
                {
                    if (newEdgeRowIndex >= anchorRowIndex) 
                    {
                        // d1 
                        if (this.Columns.DisplayInOrder(anchorColumnIndex, oldEdgeColumnIndex)) 
                        {
                            SelectCellRange(anchorColumnIndex, 
                                this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible),
                                oldEdgeColumnIndex,
                                oldEdgeRowIndex,
                                false); 
                        }
                        else 
                        { 
                            SelectCellRange(oldEdgeColumnIndex,
                                this.Rows.GetNextRow(newEdgeRowIndex, DataGridViewElementStates.Visible), 
                                anchorColumnIndex,
                                oldEdgeRowIndex,
                                false);
                        } 
                    }
                } 
            } 
            oldEdgeColumnIndex = newEdgeColumnIndex;
            oldEdgeRowIndex = newEdgeRowIndex; 
        }

        private void VertScrollTimer_Tick(object sender, System.EventArgs e)
        { 
            BeginInvoke(new MethodInvoker(VertScrollTimerHandler));
        } 
 
        private void VertScrollTimerHandler()
        { 
            // Why would the vertical scroll timer be enabled when vertical selection is not occurring
            Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]);

            Point ptMouse = PointToClient(Control.MousePosition); 
            HitTestInfo hti = HitTest(ptMouse.X, ptMouse.Y);
            int xOffset, yOffset, mouseX = ptMouse.X, mouseY = ptMouse.Y; 
 
            if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset))
            { 
                if (yOffset != 0)
                {
                    int absYOffset = Math.Abs(yOffset), normOffset = yOffset / absYOffset;
                    ScrollRowsByCount(normOffset, normOffset < 0 ? ScrollEventType.SmallDecrement : ScrollEventType.SmallIncrement); 
                    this.vertScrollTimer.Interval = GetRowScrollRate(absYOffset);
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect]) 
                    { 
                        hti = HitTest(mouseX, ptMouse.Y - yOffset - normOffset);
                        if (hti.row >= 0) 
                        {
                            OnRowSelectMouseMove(hti);
                        }
                    } 
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])
                    { 
                        if (xOffset != 0) 
                        {
                            hti = HitTest(ptMouse.X - xOffset - (xOffset / Math.Abs(xOffset)), ptMouse.Y - yOffset - normOffset); 
                        }
                        else
                        {
                            hti = HitTest(mouseX, ptMouse.Y - yOffset - normOffset); 
                        }
                        if (hti.col >= 0 && hti.row >= 0) 
                        { 
                            OnCellSelectMouseMove(hti);
                        } 
                    }
                }
                else
                { 
                    if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && hti.row >= 0)
                    { 
                        OnRowSelectMouseMove(hti); 
                    }
                    else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) 
                    {
                        OnCellSelectMouseMove(hti);
                    }
                    this.VertScrollTimer.Enabled = false; 
                }
            } 
        } 

        private void WireEditingControlEvents() 
        {
            Debug.Assert(this.editingPanel != null);
            this.editingPanel.Click += new System.EventHandler(EditingControls_Click);
            this.editingPanel.DoubleClick += new System.EventHandler(EditingControls_DoubleClick); 
            this.editingPanel.MouseClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick);
            this.editingPanel.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick); 
            this.editingPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown); 
            this.editingPanel.MouseEnter += new System.EventHandler(EditingControls_MouseEnter);
            this.editingPanel.MouseLeave += new System.EventHandler(EditingControls_MouseLeave); 
            this.editingPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove);
            this.editingPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp);

            Debug.Assert(this.editingControl != null); 
            this.editingControl.Click += new System.EventHandler(EditingControls_Click);
            this.editingControl.DoubleClick += new System.EventHandler(EditingControls_DoubleClick); 
            this.editingControl.MouseClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseClick); 
            this.editingControl.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDoubleClick);
            this.editingControl.MouseDown += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseDown); 
            this.editingControl.MouseEnter += new System.EventHandler(EditingControls_MouseEnter);
            this.editingControl.MouseLeave += new System.EventHandler(EditingControls_MouseLeave);
            this.editingControl.MouseMove += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseMove);
            this.editingControl.MouseUp += new System.Windows.Forms.MouseEventHandler(EditingControls_MouseUp); 
        }
 
        private void WireScrollBarsEvents() 
        {
            if (this.horizScrollBar != null) 
            {
                this.horizScrollBar.MouseEnter += new System.EventHandler(ScrollBar_MouseEnter);
                this.horizScrollBar.MouseLeave += new System.EventHandler(ScrollBar_MouseLeave);
            } 
            if (this.vertScrollBar != null)
            { 
                this.vertScrollBar.MouseEnter += new System.EventHandler(ScrollBar_MouseEnter); 
                this.vertScrollBar.MouseLeave += new System.EventHandler(ScrollBar_MouseLeave);
            } 
        }

        /// 
        ///     Handles the WM_CONTEXTMENU message 
        /// 
        ///  
        internal override void WmContextMenu(ref Message m) 
        {
            ContextMenuStrip contextMenuStrip; 
            int x = (int)(short)m.LParam;
            int y = (int)m.LParam >> 16;
            Point client;
            bool keyboardActivated = false; 
            // lparam will be exactly -1 when the user invokes the context menu
            // with the keyboard. 
            // 
            if ((int)m.LParam == -1)
            { 
                keyboardActivated = true;
                client = new Point(this.Width/2, this.Height/2);
                contextMenuStrip = (ContextMenuStrip) this.ContextMenuStrip;
            } 
            else
            { 
                client = PointToClientInternal(new Point(x, y)); 
                HitTestInfo hti = HitTest(client.X, client.Y);
                DataGridViewCell dataGridViewCell = null; 
                switch (hti.Type)
                {
                    case DataGridViewHitTestType.Cell:
                        dataGridViewCell = this.Rows.SharedRow(hti.row).Cells[hti.col]; 
                        break;
                    case DataGridViewHitTestType.ColumnHeader: 
                        Debug.Assert(hti.row == -1); 
                        dataGridViewCell = this.Columns[hti.col].HeaderCell;
                        break; 
                    case DataGridViewHitTestType.RowHeader:
                        Debug.Assert(hti.col == -1);
                        dataGridViewCell = this.Rows.SharedRow(hti.row).HeaderCell;
                        break; 
                    case DataGridViewHitTestType.TopLeftHeader:
                        Debug.Assert(hti.row == -1); 
                        Debug.Assert(hti.col == -1); 
                        dataGridViewCell = this.TopLeftHeaderCell;
                        break; 
                }
                if (dataGridViewCell != null)
                {
                    contextMenuStrip = dataGridViewCell.GetInheritedContextMenuStrip(hti.row); 
                }
                else 
                { 
                    contextMenuStrip = (ContextMenuStrip) this.ContextMenuStrip;
                } 
            }

            // VisualStudio7 # 156, only show the context menu when clicked in the client area
            if (contextMenuStrip != null && this.ClientRectangle.Contains(client)) 
            {
                contextMenuStrip.ShowInternal(this, client, keyboardActivated); 
            } 
            else
            { 
                DefWndProc(ref m);
            }
        }
 
        /// 
        ///     Handles the WM_GETDLGCODE message 
        ///  
        private void WmGetDlgCode(ref Message m)
        { 
            m.Result = (IntPtr)((long)m.Result | NativeMethods.DLGC_WANTARROWS | NativeMethods.DLGC_WANTCHARS);

            Keys modifierKeys = ModifierKeys;
            if (GetTabKeyEffective((modifierKeys & Keys.Shift) == Keys.Shift, (modifierKeys & Keys.Control) == Keys.Control)) 
            {
                m.Result = (IntPtr) ((long) m.Result | NativeMethods.DLGC_WANTTAB); 
            } 
        }
 
        private unsafe bool WmNotify(ref Message m)
        {
            if (m.LParam == IntPtr.Zero)
            { 
                return false;
            } 
 
            NativeMethods.NMHDR* nmhdr = (NativeMethods.NMHDR *)m.LParam;
            if (nmhdr->code == NativeMethods.TTN_GETDISPINFO && !DesignMode) 
            {
                string toolTip = this.ToolTipPrivate;

                if (!String.IsNullOrEmpty(toolTip)) 
                {
                    // MSDN: Setting the max width has the added benefit of enabling multiline tool tips! 
                    UnsafeNativeMethods.SendMessage(new HandleRef(this, nmhdr->hwndFrom), NativeMethods.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width); 
                    NativeMethods.TOOLTIPTEXT ttt = (NativeMethods.TOOLTIPTEXT) m.GetLParam(typeof(NativeMethods.TOOLTIPTEXT));
 
                    ttt.lpszText = toolTip;

                    if (this.RightToLeft == RightToLeft.Yes)
                    { 
                        ttt.uFlags |= NativeMethods.TTF_RTLREADING;
                    } 
                    Marshal.StructureToPtr(ttt, m.LParam, false); 
                    return true;
                } 
            }

            return false;
        } 

        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        protected override void WndProc(ref Message m)
        { 
            switch (m.Msg)
            {
                case NativeMethods.WM_GETDLGCODE:
                    WmGetDlgCode(ref m); 
                    return;
                case NativeMethods.WM_LBUTTONDBLCLK: 
                case NativeMethods.WM_LBUTTONDOWN: 
                    // If the OnEnter procedure is called, it's because of a mouse down event, and not a TAB key.
                    this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] = true; 
                    try
                    {
                        base.WndProc(ref m);
                    } 
                    finally
                    { 
                        this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] = false; 
                    }
                    return; 
                case NativeMethods.WM_NOTIFY:
                    if (WmNotify(ref m))
                    {
                        // we are done - skip default handling 
                        return;
                    } 
                    break; 

                case NativeMethods.WM_IME_STARTCOMPOSITION: 
                case NativeMethods.WM_IME_COMPOSITION:
                    if (this.editingControl != null)
                    {
                        // Make sure that the first character is forwarded to the editing control. 
                        this.editingControl.SendMessage(m.Msg, m.WParam, m.LParam);
                    } 
                    break; 
            }
 
            base.WndProc(ref m);
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK