当鼠标不在标题栏上时,隐藏表单的客户区(但让标题栏可见)

时间:2012-02-20 10:18:10

标签: c# winforms cursor titlebar

我正在寻找一种方法来开发它:

Heberger image http://img11.hostingpics.net/thumbs/mini_350415Explications.png

当鼠标位于表单的标题栏(图片上的矩形1)上时,表单内容(矩形2)可见&当鼠标未结束时,它会消失,但矩形1必须保持可见!

我怎么能设法做到这一点?

提前致谢

3 个答案:

答案 0 :(得分:1)

我建议您创建一个无边框表单,并使用停靠在顶部的自定义控件作为标题栏。然后就像在MouseEnter和MouseLeave事件上更改表单的高度一样简单!

希望有所帮助!

答案 1 :(得分:1)

有些鼠标事件与表单的非客户区域(WM_NCMOUSEMOVEWM_NCMOUSELEAVE,...)相关,可用于此目的。但这并不简单,因为它们不包含在Windows窗体中。要使用此活动,您应该覆盖表单的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;
    }

将此代码部分放在表单类中,并处理所有内容。

通过覆盖WndProc,我们正在处理所需的鼠标事件。在WM_NCMOUSEMOVE事件中,我们调用一种方法来通知操作系统我们对WM_NCMOUSELEAVE事件感兴趣,并且还显示表单的客户区域(如果不可见)。
WM_NCMOUSELEAVE事件中,我们隐藏表单的客户区(如果光标不在表单上)。每次调用WM_NCMOUSELEAVE事件时,TrackMouseEvent请求的所有跟踪事件都会被取消,因此我们每次都必须在TrackMouseEvent调用WM_NCMOUSEMOVE函数。

请注意,在此代码中不考虑最大化表单,您应该以某种方式处理它。

答案 2 :(得分:0)

知道你的Form BorderStyle设置为None,你可以根据鼠标的位置和矩形的大小来开发一些东西,所以你必须使用MouseEnterMouseLeave事件来表示 Digvijay

以下是我的示例代码:

    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;
        }
    }