0

私はwinformに取り組んでおり、UIにツリービューがあります.ノードを右クリックしなくてもツリーノードが強調表示されることがわかりました(たとえば、次の位置をクリックするとNode1が強調表示されます),しかし、ツリーノードをクリックしなかったときに別のコンテキストメニューを表示したいので、この動作は本当に好きではありません

+ルートノード

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

4 に答える 4

4

Kevin Wienhold の回答へのコメントから外れて、ユーザーがツリービューの空のスペースをクリックして、選択したノードの選択を解除できるようにしたいだけです。

これを行うには、コントロールのMouseDownイベントを処理し、ノードを含まない場所でマウスがクリックされた場合にプロパティを に設定します。TreeViewSelectedNodenullたとえば、次のコードを使用できます。

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 によって選択されています (TreeViewやのような .NET 提供のコントロールListViewは単なるラッパーであることに注意してください)。 Windows API によって提供されるものと同じコントロールであり、明らかにこの "select-node-while-right-button-hold-down" 動作自体を実装しています)。

ただし、機能するのは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への応答としてオーバーライドされたメソッドでコンテキスト メニューを表示し、基本クラスがメッセージを処理することを許可せずにメソッドから表示できます。これは最初のソリューションとまったく同じことを行います (右クリック イベントによってノードが選択されているように見えるのを防ぎます)。発生します。もちろん、これは、フォームの UI コードで処理されるのではなく、関連するすべてのコードがコントロールのサブクラス内に含まれている必要があることを意味します。WM_RBUTTONDOWNreturnTreeView

    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. メッセージへの応答としてカスタム クラスから独自のイベントを発生さ 、フォームの UI コードから必要に応じて処理することができます。メッセージを基本コントロール クラスに渡さないことで、前の 2 つの提案と同じ目標が達成されますが、すべてのロジックをサブクラス化する代わりに、フォームの UI コードで右ボタン クリック イベントを処理できます。コントロールの.RightMouseClickTreeViewWM_RBUTTONDOWNWM_RBUTTONDOWNTreeViewWndProc

    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);
        }   
    }
    
于 2010-12-02T09:04:41.700 に答える
2

ユーザーがノードをクリックしていないときにノードが強調表示されないようにする別の方法を見つけました。ツリーに追加するときに、各ノードの 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;
 } 
于 2010-12-03T09:20:15.293 に答える
1

これを試して

  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;
        }
    }
于 2010-12-02T09:15:02.917 に答える
0

私があなたを正しく理解していれば、ユーザーが TreeView 内の空のスペースをクリックした場合に、ノードが選択されないようにする必要があります。Tree の MouseDown-Event を処理し、ツリーの SelectedNode プロパティを TreeView.GetNodeAt(e.Location) に設定することで、これを実現できます。

于 2010-12-02T08:47:05.777 に答える