c# - ejemplo - Cómo mostrar un menú contextual al hacer clic con el botón derecho en un elemento del menú
context menu datagridview c# (3)
Probablemente tendrás que p / invocar el método.
[DllImport("user32.dll")]
static extern bool TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y,
IntPtr hwnd, IntPtr lptpm);
const int TPM_RECURSE = 0x0001;
Estoy trasladando una aplicación MFC a .NET WinForms. En la aplicación MFC, puede hacer clic con el botón derecho en un menú o en un elemento del menú contextual y mostramos otro menú contextual con elementos de diagnóstico y configuración. Estoy tratando de portar esta funcionalidad a .NET, pero estoy teniendo problemas.
He podido capturar el clic derecho, desactivar el clic del menú subyacente y abrir un menú contextual en la ubicación correcta, pero el menú original desaparece tan pronto como pierde el foco.
En MFC, mostramos el nuevo menú contextual llamando a TrackPopupMenuEx con el indicador TPM_RECURSE .
ContextMenu y las nuevas clases ContextMenuStrip en .NET solo tienen un método Show . ¿Alguien sabe cómo hacer esto en .NET?
EDITAR
He intentado usar TrackPopupMenuEx a través de ap / invoke , pero eso te limita a usar un ContextMenu en lugar de un ContextMenuStrip que parece fuera de lugar en nuestra aplicación. Tampoco funciona correctamente. No funciona con los nuevos MenuStrip y ContextMenuStrip .
También intenté subclasificar ToolStripMenuItem para ver si puedo agregarle un menú contextual. Eso está funcionando para MenuStrip , pero ContextMenuStrip todavía permite que los eventos de clic derecho pasen como clics.
Esto muestra cómo usar múltiples ContextMenus así como diferentes con cualquier combinación de clics del mouse.
Más aquí: http://code.msdn.microsoft.com/TheNotifyIconExample
Editar, debido a un comentario:
En:
protected override void OnClick(EventArgs e)
{
if (SecondaryContextMenu == null || MouseButtons != MouseButtons.Right)
{
base.OnClick(e);
}
}
esta parte
MouseButtons != MouseButtons.Right
debería y compila, ya que es una llamada a Control.MouseButtons. Como el Formulario hereda la clase Control, es suficiente llamar directamente a la propiedad MouseButtons.
Espero que esto ayude:
public partial class Form1 : Form
{
class CustomToolStripMenuItem : ToolStripMenuItem
{
private ContextMenuStrip secondaryContextMenu;
public ContextMenuStrip SecondaryContextMenu
{
get
{
return secondaryContextMenu;
}
set
{
secondaryContextMenu = value;
}
}
public CustomToolStripMenuItem(string text)
: base(text)
{ }
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (secondaryContextMenu != null)
{
secondaryContextMenu.Dispose();
secondaryContextMenu = null;
}
}
base.Dispose(disposing);
}
protected override void OnClick(EventArgs e)
{
if (SecondaryContextMenu == null || MouseButtons != MouseButtons.Right)
{
base.OnClick(e);
}
}
}
class CustomContextMenuStrip : ContextMenuStrip
{
private bool secondaryContextMenuActive = false;
private ContextMenuStrip lastShownSecondaryContextMenu = null;
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (lastShownSecondaryContextMenu != null)
{
lastShownSecondaryContextMenu.Close();
lastShownSecondaryContextMenu = null;
}
}
base.Dispose(disposing);
}
protected override void OnControlAdded(ControlEventArgs e)
{
e.Control.MouseClick += new MouseEventHandler(Control_MouseClick);
base.OnControlAdded(e);
}
protected override void OnControlRemoved(ControlEventArgs e)
{
e.Control.MouseClick -= new MouseEventHandler(Control_MouseClick);
base.OnControlRemoved(e);
}
private void Control_MouseClick(object sender, MouseEventArgs e)
{
ShowSecondaryContextMenu(e);
}
protected override void OnMouseClick(MouseEventArgs e)
{
ShowSecondaryContextMenu(e);
base.OnMouseClick(e);
}
private bool ShowSecondaryContextMenu(MouseEventArgs e)
{
CustomToolStripMenuItem ctsm = this.GetItemAt(e.Location) as CustomToolStripMenuItem;
if (ctsm == null || ctsm.SecondaryContextMenu == null || e.Button != MouseButtons.Right)
{
return false;
}
lastShownSecondaryContextMenu = ctsm.SecondaryContextMenu;
secondaryContextMenuActive = true;
ctsm.SecondaryContextMenu.Closed += new ToolStripDropDownClosedEventHandler(SecondaryContextMenu_Closed);
ctsm.SecondaryContextMenu.Show(Cursor.Position);
return true;
}
void SecondaryContextMenu_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
((ContextMenuStrip)sender).Closed -= new ToolStripDropDownClosedEventHandler(SecondaryContextMenu_Closed);
lastShownSecondaryContextMenu = null;
secondaryContextMenuActive = false;
Focus();
}
protected override void OnClosing(ToolStripDropDownClosingEventArgs e)
{
if (secondaryContextMenuActive)
{
e.Cancel = true;
}
base.OnClosing(e);
}
}
public Form1()
{
InitializeComponent();
CustomToolStripMenuItem itemPrimary1 = new CustomToolStripMenuItem("item primary 1");
itemPrimary1.SecondaryContextMenu = new ContextMenuStrip();
itemPrimary1.SecondaryContextMenu.Items.AddRange(new ToolStripMenuItem[] {
new ToolStripMenuItem("item primary 1.1"),
new ToolStripMenuItem("item primary 1.2"),
});
CustomToolStripMenuItem itemPrimary2 = new CustomToolStripMenuItem("item primary 2");
itemPrimary2.DropDownItems.Add("item primary 2, sub 1");
itemPrimary2.DropDownItems.Add("item primary 2, sub 2");
itemPrimary2.SecondaryContextMenu = new ContextMenuStrip();
itemPrimary2.SecondaryContextMenu.Items.AddRange(new ToolStripMenuItem[] {
new ToolStripMenuItem("item primary 2.1"),
new ToolStripMenuItem("item primary 2.2"),
});
CustomContextMenuStrip primaryContextMenu = new CustomContextMenuStrip();
primaryContextMenu.Items.AddRange(new ToolStripItem[]{
itemPrimary1,
itemPrimary2
});
this.ContextMenuStrip = primaryContextMenu;
}
}