You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF应用最小化时显示通知框及类Chrome自定义通知实现问询

嘿,我之前做WPF项目时刚好遇到过一模一样的需求,给你两个亲测有效的解决方案,完美解决你说的问题:

方案一:改造Popup控件,让主窗口最小化时不消失

你之前用Popup时遇到的主窗口最小化弹窗消失的问题,本质是Popup默认依附于主窗口,主窗口隐藏它也跟着隐藏。我们可以通过Win32 API把Popup的父窗口改成桌面,这样它就脱离主窗口的控制了:

步骤1:在XAML中定义Popup

先写一个基础的Popup布局,自定义你需要的通知内容:

<Popup x:Name="NotificationPopup" StaysOpen="True" Placement="Absolute" Width="300" Height="100">
    <Border Background="#FFFFFF" BorderBrush="#E5E7EB" BorderThickness="1" CornerRadius="4">
        <StackPanel Margin="12">
            <TextBlock FontWeight="SemiBold" Text="新通知" FontSize="14"/>
            <TextBlock Text="这是一条测试通知内容" FontSize="12" Margin="0,4,0,0" Foreground="#4B5563"/>
        </StackPanel>
    </Border>
</Popup>

步骤2:后台代码修改Popup的父窗口

引入Win32 API,把Popup的父窗口设置为桌面,同时监听主窗口的状态变化来控制Popup显示:

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

public partial class MainWindow : Window
{
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll")]
    private static extern IntPtr GetDesktopWindow();

    public MainWindow()
    {
        InitializeComponent();
        Loaded += MainWindow_Loaded;
        StateChanged += MainWindow_StateChanged;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        // 获取Popup的句柄并修改父窗口为桌面
        var hwndSource = PresentationSource.FromVisual(NotificationPopup.Child) as HwndSource;
        if (hwndSource != null)
        {
            SetParent(hwndSource.Handle, GetDesktopWindow());
        }
    }

    private void MainWindow_StateChanged(object sender, EventArgs e)
    {
        if (WindowState == WindowState.Minimized)
        {
            // 设置Popup到屏幕右下角位置
            var screenWidth = SystemParameters.PrimaryScreenWidth;
            var screenHeight = SystemParameters.PrimaryScreenHeight;
            NotificationPopup.HorizontalOffset = screenWidth - NotificationPopup.Width - 20;
            NotificationPopup.VerticalOffset = screenHeight - NotificationPopup.Height - 20;
            NotificationPopup.IsOpen = true;
        }
        // 主窗口恢复时可以选择关闭Popup,或者保留,根据你的需求调整
        // else { NotificationPopup.IsOpen = false; }
    }
}

注意事项

  • 如果需要Popup始终在最上层,可以设置Popup.TopMost = true
  • 记得处理Popup的关闭逻辑,比如点击弹窗后关闭,或者定时自动关闭

方案二:自定义无任务栏的通知窗口(类似Chrome风格)

如果你想要更灵活的弹窗样式(比如带动画、自定义交互),可以用自定义Window,但要去掉任务栏图标,同时避免抢焦点:

步骤1:创建通知窗口的XAML

新建一个NotificationWindow.xaml,设置窗口属性让它不在任务栏显示,并且支持透明和自定义样式:

<Window x:Class="YourAppName.NotificationWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="320" Height="120"
        ShowInTaskbar="False"
        WindowStyle="None"
        AllowsTransparency="True"
        ShowActivated="False"
        TopMost="False"
        Background="Transparent">
    <!-- 自定义你的通知内容,这里模拟Chrome的通知样式 -->
    <Border Background="#FFFFFF" BorderBrush="#E0E0E0" BorderThickness="1" CornerRadius="4">
        <Grid Margin="12">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="40"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Ellipse Fill="#4285F4" Width="32" Height="32"/>
            <StackPanel Grid.Column="1" Margin="8,0,0,0">
                <TextBlock FontWeight="Bold" Text="Chrome风格通知" FontSize="14"/>
                <TextBlock Text="这是一条来自自定义窗口的通知" FontSize="12" Margin="0,4,0,0" Foreground="#666666"/>
            </StackPanel>
        </Grid>
    </Border>
</Window>

步骤2:主窗口中控制通知窗口的显示

在主窗口的后台代码中,监听窗口状态变化,当主窗口最小化时显示通知:

using System;
using System.Windows;

public partial class MainWindow : Window
{
    private NotificationWindow _notificationWindow;

    public MainWindow()
    {
        InitializeComponent();
        StateChanged += MainWindow_StateChanged;
    }

    private void MainWindow_StateChanged(object sender, EventArgs e)
    {
        if (WindowState == WindowState.Minimized)
        {
            ShowCustomNotification();
        }
    }

    private void ShowCustomNotification()
    {
        // 避免重复创建窗口
        if (_notificationWindow == null || !_notificationWindow.IsVisible)
        {
            _notificationWindow = new NotificationWindow();
            
            // 设置窗口到屏幕右下角
            var screenWidth = SystemParameters.PrimaryScreenWidth;
            var screenHeight = SystemParameters.PrimaryScreenHeight;
            _notificationWindow.Left = screenWidth - _notificationWindow.Width - 20;
            _notificationWindow.Top = screenHeight - _notificationWindow.Height - 20;
            
            _notificationWindow.Show();

            // 可选:添加自动关闭逻辑,比如3秒后关闭
            var timer = new System.Windows.Threading.DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(3);
            timer.Tick += (s, args) =>
            {
                _notificationWindow.Close();
                timer.Stop();
            };
            timer.Start();
        }
    }
}

注意事项

  • ShowActivated="False"可以让弹窗不会激活,不会抢走主窗口的焦点
  • 如果需要弹窗动画,可以给Window添加Window.Triggers实现淡入淡出效果
  • 多个通知时可以做堆叠布局,比如新通知在旧通知上方

内容的提问来源于stack exchange,提问作者soliloquyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:23:57