2017-07-14 31 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);