How to open window system menu on right click?

与世无争的帅哥 提交于 2021-02-18 12:24:06

问题


I have a borderless splash screen form displaying loading progress and containing Minimize and Close buttons (something similar to splash screens seen in Office 2013). I would also like to provide system menu of the window which opens on right click anywhere in the form.

Classic system menu of a window

Currently I'm achieving opening the menu by sending keys Alt+Space.

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

With this approach, window system menu always opens in top-left corner of the window.

Is there a way to programatically open the system menu the same way as Windows does natively when user right-clicks title bar of the window? An API call or message which pops up the menu open?

I would like to keep the system menu available in the app because I have added also items "About" and "Settings" in there. (This app serves as an independent launcher and updater of the core app.)

The platform is WPF with Windows Forms library included, too (due to that workaround using SendWait()). Feel free to choose VB or C# in case of posting some code.


回答1:


There is no baked-in winapi function to display the system menu. You can display it yourself by using pinvoke. The GetSystemMenu() function returns a handle to the system menu, you display it by using TrackPopupMenu(), you execute the selected command by calling SendMessage to send the WM_SYSCOMMAND.

Some sample code that shows how to do this and includes the necessary declarations:

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

Note that you can display the menu anywhere you want, I just picked the upper-left corner of the window. Beware that the position values are in pixels.



来源:https://stackoverflow.com/questions/21825352/how-to-open-window-system-menu-on-right-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!