2010-03-09 4 views
4

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

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

+0

FYI, всегда полезно включать версию .Net, с которой вы имеете дело. Я дам вашему образцу попытку выяснить, полностью ли я понимаю, что вы видите. Если я думаю, что я это сделаю, я скажу вам, что я думаю, что происходит. –

+0

Кроме того, я никогда не являюсь поклонником рисования потребителем элемента управления. Я всегда стараюсь сделать это в производном классе, таким образом, если такое же поведение необходимо для другой формы или приложения, это проще сделать. –

+0

Я не могу воспроизвести описанное поведение с дефолтом по умолчанию, но может с помощью настраиваемого кода. Я запускаю Vista x64; VS 2008. .Net 3.5. Не могли бы вы добавить версию ОС, Visual Studio и .Net, которые вы используете на вопрос. (Я слышал слухи о том, что Vista и Windows 7 имеют некоторые отличия против XP за то, как TreeViews работают в ОС.) –

ответ

3

Изменить

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. Дайте мне знать, если это сработает для вас.

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

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); 
    } 
} 
+0

Кроме того, захват кнопок мыши с помощью мыши и вниз не работает. Это может быть специфично для XP, но элемент управления уже обрабатывает выбор и перерисовку, прежде чем события mosue будут подняты в элементе управления. – Coincoin

+0

Я пробовал что-то подобное, и он отлично работает ... пока вы не прокрутите и не перетащите.Я смирился с тем, что сам рисовал весь предмет, и теперь, по крайней мере, текст синхронизируется с цветом задней поверхности, хотя поведение немного странно. Я соглашусь на ваш ответ так, как есть, я думаю, ближайшее время мы сможем получить исходное поведение XP без сбоев. – Coincoin

+0

OOf. Наверное, я не беспокоился о прокрутке и перетаскивании. Я сделал все, что рисовал сам. Это много кода, но стоит при необходимости. (Я считаю, что мой код был ~ 1000 LOC, поскольку мне нужно было снять флажки, плюс минус и строки ...) –