WPF 窗体增加置顶按钮Demo

10 篇文章 0 订阅
4 篇文章 0 订阅

许多应用窗口除了最大化、最小化、关闭按钮外还包含固定置顶按钮,例如微信、一些播放窗口。

这里尝试用WPF来实现这一功能。

实现步骤:

1. 窗体增加一个固定按钮

设置窗体Style为None,便于重写窗口按钮

增加最大化最小化关闭按钮并实现

除了最大化最小化等按钮,新增ToggleButon表示是否固定

private void CloseButton_Click(object sender, RoutedEventArgs e)
{
    this.Close();
}

private void MaximizeButton_Click(object sender, RoutedEventArgs e)
{
    if (this.WindowState == WindowState.Maximized)
        this.WindowState = WindowState.Normal;
    else
        this.WindowState = WindowState.Maximized;
}

private void MinimizeButton_Click(object sender, RoutedEventArgs e)
{
    this.WindowState = WindowState.Minimized;
}

2. 实现窗体置顶

要实现固定置顶,需要在窗体失去焦点时,仍保持置顶。

所以需要监控窗体失去焦点的事件,让窗体保持TopMost = true;

this.LostKeyboardFocus += Window_PreviewLostKeyboardFocus;
private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    if (this.TopMostButton.IsChecked == false) return;
    this.Topmost = true;
}

3. 由于设置了WindowsStyle = None,窗口得拖拽和窗口得放大放小不支持 ——错误内容,请查看改动标注

文章内容错误改动:这里是因为我设置了AllowsTransparency=true,导致窗口非工作区不起效果了。所以才需要重写Thumb。其实完全可以可以将其设置为False。因为AllowsTransparency属性是为了绘制非矩形窗口提供的。一般情况下不需要使用。对于设置了WindowStyle=None,仍然会存在一定边框的问题,需要通过WindowChromelai来设置非工作区样式。可以参考链接: WPF Window始末|快速了解、自定义Window控件

所以这里实现了对这两个功能得重写。

  1. 窗口拖拽位置实现

    只需要在窗口的根控件上绑定MouseLeftButtonDown,并调用this.DragMove();

 /// <summary>
 /// 窗口移动
 /// </summary>
 private void RooGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 {
     this.DragMove();
 }
  1. 鼠标左键时,支持拖拽调整窗口大小
    窗体上下左右,右上、右下、左上、左下、四个方向增加Thumb实现窗口的大小调整

        <!--  添加 Thumb 控件以实现窗口调整大小  -->
        <Thumb
            Name="ResizeThumbLeft"
            Grid.RowSpan="2"
            Width="5"
            HorizontalAlignment="Left"
            VerticalAlignment="Stretch"
            Cursor="SizeWE"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbTop"
            Grid.RowSpan="2"
            Height="5"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Top"
            Cursor="SizeNS"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbTopLeft"
            Grid.RowSpan="2"
            Width="10"
            Height="10"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Cursor="SizeNWSE"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbTopRight"
            Grid.RowSpan="2"
            Width="10"
            Height="10"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Cursor="SizeNESW"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbRight"
            Grid.RowSpan="2"
            Width="5"
            HorizontalAlignment="Right"
            VerticalAlignment="Stretch"
            Cursor="SizeWE"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbBottom"
            Grid.RowSpan="2"
            Height="5"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Bottom"
            Cursor="SizeNS"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbBottomRight"
            Grid.RowSpan="2"
            Width="10"
            Height="10"
            HorizontalAlignment="Right"
            VerticalAlignment="Bottom"
            Cursor="SizeNWSE"
            DragDelta="ResizeThumb_DragDelta" />

ResizeThumb_DragDelta具体的实现


        private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var thumb = sender as Thumb;
            var window = Window.GetWindow(thumb);

            if (window != null)
            {
                double minWidth = 200;
                double minHeight = 150;

                if (thumb.Name == "ResizeThumbRight" || thumb.Name == "ResizeThumbBottomRight")
                {
                    window.Width = Math.Max(window.Width + e.HorizontalChange, minWidth);
                }
                if (thumb.Name == "ResizeThumbBottom" || thumb.Name == "ResizeThumbBottomRight")
                {
                    window.Height = Math.Max(window.Height + e.VerticalChange, minHeight);
                }
                if (thumb.Name == "ResizeThumbLeft" || thumb.Name == "ResizeThumbTopLeft")
                {
                    window.Width = Math.Max(window.Width - e.HorizontalChange, minWidth);
                    window.Left += e.HorizontalChange;
                }
                if (thumb.Name == "ResizeThumbTop" || thumb.Name == "ResizeThumbTopLeft")
                {
                    window.Height = Math.Max(window.Height - e.VerticalChange, minHeight);
                    window.Top += e.VerticalChange;
                }
            }
        }

效果

在这里插入图片描述

完整代码

<Window
    x:Class="WPFTopMost.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:WPFTopMost"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    AllowsTransparency="True"
    WindowStartupLocation="CenterOwner"
    WindowStyle="None"
    mc:Ignorable="d">
    <Window.Resources>
        <Style TargetType="{x:Type Thumb}">
            <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Foreground" Value="Transparent" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border
                            Background="{TemplateBinding Background}"
                            BorderBrush="Transparent"
                            BorderThickness="0">
                            <Grid>
                                <Border
                                    Background="Transparent"
                                    BorderBrush="Transparent"
                                    BorderThickness="0" />
                                <Border
                                    Margin="1"
                                    Background="Transparent"
                                    BorderBrush="Transparent"
                                    BorderThickness="0" />
                                <Border
                                    Margin="2"
                                    Background="{TemplateBinding Background}" />
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid
        Name="RooGrid"
        MouseLeftButtonDown="RooGrid_MouseLeftButtonDown">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Border
            Grid.Row="0"
            Height="30"
            Background="Transparent">
            <DockPanel LastChildFill="False">
                <ToggleButton
                    x:Name="TopMostButton"
                    Width="75"
                    Click="TopMostButton_Click"
                    Content="📌"
                    DockPanel.Dock="Right" />
                <Button
                    Width="30"
                    Click="CloseButton_Click"
                    Content="X"
                    DockPanel.Dock="Right" />
                <Button
                    Width="30"
                    Click="MaximizeButton_Click"
                    Content="□"
                    DockPanel.Dock="Right" />
                <Button
                    Width="30"
                    Click="MinimizeButton_Click"
                    Content="—"
                    DockPanel.Dock="Right" />
            </DockPanel>
        </Border>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="9*" />
                <ColumnDefinition Width="151*" />
            </Grid.ColumnDefinitions>
            <!--  其他内容  -->
        </Grid>

        <!--  添加 Thumb 控件以实现窗口调整大小  -->
        <Thumb
            Name="ResizeThumbLeft"
            Grid.RowSpan="2"
            Width="5"
            HorizontalAlignment="Left"
            VerticalAlignment="Stretch"
            Cursor="SizeWE"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbTop"
            Grid.RowSpan="2"
            Height="5"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Top"
            Cursor="SizeNS"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbTopLeft"
            Grid.RowSpan="2"
            Width="10"
            Height="10"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Cursor="SizeNWSE"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbTopRight"
            Grid.RowSpan="2"
            Width="10"
            Height="10"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Cursor="SizeNESW"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbRight"
            Grid.RowSpan="2"
            Width="5"
            HorizontalAlignment="Right"
            VerticalAlignment="Stretch"
            Cursor="SizeWE"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbBottom"
            Grid.RowSpan="2"
            Height="5"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Bottom"
            Cursor="SizeNS"
            DragDelta="ResizeThumb_DragDelta" />
        <Thumb
            Name="ResizeThumbBottomRight"
            Grid.RowSpan="2"
            Width="10"
            Height="10"
            HorizontalAlignment="Right"
            VerticalAlignment="Bottom"
            Cursor="SizeNWSE"
            DragDelta="ResizeThumb_DragDelta" />
    </Grid>
</Window>

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFTopMost
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.LostKeyboardFocus += Window_PreviewLostKeyboardFocus; 
            this.MaxHeight = SystemParameters.PrimaryScreenHeight;//防止最大化时系统任务栏被遮盖
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void MaximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
                this.WindowState = WindowState.Normal;
            else
                this.WindowState = WindowState.Maximized;
        }

        private void MinimizeButton_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;
        }

        private void TopMostButton_Click(object sender, RoutedEventArgs e)
        {
            this.Topmost = (bool)this.TopMostButton.IsChecked;
        }

        private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            if (this.TopMostButton.IsChecked == false) return;
            this.Topmost = true;
        }

        /// <summary>
        /// 窗口移动
        /// </summary>
        private void RooGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var thumb = sender as Thumb;
            var window = Window.GetWindow(thumb);

            if (window != null)
            {
                double minWidth = 200;
                double minHeight = 150;

                if (thumb.Name == "ResizeThumbRight" || thumb.Name == "ResizeThumbBottomRight")
                {
                    window.Width = Math.Max(window.Width + e.HorizontalChange, minWidth);
                }
                if (thumb.Name == "ResizeThumbBottom" || thumb.Name == "ResizeThumbBottomRight")
                {
                    window.Height = Math.Max(window.Height + e.VerticalChange, minHeight);
                }
                if (thumb.Name == "ResizeThumbLeft" || thumb.Name == "ResizeThumbTopLeft")
                {
                    window.Width = Math.Max(window.Width - e.HorizontalChange, minWidth);
                    window.Left += e.HorizontalChange;
                }
                if (thumb.Name == "ResizeThumbTop" || thumb.Name == "ResizeThumbTopLeft")
                {
                    window.Height = Math.Max(window.Height - e.VerticalChange, minHeight);
                    window.Top += e.VerticalChange;
                }
            }
        }


    }
}

Demo地址

NitasDemo/04WPFTopMost at main · Nita121388/NitasDemo (github.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值