Как изменить мои значки treeView вместо +,-, как древовидное представление проводника Windows в формах выигрыша c # .net

Как я могу изменить развертывание/свертывание изображений из изображений плюс (+) и минус (-), которые появляются, когда ShowPlusMinus и/или ShowRootLines равны true.

Чтобы помочь визуализировать, я хотел бы сделать следующий TreeView treeview плюс/минус +/-

Выглядит так (как проводник Windows)

стрелки дерева


person user1858718    schedule 29.11.2012    source источник
comment
Ссылка, предоставленная Санни, содержит всю необходимую информацию. Если вы можете понять это, вам следует прочитать о методах, используемых для более четкого понимания, а не пытаться найти более простое решение. Вы пытаетесь сделать что-то, для чего он не предназначен, скорее всего, это не будет невероятно просто, хотя я бы сказал, что использование PInvoke не очень сложно...   -  person Ian    schedule 29.11.2012


Ответы (3)


Расширение решения Ивана Ичина:

[DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern int SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList);

public static void SetTreeViewTheme(IntPtr treeHandle) {
     SetWindowTheme(treeHandle, "explorer", null);
}

Чтобы использовать, добавьте TreeView в свою форму, а в Form_Load:

SetTreeViewTheme( treeView1.Handle );

В качестве альтернативы вы можете расширить объект TreeView

public class MyTreeView : TreeView
{

    [DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static extern int SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList);

    public MyTreeView() {
        SetWindowTheme(this.Handle, "explorer", null);
    }
}

before and after treeview Изображает, как это выглядит до и после вызова SetWindowTheme

person Kraang Prime    schedule 08.08.2016
comment
Существует потенциальная проблема с вызовом SetWindowTheme в конструкторе элемента управления — возможно, у вас еще нет дескриптора. Более надежный метод — переопределить событие OnHandleCreated и сделать это там. Существует также вероятность того, что старые операционные системы будут блевать (pre-vista), поэтому уместно проверить версию ОС. a href="https://www.cyotek.com/blog/enbling-shell-styles-for-the-listview-and-treeview-controls-in-csharp" rel="nofollow noreferrer">cyotek.com/blog / - person snow_FFFFFF; 09.11.2017
comment
@snow_FFFFFF - проверка старых операционных систем не проводилась, поскольку поддержка ОС Windows до Vista в настоящее время больше не поддерживается. - person Kraang Prime; 09.11.2017
comment
Это хорошо, но нельзя ожидать, что каждый пользователь будет следовать указам Microsoft. Я работаю с несколькими корпорациями, которые до сих пор используют XP. В любом случае, я столкнулся с проблемой использования конструктора элементов управления (в списке, а не в дереве), поэтому, возможно, стоит обновить ваш ответ, чтобы вместо этого использовать событие OnHandleCreated. - person snow_FFFFFF; 09.11.2017

Я могу придумать 3 метода:

  1. Санни уже упоминала об использовании SetWindowTheme(TreeView.Handle, "explorer", null)

  2. Использование WPF, если это возможно, и добавление объекта TreeViewItem

  3. Переопределение методов OnPaint, что слишком сложно, учитывая, что вы можете сделать только 1, так что 1 или 2 на ваше усмотрение.

person Ivan Ičin    schedule 29.11.2012

Если вы хотите настроить элемент управления в виде дерева, Microsoft предоставляет свойство с именем «TreeViewDrawMode» в элементе управления в виде дерева, его значение представляет собой перечисление, которое имеет 3 значения: Normal, OwnerDrawText, OwnerDrawAll, в вашей ситуации вы должны использовать OwnerDrawAll. после того, как вы установите это свойство как OwnerDrawAll, когда отображаются узлы древовидной структуры, будет запущено событие с именем «DrawNode», поэтому вы можете обработать свой рисунок там. когда вы рисуете его самостоятельно, обычно вам нужно нарисовать 3 вещи: значок развернуть/свернуть, значок узла, текст узла. мой пример ниже: // определить путь к файлу значка string minusPath = Application.StartupPath + Path.DirectorySeparatorChar + "minus.png"; строка plusPath = Application.StartupPath + Path.DirectorySeparatorChar + "plus.png"; string nodePath = Application.StartupPath + Path.DirectorySeparatorChar + "directory.png";

    public FrmTreeView()
    {
        InitializeComponent();
        //setting to customer draw
        this.treeView1.DrawMode = TreeViewDrawMode.OwnerDrawAll;
        this.treeView1.DrawNode += new DrawTreeNodeEventHandler(treeView1_DrawNode);
    }

    void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e)
    {
        Rectangle nodeRect = e.Node.Bounds;
        /*--------- 1. draw expand/collapse icon ---------*/
        Point ptExpand = new Point(nodeRect.Location.X - 20, nodeRect.Location.Y + 2);
        Image expandImg = null;
        if (e.Node.IsExpanded || e.Node.Nodes.Count < 1)
            expandImg = Image.FromFile(minusPath);
        else
            expandImg = Image.FromFile(plusPath);
        Graphics g = Graphics.FromImage(expandImg);
        IntPtr imgPtr = g.GetHdc();
        g.ReleaseHdc();
        e.Graphics.DrawImage(expandImg, ptExpand);

        /*--------- 2. draw node icon ---------*/
        Point ptNodeIcon = new Point(nodeRect.Location.X - 4, nodeRect.Location.Y + 2);
        Image nodeImg = Image.FromFile(nodePath);
        g = Graphics.FromImage(nodeImg);
        imgPtr = g.GetHdc();
        g.ReleaseHdc();
        e.Graphics.DrawImage(nodeImg, ptNodeIcon);
        /*--------- 3. draw node text ---------*/
        Font nodeFont = e.Node.NodeFont;
        if (nodeFont == null)
            nodeFont = ((TreeView)sender).Font;
        Brush textBrush = SystemBrushes.WindowText;
        //to highlight the text when selected
        if ((e.State & TreeNodeStates.Focused) != 0)
            textBrush = SystemBrushes.HotTrack;
        //Inflate to not be cut
        Rectangle textRect = nodeRect;
        //need to extend node rect
        textRect.Width += 40;
        e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, Rectangle.Inflate(textRect, -12, 0));
     }

результат моего теста выглядит так: картинка результата

person Scott Yang    schedule 08.12.2013
comment
Обратите внимание, что в этом посте неправильно используется вызов Graphics.FromImage(). Этот вызов стоит дорого (очень дорого в случае больших деревьев). Вместо этого вы должны использовать уже созданный Graphics объект e.Graphics, который позволяет рисовать изображения методом DrawImage(). Вы должны кэшировать свои значки развертывания/свертывания один раз (используя Image.FromFile()) в начале вашей программы. - person dotNET; 28.02.2017