A
Andreas Mueller
Hi All,
I'm trying to show a context menu during a drag drop operation similar
to the windows explorers right click drag and drop behavior (A full
working sample is at the end of the post):
void treeView1_DragDrop(object sender, DragEventArgs e)
{
ContextMenu mnu = new ContextMenu();
mnu.MenuItems.Add("Click me", OnCmClick);
mnu.Show(this, PointToClient(MousePosition));
}
private void OnCmClick(object sender, EventArgs e)
{
Debug.WriteLine("Click");
}
It works, but the OnCmClick handler of the context menu is executed
*after* the drag and drop has finished. I think this is because the
click message is enqueued into the message queue behind the currently
active drag and drop handler, as a call to Application.DoEvents() solves
the problem.
As I'm burned by re entrance issues, I'm very reluctant to call DoEvents.
Is there any other way to solve this issue or to implement this behavior?
Here's a complete sample:
using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace WindowsApplication4
{
public partial class Form1 : Form
{
private readonly TreeView treeView1 = new TreeView();
public Form1()
{
InitializeComponent();
Thread.CurrentThread.Name = "GUI";
treeView1.Nodes.Add("A Node");
treeView1.ItemDrag += treeView1_ItemDrag;
treeView1.DragOver += treeView1_DragOver;
treeView1.DragDrop += treeView1_DragDrop;
}
private void InitializeComponent()
{
SuspendLayout();
treeView1.AllowDrop = true;
treeView1.Location = new Point(10, 10);
treeView1.Name = "treeView1";
treeView1.Size = new Size(120, 200);
treeView1.TabIndex = 0;
ClientSize = new Size(300, 250);
Controls.Add(treeView1);
Name = "Form1";
Text = "Form1";
ResumeLayout(false);
}
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
Debug.WriteLine("--->Started DragDrop");
Debug.WriteLine("Thread: " + Thread.CurrentThread.Name);
DoDragDrop(e.Item, DragDropEffects.All | DragDropEffects.Link);
Debug.WriteLine("--->Finished DragDrop");
}
private void treeView1_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
Debug.WriteLine("Thread: " + Thread.CurrentThread.Name);
ContextMenu mnu = new ContextMenu();
mnu.MenuItems.Add("Click me", OnCmClick);
mnu.Show(this, PointToClient(MousePosition));
//Application.DoEvents();// Good Idea??
}
private void OnCmClick(object sender, EventArgs e)
{
Debug.WriteLine("Click");
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Thank you in advance,
Andy
I'm trying to show a context menu during a drag drop operation similar
to the windows explorers right click drag and drop behavior (A full
working sample is at the end of the post):
void treeView1_DragDrop(object sender, DragEventArgs e)
{
ContextMenu mnu = new ContextMenu();
mnu.MenuItems.Add("Click me", OnCmClick);
mnu.Show(this, PointToClient(MousePosition));
}
private void OnCmClick(object sender, EventArgs e)
{
Debug.WriteLine("Click");
}
It works, but the OnCmClick handler of the context menu is executed
*after* the drag and drop has finished. I think this is because the
click message is enqueued into the message queue behind the currently
active drag and drop handler, as a call to Application.DoEvents() solves
the problem.
As I'm burned by re entrance issues, I'm very reluctant to call DoEvents.
Is there any other way to solve this issue or to implement this behavior?
Here's a complete sample:
using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace WindowsApplication4
{
public partial class Form1 : Form
{
private readonly TreeView treeView1 = new TreeView();
public Form1()
{
InitializeComponent();
Thread.CurrentThread.Name = "GUI";
treeView1.Nodes.Add("A Node");
treeView1.ItemDrag += treeView1_ItemDrag;
treeView1.DragOver += treeView1_DragOver;
treeView1.DragDrop += treeView1_DragDrop;
}
private void InitializeComponent()
{
SuspendLayout();
treeView1.AllowDrop = true;
treeView1.Location = new Point(10, 10);
treeView1.Name = "treeView1";
treeView1.Size = new Size(120, 200);
treeView1.TabIndex = 0;
ClientSize = new Size(300, 250);
Controls.Add(treeView1);
Name = "Form1";
Text = "Form1";
ResumeLayout(false);
}
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
Debug.WriteLine("--->Started DragDrop");
Debug.WriteLine("Thread: " + Thread.CurrentThread.Name);
DoDragDrop(e.Item, DragDropEffects.All | DragDropEffects.Link);
Debug.WriteLine("--->Finished DragDrop");
}
private void treeView1_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
Debug.WriteLine("Thread: " + Thread.CurrentThread.Name);
ContextMenu mnu = new ContextMenu();
mnu.MenuItems.Add("Click me", OnCmClick);
mnu.Show(this, PointToClient(MousePosition));
//Application.DoEvents();// Good Idea??
}
private void OnCmClick(object sender, EventArgs e)
{
Debug.WriteLine("Click");
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Thank you in advance,
Andy