private static Rectangle GetSpannedCellBoundsFromChildCellBounds(DataGridViewImageCellEx childCell, Rectangle childCellBounds)
        {
            var dataGridView = childCell.DataGridView;
            var ownerCell    = childCell.OwnerCell == null
                ? childCell
                : childCell.OwnerCell;
            var spannedCellBounds = childCellBounds;
            //
            var firstVisibleColumnIndex = Enumerable.Range(ownerCell.ColumnIndex, ownerCell.ColumnSpan)
                                          .First(i => dataGridView.Columns[i].Visible);

            if (dataGridView.Columns[firstVisibleColumnIndex].Frozen)
            {
                spannedCellBounds.X = dataGridView.GetColumnDisplayRectangle(firstVisibleColumnIndex, false).X;
            }
            else
            {
                spannedCellBounds.X -= Enumerable.Range(firstVisibleColumnIndex, childCell.ColumnIndex - firstVisibleColumnIndex)
                                       .Select(i => dataGridView.Columns[i])
                                       .Where(columnItem => columnItem.Visible)
                                       .Sum(columnItem => columnItem.Width);
            }
            //
            var firstVisibleRowIndex = Enumerable.Range(ownerCell.RowIndex, ownerCell.RowSpan)
                                       .First(i => dataGridView.Rows[i].Visible);

            if (dataGridView.Rows[firstVisibleRowIndex].Frozen)
            {
                spannedCellBounds.Y = dataGridView.GetRowDisplayRectangle(firstVisibleRowIndex, false).Y;
            }
            else
            {
                spannedCellBounds.Y -= Enumerable.Range(firstVisibleRowIndex, childCell.RowIndex - firstVisibleRowIndex)
                                       .Select(i => dataGridView.Rows[i])
                                       .Where(rowItem => rowItem.Visible)
                                       .Sum(rowItem => rowItem.Height);
            }
            //
            spannedCellBounds.Width = Enumerable.Range(ownerCell.ColumnIndex, ownerCell.ColumnSpan)
                                      .Select(i => dataGridView.Columns[i])
                                      .Where(columnItem => columnItem.Visible)
                                      .Sum(columnItem => columnItem.Width);
            //
            spannedCellBounds.Height = Enumerable.Range(ownerCell.RowIndex, ownerCell.RowSpan)
                                       .Select(i => dataGridView.Rows[i])
                                       .Where(rowItem => rowItem.Visible)
                                       .Sum(rowItem => rowItem.Height);

            return(spannedCellBounds);
        }
        private static Rectangle GetSpannedCellClipBounds(DataGridViewImageCellEx ownerCell,
                                                          Rectangle cellBounds)
        {
            DataGridView dataGridView = ownerCell.DataGridView;
            var          clipBounds   = cellBounds;

            //Setting X.
            foreach (int i in Enumerable.Range(ownerCell.ColumnIndex, ownerCell.m_ColumnSpan))
            {
                var columnItem = dataGridView.Columns[i];
                if (!columnItem.Visible)
                {
                    continue;
                }
                if (columnItem.Frozen ||
                    i > dataGridView.FirstDisplayedScrollingColumnIndex)
                {
                    break;
                }
                if (i == dataGridView.FirstDisplayedScrollingColumnIndex)
                {
                    clipBounds.X += dataGridView.FirstDisplayedScrollingColumnHiddenWidth;
                    break;
                }
                clipBounds.X += columnItem.Width;
            }
            //Setting Width.
            clipBounds.Width = Enumerable.Range(ownerCell.ColumnIndex, ownerCell.m_ColumnSpan)
                               .Sum(i =>
            {
                var columnItem = dataGridView.Columns[i];
                if (!columnItem.Visible)
                {
                    return(0);
                }
                if (columnItem.Frozen ||
                    i > dataGridView.FirstDisplayedScrollingColumnIndex)
                {
                    return(columnItem.Width);
                }
                if (i == dataGridView.FirstDisplayedScrollingColumnIndex)
                {
                    return(columnItem.Width
                           - dataGridView.FirstDisplayedScrollingColumnHiddenWidth);
                }
                return(0);
            });
            //Setting Y.
            foreach (var i in Enumerable.Range(ownerCell.RowIndex, ownerCell.m_RowSpan))
            {
                var rowItem = dataGridView.Rows[i];
                if (!rowItem.Visible)
                {
                    continue;
                }
                if (rowItem.Frozen ||
                    i >= dataGridView.FirstDisplayedScrollingRowIndex)
                {
                    break;
                }
                clipBounds.Y += rowItem.Height;
            }
            //Setting Height.
            clipBounds.Height = Enumerable.Range(ownerCell.RowIndex, ownerCell.m_RowSpan)
                                .Sum(i =>
            {
                var rowItem = dataGridView.Rows[i];
                if (!rowItem.Visible)
                {
                    return(0);
                }
                if (rowItem.Frozen ||
                    i >= dataGridView.FirstDisplayedScrollingRowIndex)
                {
                    return(dataGridView.Rows[i].Height);
                }
                return(0);
            });

            //exclude borders.
            if (dataGridView.BorderStyle != BorderStyle.None)
            {
                var clientRectangle = dataGridView.ClientRectangle;
                clientRectangle.Width--;
                clientRectangle.Height--;
                clipBounds.Intersect(clientRectangle);
            }
            return(clipBounds);
        }
        protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            if (m_OwnerCell != null && m_OwnerCell.DataGridView == null)
            {
                m_OwnerCell = null; //owner cell was removed.
            }
            if (DataGridView == null ||
                (m_OwnerCell == null && m_ColumnSpan == 1 && m_RowSpan == 1))
            {
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle,
                           paintParts);
                return;
            }

            var ownerCell   = this;
            var columnIndex = ColumnIndex;
            var columnSpan  = m_ColumnSpan;
            var rowSpan     = m_RowSpan;

            if (m_OwnerCell != null)
            {
                ownerCell      = m_OwnerCell;
                columnIndex    = m_OwnerCell.ColumnIndex;
                rowIndex       = m_OwnerCell.RowIndex;
                columnSpan     = m_OwnerCell.ColumnSpan;
                rowSpan        = m_OwnerCell.RowSpan;
                value          = m_OwnerCell.GetValue(rowIndex);
                errorText      = m_OwnerCell.GetErrorText(rowIndex);
                cellState      = m_OwnerCell.State;
                cellStyle      = m_OwnerCell.GetInheritedStyle(null, rowIndex, true);
                formattedValue = m_OwnerCell.GetFormattedValue(value,
                                                               rowIndex, ref cellStyle, null, null, DataGridViewDataErrorContexts.Display);
            }
            if (CellsRegionContainsSelectedCell(columnIndex, rowIndex, columnSpan, rowSpan))
            {
                cellState |= DataGridViewElementStates.Selected;
            }
            cellBounds = GetSpannedCellBoundsFromChildCellBounds(this, cellBounds);
            clipBounds = GetSpannedCellClipBounds(ownerCell, cellBounds);
            using (var g = DataGridView.CreateGraphics())
            {
                g.SetClip(clipBounds);
                //Paint the content.
                ownerCell.InternalPaint(g, clipBounds, cellBounds, rowIndex, cellState,
                                        value, formattedValue, errorText,
                                        cellStyle, advancedBorderStyle,
                                        paintParts & ~DataGridViewPaintParts.Border);
                //Paint the borders.
                if ((paintParts & DataGridViewPaintParts.Border) != DataGridViewPaintParts.None)
                {
                    var leftTopCell = ownerCell;
                    DataGridViewAdvancedBorderStyle advancedBorderStyle2 = new DataGridViewAdvancedBorderStyle()
                    {
                        Left   = advancedBorderStyle.Left,
                        Top    = advancedBorderStyle.Top,
                        Right  = DataGridViewAdvancedCellBorderStyle.None,
                        Bottom = DataGridViewAdvancedCellBorderStyle.None
                    };
                    leftTopCell.PaintBorder(g, clipBounds, cellBounds, cellStyle, advancedBorderStyle2);

                    var rightBottomCell = DataGridView[columnIndex + columnSpan - 1, rowIndex + rowSpan - 1] as DataGridViewImageCellEx;
                    if (rightBottomCell == null)
                    {
                        rightBottomCell = this;
                    }
                    DataGridViewAdvancedBorderStyle advancedBorderStyle3 = new DataGridViewAdvancedBorderStyle()
                    {
                        Left   = DataGridViewAdvancedCellBorderStyle.None,
                        Top    = DataGridViewAdvancedCellBorderStyle.None,
                        Right  = advancedBorderStyle.Right,
                        Bottom = advancedBorderStyle.Bottom
                    };
                    rightBottomCell.PaintBorder(g, clipBounds, cellBounds, cellStyle, advancedBorderStyle3);
                }
            }
        }