Is there a way to show the "lock" WinForms ContextMenu?

Is there a way to show ContextMenu and block further execution until the item is selected? In particular, I want to get behavior similar to ShowDialog() , but for a ContextMenu .

The direct approach does not work:

 ContextMenu cm = new ContextMenu(); cm.MenuItems.Add("1", (s,e) => {value = 1;}); cm.Show(control, location); 

since the Click callback is not called directly from Show() , but instead at some later point in time when the message loop processes the click event.

If you're out of luck, menu is garbage collected before the event is processed, in which case the event will simply be lost. (This means that you cannot use local variables for ContextMenu in this way.)

This seems to work, but feels "unclean":

 using (ContextMenu cm = new ContextMenu()) { cm.MenuItems.Add("1", (s,e) => {value = 1;}); cm.Show(control, location); Application.DoEvents(); } 

Is there a better way?

+4
source share
3 answers

Sorry for the first answer. Here is what I have tried. I made another form where I put the context menu and timer. Form2 format is displayed as modal from Form1, then the timer displays the context menu in Form2.

Please note: Form 2 has some properties: in order not to be visible in the taskbar, to have no borders, and the size should be equal to the size of the context menu.

Hope this helps.

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { Form2 ctxForm = new Form2(); ctxForm.Location = this.PointToScreen(e.Location); ctxForm.Size = new Size(0, 0); ctxForm.ShowDialog(); } } } public partial class Form2 : Form { public Form2() { InitializeComponent(); } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { this.Close(); } private void timer1_Tick(object sender, EventArgs e) { //show menu once contextMenuStrip1.Show(this, PointToClient(Location)); contextMenuStrip1.Focus(); timer1.Enabled = false; } private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e) { this.Close(); } } 
+1
source

You can easily prevent ContextMenu garbage collection while it is showing.

The problem is that you are using lambda as the event handler for the menu item. This is an anonymous method, so it is not bound to an object of any instance that could reference and support ContextMenu. Add a method to the surrounding object, and then create a standard EventHandler. Thus, the existence of the attached instance will support ContextMenu. Not so concise and very C # 1.0, but this will solve the problem.

0
source

Wait until the menu is visible.

 ContextMenu cm = new ContextMenu(); cm.MenuItems.Add("1", (s,e) => {value = 1;}); cm.Show(control, location); while (cm.Visible == true) Application.DoEvents(); 
0
source

Source: https://habr.com/ru/post/1384943/


All Articles