ListBox DrawItem HotLight State in the OwnerDraw m

2020-04-05 01:05发布

问题:

I'm using OwnerDrawFixed as a DrawMode for the custom ListBox control in my WinForms app.

I want to repaint the background (or do some other action) of the ListBoxItem when the user hovers over the listbox item, that is, at the MouseMove...

DrawItemState.HotLight never works for the ListBox, so i wonder how to emulate it, how to workaround this problem.

回答1:

It took me only two years to find the answer for you, but here it is:

The DrawItemState.HotLight only applies to owner drawn menus, not the listbox. For the ListBox, you have to keep track of the item yourself:

public partial class Form1 : Form
{
  private int _MouseIndex = -1;

  public Form1()
  { InitializeComponent(); }

  private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
  {
    Brush textBrush = SystemBrushes.WindowText;

    if (e.Index > -1)
    {
      if (e.Index == _MouseIndex)
      {
        e.Graphics.FillRectangle(SystemBrushes.HotTrack, e.Bounds);
        textBrush = SystemBrushes.HighlightText;
      }
      else
      {
        if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
        {
          e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
          textBrush = SystemBrushes.HighlightText;
        }
        else
          e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
      }
      e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, textBrush, e.Bounds.Left + 2, e.Bounds.Top);
    }
  }

  private void listBox1_MouseMove(object sender, MouseEventArgs e)
  {
    int index = listBox1.IndexFromPoint(e.Location);
    if (index != _MouseIndex)
    {
      _MouseIndex = index;
      listBox1.Invalidate();
    }
  }

  private void listBox1_MouseLeave(object sender, EventArgs e)
  {
    if (_MouseIndex > -1)
    {
      _MouseIndex = -1;
      listBox1.Invalidate();
    }
  }
}


回答2:

This solution will just weigh your code down; just try this:

If e.State And DrawItemState.Selected Then
                    e.Graphics.FillRectangle(SystemBrushes.HotTrack, e.Bounds)
                    e.Graphics.DrawString(drv, Me.Font, SystemBrushes.HighlightText, e.Bounds.X + 18, e.Bounds.Y + 1)
                Else
                    e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds)
                    e.Graphics.DrawString(drv, Me.Font, SystemBrushes.ControlText, e.Bounds.X + 18, e.Bounds.Y + 1)
End If

This operation: e.State And DrawItemState.Selected verifies the item is hovered. No need to put a whole pack of code just to know what item is hovered.