Browse Source

dont create multiple message queues for tray icons.

pull/6610/head
Dan Walmsley 5 years ago
parent
commit
bc772cce40
  1. 50
      src/Windows/Avalonia.Win32/TrayIconImpl.cs
  2. 6
      src/Windows/Avalonia.Win32/Win32Platform.cs

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

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.Controls;
@ -16,16 +17,24 @@ namespace Avalonia.Win32
{
private readonly int _uniqueId = 0;
private static int _nextUniqueId = 0;
private WndProc _wndProcDelegate;
private IntPtr _hwnd;
private bool _iconAdded;
private IconImpl _icon;
private static Dictionary<int, TrayIconImpl> s_trayIcons = new Dictionary<int, TrayIconImpl>();
internal static void ProcWnd(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if(msg == (int)CustomWindowsMessage.WM_TRAYMOUSE && s_trayIcons.ContainsKey(wParam.ToInt32()))
{
s_trayIcons[wParam.ToInt32()].WndProc(hWnd, msg, wParam, lParam);
}
}
public TrayIconImpl()
{
_uniqueId = ++_nextUniqueId;
CreateMessageWindow();
s_trayIcons.Add(_uniqueId, this);
UpdateIcon();
}
@ -36,34 +45,6 @@ namespace Avalonia.Win32
UpdateIcon(false);
}
private void CreateMessageWindow()
{
// Ensure that the delegate doesn't get garbage collected by storing it as a field.
_wndProcDelegate = new WndProc(WndProc);
WNDCLASSEX wndClassEx = new WNDCLASSEX
{
cbSize = Marshal.SizeOf<WNDCLASSEX>(),
lpfnWndProc = _wndProcDelegate,
hInstance = GetModuleHandle(null),
lpszClassName = "AvaloniaMessageWindow " + Guid.NewGuid(),
};
ushort atom = RegisterClassEx(ref wndClassEx);
if (atom == 0)
{
throw new Win32Exception();
}
_hwnd = CreateWindowEx(0, atom, null, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
if (_hwnd == IntPtr.Zero)
{
throw new Win32Exception();
}
}
public void SetIcon(IWindowIconImpl icon)
{
_icon = icon as IconImpl;
@ -94,7 +75,7 @@ namespace Avalonia.Win32
{
var iconData = new NOTIFYICONDATA()
{
hWnd = _hwnd,
hWnd = Win32Platform.Instance.Handle,
uID = _uniqueId,
uFlags = NIF.TIP | NIF.MESSAGE,
uCallbackMessage = (int)CustomWindowsMessage.WM_TRAYMOUSE,
@ -125,6 +106,7 @@ namespace Avalonia.Win32
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
Debug.WriteLine(wParam);
if (msg == (uint)CustomWindowsMessage.WM_TRAYMOUSE)
{
// Determine the type of message and call the matching event handlers
@ -180,7 +162,7 @@ namespace Avalonia.Win32
}
};
GetCursorPos(out UnmanagedMethods.POINT pt);
GetCursorPos(out POINT pt);
_trayMenu.Position = new PixelPoint(pt.X, pt.Y);
@ -197,6 +179,8 @@ namespace Avalonia.Win32
Topmost = true;
Deactivated += TrayPopupRoot_Deactivated;
ShowInTaskbar = false;
}
private void TrayPopupRoot_Deactivated(object sender, EventArgs e)

6
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -108,6 +108,10 @@ namespace Avalonia.Win32
CreateMessageWindow();
}
internal static Win32Platform Instance => s_instance;
internal IntPtr Handle => _hwnd;
/// <summary>
/// Gets the actual WindowsVersion. Same as the info returned from RtlGetVersion.
/// </summary>
@ -261,6 +265,8 @@ namespace Avalonia.Win32
}
}
}
TrayIconImpl.ProcWnd(hWnd, msg, wParam, lParam);
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
}

Loading…
Cancel
Save