隐藏表单的客户区

隐藏表单的客户区

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

问题描述

我在寻找一种方法来开发这个:

I'm looking for a way to develop this:

当鼠标在窗体的标题栏(图片上的矩形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!

我怎么能这样做?

提前感谢

推荐答案

有一些鼠标事件与窗体的非客户区相关code> WM_NCMOUSEMOVE , WM_NCMOUSELEAVE ,...)。但这不简单,因为它们不包括在Windows窗体中。要使用此事件,您应覆盖表单的 WndProc 。捕获 WM_NCMOUSEMOVE 事件有点简单,但 WM_NCMOSUELEAVE 是有点棘手。 Windows通常不会向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.

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

09-02 05:27