Showing a context menu during drag and drop

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
 
G

G Himangi

Why not use a timer with a small interval of say 100ms and call the Show
method in timer.tick?

---------
- G Himangi, Sky Software http://www.ssware.com
Shell MegaPack : GUI Controls For Drop-In Windows Explorer like Shell
Browsing Functionality For Your App (.Net & ActiveX Editions).
EZNamespaceExtensions.Net : Develop namespace extensions rapidly in .Net
EZShellExtensions.Net : Develop all shell extensions,explorer bars and BHOs
rapidly in .Net
---------


Andreas Mueller said:
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
 
A

Andreas Mueller

G said:
Why not use a timer with a small interval of say 100ms and call the Show
method in timer.tick?

Hi,

the context menu itself shows up fine. The problem is that when I click
on the menu, the handler is executed *after* the Drag and Drop operation
has finished.

Thanks,
Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top