Владелец TreeView рисует глюк при выборе - PullRequest
4 голосов
/ 10 марта 2010

Я пытаюсь добавить еще несколько значков к элементам стандартного элемента управления 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 фактически рисует это сейчас. Это поведение в Windows XP с .Net 3.5.

Есть ли способ обойти это странное поведение?

1 Ответ

3 голосов
/ 11 марта 2010

Изменение

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

до

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

Это работало на Vista x64 и VS 2008 с .Net 3.5. Дайте мне знать, если это работает для вас.

То, что я наблюдал, наблюдая за поведением окон по умолчанию, было то, что текст и выделение не были нарисованы, пока узел не был выбран и имел фокус. Поэтому я проверил фокусное условие, чтобы изменить цвет текста. Однако это точно не имитирует поведение вдов, когда новые цвета не используются, пока мышь не будет отпущена. Появляется точка, когда он выбирает рисовать изменения статуса синей подсветки в режиме владельца, в отличие от рисования окон ... Что, по общему признанию, сбивает с толку.

EDIT Однако, когда вы создаете свое собственное производное древовидное представление, вы полностью контролируете, когда все отрисовывается.

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);
    }
}
...