Hi community!
I'm trying to writting an app and here's some trouble about it. I write a WinUI lib using WinForm to achieve tray icon, and I made this tray icon able to react when clicked by mouse. It was working good, I tested it with my new app.
Then something strange happens. I was testing my app on other machines, and I found I'm unable to use its right tray menu while the left is still usable. I found my app(package) created when debugging by VS is not a packaged app hence it would work properly. I removed that on my machine and reinstalled with msix package and the same thing happens.
The WinUI lib is on https://github.com/ShimizuTheLotus/ShimizuToolkit.TrayIconWinUI. For whole project, it's on https://github.com/ShimizuTheLotus/DebrisToys. Nothing personal, it's completely open source.
Plus, here's new problem since I made this question. When I try to build it, it's keep showing The "GenerateProjectPriFile" task was not given a value for the required parameter "ProjectPriIndexName". I tried to revert my changes but seems doesn't works.
I was using the lib in my app(created with WinUI template with packaging project) like this. If you checked the repo DebrisToys, just ignore the code below.
// App.xaml.cs
using Windows.Storage;
using System.Windows.Forms;
using System.Diagnostics;
using System;
using Microsoft.UI;
using Microsoft.UI.Xaml;
protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
MainWindow = new MainWindow();
MainWindow.Activate();
ToysConfigManager.Current.Initialize();
SetUpTrayIcon();
}
private async void SetUpTrayIcon()
{
Uri fileUri = new("ms-appx:///Images/Icon/icon.ico");
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(fileUri);
string iconPath = file.Path;
if (System.IO.Path.Exists(file.Path))
{
NotifyIcon notifyIcon = new()
{
Icon = new System.Drawing.Icon(iconPath),
Visible = true
};
ShimizuToolkit.TrayIconWinUI.TrayIconManager.Current.SetNotifyIcon(notifyIcon);
}
TrayWindow = new();
ShimizuToolkit.TrayIconWinUI.TrayIconManager.Current.LeftClickAction += ShowTrayWindow;
ShimizuToolkit.TrayIconWinUI.TrayIconManager.Current.RightMenuWindow = new ShimizuToolkit.TrayIconWinUI.UI.TrayFlyoutBaseWindow(() =>
{
return new DebrisToys.UI.Tray.RightTrayMenu();
});
}
public void ShowTrayWindow()
{
TrayWindow = new DebrisToys.UI.Window.TrayWindow();
// Move window to right bottom corner
var (screenWidth, screenHeight) = Global.Helper.ScreenInteraction.GetMonitorWorkArea();
// Window size consts
int windowWidth = 600;
int windowHeight = 800;
int x = screenWidth - windowWidth;
int y = screenHeight - windowHeight;
IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(TrayWindow);
var windowId = Win32Interop.GetWindowIdFromWindow(hwnd);
var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
appWindow.MoveAndResize(new Windows.Graphics.RectInt32(x, y, windowWidth, windowHeight));
TrayWindow.Activate();
}
TrayWindow is the window working properly, it was invoked by clicking tray icon with left mouse button. Some classes are not included in the sample code and they're not important.
// TrayWindow.xaml.cs
public sealed partial class TrayWindow : Microsoft.UI.Xaml.Window
{
private Global.Helper.WindowExternalClickDetector _clickDetector;
public TrayWindow()
{
InitializeComponent();
// Hide app bar
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
Win32.Window.RemoveTaskbarIcon(hWnd);
if (appWindow.Presenter is Microsoft.UI.Windowing.OverlappedPresenter presenter)
{
presenter.IsAlwaysOnTop = true;
presenter.SetBorderAndTitleBar(true, false);
}
this.Closed += TrayWindow_Closed;
_clickDetector = new Global.Helper.WindowExternalClickDetector(this, () =>
{
this.Close();
});
//Global.Helper.WindowInteraction.SetForegroundWindowAndSetFocus(this);
this.Activate();
}
private void TrayWindow_Closed(object sender, WindowEventArgs args)
{
this.Closed -= TrayWindow_Closed;
_clickDetector.Dispose();
}
private void SettingsButton_Click(object sender, RoutedEventArgs e)
{
App.MainWindow?.AppWindow.Show();
App.MainWindow?.Activate();
//Global.Helper.WindowInteraction.SetForegroundWindowAndSetFocus(App.MainWindow);
this.Close();
}
}
Here's RightTrayMenu, it can't show itself after packaged.
internal class RightTrayMenu : ShimizuToolkit.TrayIconWinUI.UI.TrayMenuFlyout
{
public RightTrayMenu()
{
AddMenuItems();
}
private void AddMenuItems()
{
AddMenuItem("Open MainWindow", ShowMainWindow);
AddMenuItem("Exit", ExitApp);
}
private void ShowMainWindow()
{
App.MainWindow?.Activate();
}
public void ExitApp()
{
App.RequestExitApp();
}
}
Here's TrayMenuFlyout, base class of RightTrayMenu.
public class TrayMenuFlyout : Microsoft.UI.Xaml.Controls.MenuFlyout
{
public TrayMenuFlyout()
{
var presenterResourceDict = new ResourceDictionary
{
Source = new Uri("ms-appx:///ShimizuToolkit.TrayIconWinUI/Themes/TrayMenuFlyoutPresenterStyle.xaml")
};
this.MenuFlyoutPresenterStyle = (Style)presenterResourceDict["TrayMenuFlyoutPresenterStyle"];
this.ShouldConstrainToRootBounds = false;
}
public void AddMenuItem(TrayMenuFlyoutItem trayMenuFlyoutItem, Action action)
{
trayMenuFlyoutItem.OnClick = action;
Items.Add(trayMenuFlyoutItem);
}
public void AddMenuItem(string Text, Action action)
{
TrayMenuFlyoutItem trayMenuFlyoutItem = new()
{
Text = Text,
OnClick = action
};
Items.Add(trayMenuFlyoutItem);
}
}
If there's any other code needed, please ask. All code are open source. Please help.