如何在右键单击打开窗口系统菜单?

时间:2014-02-17 09:34:37

标签: .net user-interface

我有一个无边框的启动画面显示加载进度并包含 最小化 关闭 按钮(类似的东西)飞溅在Office 2013中看到的屏幕)。我还想提供窗口的系统菜单,该窗口在窗体的任何位置右键单击打开。

  

Classic system menu of a window

目前我正在通过发送 Alt + Space 键来打开菜单。

    System.Windows.Forms.SendKeys.SendWait("% ")   'sending Alt+Space

使用这种方法,窗口系统菜单总是在窗口的左上角打开。

当用户右键单击窗口的标题栏时,是否有一种以与Windows原生方式相同的方式以编程方式打开系统菜单?弹出菜单的API调用或消息?

我想在应用程序中保留系统菜单,因为我已在其中添加了项目“关于”“设置”。 (此应用程序充当核心应用程序的独立启动器和更新程序。)

平台 WPF ,其中包含 Windows窗体库(由于使用SendWait()的解决方法)。如果发布一些代码,请随意选择VB或C#。

1 个答案:

答案 0 :(得分:3)

没有带烘焙的winapi功能来显示系统菜单。您可以使用pinvoke自己显示它。 GetSystemMenu()函数返回系统菜单的句柄,使用TrackPopupMenu()显示它,通过调用SendMessage执行所选命令以发送WM_SYSCOMMAND。

一些示例代码,说明如何执行此操作并包含必要的声明:

using System.Runtime.InteropServices;
...
    private void Window_MouseDown(object sender, MouseButtonEventArgs e) {
        if (e.ChangedButton == MouseButton.Right) {
            IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
            RECT pos;
            GetWindowRect(hWnd, out pos);
            IntPtr hMenu = GetSystemMenu(hWnd, false);
            int cmd = TrackPopupMenu(hMenu, 0x100, pos.left, pos.top, 0, hWnd, IntPtr.Zero);
            if (cmd > 0) SendMessage(hWnd, 0x112, (IntPtr)cmd, IntPtr.Zero);
        }
    }
    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    [DllImport("user32.dll")]
    static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
    [DllImport("user32.dll")]
    static extern int TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y,
       int nReserved, IntPtr hWnd, IntPtr prcRect);
    [DllImport("user32.dll")]
    static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);
    struct RECT { public int left, top, right, bottom; }

请注意,您可以在任何地方显示菜单,我只是选择了窗口的左上角。请注意位置值以像素为单位。