treeview node is highlighted even i did not right click on the node
I am working on a winform and on my UI there is a treeview, I found that the treenode will be highlighted even I did not click on the node by right mouse (eg, Node1 will be highlighted when I click on the following position), but i really do not like this behavior because I want to show a different context menu when I did not click on a treenode
+RootNode
|_ Node1 [ Right Click He开发者_运维问答re, Node1 will be highlighted] | |_ Node2 [ Right Click Here, Node2 will be highlighted]
Going off of your comment to Kevin Wienhold's answer, you just want to allow the user to click in the empty space of the treeview and deselect any selected node.
You can do this by handling the MouseDown
event of the TreeView
control, and setting the SelectedNode
property to null
if the mouse was clicked over a location that does not contain a node. For example, you could use the following code:
private void myTreeView_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (myTreeView.HitTest(e.Location).Node == null)
{
myTreeView.SelectedNode = null;
}
}
This takes advantage of the HitTest
method to determine which node is located at a particular point, specifying the location of the mouse event as the point to test. You don't need any other code to select nodes as usual when the user does click on them; that is handled automatically by the TreeView
.
EDIT: As my comment to the question indicates, I'm still exceptionally unclear as to what you are trying to accomplish here. If you're actually interested in preventing a node from being temporarily highlighted while you hold down the right mouse button in the empty space to the side of the node, things get a little more complex.
I've looked into this problem before, and the tricky part is that window messages are not received while the mouse button is being held down, at least not until the mouse is moved (in which case, the node is no longer selected anyway). This behavior is apparently dictated by the operating system and not easily overridden using the standard .NET-provided events. You can try to cancel a click of the right button in the MouseDown
event all day long, but the node is being selected by Windows before this event is ever raised in your control (remember that .NET-provided controls like the TreeView
and ListView
are simply wrappers around those same controls provided by the Windows API, which apparently implements this "select-node-while-right-button-held-down" behavior itself).
What does work, however, is overriding WndProc
in a derived TreeView
control, and handling the WM_RBUTTONDOWN
message. But notice that even setting the SelectedNode
property to null
doesn't work here, because that's not processed until after Windows automatically selects the node as a response to the right mouse button being clicked—no matter what you do, you have to prevent the base TreeView
control from receiving the WM_RBUTTONDOWN
message. So, you have a couple of choices in how to handle this:
You can simply cancel the right-click message by bailing out early with a
return
statement. Of course, this means you're not going to be able to handle this event in yourMouseDown
handler, because it's never actually passed to the control! So if you want to show a pop-up context menu, this probably won't work for you.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); } }
You can show your context menu in the overridden
WndProc
method as a response to theWM_RBUTTONDOWN
message, and thenreturn
from the method without allowing the base class to handle the message. This does the exact same thing as the first solution (prevents the right-click event from causing the node to appear selected), but it does allow you to show a context menu (or do anything else that you want) whenever the right-click occurs. Of course, it does mean that all of the relevant code will have to be contained within your subclass of theTreeView
control, not handled in your form's UI code, which may or may not be convenient for you.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); } }
You could raise your own
RightMouseClick
event from your customTreeView
class as a response to theWM_RBUTTONDOWN
message, which you could then handle as you wish from your form's UI code. By not passing theWM_RBUTTONDOWN
message to the baseTreeView
control class, this accomplishes the same goal as the previous two suggestions, but allows you to handle the right-button click event in your form's UI code instead of having to put all of your logic into the subclassed control'sWndProc
.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); } }
I have found another method to prevent the node to be highlight when the user not click on the node, and I only set the BackColor and ForeColor for each of the node when adding it to the tree
newNode.BackColor = treeview1.BackColor;
newNode.ForeColor = treeview1.ForeColor;
treeview1.Nodes.Add(newNode);
Then in the MouseDown event, set the SelectedNode property as following
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;
}
try this
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;
}
}
If I understand you correctly you want no node to be selected if the user clicks into empty space within the TreeView. You could accomplish that by handling the MouseDown-Event of the Tree and setting the tree's SelectedNode property to TreeView.GetNodeAt(e.Location).
精彩评论