Search code examples
c#.netwinformspowershellsystemmenu

How to disable the right click context menu on the title bar of a Windows Form using PowerShell


Is it possible to disable the right-click context menu on the TitleBar, WITHOUT removing the title bar and/or the icon? If yes, how?

Image

I am using PowerShell.

I found these two posts, but they are in C# specifically. I don't have enough experience with C# to implement it properly with PowerShell:
Prevent showing system context menu on right click on Form title bar
How to handle Form caption right click

I have the basic code for detecting the mouse event, but I'm not sure how to implement it to detect the right mouse click on the TitleBar only.

$window.Add_MouseDown(
        {
            if (($_.Button.ToString() -eq "Right")) {
                # Code here
            }
        }
    )

Any help with PowerShell code would be appreciated.


Solution

  • You can override WndProc, trap WM_INITMENUPOPUP (or WM_ENTERMENULOOP) and cancel the Popup Menu sending a WM_CANCELMODE message to the Window.

    If you don't want to prevent the System Menu from showing up when you select the TitleBar icon, you can check the Mouse position and only cancel the Popup when the mouse if not in the area occupied by the Titlebar icon.

    In any case (should you decide to suppress the Popup Menu entirely), this doesn't prevent a ContexMenuStrip from showing up in the client area (different messages).

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, int lParam);
    
    private const int WM_CANCELMODE = 0x001F;
    private const int WM_INITMENUPOPUP = 0x0117;
    
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        switch (m.Msg) {
            case WM_INITMENUPOPUP:
                // If the high word is set to 1, the PopupMenu is the Window Menu
                if (m.LParam.ToInt32() >> 16 == 1) {
                    if (MousePosition.X - this.Bounds.X > SystemInformation.MenuButtonSize.Width) {
                        SendMessage(this.Handle, WM_CANCELMODE, 0, 0);
                    }
                }
                m.Result = IntPtr.Zero;
                break;
        }
    }
    

    You can execute C# code in Powershell with:

    $source = @"[...code...]"
    // [...]
    $assemblies = ("System.Windows.Forms", "System.Runtime.InteropServices")
    
    Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $source -Language CSharp
    

    See these posts, for example:

    For an older version of PowerShell, see e.g.:
    C#/PowerShell] Clipboard Watcher