Browse Source

add example win32 tray icon.

pull/6610/head
Dan Walmsley 5 years ago
parent
commit
2d2d8fa5a7
  1. 8
      samples/ControlCatalog/App.xaml.cs
  2. 2
      samples/ControlCatalog/MainWindow.xaml.cs
  3. 182
      src/Windows/Avalonia.Win32/TrayIconImpl.cs

8
samples/ControlCatalog/App.xaml.cs

@ -103,9 +103,13 @@ namespace ControlCatalog
{
desktopLifetime.MainWindow = new MainWindow();
var trayIcon = new TrayIcon();
var trayIcon1 = new TrayIcon();
trayIcon.Icon = desktopLifetime.MainWindow.Icon;
trayIcon1.Icon = desktopLifetime.MainWindow.Icon;
var trayIcon2 = new TrayIcon();
trayIcon2.Icon = desktopLifetime.MainWindow.Icon;
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
singleViewLifetime.MainView = new MainView();

2
samples/ControlCatalog/MainWindow.xaml.cs

@ -35,6 +35,8 @@ namespace ControlCatalog
var mainMenu = this.FindControl<Menu>("MainMenu");
mainMenu.AttachedToVisualTree += MenuAttached;
ExtendClientAreaChromeHints = Avalonia.Platform.ExtendClientAreaChromeHints.OSXThickTitleBar;
}
public static string MenuQuitHeader => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "Quit Avalonia" : "E_xit";

182
src/Windows/Avalonia.Win32/TrayIconImpl.cs

@ -6,93 +6,12 @@ using System.Runtime.InteropServices;
using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Platform;
using Avalonia.Threading;
using Avalonia.Win32.Interop;
using static Avalonia.Win32.Interop.UnmanagedMethods;
namespace Avalonia.Win32
{
/// <summary>
/// Custom Win32 window messages for the NotifyIcon
/// </summary>
public enum CustomWindowsMessage : uint
{
WM_TRAYICON = WindowsMessage.WM_APP + 1024,
WM_TRAYMOUSE = WindowsMessage.WM_USER + 1024
}
public class TrayIconManagedPopupPositionerPopupImplHelper : IManagedPopupPositionerPopup
{
public delegate void MoveResizeDelegate(PixelPoint position, Size size, double scaling);
private readonly MoveResizeDelegate _moveResize;
private Window _hiddenWindow;
public TrayIconManagedPopupPositionerPopupImplHelper(MoveResizeDelegate moveResize)
{
_moveResize = moveResize;
_hiddenWindow = new Window();
}
public IReadOnlyList<ManagedPopupPositionerScreenInfo> Screens =>
_hiddenWindow.Screens.All.Select(s => new ManagedPopupPositionerScreenInfo(
s.Bounds.ToRect(1), s.Bounds.ToRect(1))).ToList();
public Rect ParentClientAreaScreenGeometry
{
get
{
var point = _hiddenWindow.Screens.Primary.Bounds.TopLeft;
var size = _hiddenWindow.Screens.Primary.Bounds.Size;
return new Rect(point.X, point.Y, size.Width * _hiddenWindow.Screens.Primary.PixelDensity, size.Height * _hiddenWindow.Screens.Primary.PixelDensity);
}
}
public void MoveAndResize(Point devicePoint, Size virtualSize)
{
_moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _hiddenWindow.Screens.Primary.PixelDensity);
}
public virtual double Scaling => _hiddenWindow.Screens.Primary.PixelDensity;
}
public class TrayPopupRoot : Window
{
private ManagedPopupPositioner _positioner;
public TrayPopupRoot()
{
_positioner = new ManagedPopupPositioner(new TrayIconManagedPopupPositionerPopupImplHelper(MoveResize));
Topmost = true;
LostFocus += TrayPopupRoot_LostFocus;
}
private void MoveResize(PixelPoint position, Size size, double scaling)
{
PlatformImpl.Move(position);
PlatformImpl.Resize(size, PlatformResizeReason.Layout);
}
private void TrayPopupRoot_LostFocus(object sender, Interactivity.RoutedEventArgs e)
{
Close();
}
protected override void ArrangeCore(Rect finalRect)
{
base.ArrangeCore(finalRect);
_positioner.Update(new PopupPositionerParameters
{
Anchor = PopupAnchor.TopLeft,
Gravity = PopupGravity.BottomRight,
AnchorRectangle = new Rect(Position.ToPoint(1) / Screens.Primary.PixelDensity, new Size(1, 1)),
Size = finalRect.Size,
ConstraintAdjustment = PopupPositionerConstraintAdjustment.FlipX | PopupPositionerConstraintAdjustment.FlipY,
});
}
}
public class TrayIconImpl : ITrayIconImpl
{
private readonly int _uniqueId = 0;
@ -163,7 +82,14 @@ namespace Avalonia.Win32
{
throw new NotImplementedException();
}
/// <summary>
/// Custom Win32 window messages for the NotifyIcon
/// </summary>
public enum CustomWindowsMessage : uint
{
WM_TRAYICON = WindowsMessage.WM_APP + 1024,
WM_TRAYMOUSE = WindowsMessage.WM_USER + 1024
}
private void UpdateIcon(bool remove = false)
{
var iconData = new NOTIFYICONDATA()
@ -210,8 +136,6 @@ namespace Avalonia.Win32
// Click?.Invoke(this, new EventArgs());
//}
//_doubleClick = false;
Debug.WriteLine($"Clicked {lParam:X}");
break;
case (int)WindowsMessage.WM_LBUTTONDBLCLK:
@ -226,9 +150,13 @@ namespace Avalonia.Win32
default:
break;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
return IntPtr.Zero;
}
else
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
private static void OnRightClicked()
@ -258,5 +186,85 @@ namespace Avalonia.Win32
_trayMenu.Show();
}
class TrayPopupRoot : Window
{
private ManagedPopupPositioner _positioner;
public TrayPopupRoot()
{
_positioner = new ManagedPopupPositioner(new TrayIconManagedPopupPositionerPopupImplHelper(MoveResize));
Topmost = true;
Deactivated += TrayPopupRoot_Deactivated;
}
private void TrayPopupRoot_Deactivated(object sender, EventArgs e)
{
Dispatcher.UIThread.Post(() =>
{
Close();
});
}
private void MoveResize(PixelPoint position, Size size, double scaling)
{
PlatformImpl.Move(position);
PlatformImpl.Resize(size, PlatformResizeReason.Layout);
}
private void TrayPopupRoot_LostFocus(object sender, Interactivity.RoutedEventArgs e)
{
Close();
}
protected override void ArrangeCore(Rect finalRect)
{
base.ArrangeCore(finalRect);
_positioner.Update(new PopupPositionerParameters
{
Anchor = PopupAnchor.TopLeft,
Gravity = PopupGravity.BottomRight,
AnchorRectangle = new Rect(Position.ToPoint(1) / Screens.Primary.PixelDensity, new Size(1, 1)),
Size = finalRect.Size,
ConstraintAdjustment = PopupPositionerConstraintAdjustment.FlipX | PopupPositionerConstraintAdjustment.FlipY,
});
}
class TrayIconManagedPopupPositionerPopupImplHelper : IManagedPopupPositionerPopup
{
public delegate void MoveResizeDelegate(PixelPoint position, Size size, double scaling);
private readonly MoveResizeDelegate _moveResize;
private Window _hiddenWindow;
public TrayIconManagedPopupPositionerPopupImplHelper(MoveResizeDelegate moveResize)
{
_moveResize = moveResize;
_hiddenWindow = new Window();
}
public IReadOnlyList<ManagedPopupPositionerScreenInfo> Screens =>
_hiddenWindow.Screens.All.Select(s => new ManagedPopupPositionerScreenInfo(
s.Bounds.ToRect(1), s.Bounds.ToRect(1))).ToList();
public Rect ParentClientAreaScreenGeometry
{
get
{
var point = _hiddenWindow.Screens.Primary.Bounds.TopLeft;
var size = _hiddenWindow.Screens.Primary.Bounds.Size;
return new Rect(point.X, point.Y, size.Width * _hiddenWindow.Screens.Primary.PixelDensity, size.Height * _hiddenWindow.Screens.Primary.PixelDensity);
}
}
public void MoveAndResize(Point devicePoint, Size virtualSize)
{
_moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _hiddenWindow.Screens.Primary.PixelDensity);
}
public virtual double Scaling => _hiddenWindow.Screens.Primary.PixelDensity;
}
}
}
}

Loading…
Cancel
Save