Reputation: 6175
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
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
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
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
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