Существуют некоторые события мыши, связанные с не-клиентской областью форм (WM_NCMOUSEMOVE
, WM_NCMOUSELEAVE
, ...), которые можно использовать для этой цели.Но это не просто, потому что они не включены в Windows Forms.Чтобы использовать это событие, вы должны переопределить WndProc
вашей формы.Поймать событие WM_NCMOUSEMOVE
довольно просто, но WM_NCMOSUELEAVE
немного сложно.Windows обычно не отправляет события отпускания мыши в окна, если они не запрашивают это явно, используя функцию TrackMouseEvent
.
Вот полный код, который делает именно то, что вы хотите:
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этот раздел кода в вашем классе формы, и обо всем позаботится.
Переопределяя WndProc
, мы обрабатываем необходимые события мыши.В событии WM_NCMOUSEMOVE
мы вызываем метод для информирования операционной системы о том, что нас интересует событие WM_NCMOUSELEAVE
, а также показываем клиентскую область формы (если ее не видно).
В событии WM_NCMOUSELEAVE
мыскрыть клиентскую область формы (если курсор не находится на форме).Каждый раз, когда вызывается событие WM_NCMOUSELEAVE
, все события отслеживания, запрошенные TrackMouseEvent
, отменяются, поэтому мы должны вызывать функцию TrackMouseEvent
каждый раз в WM_NCMOUSEMOVE
.
. Имейте в виду, что максимизация формыне рассматривается в этом коде, и вы должны как-то с этим справиться.