隐藏窗体的客户区(但让标题栏是可见的),当鼠标不在标题栏 [英] Hide a form's client area (but let the title bar be visible) when mouse is not over the title bar

查看:142
本文介绍了隐藏窗体的客户区(但让标题栏是可见的),当鼠标不在标题栏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方式来开发这样的:

I'm looking for a way to develop this:

当鼠标在窗体的标题栏(在图片上rectange 1)形式的内容(矩形2)是可见的放大器;当鼠标还没有结束,它就会消失,但矩形1必须保持可见!

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!

我怎么能设法做到的?

在此先感谢

推荐答案

有相关的形式非客户区(有些鼠标事件 WM_NCMOUSEMOVE WM_NCMOUSELEAVE ,...),可用于这一目的。但是,这并不简单,因为他们没有在Windows窗体包括在内。要使用此活动,您应该重写的WndProc 的形式。醒目 WM_NCMOUSEMOVE 事件是有点简单,但 WM_NCMOSUELEAVE 是有点棘手。 Windows是否正常不发送鼠标离开事件窗口,除非他们提出要求明确使用 TrackMouseEvent 功能。

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.

通过覆盖的WndProc 我们正在处理需要鼠标事件。在 WM_NCMOUSEMOVE 事件中,我们调用一个方法来告知操作系统,我们感兴趣的是 WM_NCMOUSELEAVE 事件,我们也显示窗体的客户区域(如果不可见)。结果
WM_NCMOUSELEAVE 事件,我们隐藏了窗体的客户区域(如果光标不在在窗体上)。每次 WM_NCMOUSELEAVE 事件被称为,由 TrackMouseEvent 要求所有跟踪事件都取消了,所以我们必须调用 TrackMouseEvent 功能 WM_NCMOUSEMOVE 每次

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.

这篇关于隐藏窗体的客户区(但让标题栏是可见的),当鼠标不在标题栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆