Home > Software engineering >  How to show the Window's System Menu Programmatically When FormBorderStyle Is None?
How to show the Window's System Menu Programmatically When FormBorderStyle Is None?

Time:10-03

I have a Form with the FormBorderStyle set to None, and I have also made my own little GUI replacing the Title Bar, I'm trying to find a way to show the Menu that shows up whenever you right click the title bar or click the icon on the title bar

System Menu shown on Notepad

I have tried using this post but after calling the function nothing happened, I'm at a loss now and I cannot find more resources about this.

CodePudding user response:

When the border style of Form is set to FormBorderStyle.None, GetSystemMenu() always returns a NULL handle.

Because you remove some important Window Styles from HWND when you set the border style to None, this function doesn't return a HMENU.
Probably, it does some checks if the window has a title bar or not. This is why it returns NULL.

The workaround for the issue is to get the menu handle before setting the FoormBorderStyle to None.

using System.Runtime.InteropServices;

public partial class MainForm : Form
{
    public MainForm() => InitializeComponent();

    [DllImport("user32.dll")]
    private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

    [DllImport("user32.dll")]
    private static extern int TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y,
       int nReserved, IntPtr hWnd, IntPtr prcRect);
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    private IntPtr hMenu;
    private const int WM_SYSCOMMAND = 0x112;
    protected override void OnHandleCreated(EventArgs e)
    {
        // Get the system menu and set the border style after that.
        hMenu = GetSystemMenu(Handle, false);
        FormBorderStyle = FormBorderStyle.None;
        
    }
    protected override void onm ouseUp(MouseEventArgs e)
    {
        int menuIdentifier = TrackPopupMenu(hMenu, 0x102, Control.MousePosition.X, Control.MousePosition.Y, 0, Handle, IntPtr.Zero);
        if(menuIdentifier != 0)
        {
            SendMessage(Handle, WM_SYSCOMMAND, (IntPtr)menuIdentifier, IntPtr.Zero);
        }
    }
}
  • Related