在自定义窗口上启动窗口的系统菜单

当您单击应用程序的图标或在应用程序的标题栏上单击鼠标右键时,我想调用ContextMenu

这是ContextMenu我的意思是:

在此处输入图像描述

我需要它,因为我做了像窗口一样的自定义控件。
我需要这种行为来完成我的控制。

编辑:
Leo Lorenzo Luis问我代码:

https://skydrive.live.com/?cid=c3392940f5cf5f74&id=C3392940F5CF5F74%21107&authkey=!APd2X3tDxWRfpL4

要么:

我的MainWindow.xaml:

  <!--                 

我的MainWindow.cs(代码隐藏):

 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Interop; using System.Windows.Forms; namespace WpfApplication16 { ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.SourceInitialized += new EventHandler(win_SourceInitialized); } private void TriggerMaximize(object sender, MouseButtonEventArgs e) { TriggerMaximize(); } private void TriggerMaximize(object sender, RoutedEventArgs e) { TriggerMaximize(); } private void TriggerMaximize() { if (WindowState == System.Windows.WindowState.Maximized) { WindowState = System.Windows.WindowState.Normal; Restore.Visibility = Visibility.Collapsed; Maximize.Visibility = Visibility.Visible; } else if (WindowState == System.Windows.WindowState.Normal) { WindowState = System.Windows.WindowState.Maximized; Maximize.Visibility = Visibility.Collapsed; Restore.Visibility = Visibility.Visible; } } private void Window_LocationChanged(object sender, EventArgs e) { TriggerBorderChanges(); } private void Window_SizeChanged(object sender, SizeChangedEventArgs e) { TriggerBorderChanges(); } private void TriggerBorderChanges() { TopBorder.BorderThickness = new Thickness(0.5); RightBorder.BorderThickness = new Thickness(0.5); BottomBorder.BorderThickness = new Thickness(0.5); LeftBorder.BorderThickness = new Thickness(0.5); if (Top == 0) { TopBorder.BorderThickness = new Thickness(0); BottomBorder.BorderThickness = new Thickness(0); } if (Left == 0) { LeftBorder.BorderThickness = new Thickness(0); } // need to test in dual view -if not needed, remove drawing and windows.forms (from refereance and from the using) //Screen currentScreen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); //if (Left == (currentScreen.WorkArea.Width - Width)) if (Left == (System.Windows.SystemParameters.WorkArea.Width - 1 - Width)) { RightBorder.BorderThickness = new Thickness(0); } } private void TriggerClose(object sender, RoutedEventArgs e) { Close(); } private void TriggerMinimize(object sender, RoutedEventArgs e) { WindowState = System.Windows.WindowState.Minimized; } private void StatusBar_MouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) this.DragMove(); } void win_SourceInitialized(object sender, EventArgs e) { System.IntPtr handle = (new WindowInteropHelper(this)).Handle; HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc)); } ///  /// POINT aka POINTAPI /// 5 [StructLayout(LayoutKind.Sequential)] public struct POINT { ///  /// x coordinate of point. ///  public int x; ///  /// y coordinate of point. ///  public int y; ///  /// Construct a point of coordinates (x,y). ///  public POINT(int x, int y) { this.x = x; this.y = y; } } [StructLayout(LayoutKind.Sequential)] public struct MINMAXINFO { public POINT ptReserved; public POINT ptMaxSize; public POINT ptMaxPosition; public POINT ptMinTrackSize; public POINT ptMaxTrackSize; }; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class MONITORINFO { ///  ///  public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); ///  ///  public RECT rcMonitor = new RECT(); ///  ///  public RECT rcWork = new RECT(); ///  ///  public int dwFlags = 0; } ///  Win32  [StructLayout(LayoutKind.Sequential, Pack = 0)] public struct RECT { ///  Win32  public int left; ///  Win32  public int top; ///  Win32  public int right; ///  Win32  public int bottom; ///  Win32  public static readonly RECT Empty = new RECT(); ///  Win32  public int Width { get { return Math.Abs(right - left); } // Abs needed for BIDI OS } ///  Win32  public int Height { get { return bottom - top; } } ///  Win32  public RECT(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } ///  Win32  public RECT(RECT rcSrc) { this.left = rcSrc.left; this.top = rcSrc.top; this.right = rcSrc.right; this.bottom = rcSrc.bottom; } ///  Win32  public bool IsEmpty { get { // BUGBUG : On Bidi OS (hebrew arabic) left > right return left >= right || top >= bottom; } } ///  Return a user friendly representation of this struct  public override string ToString() { if (this == RECT.Empty) { return "RECT {Empty}"; } return "RECT { left : " + left + " / top : " + top + " / right : " + right + " / bottom : " + bottom + " }"; } ///  Determine if 2 RECT are equal (deep compare)  public override bool Equals(object obj) { if (!(obj is Rect)) { return false; } return (this == (RECT)obj); } /// Return the HashCode for this struct (not garanteed to be unique) public override int GetHashCode() { return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode(); } ///  Determine if 2 RECT are equal (deep compare) public static bool operator ==(RECT rect1, RECT rect2) { return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom); } ///  Determine if 2 RECT are different(deep compare) public static bool operator !=(RECT rect1, RECT rect2) { return !(rect1 == rect2); } } [DllImport("user32")] internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); [DllImport("User32")] internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags); private static System.IntPtr WindowProc( System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) { switch (msg) { case 0x0024: WmGetMinMaxInfo(hwnd, lParam); handled = true; break; } return (System.IntPtr)0; } private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam) { MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); // Adjust the maximized size and position to fit the work area of the correct monitor int MONITOR_DEFAULTTONEAREST = 0x00000002; System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); if (monitor != System.IntPtr.Zero) { MONITORINFO monitorInfo = new MONITORINFO(); GetMonitorInfo(monitor, monitorInfo); RECT rcWorkArea = monitorInfo.rcWork; RECT rcMonitorArea = monitorInfo.rcMonitor; mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left); mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left); mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); } Marshal.StructureToPtr(mmi, lParam, true); } } } 

我的App.xaml:

                                  

非常感谢您的帮助。

您要显示的菜单是系统ContextMenu 。 要使用它,您需要导入一些user32函数,如下面的代码所示。 我点击了按钮启动了系统菜单。 您可以在任何操作,鼠标右键单击等上启动它

GetSystemMenu获取系统菜单, TrackPopupMenuEx用于显示它。 PostMessage是menuitem click上的send system命令。

 public partial class Window3 : Window { private const int WM_SYSCOMMAND = 0x112; uint TPM_LEFTALIGN = 0x0000; uint TPM_RETURNCMD = 0x0100; const UInt32 MF_ENABLED = 0x00000000; const UInt32 MF_GRAYED = 0x00000001; internal const UInt32 SC_MAXIMIZE = 0xF030; internal const UInt32 SC_RESTORE = 0xF120; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); [DllImport("user32.dll")] static extern int TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm); [DllImport("user32.dll")] public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable); private void Button_Click(object sender, RoutedEventArgs e) { WindowInteropHelper helper = new WindowInteropHelper(this); IntPtr callingWindow = helper.Handle; IntPtr wMenu = GetSystemMenu(callingWindow, false); // Display the menu if (this.WindowState == System.Windows.WindowState.Maximized) { EnableMenuItem(wMenu, SC_MAXIMIZE, MF_GRAYED); } else { EnableMenuItem(wMenu, SC_MAXIMIZE, MF_ENABLED); } int command = TrackPopupMenuEx(wMenu, TPM_LEFTALIGN | TPM_RETURNCMD, 100, 100, callingWindow, IntPtr.Zero); if (command == 0) return; PostMessage(callingWindow, WM_SYSCOMMAND, new IntPtr(command), IntPtr.Zero); } 

在自定义控件(如您共享的图像)中,将Visual Studio(图标)设置为图像按钮/按钮,并在单击时显示ContextMenu。

  

然后在Click处理程序上,只需说buttonName.ContextMenu.IsOpen = true

有关如何实现这一点的更多信息,请点击此处

已经有一个依赖项属性,您可以设置它来显示上下文菜单。 我不确定你的意思是“你需要自己制作一个,还是可以直接打电话”

编辑:我不明白为什么你要重新创建 Window行为而不是将自定义窗口inheritance到Window类并覆盖你需要自定义的内容。