问题
I'm looking for a way to develop this:
(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
回答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.
回答2:
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!
回答3:
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;
}
}
来源:https://stackoverflow.com/questions/9359484/hide-a-forms-client-area-but-let-the-title-bar-be-visible-when-mouse-is-not-o