2008-11-11 11 views
10

Ich portiere eine MFC-Anwendung in .NET WinForms. In der MFC-Anwendung können Sie mit der rechten Maustaste auf ein Menü oder einen Kontextmenüeintrag klicken, und wir zeigen ein anderes Kontextmenü mit Diagnose- und Konfigurationselementen. Ich versuche, diese Funktionalität in .NET zu portieren, aber ich habe Probleme.So zeigen Sie ein Kontextmenü an, wenn Sie mit der rechten Maustaste auf ein Menüelement klicken

Ich konnte den Rechtsklick erfassen, deaktivieren Sie den Klick des zugrunde liegenden Menüs und Pop-up ein Kontextmenü an der richtigen Stelle, aber das ursprüngliche Menü verschwindet, sobald es den Fokus verliert.

In MFC, zeigen wir das neue Kontextmenü von TrackPopupMenuEx mit dem TPM_RECURSE Flag aufrufen.

ContextMenu und der neuer Context Klassen in .NET nur ein Methode zeigen. Weiß jemand, wie man das in .NET macht?

EDIT

ich versucht habe TrackPopupMenuEx durch eine p mit/aufrufen, aber das schränkt Sie ein ContextMenu anstelle eines Context verwendet, die in unserer Anwendung deplatziert aussieht. Es funktioniert auch immer noch nicht richtig. Es funktioniert nicht mit dem neuen MenuStrip und ContextMenuStrip.

Ich habe auch versucht, ToolStripMenuItem Unterklasse zu sehen, ob ich ein Kontextmenü hinzufügen kann. Das funktioniert für MenuStrip, aber ContextMenuStrip ermöglicht weiterhin das Durchlaufen der Rechtsklickereignisse als Klicks.

+0

Warum nicht einfach ein Untermenü verwenden, so dass, wenn Sie über den Menüpunkt schweben, ist es mehr Artikel zeigt? –

+0

Viele unserer Menüs haben bereits Untermenüs. Wir verwenden diese Funktion für Administratoren, um die Sicherheit von Menüs anzupassen. Klicken Sie zum Beispiel mit der rechten Maustaste auf ein Menü und setzen Sie es auf deaktiviert. Dies wird in der Datenbank gespeichert und wirkt sich auf alle Benutzer aus. –

Antwort

10

bearbeiten, aufgrund eines Kommentars:

In:

protected override void OnClick(EventArgs e) 
{ 
    if (SecondaryContextMenu == null || MouseButtons != MouseButtons.Right) 
    { 
     base.OnClick(e); 
    } 
} 

dieser Teil

MouseButtons != MouseButtons.Right 

sollte und nicht kompiliert, wie es ein Aufruf an Control.MouseButtons ist. Da das Formular die Control-Klasse erbt, genügt es, die MouseButtons-Eigenschaft direkt aufzurufen.

this helps:

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; 
    } 
} 
+0

Ich werde dies versuchen, danke. –

+0

Danke, dies funktioniert für ContextMenuStrip und modifiziert für die Top-Level-Menüs eines MenuStrip. Ich kann es immer noch nicht für die Untermenüs von MenuStrip verwenden, aber ich denke, das ist nur ein Problem mit dem GetItemAt-Aufruf. –

+0

Die OnClick-Überschreibung in der CustomToolstripMenuItem-Klasse wird nicht kompiliert. Kann nicht haben (MouseButtons! = MouseButtons.Right). Was soll diese Linie sein? Wie ermitteln Sie, welche Taste gedrückt wurde, ich das Click-Ereignis. –

2

Sie müssen wahrscheinlich die Methode aufrufen/aufrufen.

[DllImport("user32.dll")] 
static extern bool TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, 
IntPtr hwnd, IntPtr lptpm); 

const int TPM_RECURSE = 0x0001; 
+0

Bisher habe ich es nicht geschafft, das funktioniert zu bekommen. –

+0

Ich habe dies teilweise mit dem alten ContextMenu funktioniert, aber nicht ContextMenuStrip. Selbst dann hatte es einige Probleme mit Fokus und Hervorhebung, und die alten ContextMenu-Klassen sehen mit den neueren Menüs nicht richtig aus. –

Verwandte Themen