您必须自定义自己的DataGridView
. 这允许您将自定义代码添加到WndProc
然后您可以捕获消息WM_LBUTTONDOWN
,检查鼠标是否在 a 上DataGridViewButtonCell
以丢弃该消息。不知何故,CellContentClick
仍然提出了(这是由 的内部实现完成的DataGridView
)。然而丢弃后WM_LBUTTONDOWN
,就失去了压制状态Button
的观感。这有点烦人。因此,为了模仿这种状态,我们必须自己绘制按钮。绘制按钮让我们模仿更多的状态,而不仅仅是按下状态(例如hot state,normal state)。这是适合您的代码,可以完美运行:
public class CustomGrid : DataGridView
{
DataGridViewCell downButton;
DataGridViewCell lastHoveredCell;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x201)//WM_LBUTTONDOWN = 0x201
{
HitTestInfo ht = TryHitTest(m);
if (ht.Type == DataGridViewHitTestType.Cell)
{
downButton = this[ht.ColumnIndex, ht.RowIndex];
if (SelectedCells.Count > 1&&downButton is DataGridViewButtonCell){
InvalidateCell(ht.ColumnIndex, ht.RowIndex);
return;
}
}
} else if (m.Msg == 0x202) downButton = null; //WM_LBUTTONUP = 0x202
else if (m.Msg == 0x200) { //WM_MOUSEMOVE = 0x200
HitTestInfo ht = TryHitTest(m);
if (ht.Type == DataGridViewHitTestType.Cell)
{
if (lastHoveredCell != this[ht.ColumnIndex, ht.RowIndex]){
if(lastHoveredCell != null &&
lastHoveredCell.DataGridView!=null)
InvalidateCell(lastHoveredCell);
lastHoveredCell = this[ht.ColumnIndex, ht.RowIndex];
InvalidateCell(lastHoveredCell);
}
}
}
base.WndProc(ref m);
}
private HitTestInfo TryHitTest(Message m)
{
int x = m.LParam.ToInt32() & 0xffff;
int y = m.LParam.ToInt32() >> 16;
return HitTest(x, y);
}
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex > -1 && e.RowIndex > -1 && this[e.ColumnIndex, e.RowIndex] is DataGridViewButtonCell)
{
e.Handled = true;
e.PaintBackground(e.ClipBounds, false);
Rectangle buttonBounds = e.CellBounds;
string text = ((DataGridViewButtonColumn)Columns[e.ColumnIndex]).Text;
var buttonState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
if(buttonBounds.Contains(PointToClient(MousePosition))){
buttonState = MouseButtons == MouseButtons.Left && downButton == this[e.ColumnIndex, e.RowIndex] ?
System.Windows.Forms.VisualStyles.PushButtonState.Pressed :
System.Windows.Forms.VisualStyles.PushButtonState.Hot;
}
ButtonRenderer.DrawButton(e.Graphics, buttonBounds, text, e.CellStyle.Font, false, buttonState);
}
else base.OnCellPainting(e);
}
protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e) {
base.OnColumnWidthChanged(e);
InvalidateColumn(e.Column.Index);
}
}
此屏幕截图显示,当所有选定的单元格仍处于选中状态时,正在按下一个按钮。