C# WPF 创建透明边框窗口以及最小化到后台

透明窗口

将窗口的 WindowStyle 属性设置为 NoneAllowsTransparency 属性设置为 True,并将 Background 设置为 Transparent

1
2
3
4
5
6
7
8
9
10
11
12
13
<Window x:Class="Window1"
mc:Ignorable="d"
Title="SetPageY"
WindowStyle="None"
ResizeMode="CanMinimize"
AllowsTransparency="True"
Background="Transparent">
<Border Margin="10" MouseLeftButtonDown="Window_MouseLeftButtonDown">
<Border.Effect>
<DropShadowEffect BlurRadius="10" Color="#FF486DAA" ShadowDepth="11"/>
</Border.Effect>
</Border>
</Window>

支持拖拽

在窗口的根容器(如Border、Grid等)上绑定MouseLeftButtonDown事件,用于触发拖拽操作。

1
2
3
4
5
6
7
8
9
10
11
12
<Window x:Class="WpfApp1.MainWindow"
...
WindowStyle="None" <!-- 无边框 -->
AllowsTransparency="True" <!-- 允许透明 -->
Background="Transparent"> <!-- 背景透明 -->

<!-- 根容器(Border/Grid等),用于承载内容并绑定拖拽事件 -->
<Border Background="White" <!-- 实际窗口背景色区别于窗口的透明背景-->
MouseLeftButtonDown="Border_MouseLeftButtonDown"> <!-- 绑定拖拽触发事件 -->
...
</Border>
</Window>
1
2
3
4
5
6
7
8
9
10
// 鼠标左键按下时触发拖拽
private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 只有当左键按下时,才允许拖拽
if (e.ButtonState == MouseButtonState.Pressed)
{
// 调用DragMove()实现窗口拖拽
this.DragMove();
}
}

拖拽缩放

为了简单,选择在右下角创建一个 Border,并绑定鼠标左键按下、移动、释放事件,实现窗口的拖拽缩放。

1
2
3
4
5
6
7
8
9
10
<Border
Name="ResizeGrip"
Grid.Column="1"
Width="24"
Height="24"
Background="#7af0b3"
Cursor="SizeNWSE"
MouseLeftButtonDown="Border_MouseLeftButtonDown"
MouseMove="Border_MouseMove"
PreviewMouseLeftButtonUp="Border_PreviewMouseLeftButtonUp" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#region drag scale 
// 标记是否正在拖拽调整大小
private bool isResizing = false;
// 记录拖拽开始时的鼠标位置和窗口大小
private Point startMousePos;
private double startWidth;
private double startHeight;

private void Border_MouseMove(object sender, MouseEventArgs e)
{
if (isResizing && e.LeftButton == MouseButtonState.Pressed)
{
// 计算鼠标移动的偏移量
var currentMousePos = e.GetPosition(this);
double deltaX = currentMousePos.X - startMousePos.X;
double deltaY = currentMousePos.Y - startMousePos.Y;

// 计算新的窗口大小(限制最小尺寸)
double newWidth = startWidth + deltaX;
double newHeight = startHeight + deltaY;
this.Width = Math.Max(newWidth, 300); // 最小宽度200
this.Height = Math.Max(newHeight, 200); // 最小高度150
//Debug.WriteLine($"newWidth: {newWidth}, newHeight: {newHeight}");
}
}

private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isResizing = true;
// 记录初始位置和窗口大小
startMousePos = e.GetPosition(this);
startWidth = this.Width;
startHeight = this.Height;
// 捕获鼠标,确保鼠标移出窗口后仍能响应事件
ResizeGrip.CaptureMouse();
}

private void Border_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
isResizing = false;
// 释放鼠标捕获
ResizeGrip.ReleaseMouseCapture();
}
#endregion

注意:如果同时启用了拖拽移动和拖拽缩放,并且它们的范围有重叠,那么缩放会出bug

解决同时使用拖拽和缩放

解决方法:拖拽移动添加判断逻辑,只要鼠标在 Border 上移动,就不允许缩放。

1
2
3
4
5
6
7
8
9
10
11
12
private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (ResizeGrip.IsMouseOver || isResizing) // isResizing 就是上面标记进行拖拽缩放的
{
return;
}
if (e.ButtonState == MouseButtonState.Pressed)
{
// 调用DragMove()实现窗口拖拽
this.DragMove();
}
}

窗口的隐藏和显示

期望效果:鼠标点击窗口外面,隐藏窗口。使用 Deactivated 事件实现。

1
2
3
4
5
6
<Window
x:Class="RestoreOpenedExplorer.MainWindow"
...
AllowsTransparency="True"
Background="Transparent"
Deactivated="Window_Deactivated">
1
2
3
4
private void Window_Deactivated(object sender, EventArgs e)
{
this.Hide();
}

显示:

1
2
3
4
5
6
7
private void ShowMe()
{
Show(); // 显示窗口
Topmost = true; // 置顶显示
Activate(); // 激活窗口
Focus(); // 聚焦窗口
}

通过任意方式调用 ShowMe() 方法,即可显示窗口。

最小化到后台

由于 .NET 8.0 不再支持引入 Windows 窗体,所以无法使用原生提供的最小化到后台功能。

使用 H.NotifyIcon 库实现最小化到后台功能。

按需引入:

1
2
3
4
5
6
7
Install-Package H.NotifyIcon.Wpf
Install-Package H.NotifyIcon.WinUI
Install-Package H.NotifyIcon.Uno
Install-Package H.NotifyIcon.Uno.WinUI
# If you need other platforms, you can use this Core library -
# it allows you to make NotifyIcon even in a console application.
Install-Package H.NotifyIcon

其官方示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Window
xmlns:tb="clr-namespace:H.NotifyIcon;assembly=H.NotifyIcon.Wpf" // WPF
xmlns:tb="using:H.NotifyIcon" // WinUI
>
<tb:TaskbarIcon
ToolTipText="ToolTip"
IconSource="/Images/TrayIcons/Logo.ico"
ContextMenu="{StaticResource TrayMenu}"
MenuActivation="LeftOrRightClick"
TrayPopup="{StaticResource TrayStatusPopup}"
PopupActivation="DoubleClick"
TrayToolTip="{StaticResource TrayToolTip}"
/>
</Window>

实际操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<Window
x:Class="RestoreOpenedExplorer.MainWindow"
xmlns:local="clr-namespace:RestoreOpenedExplorer"
xmlns:tb="clr-namespace:H.NotifyIcon;assembly=H.NotifyIcon.Wpf"
AllowsTransparency="True"
Background="Transparent"
Deactivated="Window_Deactivated"
ResizeMode="CanMinimize"
WindowStartupLocation="CenterScreen"
WindowStyle="None">
<Grid Margin="4">
<!-- 系统托盘图标 -->
<tb:TaskbarIcon
x:Name="TaskbarIcon"
IconSource="./ico/ie.ico"
ToolTipText="Explorer 打开的历史"
TrayMouseDoubleClick="TaskbarIcon_TrayMouseDoubleClick">
<!-- 自定义右键菜单 -->
<tb:TaskbarIcon.ContextMenu>
<ContextMenu>
<MenuItem Click="MenuItem_Click" Header="显示窗口" />
<Separator />
<MenuItem Click="MenuItem_Click_1" Header="退出" />
</ContextMenu>
</tb:TaskbarIcon.ContextMenu>
</tb:TaskbarIcon>
...

C# WPF 创建透明边框窗口以及最小化到后台
https://taylorandtony.github.io/2025/07/10/csharp-WPF-创建透明边框窗口以及最小化到后台/
作者
TaylorAndTony
发布于
2025年7月10日
许可协议