views:

962

answers:

3

I have a C# WinForms borderless window, for which I override WndProc and handle the WM_NCHITTEST message. For an area of that form, my hit test function returns HTSYSMENU. Double-clicking that area successfully closes the form, but right-clicking it does not show the window's system menu, nor does it show up when right-clicking the window's name in the taskbar.

This form uses these styles:

this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
this.SetStyle( ControlStyles.ResizeRedraw, true );

And has these non-default property values:

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.KeyPreview = true;
this.MaximizeBox = false;
this.MinimizeBox = false;

I've tried handling WM_NCRBUTTONDOWN and WM_NCRBUTTONUP, and send the WM_GETSYSMENU message, but it didn't work.

A: 

I have the same properties in my application and Right click doesn't work either, so this is not your problem, it appears to be the way windows forms respond when they have no border.

If you set your border to the normal value, you will be able to have right click in the taskbar and such.

For right click on other controls, you'll need to set the ContextMenuStrip and provide your "menu". But I'm not sure if this works when you have it without border. I have been unable to make it work.

Martín Marconcini
+1  A: 

A borderless window, if I am not mistaken, is flagged such that it offers no system menu, and that it does not appear in the taskbar.

The fact that any given window does not have a border and does not appear in the taskbar is the result of the style flags set on the window. These particular Style flags can be set using the GetWindowLong and SetWindowLong API calls. However you have to be careful as certain styles just don't work together.

I have written a number of custom controls over the years and I am constantly coaxing windows to become something they weren't originally intended to be. For example I have written my own dropdown control where I needed a window to behave as a popup and not to activate. The following code will do that. Note that the code appears in the OnHandleCreated event handler. This is because the flags need to be changed just after the handle is setup which indicates that Windows has already set what it thinks the flags should be.

protected override void OnHandleCreated(EventArgs e) {
    uint dwWindowProperty;

    User32.SetParent( this.Handle, IntPtr.Zero );

    dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.EXSTYLE );
    dwWindowProperty = dwWindowProperty | (uint)User32.WSEX.TOOLWINDOW | (uint)User32.WSEX.NOACTIVATE;
    User32.SetWindowLong( this.Handle, User32.GWL.EXSTYLE, dwWindowProperty );

    dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.STYLE );
    dwWindowProperty = ( dwWindowProperty & ~(uint)User32.WS.CHILD ) | (uint)User32.WS.POPUP; 
    User32.SetWindowLong( this.Handle, User32.GWL.STYLE, dwWindowProperty );
    base.OnHandleCreated (e);
}



//this is a fragment of my User32 library wrapper needed for the previous code segment.
class User32 { 


    [DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
    public  static extern int SetWindowLong( IntPtr hWnd, User32.GWL gwlIndex, uint dwNewLong); 

    [DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
    public static extern uint GetWindowLong( IntPtr hWnd, User32.GWL gwlIndex );


    [FlagsAttribute] 
    public enum WS: uint { 
        POPUP        = 0x80000000,
        CHILD        = 0x40000000,
    }

    public enum GWL {
        STYLE = -16,
        EXSTYLE = -20
    }

    [FlagsAttribute]
    public enum WSEX: uint {
        TOP = 0x0,
        TOPMOST = 0x8,
        TOOLWINDOW = 0x80,
        NOACTIVATE = 0x08000000,
    }
}

Unfortunately the SysMenu style cannot be set without using the Caption style, so I can't say if this is a problem in your implementation.

You can check out the original style list and the extend style list at these two links. http://msdn.microsoft.com/en-us/library/ms632600(VS.85).aspx

http://msdn.microsoft.com/en-us/library/ms632680(VS.85).aspx

Bill
"WS_SYSMENU : Creates a window that has a window menu on its title bar. The WS_CAPTION style must also be specified."Yup, that's it. It's a borderless and captionless form.
Martin Plante
A: 
    protected override void WndProc( ref System.Windows.Forms.Message m )
    { // RightClickMenu
        if ( m.Msg == 0x313 )
        {
            this.contextMenuStrip1.Show(this, this.PointToClient(new Point(m.LParam.ToInt32())));
        }}

This detects rightclick on the applications taskbar "area"..

maybe it will help ?

Thanks, but I don't want to fake the system menu, I was looking for an answer about the absence of a system menu (Restore, Move, Size, Minimize, Maximize, Close) in the first place.
Martin Plante