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

cbeh67ev  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(143)

我使用Hardcodet WPF NotifyIcon来显示一些事件的自定义气球。
如果我在MainWindow的xaml中创建TaskbarIcon,那么我的气球将放置在xaml附近:


的数据
但是当我在资源文件(xaml)或应用程序类中创建TaskbarIcon时,我的气球会放在xaml上:



为什么这些情况下的行为存在差异,以及如何控制自定义引出序号的位置?

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

(App.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>

字符串
(App.xaml.cs):

public partial class App : Application
{
    public TaskbarIcon AppTrayIcon;

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


(MainWindow.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);
    }
}

lqfhib0f

lqfhib0f1#

我知道,我是考古学家,但是嘿,问题还没有得到回答!
在我的安装程序上进行了测试,该安装程序为Windows 10 build 19045.3570,在**.NET Framework 4.8.NET6中均安装了WPF应用程序**,并安装了**Hardcodet.NotifyIcon.Wpf v.1.1.0*。
问题不再存在,在我的例子中,调用在App.xamlMainWindow.xaml中创建的TaskBatItemFancyBalloon被正确显示。
顺便说一句,这里缺少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;
        }
    }
}

相关问题