如何设置自定义气球位置?

问题描述 投票:0回答:1

我使用 Hardcodet WPF NotifyIcon 在某些事件上显示自定义气球。

如果我在MainWindow的xaml中创建

TaskbarIcon
,那么我的气球就会放置在任务栏附近:

TaskbarIcon created in MainWindow

但是当我在资源文件(xaml)或应用程序类中创建

TaskbarIcon
时,我的气球就会放置在任务栏上:

enter image description here

为什么这些情况之间的行为存在差异以及如何控制自定义气球的位置?

编辑:我使用下一个代码来测试它:

(应用程序.xaml):

<Application x:Class="TestBalloon.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:tb="http://www.hardcodet.net/taskbar"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <tb:TaskbarIcon x:Key="TrayIcon" ToolTipText="Created From Resources" />
    </Application.Resources>
</Application>

(应用程序.xaml.cs):

public partial class App : Application
{
    public TaskbarIcon AppTrayIcon;

    protected override void OnStartup(StartupEventArgs e)
    {
        AppTrayIcon = (TaskbarIcon)FindResource("TrayIcon");
    }
}

(主窗口.xaml):

<Window x:Class="TestBalloon.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:tb="http://www.hardcodet.net/taskbar"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <tb:TaskbarIcon x:Name="MainWindowTrayIcon" ToolTipText="Created in MainWindow" />

        <Button x:Name="MyButton" 
                Content="ClickMe"
                Margin="10,10,10,10"
                Click="MyButton_OnClick"/>
    </Grid>
</Window>

(MainWindow.xaml.cs):

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void MyButton_OnClick(object sender, RoutedEventArgs e)
    {
        FancyBalloon bal = new FancyBalloon(); // From Hardcodet WPF NotifyIcon Tutorial

        // To use TaskbarItem created in MainWindow.xaml
        //MainWindowTrayIcon.ShowCustomBalloon(bal, PopupAnimation.Slide, null);

        // To use TaskbarItem created in App.xaml
        ((App)Application.Current).AppTrayIcon.ShowCustomBalloon(bal, PopupAnimation.Slide, null);
    }
}
c# wpf taskbar popup-balloons
1个回答
0
投票

我知道,我是这里的考古学家,但是嘿,问题还没有得到解答!

在我的设置上进行了测试,即 Windows 10 build 19045.3570,在 .NET Framework 4.8.NET6 中安装了 WPF App,并安装了 Hardcodet.NotifyIcon.Wpf v.1.1.0

问题不再存在,在我的情况下,调用在

TaskBatItem
App.xaml
中创建的
MainWindow.xaml
FancyBalloon
已正确显示。

顺便说一句,有问题的是

FancyBalloon UserControl
实现缺失(不是我的代码,取自https://www.codeproject.com/Articles/36468/WPF-NotifyIcon-2)。

用户界面

<UserControl x:Class="WpfApp9.FancyBalloon"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WpfApp9"
             xmlns:tb="http://www.hardcodet.net/taskbar"
             x:Name="me"
             Width="240"
             Height="120"
             mc:Ignorable="d">
    <UserControl.Resources>
        <Storyboard x:Key="FadeIn">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="grid"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="0.95"/>
                <SplineDoubleKeyFrame KeyTime="00:00:03" Value="0.95"/>
                <!--                <SplineDoubleKeyFrame KeyTime="00:00:05" Value="0"/>-->
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="HighlightCloseButton">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="imgClose"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.4"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="FadeCloseButton">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="imgClose"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.4"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="FadeBack">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="grid"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="FadeOut" Completed="OnFadeOutCompleted">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="grid"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.2"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>
    <UserControl.Triggers>
        <EventTrigger RoutedEvent="tb:TaskbarIcon.BalloonShowing">
            <BeginStoryboard x:Name="FadeIn_BeginStoryboard" Storyboard="{StaticResource FadeIn}"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="Mouse.MouseEnter" SourceName="imgClose">
            <BeginStoryboard x:Name="HighlightCloseButton_BeginStoryboard" Storyboard="{StaticResource HighlightCloseButton}"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="Mouse.MouseLeave" SourceName="imgClose">
            <BeginStoryboard x:Name="FadeCloseButton_BeginStoryboard" Storyboard="{StaticResource FadeCloseButton}"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="Mouse.MouseEnter">
            <StopStoryboard BeginStoryboardName="FadeIn_BeginStoryboard"/>
            <BeginStoryboard x:Name="FadeBack_BeginStoryboard1" Storyboard="{StaticResource FadeBack}"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="tb:TaskbarIcon.BalloonClosing">
            <BeginStoryboard x:Name="FadeOut_BeginStoryboard" Storyboard="{StaticResource FadeOut}"/>
        </EventTrigger>
    </UserControl.Triggers>
    <Grid x:Name="grid" MouseEnter="grid_MouseEnter">
        <Border Margin="5,5,5,5"
                HorizontalAlignment="Stretch"
                BorderThickness="1,1,1,1"
                BorderBrush="#FF997137">
            <Border.Effect>
                <DropShadowEffect Color="#FF747474"/>
            </Border.Effect>
            <Border.Background>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Offset="0" Color="#FF4B4B4B"/>
                    <GradientStop Offset="1" Color="#FF8F8F8F"/>
                </LinearGradientBrush>
            </Border.Background>
        </Border>
        <Image Width="72"
               Height="72"
               Margin="0,10,0,0"
               HorizontalAlignment="Left"
               VerticalAlignment="Top"
               Source="/Images/Info.png"
               Stretch="Fill"/>
        <TextBlock Margin="72,49.2,10,0"
                   VerticalAlignment="Top"
                   Foreground="#FFECAD25"
                   TextWrapping="Wrap">
            <Run Text="This is a user control. The animation uses the attached "/>
            <Run FontStyle="Italic"
                 FontWeight="Bold"
                 Text="BalloonShowing "/>
            <Run Text="event."/>
        </TextBlock>
        <Path Height="1"
              Margin="72,38.2,34,0"
              VerticalAlignment="Top"
              Fill="#FFFFFFFF"
              Stretch="Fill"
              Data="M26,107 L220.04123,107"
              SnapsToDevicePixels="True">
            <Path.Stroke>
                <LinearGradientBrush StartPoint="0.005,0.5" EndPoint="0.973,0.5">
                    <GradientStop Offset="1" Color="#00ECAD25"/>
                    <GradientStop Offset="0" Color="#87ECAD25"/>
                </LinearGradientBrush>
            </Path.Stroke>
        </Path>
        <TextBlock Height="23.2"
                   Margin="72,10,10,0"
                   VerticalAlignment="Top"
                   Text="{Binding Path=BalloonText, ElementName=me, Mode=Default}"
                   TextWrapping="Wrap"
                   Foreground="#FFECAD25"
                   FontWeight="Bold"/>
        <Image x:Name="imgClose"
               Width="16"
               Height="16"
               Margin="0,10,10,0"
               HorizontalAlignment="Right"
               VerticalAlignment="Top"
               Source="/Images/Close.png"
               Stretch="Fill"
               Opacity="0.4"
               ToolTip="Close Balloon"
               MouseDown="imgClose_MouseDown"/>
    </Grid>
</UserControl>

隐藏代码

using Hardcodet.Wpf.TaskbarNotification;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

namespace WpfApp9
{
    public partial class FancyBalloon : UserControl
    {
        private bool isClosing = false;

        #region BalloonText dependency property

        /// <summary>
        /// Description
        /// </summary>
        public static readonly DependencyProperty BalloonTextProperty =
            DependencyProperty.Register("BalloonText",
                typeof(string),
                typeof(FancyBalloon),
                new FrameworkPropertyMetadata(""));

        /// <summary>
        /// A property wrapper for the <see cref="BalloonTextProperty"/>
        /// dependency property:<br/>
        /// Description
        /// </summary>
        public string BalloonText
        {
            get { return (string)GetValue(BalloonTextProperty); }
            set { SetValue(BalloonTextProperty, value); }
        }

        #endregion

        public FancyBalloon()
        {
            InitializeComponent();
            TaskbarIcon.AddBalloonClosingHandler(this, OnBalloonClosing);
        }


        /// <summary>
        /// By subscribing to the <see cref="TaskbarIcon.BalloonClosingEvent"/>
        /// and setting the "Handled" property to true, we suppress the popup
        /// from being closed in order to display the custom fade-out animation.
        /// </summary>
        private void OnBalloonClosing(object sender, RoutedEventArgs e)
        {
            e.Handled = true; //suppresses the popup from being closed immediately
            isClosing = true;
        }


        /// <summary>
        /// Resolves the <see cref="TaskbarIcon"/> that displayed
        /// the balloon and requests a close action.
        /// </summary>
        private void imgClose_MouseDown(object sender, MouseButtonEventArgs e)
        {
            //the tray icon assigned this attached property to simplify access
            TaskbarIcon taskbarIcon = TaskbarIcon.GetParentTaskbarIcon(this);
            taskbarIcon.CloseBalloon();
        }

        /// <summary>
        /// If the users hovers over the balloon, we don't close it.
        /// </summary>
        private void grid_MouseEnter(object sender, MouseEventArgs e)
        {
            //if we're already running the fade-out animation, do not interrupt anymore
            //(makes things too complicated for the sample)
            if (isClosing) return;

            //the tray icon assigned this attached property to simplify access
            TaskbarIcon taskbarIcon = TaskbarIcon.GetParentTaskbarIcon(this);
            taskbarIcon.ResetBalloonCloseTimer();
        }


        /// <summary>
        /// Closes the popup once the fade-out animation completed.
        /// The animation was triggered in XAML through the attached
        /// BalloonClosing event.
        /// </summary>
        private void OnFadeOutCompleted(object sender, EventArgs e)
        {
            Popup pp = (Popup)Parent;
            pp.IsOpen = false;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.