在 DataGridViewCell 上绘制 ComboBox DropDown 箭头
Painting ComboBox DropDown arrow on DataGridViewCell
我想要的是当鼠标移到DataGridViewCell 上时,我想识别鼠标下方的单元格,并在其上绘制一个ComboBox DownArrow。当鼠标移出单元格时,我只想绘制 "normal" 单元格。
我认为我需要绘制鼠标下方的单元格,和 重新绘制它之前所在的单元格,以清除之前任何自定义绘制的箭头。
我这样做的方法如下注意:所有这些代码都在 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;
}
}
我已经测试过了,用鼠标在单元格下方绘制并清除其他单元格效果很好。
"Test" 是使用此代码完成的,只需在单元格周围绘制一个矩形。
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 周围出现了一个漂亮的蓝色矩形。
然后我尝试开发类似的代码来绘制 ComboBox 下拉箭头,并尝试使用 ComboBoxRenderer class:
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()
效果更好
注意上面代码的"Paint the cell"部分用到了这段代码
有任何解决此问题的建议,或者可能出了什么问题?
好的 - 问题已解决!
我将绘图设置为:
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);
我想要的是当鼠标移到DataGridViewCell 上时,我想识别鼠标下方的单元格,并在其上绘制一个ComboBox DownArrow。当鼠标移出单元格时,我只想绘制 "normal" 单元格。
我认为我需要绘制鼠标下方的单元格,和 重新绘制它之前所在的单元格,以清除之前任何自定义绘制的箭头。
我这样做的方法如下注意:所有这些代码都在 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;
}
}
我已经测试过了,用鼠标在单元格下方绘制并清除其他单元格效果很好。
"Test" 是使用此代码完成的,只需在单元格周围绘制一个矩形。
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 周围出现了一个漂亮的蓝色矩形。
然后我尝试开发类似的代码来绘制 ComboBox 下拉箭头,并尝试使用 ComboBoxRenderer class:
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()
注意上面代码的"Paint the cell"部分用到了这段代码
有任何解决此问题的建议,或者可能出了什么问题?
好的 - 问题已解决!
我将绘图设置为:
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);