单击空白区域时,如何防止ListBox的最后一项被选中

时间:2011-03-08 23:52:12

标签: c# .net winforms listbox

我有一个未完全填充项目的列表框,并且在最后一项之后有一些空白区域。当我单击该空白区域时,最后一项将自动被选中。并且该选择发生在MouseDown事件之前。而且我希望它不会发生。

我可以在SelectedIndexChanged的变量中保留当前选定的索引(只能选择一个项目),并在MouseDown中重置,但在MouseDownMouseUp之间重置最后一项被选中 - 看起来不太好。

如何在单击空白区域时阻止选择最后一项?


P.S。这是所有者绘制的ListBox,但我不确定它与此问题有什么关系。

private void listBox_DrawItem(object sender, DrawItemEventArgs e)
{
    if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
    {
        e.Graphics.FillRectangle(Brushes.LightSteelBlue, e.Bounds);
    }
    else
    {
        e.Graphics.FillRectangle(Brushes.White, e.Bounds);
    }

    if (_commands.Count > 0)
    {
        KeyValuePair<string, string> cmd = (KeyValuePair<string, string>)_commands[e.Index];

        // FIRST ROW
        e.Graphics.DrawString(cmd.Key, _cmdNameFont, Brushes.Black, e.Bounds.X, e.Bounds.Y + _cellPadding);

        // SECOND ROW
        e.Graphics.DrawString(cmd.Value,
            _cmdCommandFont, Brushes.Black, e.Bounds.X + 5, e.Bounds.Y + _cmdNameFont.Height + _cellPadding);
    }

    e.DrawFocusRectangle();
}

private void listBox_MeasureItem(object sender, MeasureItemEventArgs e)
{
    e.ItemHeight = _cmdNameFont.Height + _cmdCommandFont.Height + _cellPadding * 2 ;
}

3 个答案:

答案 0 :(得分:1)

我有一个解决方法。您可以放置​​面板并根据屏幕高度,列表框高度动态更改其高度。在这种情况下,当您单击空白区域时,新面板将单击该按钮。

答案 1 :(得分:0)

确保从OnMeasureItem返回正确的值。


编辑:似乎与OwnerDrawVariable的工作方式不同 通常,如果单击空白空间,则IndexFromPoint(命中测试)返回-1。 使用OwnerDrawVariable,它返回底部项目。

你有两个选择。

1)你的物品都是相同的高度,所以你可以使用OwnerDrawFixed,你的问题就会消失。

base.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.ItemHeight = this.Font.Height + this.Font.Height + _cellPadding * 2;

2)在较低级别处理鼠标并丢弃空白区域。

答案 2 :(得分:0)

您可以通过检查鼠标按下消息来执行此操作,如果用户没有单击某个项目,则不允许它处理消息:

public class ListBoxEx : ListBox {
  private const int WM_LBUTTONDOWN = 0x201;

  protected override void WndProc(ref Message m) {
    int lParam = m.LParam.ToInt32();
    int wParam = m.WParam.ToInt32();
    if (m.Msg == WM_LBUTTONDOWN) {
      Point clickedPt = new Point();
      clickedPt.X = lParam & 0x0000FFFF;
      clickedPt.Y = lParam >> 16;
      bool lineOK = false;
      for (int i = 0; i < Items.Count; i++) {
        if (GetItemRectangle(i).Contains(clickedPt)) {
          lineOK = true;
        }
      }
      if (!lineOK) {
        return;
      }        
    }
    base.WndProc(ref m);
  }
}

OwnerDrawVariable ListBox selects last item when clicking on control below items

的答案中发布此内容