独自にカスタマイズする必要がありますDataGridView
。これにより、カスタム コードを に追加してWndProc
、メッセージをキャッチしWM_LBUTTONDOWN
、マウスが上にあるかどうかを確認して、DataGridViewButtonCell
そのメッセージを破棄することができます。どういうわけかCellContentClick
がまだ発生しています (これは の内部実装によって行われますDataGridView
)。ただし、 を廃棄するWM_LBUTTONDOWN
と、は押された状態Button
のルック アンド フィールを失います。それは少し面倒です。その状態を模倣するには、自分でボタンを描画する必要があります。ボタンを描画すると、押された状態だけでなく、より多くの状態(ホット状態、通常状態など) を模倣できます。これがあなたのためのコードです、完全に動作します:
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);
}
}
このスクリーンショットは、選択されたすべてのセルがまだ選択されている間に、1 つのボタンが押されていることを示しています。
