dev 19-3-30
This commit is contained in:
1 parent
5ee2bdd3f7
commit
6e56c967ce
7 files changed
+147
-27
No files matched your search
@@ -5,6 +5,7 @@ using System.Windows.Controls.Primitives;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Threading;
|
||||||
using HandyControl.Data;
|
using HandyControl.Data;
|
||||||
using HandyControl.Tools;
|
using HandyControl.Tools;
|
||||||
using HandyControl.Tools.Interop;
|
using HandyControl.Tools.Interop;
|
||||||
@@ -45,6 +46,10 @@ namespace HandyControl.Controls
|
|||||||
|
|
||||||
private bool _doubleClick;
|
private bool _doubleClick;
|
||||||
|
|
||||||
|
private DispatcherTimer _dispatcherTimer;
|
||||||
|
|
||||||
|
private bool _isTransparent;
|
||||||
|
|
||||||
static NotifyIcon()
|
static NotifyIcon()
|
||||||
{
|
{
|
||||||
VisibilityProperty.OverrideMetadata(typeof(NotifyIcon), new PropertyMetadata(Visibility.Visible, OnVisibilityChanged));
|
VisibilityProperty.OverrideMetadata(typeof(NotifyIcon), new PropertyMetadata(Visibility.Visible, OnVisibilityChanged));
|
||||||
@@ -111,6 +116,12 @@ namespace HandyControl.Controls
|
|||||||
ctl.OnIconChanged();
|
ctl.OnIconChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImageSource Icon
|
||||||
|
{
|
||||||
|
get => (ImageSource)GetValue(IconProperty);
|
||||||
|
set => SetValue(IconProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly DependencyProperty ContextContentProperty = DependencyProperty.Register(
|
public static readonly DependencyProperty ContextContentProperty = DependencyProperty.Register(
|
||||||
"ContextContent", typeof(object), typeof(NotifyIcon), new PropertyMetadata(default(object)));
|
"ContextContent", typeof(object), typeof(NotifyIcon), new PropertyMetadata(default(object)));
|
||||||
|
|
||||||
@@ -120,8 +131,56 @@ namespace HandyControl.Controls
|
|||||||
set => SetValue(ContextContentProperty, value);
|
set => SetValue(ContextContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty BlinkIntervalProperty = DependencyProperty.Register(
|
||||||
|
"BlinkInterval", typeof(TimeSpan), typeof(NotifyIcon), new PropertyMetadata(TimeSpan.FromMilliseconds(500), OnBlinkIntervalChanged));
|
||||||
|
|
||||||
|
private static void OnBlinkIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var ctl = (NotifyIcon)d;
|
||||||
|
if (ctl._dispatcherTimer != null)
|
||||||
|
{
|
||||||
|
ctl._dispatcherTimer.Interval = (TimeSpan) e.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSpan BlinkInterval
|
||||||
|
{
|
||||||
|
get => (TimeSpan) GetValue(BlinkIntervalProperty);
|
||||||
|
set => SetValue(BlinkIntervalProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly DependencyProperty IsBlinkProperty = DependencyProperty.Register(
|
public static readonly DependencyProperty IsBlinkProperty = DependencyProperty.Register(
|
||||||
"IsBlink", typeof(bool), typeof(NotifyIcon), new PropertyMetadata(ValueBoxes.FalseBox));
|
"IsBlink", typeof(bool), typeof(NotifyIcon), new PropertyMetadata(ValueBoxes.FalseBox, OnIsBlinkChanged));
|
||||||
|
|
||||||
|
private static void OnIsBlinkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var ctl = (NotifyIcon)d;
|
||||||
|
if (ctl.Visibility != Visibility.Visible) return;
|
||||||
|
if ((bool) e.NewValue)
|
||||||
|
{
|
||||||
|
if (ctl._dispatcherTimer == null)
|
||||||
|
{
|
||||||
|
ctl._dispatcherTimer = new DispatcherTimer
|
||||||
|
{
|
||||||
|
Interval = ctl.BlinkInterval
|
||||||
|
};
|
||||||
|
ctl._dispatcherTimer.Tick += ctl.DispatcherTimer_Tick;
|
||||||
|
}
|
||||||
|
ctl._dispatcherTimer.Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctl._dispatcherTimer?.Stop();
|
||||||
|
ctl._dispatcherTimer = null;
|
||||||
|
ctl.UpdateIcon(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DispatcherTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (Visibility != Visibility.Visible || _currentSmallIconHandle == null) return;
|
||||||
|
UpdateIcon(true, !_isTransparent);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsBlink
|
public bool IsBlink
|
||||||
{
|
{
|
||||||
@@ -129,12 +188,6 @@ namespace HandyControl.Controls
|
|||||||
set => SetValue(IsBlinkProperty, value);
|
set => SetValue(IsBlinkProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageSource Icon
|
|
||||||
{
|
|
||||||
get => (ImageSource)GetValue(IconProperty);
|
|
||||||
set => SetValue(IconProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnIconChanged()
|
private void OnIconChanged()
|
||||||
{
|
{
|
||||||
IconHandle largeIconHandle;
|
IconHandle largeIconHandle;
|
||||||
@@ -173,12 +226,13 @@ namespace HandyControl.Controls
|
|||||||
_currentSmallIconHandle = smallIconHandle;
|
_currentSmallIconHandle = smallIconHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateIcon(bool showIconInTray)
|
private void UpdateIcon(bool showIconInTray, bool isTransparent = false)
|
||||||
{
|
{
|
||||||
lock (_syncObj)
|
lock (_syncObj)
|
||||||
{
|
{
|
||||||
if (DesignerHelper.IsInDesignMode) return;
|
if (_currentSmallIconHandle == null || DesignerHelper.IsInDesignMode) return;
|
||||||
|
|
||||||
|
_isTransparent = isTransparent;
|
||||||
var data = new NOTIFYICONDATA
|
var data = new NOTIFYICONDATA
|
||||||
{
|
{
|
||||||
uCallbackMessage = WmTrayMouseMessage,
|
uCallbackMessage = WmTrayMouseMessage,
|
||||||
@@ -187,7 +241,7 @@ namespace HandyControl.Controls
|
|||||||
uTimeoutOrVersion = 10,
|
uTimeoutOrVersion = 10,
|
||||||
uID = _id,
|
uID = _id,
|
||||||
dwInfoFlags = NativeMethods.NIF_TIP,
|
dwInfoFlags = NativeMethods.NIF_TIP,
|
||||||
hIcon = _currentSmallIconHandle.CriticalGetHandle(),
|
hIcon = isTransparent ? IntPtr.Zero : _currentSmallIconHandle.CriticalGetHandle(),
|
||||||
szTip = Text
|
szTip = Text
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -397,6 +451,10 @@ namespace HandyControl.Controls
|
|||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
if (_dispatcherTimer != null && IsBlink)
|
||||||
|
{
|
||||||
|
_dispatcherTimer.Stop();
|
||||||
|
}
|
||||||
UpdateIcon(false);
|
UpdateIcon(false);
|
||||||
_defaultLargeIconHandle?.Dispose();
|
_defaultLargeIconHandle?.Dispose();
|
||||||
_defaultSmallIconHandle?.Dispose();
|
_defaultSmallIconHandle?.Dispose();
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
|
|
||||||
namespace HandyControl.Tools.Interop
|
namespace HandyControl.Tools.Interop
|
||||||
{
|
{
|
||||||
|
[SuppressMessage("ReSharper", "UnusedMember.Local")]
|
||||||
internal sealed class BitmapHandle : WpfSafeHandle
|
internal sealed class BitmapHandle : WpfSafeHandle
|
||||||
{
|
{
|
||||||
|
[SecurityCritical]
|
||||||
|
private BitmapHandle() : this(true)
|
||||||
|
{
|
||||||
|
//请不要删除此构造函数,否则当使用自定义ico文件时会报错
|
||||||
|
}
|
||||||
|
|
||||||
[SecurityCritical]
|
[SecurityCritical]
|
||||||
private BitmapHandle(bool ownsHandle) : base(ownsHandle, CommonHandles.GDI)
|
private BitmapHandle(bool ownsHandle) : base(ownsHandle, CommonHandles.GDI)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -805,6 +805,7 @@
|
|||||||
<Generator>TextTemplatingFileGenerator</Generator>
|
<Generator>TextTemplatingFileGenerator</Generator>
|
||||||
<LastGenOutput>MessageToken.cs</LastGenOutput>
|
<LastGenOutput>MessageToken.cs</LastGenOutput>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Resource Include="Resources\Img\icon-white.ico" />
|
||||||
<Resource Include="Resources\Img\LeftMainContent\NotificationHub_16x.png" />
|
<Resource Include="Resources\Img\LeftMainContent\NotificationHub_16x.png" />
|
||||||
<Resource Include="Resources\Img\LeftMainContent\Dialog_16x.png" />
|
<Resource Include="Resources\Img\LeftMainContent\Dialog_16x.png" />
|
||||||
<Resource Include="Resources\Img\under_construction.gif" />
|
<Resource Include="Resources\Img\under_construction.gif" />
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
@@ -6,20 +6,32 @@
|
|||||||
xmlns:interactivity="clr-namespace:HandyControl.Interactivity;assembly=HandyControl"
|
xmlns:interactivity="clr-namespace:HandyControl.Interactivity;assembly=HandyControl"
|
||||||
DataContext="{Binding NotifyIconDemo,Source={StaticResource Locator}}"
|
DataContext="{Binding NotifyIconDemo,Source={StaticResource Locator}}"
|
||||||
Background="{DynamicResource RegionBrush}">
|
Background="{DynamicResource RegionBrush}">
|
||||||
<Grid>
|
<controls:SimplePanel>
|
||||||
<StackPanel Margin="32">
|
<StackPanel Orientation="Horizontal" Margin="32" VerticalAlignment="Center">
|
||||||
<GroupBox controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Visibility}">
|
<GroupBox Header="ContextMenu" Padding="10">
|
||||||
<ToggleButton IsChecked="{Binding IsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
|
<StackPanel>
|
||||||
|
<GroupBox controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Visibility}">
|
||||||
|
<ToggleButton IsChecked="{Binding ContextMenuIsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
|
||||||
|
</GroupBox>
|
||||||
|
<TextBlock Foreground="{DynamicResource InfoBrush}" Visibility="{Binding ContextMenuIsShow,Converter={StaticResource Boolean2VisibilityConverter}}" Text="{x:Static langs:Lang.Try2CloseApp}" Margin="0,6,0,0"/>
|
||||||
|
<GroupBox Margin="0,10,0,0" controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Blink}">
|
||||||
|
<ToggleButton IsChecked="{Binding ContextMenuIsBlink}" IsEnabled="{Binding ContextMenuIsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
|
||||||
|
</GroupBox>
|
||||||
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
<TextBlock Foreground="{DynamicResource InfoBrush}" Visibility="{Binding IsShow,Converter={StaticResource Boolean2VisibilityConverter}}" Text="{x:Static langs:Lang.Try2CloseApp}" Margin="0,6,0,0"/>
|
<GroupBox Header="ContextContent" Margin="16,0,0,0" Padding="10">
|
||||||
<GroupBox Margin="0,16,0,0" controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Blink}">
|
<StackPanel>
|
||||||
<ToggleButton IsEnabled="{Binding IsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
|
<GroupBox controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Visibility}">
|
||||||
|
<ToggleButton IsChecked="{Binding ContextContentIsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
|
||||||
|
</GroupBox>
|
||||||
|
<TextBlock Foreground="{DynamicResource InfoBrush}" Visibility="{Binding ContextContentIsShow,Converter={StaticResource Boolean2VisibilityConverter}}" Text="{x:Static langs:Lang.Try2CloseApp}" Margin="0,6,0,0"/>
|
||||||
|
<GroupBox Margin="0,10,0,0" controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Blink}">
|
||||||
|
<ToggleButton IsChecked="{Binding ContextContentIsBlink}" IsEnabled="{Binding ContextContentIsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
|
||||||
|
</GroupBox>
|
||||||
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<controls:NotifyIcon Text="123" Visibility="{Binding IsShow,Converter={StaticResource Boolean2VisibilityConverter}}">
|
<controls:NotifyIcon Text="HandyControl" IsBlink="{Binding ContextMenuIsBlink}" Visibility="{Binding ContextMenuIsShow,Converter={StaticResource Boolean2VisibilityConverter}}">
|
||||||
<!--<controls:NotifyIcon.ContextContent>
|
|
||||||
<Border Width="100" Height="300" Background="Black"/>
|
|
||||||
</controls:NotifyIcon.ContextContent>-->
|
|
||||||
<controls:NotifyIcon.ContextMenu>
|
<controls:NotifyIcon.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<MenuItem Command="interactivity:ControlCommands.PushMainWindow2Top" Header="{x:Static langs:Lang.OpenPanel}"/>
|
<MenuItem Command="interactivity:ControlCommands.PushMainWindow2Top" Header="{x:Static langs:Lang.OpenPanel}"/>
|
||||||
@@ -27,5 +39,18 @@
|
|||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</controls:NotifyIcon.ContextMenu>
|
</controls:NotifyIcon.ContextMenu>
|
||||||
</controls:NotifyIcon>
|
</controls:NotifyIcon>
|
||||||
</Grid>
|
<controls:NotifyIcon Text="HandyControl" IsBlink="{Binding ContextContentIsBlink}" Visibility="{Binding ContextContentIsShow,Converter={StaticResource Boolean2VisibilityConverter}}" Icon="/HandyControlDemo;component/Resources/Img/icon-white.ico">
|
||||||
|
<controls:NotifyIcon.ContextContent>
|
||||||
|
<Border CornerRadius="4" Margin="10" Background="White" Effect="{StaticResource EffectShadow2}">
|
||||||
|
<StackPanel VerticalAlignment="Center" Margin="16">
|
||||||
|
<Path Width="100" Height="100" Fill="#f06632" Data="{StaticResource LogoGeometry}"/>
|
||||||
|
<StackPanel Margin="0,16,0,0" HorizontalAlignment="Center" Orientation="Horizontal">
|
||||||
|
<Button Command="interactivity:ControlCommands.PushMainWindow2Top" MinWidth="100" Content="{x:Static langs:Lang.OpenPanel}"/>
|
||||||
|
<Button Command="interactivity:ControlCommands.ShutdownApp" Margin="16,0,0,0" MinWidth="100" Style="{StaticResource ButtonPrimary}" Content="{x:Static langs:Lang.Exit}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</controls:NotifyIcon.ContextContent>
|
||||||
|
</controls:NotifyIcon>
|
||||||
|
</controls:SimplePanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@@ -5,16 +5,44 @@ namespace HandyControlDemo.ViewModel
|
|||||||
{
|
{
|
||||||
public class NotifyIconDemoViewModel : ViewModelBase
|
public class NotifyIconDemoViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private bool _isShow;
|
private bool _contextMenuIsShow;
|
||||||
|
|
||||||
public bool IsShow
|
public bool ContextMenuIsShow
|
||||||
{
|
{
|
||||||
get => _isShow;
|
get => _contextMenuIsShow;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Set(ref _isShow, value);
|
Set(ref _contextMenuIsShow, value);
|
||||||
GlobalData.NotifyIconIsShow = value;
|
GlobalData.NotifyIconIsShow = ContextMenuIsShow || ContextContentIsShow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _contextMenuIsBlink;
|
||||||
|
|
||||||
|
public bool ContextMenuIsBlink
|
||||||
|
{
|
||||||
|
get => _contextMenuIsBlink;
|
||||||
|
set => Set(ref _contextMenuIsBlink, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _contextContentIsShow;
|
||||||
|
|
||||||
|
public bool ContextContentIsShow
|
||||||
|
{
|
||||||
|
get => _contextContentIsShow;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Set(ref _contextContentIsShow, value);
|
||||||
|
GlobalData.NotifyIconIsShow = ContextMenuIsShow || ContextContentIsShow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _contextContentIsBlink;
|
||||||
|
|
||||||
|
public bool ContextContentIsBlink
|
||||||
|
{
|
||||||
|
get => _contextContentIsBlink;
|
||||||
|
set => Set(ref _contextContentIsBlink, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user