【问题标题】:TreeView owner draw glitch when selecting选择时 TreeView 所有者绘制故障
【发布时间】:2010-03-09 21:38:51
【问题描述】:

我正在尝试向标准 System.Windows.Forms.TreeView 控件的元素添加更多图标。

我的计划是只更改树视图控件的标签区域,但它显示出一种奇怪的行为。如果我单击一个节点来选择它,当按下鼠标按钮时,背景会以高亮颜色正确绘制。但是,在我释放鼠标按钮之前,文本是错误的未选择颜色。就好像e.State 在按下和释放鼠标按钮之间包含错误的状态。

这就是我正在做的事情:我使用this.DrawMode = TreeViewDrawMode.OwnerDrawText 进行初始化,然后使用this.DrawNode += LayoutTreeView_DrawNode 注册我的事件处理程序。这是处理程序:

void LayoutTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
{

    Color color = (e.State & TreeNodeStates.Selected) != 0 ?
        SystemColors.HighlightText : SystemColors.WindowText;

    TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.SingleLine |
       TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis;

    TextRenderer.DrawText(e.Graphics, e.Node.Text, Font, e.Bounds, color, flags);
}

如果我将处理程序设置为默认情况...

void LayoutTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
    e.DefaultDraw = true;
}

...同样的事情发生了,这很奇怪,因为 windows 现在实际上正在绘制它。此行为在带有 .Net 3.5 的 Windows XP 中。

有什么办法可以解决这种奇怪的行为吗?

【问题讨论】:

  • 仅供参考,包含您正在处理的 .Net 版本总是很有用的。我会试一试你的样本,看看我是否完全理解你所看到的。如果我想我会告诉你我的想法。
  • 另外,我从不喜欢在控件的使用者中进行绘图。我总是推动在派生类中完成它,这样如果在另一个表单或应用程序上需要相同的行为,它会更容易做到。
  • 我无法使用默认绘制重现所描述的行为,但可以使用自定义代码。我正在运行 Vista x64; VS 2008。.Net 3.5。您能否将您正在使用的操作系统、Visual Studio 和 .Net 版本添加到问题中。 (我听说 Vista 和 Windows 7 在 TreeViews 在操作系统中的工作方式方面与 XP 存在一些差异。)
  • 嗯,实际上它是一个使用自己的事件的派生控件。该行为在带有 .Net 3.5 的 Windows XP 中

标签: c# .net winforms treeview ownerdrawn


【解决方案1】:

改变

Color color = (e.State & TreeNodeStates.Selected) != 0 ?
    SystemColors.HighlightText : SystemColors.WindowText;

Color color = (e.State & TreeNodeStates.Focused) != 0 ?
    SystemColors.HighlightText : SystemColors.WindowText;

这适用于带有 .Net 3.5 的 Vista x64 和 VS 2008。让我知道它是否适合您。

在观察默认窗口行为时,我观察到的是文本和突出显示在节点被选中并获得焦点之前不会被绘制。所以我检查了焦点条件以更改文本颜色。然而,这并不能精确地模仿寡妇行为,在鼠标释放之前不使用新颜色。当它选择在所有者绘制模式下绘制蓝色突出显示状态时,它出现了这一点,而不是在 Windows 绘制它时......这无疑是令人困惑的。

编辑 但是,当您创建自己的派生树视图时,您可以完全控制何时绘制所有内容。

public class MyTreeView : TreeView
{
    bool isLeftMouseDown = false;
    bool isRightMouseDown = false;
    public MyTreeView()
    {
        DrawMode = TreeViewDrawMode.OwnerDrawText;
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        TrackMouseButtons(e);
        base.OnMouseDown(e);
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        TrackMouseButtons(e);
        base.OnMouseUp(e);
    }
    protected override void OnMouseMove(MouseEventArgs e)
    {
        TrackMouseButtons(e);
        base.OnMouseMove(e);
    }

    private void TrackMouseButtons(MouseEventArgs e)
    {
        isLeftMouseDown = e.Button == MouseButtons.Left;
        isRightMouseDown = e.Button == MouseButtons.Right;
    }

    protected override void OnDrawNode(DrawTreeNodeEventArgs e)
    {
        // don't call the base or it will goof up your display!
        // capture the selected/focused states
        bool isFocused = (e.State & TreeNodeStates.Focused) != 0;
        bool isSelected = (e.State & TreeNodeStates.Selected) != 0;
        // set up default colors.
        Color color = SystemColors.WindowText;
        Color backColor = BackColor;

        if (isFocused && isRightMouseDown)
        {
            // right clicking on a 
            color = SystemColors.HighlightText;
            backColor = SystemColors.Highlight;
        }
        else if (isSelected && !isRightMouseDown)
        {
            // if the node is selected and we're not right clicking on another node.
            color = SystemColors.HighlightText;
            backColor = SystemColors.Highlight;
        }

        using (Brush sb = new SolidBrush(backColor))
            e.Graphics.FillRectangle(sb,e.Bounds);

        TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.SingleLine |
           TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis;

        TextRenderer.DrawText(e.Graphics, e.Node.Text, Font, e.Bounds, color, backColor, flags);
    }
}

【讨论】:

  • 此外,使用 mouseup 和 down 捕获鼠标按钮也不起作用。这可能是特定于 XP 的,但在控件中引发鼠标事件之前,控件已经在处理选择和重绘。
  • 我尝试了类似的方法,但效果很好....直到您滚动并拖放。我辞职自己绘制整个项目,现在至少文本与背景颜色同步,即使行为有点奇怪。我会接受您的回答,我想,这是我们可以在没有故障的情况下最接近原始 XP 行为的方式。
  • OOf.我想我没有打扰滚动和拖放。我已经完成了整个绘制它自己一点点。这是很多代码,但如果需要,它是值得的。 (我相信我的代码约为 1000 LOC,因为我需要绘制复选框,加上减号和线条......)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-03
  • 2011-08-15
  • 2012-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多