Gerhard Powell
Gerhard Powell

Reputation: 6175

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!

Upvotes: 4

Views: 4641

Answers (4)

Orien
Orien

Reputation: 77

Hans Passant, many thanks you solution. Here is how I was implemented it + some more features that I found here.

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
var node = (TreeNode)SelectedNode;
var key = keyData & Keys.KeyCode;
var ctrlPressed = (keyData & Keys.Control) != Keys.None;
var shiftPressed = (keyData & Keys.Shift) != Keys.None;
// on keyboard KeyDown
if (msg.Msg == (int)SystemApi.WM.WM_KEYDOWN) {
    var keyHandled = false;
    switch (key) {
        case Keys.F2:
            // Start edit node label
            if (node != null && !node.IsEditing){
                LabelEdit = true;
                node.BeginEdit();
                keyHandled = true;
            }
            break;
        case Keys.V:
            // Paste text from clipboard into selected node
            if (node != null && ctrlPressed && node.IsEditing) Paste();
            break;
            case Keys.C:
            if (node != null) {
                if (ctrlPressed && node.IsEditing) {
                    // Copy text form selected node into clipboard
                    Copy();
                } else {
                    if (node.IsFolder) {
                        // Collapse folder node
                        node.Collapse();
                        node.EnsureVisible();
                    } else {
                        if (node.Parent != null) {
                            // Collapse parent folder
                            node.Parent.Collapse();
                            SelectedNode = node.Parent;
                            node.Parent.EnsureVisible();
                        } else {
                            // Collapse all nodes
                            CollapseAll();
                        }
                    }
                }
                keyHandled = true;
            } else {
                // Collapse all nodes
                CollapseAll();
            }
            break;
            case Keys.E:
                if (node != null && node.IsFolder) {
                    // Expand folder node
                    node.ExpandAll();
                    node.EnsureVisible();
                } else {
                    // Expand all nodes
                    ExpandAll();
                }
                keyHandled = true;
                break;
    }
    if (keyHandled == true) return true;
}
return base.ProcessCmdKey(ref msg, keyData);

}

Upvotes: 1

Carlos santos
Carlos santos

Reputation: 1

I use this code to copy:

    //copia a linha duploclick
    private void nametreeView_DoubleClick(object sender, EventArgs e)
    {
        Clipboard.SetText(nametreeView.SelectedNode.Text);
    }

And control-v.

Upvotes: 0

Paul Hope
Paul Hope

Reputation: 31

    private void treeXmlNode_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode.ToString() == "C")
        {
            if (treeXmlNode.SelectedNode != null)
            {
                e.Handled = true;
                this.KeyPreview = true;

                //copy node label to clipboard
                Clipboard.SetText(treeXmlNode.SelectedNode.Text);
            }
        }
    }

Upvotes: 3

Hans Passant
Hans Passant

Reputation: 941377

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);
}

Upvotes: 7

Related Questions