древовидный узел выделен, даже если я не щелкнул правой кнопкой мыши на узле - PullRequest
0 голосов
/ 02 декабря 2010

Я работаю над winform, и в моем пользовательском интерфейсе есть древовидная структура, я обнаружил, что триод будет выделен, даже если я не щелкну правой кнопкой мыши по узлу (например, Node1 будет выделен, когда я нажму на следующую положение), но мне действительно не нравится это поведение, потому что я хочу показать другое контекстное меню, когда я не нажал на триоде

+ RootNode

  |_ Node1                [ Right Click Here, Node1 will be highlighted]
  |
  |_ Node2                [ Right Click Here, Node2 will be highlighted]

Ответы [ 4 ]

4 голосов
/ 02 декабря 2010

Начиная с вашего комментария к ответу Кевина Винхолда, вы просто хотите позволить пользователю щелкнуть в пустом месте дерева и отменить выбор любого выбранного узла.

Это можно сделать, обработав событие MouseDown элемента управления TreeView и установив для свойства SelectedNode значение null, если мышь был нажат по местоположению, которое не содержит узла. Например, вы можете использовать следующий код:

private void myTreeView_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
    if (myTreeView.HitTest(e.Location).Node == null)
    {
        myTreeView.SelectedNode = null;
    }
}

Это использует метод HitTest , чтобы определить, какой узел расположен в конкретной точке, указав местоположение события мыши в качестве точки для тестирования. Вам не нужен какой-либо другой код для обычного выбора узлов, когда пользователь нажимает на них ; это обрабатывается автоматически TreeView.


РЕДАКТИРОВАТЬ: Как показывает мой комментарий к вопросу, мне все еще исключительно неясно, что вы пытаетесь достичь здесь. Если вы на самом деле заинтересованы в том, чтобы предотвратить временное выделение узла, пока вы удерживаете правую кнопку мыши в пустом месте сбоку от узла, все становится немного сложнее.

Я уже рассматривал эту проблему раньше, и сложность заключается в том, что оконные сообщения не принимаются, пока удерживается кнопка мыши, по крайней мере, до тех пор, пока мышь не будет перемещена (в этом случае узел больше не будет выбрал в любом случае). Такое поведение, по-видимому, диктуется операционной системой и не может быть легко переопределено с помощью стандартных событий, предоставляемых .NET. Вы можете попытаться отменить нажатие правой кнопки в событии MouseDown в течение всего дня, но Windows выбирает узел еще до того, как это событие будет вызвано вашим контролем (помните, что элементы управления, предоставленные .NET, такие как * 1030) * и ListView - это просто обертки вокруг тех же элементов управления, которые предоставляются Windows API, который, по-видимому, сам реализует это поведение «выбрать-узел-пока-правая-кнопка-удерживаемая»).

Что работает , однако переопределяет WndProc в производном элементе управления TreeView и обрабатывает сообщение WM_RBUTTONDOWN . Но обратите внимание, что даже установка свойства SelectedNode на null здесь не работает, потому что он не обрабатывается, пока после Windows автоматически не выберет узел как ответ на нажатие правой кнопки мыши - независимо от того, что вы делаете, вы должны запретить базовому элементу управления TreeView получать сообщение WM_RBUTTONDOWN. Итак, у вас есть несколько вариантов, как справиться с этим:

  1. Вы можете просто отменить сообщение правой кнопкой мыши, выполнив досрочное освобождение с помощью оператора return. Конечно, это означает, что вы не сможете обработать это событие в своем обработчике MouseDown, потому что оно никогда фактически не передается элементу управления! Поэтому, если вы хотите показать всплывающее контекстное меню, это, вероятно, не сработает для вас.

    public class NewTreeView : System.Windows.Forms.TreeView
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_RBUTTONDOWN = 0x204;
            if (m.Msg == WM_RBUTTONDOWN)
            {
                return;
            }
            base.WndProc(ref m);
        }   
    }
    
  2. Вы можете отобразить свое контекстное меню в переопределенном методе WndProc как ответ на сообщение WM_RBUTTONDOWN, а затем return из метода, не позволяя базовому классу обрабатывать сообщение. Это делает то же самое, что и первое решение (препятствует тому, чтобы событие щелчка правой кнопкой мыши заставляло узел казаться выбранным), но позволяет отображать контекстное меню (или делать что-либо еще, что вы хотите) всякий раз, когда щелкаете правой кнопкой мыши происходит. Конечно, это означает, что весь соответствующий код должен содержаться в вашем подклассе элемента управления TreeView, а не обрабатываться в коде пользовательского интерфейса вашей формы, что может или не может быть удобным для вас.

    public class NewTreeView : System.Windows.Forms.TreeView
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_RBUTTONDOWN = 0x204;
            if (m.Msg == WM_RBUTTONDOWN)
            {
                //Create and show a context menu
                var myContextMenu = new ContextMenuStrip();
                myContextMenu.Items.Add("First Item");
                myContextMenu.Items.Add("Second Item");
                return;
            }
            base.WndProc(ref m);
        }   
    }
    
  3. Вы можете поднять свое свое RightMouseClick событие из своего пользовательского класса TreeView в качестве ответа на сообщение WM_RBUTTONDOWN, которое затем вы можете обрабатывать по мерепожелание от кода вашей формы.Не передавая сообщение WM_RBUTTONDOWN в базовый класс управления TreeView, это достигает той же цели, что и предыдущие два предложения, но позволяет обрабатывать событие нажатия правой кнопки в коде пользовательского интерфейса формы вместо того, чтобы помещать всевашей логики в подклассе управления WndProc.

    public class NewTreeView : System.Windows.Forms.TreeView
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_RBUTTONDOWN = 0x204;
            if (m.Msg == WM_RBUTTONDOWN)
            {
                //Raise your custom event
                OnRightMouseClick(new EventArgs());
                return;
            }
            base.WndProc(ref m);
        }   
    }
    
1 голос
/ 03 декабря 2010

Я нашел другой способ предотвратить выделение узла, когда пользователь не щелкает по узлу, и я устанавливал BackColor и ForeColor для каждого узла при добавлении его в дерево

newNode.BackColor = treeview1.BackColor;
newNode.ForeColor = treeview1.ForeColor;
treeview1.Nodes.Add(newNode);

Затем в событии MouseDown установите свойство SelectedNode следующим образом

 private void treeView1_MouseDown(object sender, MouseEventArgs e)
 {
        TreeNode Node = treeView1.GetNodeAt(e.Location);
        if (Node != null && Node.Bounds.Contains(e.Location))
            treeView1.SelectedNode = Node;
        else
            treeView1.SelectedNode = null;
 } 
1 голос
/ 02 декабря 2010

попробуйте

  void treeView1_MouseDown(object sender, MouseEventArgs e)
    {


        TreeViewHitTestInfo h = treeView1.HitTest(e.Location);

        if (h.Location != TreeViewHitTestLocations.Label && h.Location!= TreeViewHitTestLocations.None )
        {
            treeView1.SelectedNode = null;
        }
    }
0 голосов
/ 02 декабря 2010

Если я вас правильно понимаю, вы не хотите, чтобы узел был выбран, если пользователь щелкает в пустом пространстве внутри TreeView. Этого можно достичь, обработав MouseDown-Event дерева и установив для свойства SelectedNode дерева значение TreeView.GetNodeAt (e.Location).

...