Начиная с вашего комментария к ответу Кевина Винхолда, вы просто хотите позволить пользователю щелкнуть в пустом месте дерева и отменить выбор любого выбранного узла.
Это можно сделать, обработав событие 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
. Итак, у вас есть несколько вариантов, как справиться с этим:
Вы можете просто отменить сообщение правой кнопкой мыши, выполнив досрочное освобождение с помощью оператора 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);
}
}
Вы можете отобразить свое контекстное меню в переопределенном методе 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);
}
}
Вы можете поднять свое свое 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);
}
}