.netwinformstreeview

Copy / Paste Treeview Node Label


I want to support copy / paste with a treeView. If you select the Node, then it must copy / paste the node. If you are busy renaming the label, it must copy / paste the text in the label. There are also copy / paste buttons and they must do the same function as the shortcut keys Ctrl+C and Ctrl+V.

I was thinking of two options:

1) Add a keydown method for the Controls. How do you add support for Copy / Paste for the Label?

TreeNode selectedNode = trvProjects.SelectedNode;    
if (selectedNode.IsEditing)
{
    // Copy Label
    selectedNode.Copy(); // .Copy / .Paste() are not supported. I need help with this
}
else
{
    // Copy Node
    CopyNode(selectedNode); // Got this working
}

2) Is there a way that for Label edit, it use the build in Copy / Paste, and if the Node is selected, custom code is launched?

Is there a better way of doing it?

I do not mind if the sample is in C# or VB.

Thank you!


Solution

  • The TreeView control uses a dynamically created TextBox to edit the label. You can get a handle to that text box and send it the WM_CUT, WM_PASTE and WM_COPY messages. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form. You can use its IsEditing property or its BeforeLabelEdit and AfterLabelEdit events to check if your shortcuts are going to work.

    using System;
    using System.Windows.Forms;
    
    class MyTreeView : TreeView {
        public bool IsEditing { get; private set; }
        public void Cut()   { SendMessage(GetEditControl(), 0x300, IntPtr.Zero, IntPtr.Zero); }
        public void Copy()  { SendMessage(GetEditControl(), 0x301, IntPtr.Zero, IntPtr.Zero); }
        public void Paste() { SendMessage(GetEditControl(), 0x302, IntPtr.Zero, IntPtr.Zero); }
    
        protected override void OnBeforeLabelEdit(NodeLabelEditEventArgs e) {
            IsEditing = true;
            base.OnBeforeLabelEdit(e);
        }
        protected override void OnAfterLabelEdit(NodeLabelEditEventArgs e) {
            IsEditing = false;
            base.OnAfterLabelEdit(e);
        }
        private IntPtr GetEditControl() {
            // Use TVM_GETEDITCONTROL to get the handle of the edit box
            IntPtr hEdit = SendMessage(this.Handle, 0x1100 + 15, IntPtr.Zero, IntPtr.Zero);
            if (hEdit == IntPtr.Zero) throw new InvalidOperationException("Not currently editing a label");
            return hEdit;
        }
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    }