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;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.Controls; using Avalonia.Controls;
@ -16,16 +17,24 @@ namespace Avalonia.Win32
{ {
private readonly int _uniqueId = 0; private readonly int _uniqueId = 0;
private static int _nextUniqueId = 0; private static int _nextUniqueId = 0;
private WndProc _wndProcDelegate;
private IntPtr _hwnd;
private bool _iconAdded; private bool _iconAdded;
private IconImpl _icon; 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() public TrayIconImpl()
{ {
_uniqueId = ++_nextUniqueId; _uniqueId = ++_nextUniqueId;
CreateMessageWindow(); s_trayIcons.Add(_uniqueId, this);
UpdateIcon(); UpdateIcon();
} }
@ -36,34 +45,6 @@ namespace Avalonia.Win32
UpdateIcon(false); 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) public void SetIcon(IWindowIconImpl icon)
{ {
_icon = icon as IconImpl; _icon = icon as IconImpl;
@ -94,7 +75,7 @@ namespace Avalonia.Win32
{ {
var iconData = new NOTIFYICONDATA() var iconData = new NOTIFYICONDATA()
{ {
hWnd = _hwnd, hWnd = Win32Platform.Instance.Handle,
uID = _uniqueId, uID = _uniqueId,
uFlags = NIF.TIP | NIF.MESSAGE, uFlags = NIF.TIP | NIF.MESSAGE,
uCallbackMessage = (int)CustomWindowsMessage.WM_TRAYMOUSE, uCallbackMessage = (int)CustomWindowsMessage.WM_TRAYMOUSE,
@ -125,6 +106,7 @@ namespace Avalonia.Win32
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{ {
Debug.WriteLine(wParam);
if (msg == (uint)CustomWindowsMessage.WM_TRAYMOUSE) if (msg == (uint)CustomWindowsMessage.WM_TRAYMOUSE)
{ {
// Determine the type of message and call the matching event handlers // 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); _trayMenu.Position = new PixelPoint(pt.X, pt.Y);
@ -197,6 +179,8 @@ namespace Avalonia.Win32
Topmost = true; Topmost = true;
Deactivated += TrayPopupRoot_Deactivated; Deactivated += TrayPopupRoot_Deactivated;
ShowInTaskbar = false;
} }
private void TrayPopupRoot_Deactivated(object sender, EventArgs e) private void TrayPopupRoot_Deactivated(object sender, EventArgs e)

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

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

Loading…
Cancel
Save