dev 19-3-29

This commit is contained in:
NaBian committed 2019-03-29 23:45:16 +08:00
1 parent 67dc02ae83
commit 5ee2bdd3f7
17 files changed
+321 -97

No files matched your search

@@ -2,10 +2,10 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
@@ -35,18 +35,40 @@ namespace HandyControl.Controls
private string _windowClassName;
private static readonly int WmTaskbarcreated = NativeMethods.RegisterWindowMessage("TaskbarCreated");
private int _wmTaskbarCreated;
private IntPtr _messageWindowHandle;
private readonly WndProc _callback;
private ToolTip _toolTip;
private Popup _contextMenu;
private Popup _contextContent;
private bool _doubleClick;
static NotifyIcon()
{
VisibilityProperty.OverrideMetadata(typeof(NotifyIcon), new PropertyMetadata(Visibility.Visible, OnVisibilityChanged));
}
private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (NotifyIcon) d;
var v = (Visibility)e.NewValue;
if (v == Visibility.Visible)
{
if (ctl._currentSmallIconHandle == null)
{
ctl.OnIconChanged();
}
ctl.UpdateIcon(true);
}
else if(ctl._currentSmallIconHandle !=null)
{
ctl.UpdateIcon(false);
}
}
public NotifyIcon()
{
_id = ++NextId;
@@ -54,10 +76,12 @@ namespace HandyControl.Controls
Loaded += (s, e) =>
{
CreateToolTip();
RegisterClass();
OnIconChanged();
UpdateIcon(true);
if (Visibility == Visibility.Visible)
{
OnIconChanged();
UpdateIcon(true);
}
};
if (Application.Current != null) Application.Current.Exit += (s, e) => Dispose();
@@ -87,6 +111,24 @@ namespace HandyControl.Controls
ctl.OnIconChanged();
}
public static readonly DependencyProperty ContextContentProperty = DependencyProperty.Register(
"ContextContent", typeof(object), typeof(NotifyIcon), new PropertyMetadata(default(object)));
public object ContextContent
{
get => GetValue(ContextContentProperty);
set => SetValue(ContextContentProperty, value);
}
public static readonly DependencyProperty IsBlinkProperty = DependencyProperty.Register(
"IsBlink", typeof(bool), typeof(NotifyIcon), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsBlink
{
get => (bool) GetValue(IsBlinkProperty);
set => SetValue(IsBlinkProperty, value);
}
public ImageSource Icon
{
get => (ImageSource)GetValue(IconProperty);
@@ -145,7 +187,7 @@ namespace HandyControl.Controls
uTimeoutOrVersion = 10,
uID = _id,
dwInfoFlags = NativeMethods.NIF_TIP,
hIcon = _currentSmallIconHandle.DangerousGetHandle(),
hIcon = _currentSmallIconHandle.CriticalGetHandle(),
szTip = Text
};
@@ -182,11 +224,12 @@ namespace HandyControl.Controls
hIcon = IntPtr.Zero,
hCursor = IntPtr.Zero,
hbrBackground = IntPtr.Zero,
lpszMenuName = string.Empty,
lpszMenuName = "",
lpszClassName = _windowClassName
};
UnsafeNativeMethods.RegisterClass(wndclass);
_wmTaskbarCreated = NativeMethods.RegisterWindowMessage("TaskbarCreated");
_messageWindowHandle = UnsafeNativeMethods.CreateWindowEx(0, _windowClassName, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
}
@@ -194,13 +237,12 @@ namespace HandyControl.Controls
{
if (IsLoaded)
{
if (msg == WmTaskbarcreated)
if (msg == _wmTaskbarCreated)
{
UpdateIcon(true);
}
else
{
Console.WriteLine(lparam);
switch (lparam.ToInt32())
{
case NativeMethods.WM_LBUTTONDBLCLK:
@@ -234,15 +276,6 @@ namespace HandyControl.Controls
ShowContextMenu();
WmMouseUp(MouseButton.Right);
break;
case 0x406:
OnBalloonTipShown();
break;
case 0x407:
OnBalloonTipClosed();
break;
case NativeMethods.NIN_BALLOONTIMEOUT:
OnBalloonTipClosed();
break;
}
}
}
@@ -250,15 +283,6 @@ namespace HandyControl.Controls
return UnsafeNativeMethods.DefWindowProc(hWnd, msg, wparam, lparam);
}
private void OnBalloonTipShown()
{
var point = new POINT();
UnsafeNativeMethods.GetCursorPos(point);
ShowToolTip(point);
}
private void OnBalloonTipClosed() => _toolTip.IsOpen = false;
private void WmMouseDown(MouseButton button, int clicks)
{
if (clicks == 2)
@@ -302,11 +326,38 @@ namespace HandyControl.Controls
private void ShowContextMenu()
{
if (ContextMenu != null)
{
var point = new POINT();
UnsafeNativeMethods.GetCursorPos(point);
var point = new POINT();
UnsafeNativeMethods.GetCursorPos(point);
if (ContextContent != null)
{
if (_contextContent == null)
{
_contextContent = new Popup
{
Placement = PlacementMode.AbsolutePoint,
AllowsTransparency = true,
StaysOpen = false
};
}
_contextContent.HorizontalOffset = point.x;
_contextContent.VerticalOffset = point.y;
_contextContent.Child = new ContentControl
{
Content = ContextContent
};
_contextContent.IsOpen = true;
var handle = IntPtr.Zero;
var hwndSource = (HwndSource)PresentationSource.FromVisual(_contextContent.Child);
if (hwndSource != null)
{
handle = hwndSource.Handle;
}
UnsafeNativeMethods.SetForegroundWindow(handle);
}
else if (ContextMenu != null)
{
ContextMenu.Placement = PlacementMode.AbsolutePoint;
ContextMenu.HorizontalOffset = point.x;
ContextMenu.VerticalOffset = point.y;
@@ -322,28 +373,6 @@ namespace HandyControl.Controls
}
}
private void ShowToolTip(POINT point)
{
if (_toolTip != null)
{
_toolTip.HorizontalOffset = point.x;
_toolTip.VerticalOffset = point.x;
_toolTip.IsOpen = true;
}
}
private void CreateToolTip()
{
_toolTip = new ToolTip
{
Placement = PlacementMode.AbsolutePoint,
Style = null
};
_toolTip.SetBinding(ContentControl.ContentProperty, new Binding(ToolTipProperty.Name) { Source = this });
_toolTip.SetBinding(DataContextProperty, new Binding(DataContextProperty.Name) { Source = this });
}
public static readonly RoutedEvent ClickEvent =
EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(NotifyIcon));
@@ -362,27 +391,7 @@ namespace HandyControl.Controls
{
add => AddHandler(MouseDoubleClickEvent, value);
remove => RemoveHandler(MouseDoubleClickEvent, value);
}
//public static readonly RoutedEvent BalloonTipShownEvent =
// EventManager.RegisterRoutedEvent("BalloonTipShown", RoutingStrategy.Bubble,
// typeof(RoutedEventHandler), typeof(NotifyIcon));
//public event RoutedEventHandler BalloonTipShown
//{
// add => AddHandler(BalloonTipShownEvent, value);
// remove => RemoveHandler(BalloonTipShownEvent, value);
//}
//public static readonly RoutedEvent BalloonTipClosedEvent =
// EventManager.RegisterRoutedEvent("BalloonTipClosed", RoutingStrategy.Bubble,
// typeof(RoutedEventHandler), typeof(NotifyIcon));
//public event RoutedEventHandler BalloonTipClosed
//{
// add => AddHandler(BalloonTipClosedEvent, value);
// remove => RemoveHandler(BalloonTipClosedEvent, value);
//}
}
private void Dispose(bool disposing)
{
+3 -1
View File
@@ -115,7 +115,7 @@
<Compile Include="Controls\Other\ChatBubble.cs" />
<Compile Include="Controls\Other\Dialog.cs" />
<Compile Include="Controls\Other\GotoTop.cs" />
<Compile Include="Controls\NotifyIcon\NotifyIcon.cs" />
<Compile Include="Controls\Other\NotifyIcon.cs" />
<Compile Include="Controls\Other\Gravatar.cs" />
<Compile Include="Controls\Panel\SimplePanel.cs" />
<Compile Include="Controls\ProgressBar\WaveProgressBar.cs" />
@@ -182,6 +182,8 @@
<Compile Include="Data\MessageBoxInfo.cs" />
<Compile Include="Data\ResourceToken.cs" />
<Compile Include="Data\SystemVersionInfo.cs" />
<Compile Include="Interactivity\PushMainWindow2TopCommand.cs" />
<Compile Include="Interactivity\ShutdownAppCommand.cs" />
<Compile Include="Tools\Converter\Boolean2StrConverter.cs" />
<Compile Include="Tools\Converter\BorderClipConverter.cs" />
<Compile Include="Tools\Converter\BorderCircularConverter.cs" />
@@ -146,5 +146,15 @@ namespace HandyControl.Interactivity
/// 打开链接
/// </summary>
public static RoutedCommand OpenLink { get; } = new RoutedCommand(nameof(OpenLink), typeof(ControlCommands));
/// <summary>
/// 关闭程序
/// </summary>
public static ShutdownAppCommand ShutdownApp { get; } = new ShutdownAppCommand();
/// <summary>
/// 前置主窗口
/// </summary>
public static PushMainWindow2TopCommand PushMainWindow2Top { get; } = new PushMainWindow2TopCommand();
}
}
@@ -0,0 +1,28 @@
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using HandyControl.Tools.Interop;
namespace HandyControl.Interactivity
{
public class PushMainWindow2TopCommand : ICommand
{
public bool CanExecute(object parameter) => true;
public void Execute(object parameter)
{
if (Application.Current.MainWindow != null)
{
Application.Current.MainWindow.Show();
var hwndSource = (HwndSource)PresentationSource.FromDependencyObject(Application.Current.MainWindow);
if (hwndSource != null)
{
UnsafeNativeMethods.SetForegroundWindow(hwndSource.Handle);
}
}
}
public event EventHandler CanExecuteChanged;
}
}
@@ -0,0 +1,15 @@
using System;
using System.Windows;
using System.Windows.Input;
namespace HandyControl.Interactivity
{
public class ShutdownAppCommand : ICommand
{
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => Application.Current.Shutdown();
public event EventHandler CanExecuteChanged;
}
}
@@ -123,22 +123,22 @@
</Grid.ColumnDefinitions>
<Border Height="22" Width="36" x:Name="backBorder" Background="{DynamicResource BorderBrush}" CornerRadius="11"/>
<Border Grid.Column="0" Height="22" Width="36" Opacity="0" x:Name="lightBorder" Background="{DynamicResource PrimaryBrush}" CornerRadius="11" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
<Border Grid.Column="0" Margin="1" Background="{TemplateBinding Background}" CornerRadius="11" Name="innerBorder" RenderTransformOrigin=".8,0.5">
<Border Grid.Column="0" Height="20" Margin="1" Background="{TemplateBinding Background}" CornerRadius="11" Name="innerBorder" RenderTransformOrigin=".8,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
<Canvas Grid.Column="0" Margin="1">
<Border CornerRadius="10" Name="thumb" Effect="{StaticResource EffectShadow2}" Background="White" Width="20" Height="20" RenderTransformOrigin="0.5,0.5">
<controls:SimplePanel Grid.Column="0" Margin="1">
<Border HorizontalAlignment="Left" CornerRadius="10" Name="thumb" Effect="{StaticResource EffectShadow2}" Background="White" Width="20" Height="20" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
</Canvas>
</controls:SimplePanel>
<ContentPresenter x:Name="contentPresenter" Visibility="Collapsed" Grid.Column="1" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
+8 -8
View File
@@ -11,13 +11,13 @@ namespace HandyControl.Tools.Interop
{
public int style;
public WndProc lpfnWndProc;
public int cbClsExtra = 0;
public int cbWndExtra = 0;
public IntPtr hInstance = IntPtr.Zero;
public IntPtr hIcon = IntPtr.Zero;
public IntPtr hCursor = IntPtr.Zero;
public IntPtr hbrBackground = IntPtr.Zero;
public string lpszMenuName = null;
public string lpszClassName = null;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
public string lpszMenuName;
public string lpszClassName;
}
}
+2
View File
@@ -32,5 +32,7 @@ namespace HandyControlDemo.Data
}
public static AppConfig Config { get; set; }
public static bool NotifyIconIsShow { get; set; }
}
}
+1
View File
@@ -362,6 +362,7 @@
<Compile Include="ViewModel\Common\ComboBoxDemoViewModel.cs" />
<Compile Include="ViewModel\Controls\CoverViewModel.cs" />
<Compile Include="ViewModel\Controls\DialogDemoViewModel.cs" />
<Compile Include="ViewModel\Controls\NotifyIconDemoViewModel.cs" />
<Compile Include="ViewModel\Controls\SearchBarDemoViewModel.cs" />
<Compile Include="ViewModel\DemoViewModelBase!1.cs" />
<Compile Include="ViewModel\Main\ContributorsViewModel.cs" />
+16
View File
@@ -1,5 +1,7 @@
using System;
using System.ComponentModel;
using HandyControl.Controls;
using HandyControlDemo.Data;
namespace HandyControlDemo
{
@@ -23,5 +25,19 @@ namespace HandyControlDemo
Growl.SetGrowlParent(GrowlPanel, false);
}
protected override void OnClosing(CancelEventArgs e)
{
if (GlobalData.NotifyIconIsShow)
{
MessageBox.Info(Properties.Langs.Lang.AppClosingTip, Properties.Langs.Lang.Tip);
Hide();
e.Cancel = true;
}
else
{
base.OnClosing(e);
}
}
}
}
+63
View File
@@ -78,6 +78,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 托盘图标已打开,将隐藏窗口而不是关闭程序 的本地化字符串。
/// </summary>
public static string AppClosingTip {
get {
return ResourceManager.GetString("AppClosingTip", resourceCulture);
}
}
/// <summary>
/// 查找类似 询问 的本地化字符串。
/// </summary>
@@ -105,6 +114,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 闪烁 的本地化字符串。
/// </summary>
public static string Blink {
get {
return ResourceManager.GetString("Blink", resourceCulture);
}
}
/// <summary>
/// 查找类似 博客 的本地化字符串。
/// </summary>
@@ -429,6 +447,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 退出 的本地化字符串。
/// </summary>
public static string Exit {
get {
return ResourceManager.GetString("Exit", resourceCulture);
}
}
/// <summary>
/// 查找类似 展开框 的本地化字符串。
/// </summary>
@@ -798,6 +825,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 打开面板 的本地化字符串。
/// </summary>
public static string OpenPanel {
get {
return ResourceManager.GetString("OpenPanel", resourceCulture);
}
}
/// <summary>
/// 查找类似 轮廓文本 的本地化字符串。
/// </summary>
@@ -1176,6 +1212,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 提示 的本地化字符串。
/// </summary>
public static string Tip {
get {
return ResourceManager.GetString("Tip", resourceCulture);
}
}
/// <summary>
/// 查找类似 标题 的本地化字符串。
/// </summary>
@@ -1248,6 +1293,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 试试关闭程序吧? 的本地化字符串。
/// </summary>
public static string Try2CloseApp {
get {
return ResourceManager.GetString("Try2CloseApp", resourceCulture);
}
}
/// <summary>
/// 查找类似 类型 的本地化字符串。
/// </summary>
@@ -1275,6 +1329,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 可见性 的本地化字符串。
/// </summary>
public static string Visibility {
get {
return ResourceManager.GetString("Visibility", resourceCulture);
}
}
/// <summary>
/// 查找类似 警告 的本地化字符串。
/// </summary>
@@ -531,4 +531,25 @@
<data name="NewWindow" xml:space="preserve">
<value>New window</value>
</data>
<data name="Visibility" xml:space="preserve">
<value>Visibility</value>
</data>
<data name="Blink" xml:space="preserve">
<value>Blink</value>
</data>
<data name="Exit" xml:space="preserve">
<value>Exit</value>
</data>
<data name="OpenPanel" xml:space="preserve">
<value>Open Panel</value>
</data>
<data name="AppClosingTip" xml:space="preserve">
<value>The tray icon is open and will hide the window instead of closing the program</value>
</data>
<data name="Tip" xml:space="preserve">
<value>Prompt</value>
</data>
<data name="Try2CloseApp" xml:space="preserve">
<value>Try to close app?</value>
</data>
</root>
@@ -531,4 +531,25 @@
<data name="NewWindow" xml:space="preserve">
<value>新建窗口</value>
</data>
<data name="Visibility" xml:space="preserve">
<value>可见性</value>
</data>
<data name="Blink" xml:space="preserve">
<value>闪烁</value>
</data>
<data name="Exit" xml:space="preserve">
<value>退出</value>
</data>
<data name="OpenPanel" xml:space="preserve">
<value>打开面板</value>
</data>
<data name="AppClosingTip" xml:space="preserve">
<value>托盘图标已打开,将隐藏窗口而不是关闭程序</value>
</data>
<data name="Tip" xml:space="preserve">
<value>提示</value>
</data>
<data name="Try2CloseApp" xml:space="preserve">
<value>试试关闭程序吧?</value>
</data>
</root>
@@ -1,15 +1,29 @@
<UserControl x:Class="HandyControlDemo.UserControl.NotifyIconDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
xmlns:interactivity="clr-namespace:HandyControl.Interactivity;assembly=HandyControl"
DataContext="{Binding NotifyIconDemo,Source={StaticResource Locator}}"
Background="{DynamicResource RegionBrush}">
<Grid>
<controls:NotifyIcon Text="123">
<StackPanel Margin="32">
<GroupBox controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Visibility}">
<ToggleButton IsChecked="{Binding IsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
</GroupBox>
<TextBlock Foreground="{DynamicResource InfoBrush}" Visibility="{Binding IsShow,Converter={StaticResource Boolean2VisibilityConverter}}" Text="{x:Static langs:Lang.Try2CloseApp}" Margin="0,6,0,0"/>
<GroupBox Margin="0,16,0,0" controls:TitleElement.TitleAlignment="Left" Style="{StaticResource GroupBoxOriginal}" Header="{x:Static langs:Lang.Blink}">
<ToggleButton IsEnabled="{Binding IsShow}" Style="{StaticResource ToggleButtonSwitch}"/>
</GroupBox>
</StackPanel>
<controls:NotifyIcon Text="123" Visibility="{Binding IsShow,Converter={StaticResource Boolean2VisibilityConverter}}">
<!--<controls:NotifyIcon.ContextContent>
<Border Width="100" Height="300" Background="Black"/>
</controls:NotifyIcon.ContextContent>-->
<controls:NotifyIcon.ContextMenu>
<ContextMenu>
<MenuItem Header="123"/>
<MenuItem Header="123"/>
<MenuItem Header="123"/>
<MenuItem Command="interactivity:ControlCommands.PushMainWindow2Top" Header="{x:Static langs:Lang.OpenPanel}"/>
<MenuItem Command="interactivity:ControlCommands.ShutdownApp" Header="{x:Static langs:Lang.Exit}"/>
</ContextMenu>
</controls:NotifyIcon.ContextMenu>
</controls:NotifyIcon>
@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
@@ -32,7 +31,7 @@ namespace HandyControlDemo.UserControl
GlobalData.Config.Lang = tag;
GlobalData.Save();
Process.Start(Assembly.GetExecutingAssembly().Location);
Environment.Exit(0);
Application.Current.Shutdown();
return true;
});
}
@@ -0,0 +1,20 @@
using GalaSoft.MvvmLight;
using HandyControlDemo.Data;
namespace HandyControlDemo.ViewModel
{
public class NotifyIconDemoViewModel : ViewModelBase
{
private bool _isShow;
public bool IsShow
{
get => _isShow;
set
{
Set(ref _isShow, value);
GlobalData.NotifyIconIsShow = value;
}
}
}
}
@@ -26,6 +26,7 @@ namespace HandyControlDemo.ViewModel
SimpleIoc.Default.Register<CoverViewModel>();
SimpleIoc.Default.Register<DialogDemoViewModel>();
SimpleIoc.Default.Register<SearchBarDemoViewModel>();
SimpleIoc.Default.Register<NotifyIconDemoViewModel>();
}
public static ViewModelLocator Instance => new Lazy<ViewModelLocator>(() =>
@@ -57,6 +58,8 @@ namespace HandyControlDemo.ViewModel
public SearchBarDemoViewModel SearchBarDemo => ServiceLocator.Current.GetInstance<SearchBarDemoViewModel>();
public NotifyIconDemoViewModel NotifyIconDemo => ServiceLocator.Current.GetInstance<NotifyIconDemoViewModel>();
#endregion
}
}