【问题标题】:Owner drawn listbox not drawing previously selected item所有者绘制的列表框未绘制先前选择的项目
【发布时间】:2012-10-11 01:12:53
【问题描述】:

我想增加列表框中项目的高度 - 基本上是在内部填充它们。除此之外,我不想更改默认列表框行为。我已按照 MSDN 示例进行所有者绘制的列表项,但我遇到了问题。默认列表框以黑色绘制项目,以蓝色突出显示选定的项目。为了完成同样的功能,我在 DrawItem 事件处理程序中使用了以下代码:

private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
    {
        Brush b = (e.Index == ((ListBox)sender).SelectedIndex ? Brushes.White : Brushes.Black);
        e.DrawBackground();
        e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, b, new Rectangle(new Point(e.Bounds.X, e.Bounds.Y + 2), e.Bounds.Size));
        e.DrawFocusRectangle();
    }

这似乎工作正常,除非我在列表中单击。所选项目确实显示为蓝色背景上的白色文本,但之前选择的项目仍为白色。似乎我选择的项目被重绘,但之前选择的项目没有。如果我移动到另一个控件,列表框会重新绘制。我错过了什么?

【问题讨论】:

  • 使用 SelectedIndex 是错误的,它的值会在不可预知的时刻发生变化。您必须改用 e.State。

标签: c# winforms listbox ownerdrawn


【解决方案1】:

要为列表框添加内边距,只需将列表框的 .ItemHeight 设置为某个高度即可。

否则,如果您想进行所有者绘制,而不是手动选择颜色,请使用 e.ForeColor。像这样:

Brush b = new SolidBrush(e.ForeColor);

请注意,在这种情况下,您也必须为所选项目绘制背景。 检查列表框项的状态可以这样执行:

e.Graphics.FillRectangle((e.State & DrawItemState.Selected) != 0 ? SystemBrushes.Highlight : SystemBrushes.Window, new Rectangle(new Point(e.Bounds.X, e.Bounds.Y + 2), e.Bounds.Size));

【讨论】:

    【解决方案2】:

    答案: ListBox.SelectedIndex 非常不合理(就像 Hans 所说的那样),但 e.ForeColor 足够正确。改用它。

    替换你的代码:e.Index == ((ListBox)sender).SelectedIndex

    e.ForeColor == SystemColors.HighlightText

     

    支持数据:

    将此行添加到listBox1_DrawItem 的顶部:

    Console.WriteLine("e.Index=" + e.Index + " SelectedIndex=" + 
      listBox1.SelectedIndex + " ForeColor=" + e.ForeColor);
    

    它产生这样的输出(//注释)

    // Added 4 items to listbox
    e.Index=0 SelectedIndex=-1 ForeColor=Color [WindowText]
    e.Index=1 SelectedIndex=-1 ForeColor=Color [WindowText]
    e.Index=2 SelectedIndex=-1 ForeColor=Color [WindowText]
    e.Index=3 SelectedIndex=-1 ForeColor=Color [WindowText]
    
    // MouseDown on item 0
    e.Index=0 SelectedIndex=-1 ForeColor=Color [WindowText]
    e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
    e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
    e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
    e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
    e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
    e.Index=1 SelectedIndex=0 ForeColor=Color [WindowText]
    e.Index=2 SelectedIndex=0 ForeColor=Color [WindowText]
    e.Index=3 SelectedIndex=0 ForeColor=Color [WindowText]
    e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
    // MouseUp on item 0 (no DrawItem events)
    
    // MouseDown for item 1
    e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
    e.Index=0 SelectedIndex=0 ForeColor=Color [WindowText]
    e.Index=1 SelectedIndex=1 ForeColor=Color [HighlightText]
    e.Index=1 SelectedIndex=1 ForeColor=Color [HighlightText]
    // MouseUp for item 1 (no DrawItem events)
    
    // MouseDown for item 2
    e.Index=1 SelectedIndex=1 ForeColor=Color [HighlightText]
    e.Index=1 SelectedIndex=1 ForeColor=Color [WindowText]
    e.Index=2 SelectedIndex=2 ForeColor=Color [HighlightText]
    e.Index=2 SelectedIndex=2 ForeColor=Color [HighlightText]
    
    // Drag to item 3
    e.Index=2 SelectedIndex=2 ForeColor=Color [HighlightText]
    e.Index=2 SelectedIndex=2 ForeColor=Color [WindowText]
    e.Index=3 SelectedIndex=3 ForeColor=Color [HighlightText]
    e.Index=3 SelectedIndex=3 ForeColor=Color [HighlightText]
    // MouseUp over item 3 (no DrawItem events)
    

    所以基本上... ListBox 绘制的可能比我们想要的多,但您最终会在最后一次绘制时获得正确的颜色。

    我也推荐DoubleBuffering

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多