1

I'm looking for a way to develop this:

Heberger image
(source: hostingpics.net)

When the mouse is over the form's title bar (rectange 1 on the picture) the form content (the rectangle 2) is visible & when the mouse is not over, it disappears but the rectangle 1 must remain visible!

How could i manage to do that ?

Thanks in advance

Community
  • 1
  • 1

3 Answers3

1

I suggest that you make a borderless form and use a custom control docked to the top as the title bar. Then it becomes as simple as changing the height of the form on MouseEnter and MouseLeave events!

Hope that helps!

Digvijay
  • 361
  • 1
  • 9
1

There are some mouse events related to the non-client area of the forms (WM_NCMOUSEMOVE, WM_NCMOUSELEAVE, ...) that can be used for this purpose. But this is not simple, because they are not included in Windows Forms. To use this events, you should override WndProc of your form. Catching WM_NCMOUSEMOVE event is somehow simple, but WM_NCMOSUELEAVE is a little tricky. Windows normally does not send mouse leave events to windows, unless they request it explicitly using TrackMouseEvent function.

Here is the complete code that does exactly what you want:

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0xA0) // WM_NCMOUSEMOVE
        {
            TrackNcMouseLeave(this);
            ShowClientArea();
        }
        else if (m.Msg == 0x2A2) // WM_NCMOUSELEAVE
        {
            HideClientAreaIfPointerIsOut();
        }

        base.WndProc(ref m);
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        HideClientAreaIfPointerIsOut();
    }

    private int previouseHeight;

    private void ShowClientArea()
    {
        if (this.ClientSize.Height == 0)
            this.ClientSize = new Size(this.ClientSize.Width, previouseHeight);
    }

    private void HideClientAreaIfPointerIsOut()
    {
        if (this.Bounds.Contains(Cursor.Position))
            return;
        previouseHeight = this.ClientSize.Height;
        this.ClientSize = new Size(this.ClientSize.Width, 0);
    }

    public static void TrackNcMouseLeave(Control control)
    {
        TRACKMOUSEEVENT tme = new TRACKMOUSEEVENT();
        tme.cbSize = (uint)Marshal.SizeOf(tme);
        tme.dwFlags = 2 | 0x10; // TME_LEAVE | TME_NONCLIENT
        tme.hwndTrack = control.Handle;
        TrackMouseEvent(tme);
    }

    [DllImport("user32")]
    public static extern bool TrackMouseEvent([In, Out] TRACKMOUSEEVENT lpEventTrack);

    [StructLayout(LayoutKind.Sequential)]
    public class TRACKMOUSEEVENT
    {
        public uint cbSize;
        public uint dwFlags;
        public IntPtr hwndTrack;
        public uint dwHoverTime;
    }

Put this code section in your form class, and that takes care of everything.

By overriding WndProc we are handling required mouse events. In WM_NCMOUSEMOVE event, we call a method to inform the operating system that we are interested in WM_NCMOUSELEAVE event, and also we show the client area of the form (if not visible).
In WM_NCMOUSELEAVE event we hide the client area of the form (if the cursor is not on the form). Every time the WM_NCMOUSELEAVE event is called, all tracking events requested by TrackMouseEvent are canceled, so we must call the TrackMouseEvent function every time in WM_NCMOUSEMOVE.

Be aware that maximizing the form is not considered in this code and you should handle it somehow.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72
  • Actually, i just have one little problem. The form disappears when the mouse is not on the header's form. I need the form to disappear when the mouse is not on the whole form. The problem i have is i cannot click anywhere on the form since it automaticaly disappears before. I don't know if you see what i mean. Thanks in advance –  Feb 21 '12 at 11:08
  • This behavior is according to what you described in your question. If it is not what you want, what exactly do you need? Please describe it, and I will explain how can you achieve that. – Mohammad Dehghan Feb 21 '12 at 11:19
  • The form disappears if i'm not in Rectangle 1. I need to see the form if i'm in rectangle 2 –  Feb 21 '12 at 12:10
  • @ArnaudAdigard: I modified the answer's code slightly to behave according to your needs. It works only if your form is **not** child of another form. Otherwise you need to change the cursor position before checking it in `HideClientAreaIfPointerIsOut()`. – Mohammad Dehghan Feb 21 '12 at 17:26
0

Knowing that your Form BorderStyle is set on None, you can develop something based on the position of the mouse and the size of your rectangles, so you must use the MouseEnter and MouseLeave event as said Digvijay.

Here is my sample code:

    private void Rectangle1_MouseEnter(object sender, EventArgs e)
    {
        myForm.Height = Rectangle1.Height + Rectangle2.Height;
    }

    private void Rectangle1_MouseLeave(object sender, EventArgs e)
    {
        if (!myForm.Bounds.Contains(MousePosition))
        {
            myForm.Height = Rectangle1.Height;
        }
    }
Omar
  • 16,329
  • 10
  • 48
  • 66