WPF中鼠标事件MouseLeftButtonDown,MouseLeftButtonUp实现无边框窗体的最大化,还原

最近在工作中,开始边学WPF,边在工作中应用。

在做一个自定义边框的WPF窗体的时候,想要实现无边框窗体的:双击标题栏最大化/还原,拖动标题栏移动窗体,拖动标题栏移动到屏幕顶端最大化,在窗体最大化时拖动标题栏恢复窗体原始尺寸。

这个效果在WPF自带边框的前提下,不需要我们去实现,在Window类中已经帮我们做好了。

可是现在我去掉了WPF窗体自带的边框,自己用控件做了一个标题栏和最大化、最小化、关闭按钮,上述的交互效果就要自己实现一下了。

一开始的思路:在作为标题栏的TextBlock控件中,添加MouseDown事件,在这个事件中,处理双击和拖拽交互。然后添加一个MouseLeftButtonUp事件,在这个事件中,处理松开鼠标时,窗体的位置和尺寸。

private void Lb_AppTitle_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2) { if (this.ActualWidth == SystemParameters.WorkArea.Width) { Btn_MaxSize_Clicked(null, null); } else { Btn_MaxSize_Clicked(null, null); } } }

 

上面代码是处理【双击标题栏,最大化窗体,或者还原窗体】的交互逻辑。

然后在上面代码的基础上,又添加了拖拽交互

private void Lb_AppTitle_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
    {
        if (this.ActualWidth == SystemParameters.WorkArea.Width)
        {
            Btn_MaxSize_Clicked(null, null);
        }
        else
        {
            Btn_MaxSize_Clicked(null, null);
        }
    }
    this.DragMove();
}

然后就是在MouseLeftButtonUp事件中,添加鼠标左键抬起后的窗体交互逻辑

private void Lb_AppTitle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
     if (this.Top <= 0)
     {
         CurrentWindowState = WindowState.Maximized;
         rcnormal = new Rect(this.Left, this.Top, this.Width, this.Height);//保存下当前位置与大小
         this.Left = 0;//设置位置
         this.Top = 0;
         Rect rc = SystemParameters.WorkArea;//获取工作区大小
         this.Width = rc.Width;
         this.Height = rc.Height;
     }  
}

但是神奇的事情发生了:MouseLeftButtonUp事件竟然无法触发

然后,在其他TextBlock控件中,添加了一个MouseLeftButtonUp事件,发现是可以触发的。

所以,肯定是之前TextBlock控件中的其他属性或者事件影响到了它的MouseLeftButtonUp事件的触发。

于是,就开始简单粗暴的删除之前TextBlock控件上的属性和事件,一开始,直接删除了MouseDown事件,发现该控件的MouseLeftButtonUp事件竟然可以触发了,

那么,肯定就是MouseDown事件中的代码影响到了MouseLeftButtonUp事件的触发。

最后,发现是拖拽代码DragMove();影响了MouseLeftButtonUp事件的触发。

DragMove();为阻塞方法,在该事件中已经有鼠标按键抬起事件的响应,所以会屏蔽掉外部的鼠标按键抬起事件的触发。

既然如此,那么,就不需要外部的MouseLeftButtonUp事件了。原本该事件存在的目的就是鼠标拖拽窗体结束后,通过检查窗体位置是否在屏幕最顶部,来判断是否最大化窗体。

现在DragMove();方法中,已经有了响应鼠标按键抬起,那么当这个阻塞方法结束后,就意味着鼠标按键已经抬起,那么,我可以将原来的鼠标按键抬起事件中的处理,挪到DragMove();方法之后,就可以起到相同目的。

 

private void Lb_AppTitle_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ClickCount == 2)
    {
        if (this.ActualWidth == SystemParameters.WorkArea.Width)
        {
            Btn_MaxSize_Clicked(null, null);
        }
        else
        {
            Btn_MaxSize_Clicked(null, null);
        }
    }
    else
    {
        if (CurrentWindowState == WindowState.Maximized)
        {
            CurrentWindowState = WindowState.Normal;
            this.Left = rcnormal.Left;
            this.Top = e.GetPosition(this).Y;//rcnormal.Top;
            this.Width = rcnormal.Width;
            this.Height = rcnormal.Height;
            this.Btn_MaxSize.Text = "\uE922";
        }
        this.DragMove();
        if (this.Top <= 0)
        {
            CurrentWindowState = WindowState.Maximized;
            rcnormal = new Rect(this.Left, this.Top, this.Width, this.Height);//保存下当前位置与大小
            this.Left = 0;//设置位置
            this.Top = 0;
            Rect rc = SystemParameters.WorkArea;//获取工作区大小
            this.Width = rc.Width;
            this.Height = rc.Height;
            this.Btn_MaxSize.Text = "\uE923";
        }
    }
}

 

至此结束!

 

posted on 2022-06-23 09:53  双子双星  阅读(2003)  评论(0编辑  收藏  举报

导航