Compartilhar via


Como: Subclasse a TreeView by Using nativo Callbacks

Este exemplo mostra como subclasse um TreeView controle para criar um NodeMouseClick evento, que não está disponível no .NET Compact estrutura.

O formulário exibe a subclasse TreeView controle e informações sobre um nó clicado. Ele mostra o texto de um nó e sistema autônomo coordenadas x e y de onde o TreeView controle foi clicado, que altera enquanto você clica em locais diferentes em um nó.

Este programa exemplo é descrito detalhadamente no Subclassificação dos controles com um procedimento de janela gerenciado.

Para "subclasse" um controle TreeView para criar um evento NodeMouseClick

  1. In Microsoft Visual Studio 2005, criar um projeto dispositivo inteligente Pocket PC.

  2. Adicionar o Win32 classe auxiliar para seu projeto. Este código está disponível em Como: Use a auxiliar classe para plataforma Invokes.

  3. Adicionar o WinProcHooker classe para seu projeto. Este código está disponível em Como: Usar uma classe de interceptação de procedimentos do Windows.

  4. Adicionar o TreeViewBonus classe para seu projeto.

    // Extends the standard TreeView control to add an implementation
    // of the NodeMouseClick event.
    public class TreeViewBonus : TreeView
    {
        // The original parent of this control.
        Control prevParent = null;
    
        // Creates a new instance of the derived TreeView control
        public TreeViewBonus()
        {
        }
    
        // Called when the control's parent is changed. Here we hook into that
        // parent's WndProc and spy on the WM_NOTIFY message. When the parent
        // changes, we unhook the old parent's WndProc and hook into the new one.
        protected override void OnParentChanged(EventArgs e)
        {
            // unhook the old parent
            if (this.prevParent != null)
            {
                WndProcHooker.UnhookWndProc(prevParent, Win32.WM_NOTIFY);
            }
            // update the previous parent
            prevParent = this.Parent;
    
            // hook up the new parent
            if (this.Parent != null)
            {
                WndProcHooker.HookWndProc(this.Parent,
                new WndProcHooker.WndProcCallback(this.WM_Notify_Handler),
                Win32.WM_NOTIFY);
            }
    
            base.OnParentChanged(e);
        }
    
        // Occurs when the user clicks a TreeNode with the mouse.
        public event TreeNodeMouseClickEventHandler NodeMouseClick;
    
        // Occurs when the mouse pointer is over the control and a mouse button is clicked.
        protected void OnNodeMouseClick(TreeNodeMouseClickEventArgs e)
        {
            if (NodeMouseClick != null)
                NodeMouseClick(this, e);
       }
    
        // The method that gets called when a WM_NOTIFY message is received by the
        // TreeView's parent.
        // hwnd - The handle of the window that received the message
        // msg - The message received
        // wParam - The wParam arguments for the message
        // lParam - The lParam arguments for the message
        // handled - Set to true to indicate that this message was handled
        // Returns an appropriate return code for the message handled
        int WM_Notify_Handler(
            IntPtr hwnd, uint msg, uint wParam, int lParam,
            ref bool handled)
        {
            Win32.NMHDR nmHdr = new Win32.NMHDR();
            System.Runtime.InteropServices.Marshal.PtrToStructure((IntPtr)lParam, nmHdr);
            switch (nmHdr.code)
            {
                case Win32.NM_RCLICK:
                case Win32.NM_CLICK:
                    // get the cursor coordinates on the client
                    Point msgPos = Win32.LParamToPoint((int)Win32.GetMessagePos());
                    msgPos = this.PointToClient(msgPos);
    
                    // check to see if the click was on an item
                    Win32.TVHITTESTINFO hti = new Win32.TVHITTESTINFO();
                    hti.pt.X = msgPos.X;
                    hti.pt.Y = msgPos.Y;
                    int hitem = Win32.SendMessage(this.Handle, Win32.TVM_HITTEST, 0, ref hti);
                    uint htMask = (
                        Win32.TVHT_ONITEMICON |
                        Win32.TVHT_ONITEMLABEL |
                        Win32.TVHT_ONITEMINDENT |
                        Win32.TVHT_ONITEMBUTTON |
                        Win32.TVHT_ONITEMRIGHT |
                        Win32.TVHT_ONITEMSTATEICON);
                    if ((hti.flags & htMask) != 0)
                    {
                        bool leftButton = (nmHdr.code == Win32.NM_CLICK);
                        RaiseNodeMouseClickEvent(hti.hItem,
                            leftButton ? MouseButtons.Left : MouseButtons.Right,
                            msgPos);
                        return 0;
                    }
                    break;
                default:
                    break;
            }
            return 0;
        }
    
        // Raises the TreeNodeMouseClick event for the TreeNode with the specified handle.
        // hNode - The handle of the node for which the event is raised
        // button - The [mouse] buttons that were pressed to raise the event
        // coords - The [client] cursor coordinates at the time of the event
        void RaiseNodeMouseClickEvent(IntPtr hNode, MouseButtons button, Point coords)
        {
            TreeNode tn = FindTreeNodeFromHandle(this.Nodes, hNode);
    
            TreeNodeMouseClickEventArgs e = new TreeNodeMouseClickEventArgs(
                tn,
                button,
                1, coords.X, coords.Y);
    
            OnNodeMouseClick(e);
        }
    
        // Finds a TreeNode in the provided TreeNodeCollection that has the handle specified.
        // Warning: recursion!
        // tnc - The TreeNodeCollection to search
        // handle - The handle of the TreeNode to find in the collection
        // Returns tThe TreeNode if found; null otherwise
        TreeNode FindTreeNodeFromHandle(TreeNodeCollection tnc, IntPtr handle)
        {
            foreach (TreeNode tn in tnc)
            {
            if (tn.Handle == handle) return tn;
                // we couldn't have clicked on a child of this node if this node
                // is not expanded!
                if (tn.IsExpanded)
                {
                    TreeNode tn2 = FindTreeNodeFromHandle(tn.Nodes, handle);
                    if (tn2 != null) return tn2;
                }
            }
            return null;
        }
    }
    
  5. Adicionar o TreeNodeMouseClickEventArgs classe para seu projeto.

    // Provides data for the System.Windows.Forms.TreeView.NodeMouseClick event
    public class TreeNodeMouseClickEventArgs : MouseEventArgs
    {
        // Initializes a new instance of the TreeNodeMouseClickEventArgs class.
        // node - The node that was clicked
        // button - One of the System.Windows.Forms.MouseButtons members
        // clicks - The number of clicks that occurred
        // x - The x-coordinate where the click occurred
        // y - The y-coordinate where the click occurred
        public TreeNodeMouseClickEventArgs(TreeNode node, MouseButtons button, int clicks, int x, int y)
            :
            base(button, clicks, x, y, 0)
        {
            nodeValue = node;
        }
    
        //
        // Gets the node that was clicked.
        //
        public TreeNode Node
        {
            get { return nodeValue; }
            set { nodeValue = value; }
        }
        TreeNode nodeValue;
    
        public override string ToString()
        {
            return string.Format(
                "TreeNodeMouseClickEventArgs\r\n\tNode: {0}\r\n\tButton: {1}\r\n\tX: {2}\r\n\tY: {3}",
                nodeValue.Text, Button.ToString(), X, Y);
        }
    }
    
  6. Declare uma variável de formulário chamada treeViewB do tipo TreeViewBonus.

    private TreeViewBonus treeViewB;
    
  7. Adicione o seguinte código ao construtor do Form1 classe, que deve seguir a telefonar para InitializeComponent. Este código também adiciona um grupo de nós de árvore e organiza suas hierarquia.

    InitializeComponent();
    this.treeViewB = new TreeViewBonus();
    this.treeViewB.NodeMouseClick += new TreeNodeMouseClickEventHandler(this.tv_NodeMouseClicked);
    this.treeViewB.Location = new System.Drawing.Point(18, 16);
    this.treeViewB.Size = new System.Drawing.Size(205, 144);
    this.treeViewB.Name = "treeViewB";
    
    
    // Set up the tree nodes.
    System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Node0");
    System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Node2");
    System.Windows.Forms.TreeNode treeNode3 = new System.Windows.Forms.TreeNode("Node3");
    System.Windows.Forms.TreeNode treeNode4 = new System.Windows.Forms.TreeNode("Node6");
    System.Windows.Forms.TreeNode treeNode5 = new System.Windows.Forms.TreeNode("Node7");
    System.Windows.Forms.TreeNode treeNode6 = new System.Windows.Forms.TreeNode("Node8");
    System.Windows.Forms.TreeNode treeNode7 = new System.Windows.Forms.TreeNode("Node4");
    System.Windows.Forms.TreeNode treeNode8 = new System.Windows.Forms.TreeNode("Node1");
    System.Windows.Forms.TreeNode treeNode9 = new System.Windows.Forms.TreeNode("Node5");
    System.Windows.Forms.TreeNode treeNode10 = new System.Windows.Forms.TreeNode("Node9");
    System.Windows.Forms.TreeNode treeNode11 = new System.Windows.Forms.TreeNode("Node10");
    System.Windows.Forms.TreeNode treeNode12 = new System.Windows.Forms.TreeNode("Node11");
    
    treeNode2.Text = "Node2";
    treeNode4.Text = "Node6";
    treeNode5.Text = "Node7";
    treeNode6.Text = "Node8";
    treeNode3.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode4,
            treeNode5,
            treeNode6});
    treeNode3.Text = "Node3";
    treeNode7.Text = "Node4";
    treeNode1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode2,
            treeNode3,
            treeNode7});
    treeNode1.Text = "Node0";
    treeNode12.Text = "Node11";
    treeNode11.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode12});
    treeNode11.Text = "Node10";
    treeNode10.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode11});
    treeNode10.Text = "Node9";
    treeNode9.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode10});
    treeNode9.Text = "Node5";
    treeNode8.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode9});
    treeNode8.Text = "Node1";
    this.treeViewB.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode1,
            treeNode8});
    
    this.Controls.Add(treeViewB);
    
    
  8. Adicione o delegado e o método de manipulação de eventos para o derivada NodeMouseClick evento para o Form1 classe.

        // Delegate represents the method that will handle
        // the NodeMouseClick event of a TreeView.
        // Parameters:
        // sender - The source of the event.
        // e - A TreeNodeMouseClickEventArgs that contains the event data.
        public delegate void TreeNodeMouseClickEventHandler(object sender, TreeNodeMouseClickEventArgs e);
    
    private void tv_NodeMouseClicked(object sender, TreeNodeMouseClickEventArgs e)
    {
        // Show the current node and the coordinates
        // in TreeView control where it was clicked.
        // This is just some of the information you
        // can obtain from TreeNodeMouseClickEventArgs.
    
        // Use a StringBuilder for efficient
        // use of device resources.
        StringBuilder sb = new StringBuilder();
        sb.Append(e.Node.Text + " ");
        sb.Append("X: " + e.X.ToString() + ", ");
        sb.Append("Y: " + e.Y.ToString());
    
        label1.Text = sb.ToString();
    
    }
    
  9. Compile e execute o aplicativo.

Consulte também

Tarefas

Como: Usar uma classe de interceptação de procedimentos do Windows

Como: Use a auxiliar classe para plataforma Invokes

Como: Subclasse a TreeView by Using nativo Callbacks

Como: Exibir um preenchimento gradual

Conceitos

Tópicos "como" do .NET compact estrutura

Outros recursos

Interoperabilidade no .NET Compact Framework