2017-07-14 42 views
0

我想要的是,当鼠标移过DataGridViewCell时,我想识别鼠标下方的单元格,并在其上绘制ComboBox DownArrow。当鼠标离开单元格时,我只需要绘制“正常”单元格。在DataGridViewCell上绘制组合框下拉箭头

我觉得我需要在鼠标下绘制单元格,重新绘制它之前所在的单元格,以清除以前自定义绘制的箭头。

我这样做的方式如下注意:所有这些代码位于DataGridView级别,而不是单元级别。

private DataGridViewCell LastCell; 
private DataGridViewCell MouseCell; 
protected override void OnMouseMove(MouseEventArgs e) 
{ 
    base.OnMouseMove(e); 

    DataGridViewCell currentCell = GetCellUnderCursor(); 
    if (currentCell != MouseCell) //Has moved to a new cell 
    { 
     LastCell = MouseCell; 
     MouseCell = currentCell; 
     if (currentCell != null) this.InvalidateCell(currentCell); 
     if (LastCell != null) this.InvalidateCell(LastCell); 
    } 
    else 
    { 
     //Has not changed cell - don't paint again - exit to prevent flicker 
     return; 
    } 
} 

我已经进行了测试,效果很好油漆用鼠标电池在它之下,并清除其他细胞。

使用此代码完成“测试”以简单地在单元格周围绘制矩形。

protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e) 
{ 
    //call base method 
    base.OnCellPainting(e); 
    e.PaintContent(e.ClipBounds); 
    if (e.RowIndex == -1 || e.ColumnIndex == -1) return; 

    //Is the mouse over this cell? 
    DataGridViewCell cell = GetCellUnderCursor(); 
    if (cell == null) return; //row or column is -1 

    DataGridViewCell paintingCell = this.Rows[e.RowIndex].Cells[e.ColumnIndex]; 
    if (paintingCell != cell) return; 


    //Paint the cell, excluding the border. 
    e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Border); 

    //Now paint a custom border. 
    using (Pen p = new Pen(Color.RoyalBlue, 1)) 
    { 
     Rectangle rect = e.CellBounds; 
     rect.Width -= 2; 
     rect.Height -= 2; 
     e.Graphics.DrawRectangle(p, rect); 
    } 
    e.PaintContent(e.ClipBounds); 
    e.Handled = true; 
} 

如上所述,这一切运作良好 - 我的鼠标围绕着DataGridView,出现一个漂亮的蓝色矩形。

然后我试图开发类似的代码来绘制一个组合框的下拉箭头,并正尝试与ComboBoxRenderer类做到这一点:

Size arrowSize = new Size(18,20); 
Rectangle arrowRectangle = new Rectangle(e.ClipBounds.X + e.ClipBounds.Width - arrowSize.Width -1, e.ClipBounds.Y+1,arrowSize.Width, arrowSize.Height); 
Rectangle topTextBoxRectangle = new Rectangle(e.ClipBounds.X, e.ClipBounds.Y, e.ClipBounds.Width, arrowSize.Height+2); 
ComboBoxState arrowState = ComboBoxState.Normal; 
if (!ComboBoxRenderer.IsSupported) 
{ 
    Debug.WriteLine("Renderer not supported"); 
    return; 
} 
else 
{ 
    string cellText = cell.Value == null ? "" : cell.Value.ToString(); 
    ComboBoxRenderer.DrawDropDownButton(e.Graphics, arrowRectangle, arrowState); 
    //ComboBoxRenderer.DrawTextBox(e.Graphics, topTextBoxRectangle, cellText, this.Font, ComboBoxState.Normal); 
    e.PaintContent(e.ClipBounds); 
} 
e.Handled = true; 

这真的完全不很好地工作 - 细胞的画有时描绘下拉菜单(似乎将它绘制在错误的单元格上面的单元格中)如果您将鼠标移动到DataGridView上方,它将绘制上面的单元格。如果你正在移动它,它会绘制正确的单元格(真的!),向下移动并不能清除任何旧的绘图,但是向上移动却是。同样,将鼠标从左到右移动会产生正确的行为,但不是向左移动。

我发现e.PaintContents(e.ClipBounds)似乎工作,这段代码在上面的代码中的“画图小区”部分使用比ComboBoxRenderer.DrawTextBox()

注意要好得多。

任何建议来解决这个问题,或者可能会出错?

回答

0

好的 - 问题解决了!

我的图纸设置为:

Rectangle arrowRectangle = new Rectangle(e.ClipBounds.X + e.ClipBounds.Width - arrowSize.Width -1, 
    e.ClipBounds.Y+1,arrowSize.Width, arrowSize.Height); 

当它应该使用CellBounds,不ClipBounds了:

Rectangle arrowRectangle = new Rectangle(e.CellBounds.X + e.CellBounds.Width - arrowSize.Width - 1, 
    e.CellBounds.Y + 1, arrowSize.Width, arrowSize.Height);