dev 19-3-30

This commit is contained in:
NaBian committed 2019-03-30 23:42:21 +08:00
1 parent 5ee2bdd3f7
commit 6e56c967ce
7 files changed
+147 -27

No files matched your search

+68 -10
View File
@@ -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)
{ {
+1
View File
@@ -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);
}
} }
} }