microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.2k stars 669 forks source link

How to minimize WinUI app on System Tray? #6723

Open akash07k opened 2 years ago

akash07k commented 2 years ago

So I'm developing a WinUI app and The app will run in background if user closes the app window. Now I want that once user closes the window, the app should be minimized to the system tray and from system tray user should be able to take actions for our app regarding open, exit etc. I researched a lot, but I didn't find anything like NotifyIcon in winforms. Please help.

mayurpaghdal commented 2 years ago

Hii,

WinUI app actually do not run in background. That's by concept. If you close the window, it will close the app itself.

However, certain implementations are there which suggest a way to achieve what you want to do.

Explore this to find out more about the tray implementation. You have to implement Native Window APIs to achieve so.

About Hiding window (we actually cannot close it): use AppWindow which you can derive using native Win32 dll API calls.

Cheers :)

castorix commented 2 years ago

Like in any Win32 desktop application, with Shell_NotifyIcon

akash07k commented 2 years ago

@mayurpaghdal Please correct if I'm wrong, I think it is possible to run WinUI apps in background? I.E: By default I'm not launching the MainWindow in App's OnLaunched method. I've removed those 2 calls: // m_window = new MainWindow(); // m_window.Activate();

By this, only the App class is running which is derived from the Application class. Now whenever my user opens the window by pressing a shortcut keys, I create MainWindow and activate it. Is it wrong? any downsides to that?

akash07k commented 2 years ago

Oh, ok, isn't there any other way available? Shell_Notify is a native API and using it is quite difficult

castorix commented 2 years ago

Oh, ok, isn't there any other way available? Shell_Notify is a native API and using it is quite difficult

It is not too difficult. I did a quick test in C#, just by copying declarations from .NET source code (NativeMethods.cs), to see if it worked (just a Tip + empty icon in the System Tray)

akash07k commented 2 years ago

@castorix Great, so did it work properly? Any example code please?

mayurpaghdal commented 2 years ago

@akash07k

Please follow this repo to understand more how WinUI3 with system tray would work.

I've borrowed some classes from the MAUI app reference I've shared before. this might help.

About backgrounding -> As I've already stated, WinUI3 doesn't support backgrounding. i.e. You must activate the Window Instance.

But, there is a catch, you cannot close the App Window while app is running but you surely can hide it using some tweaks.

The repo I've shared demonstrates the same (check App.xaml.cs for more info)

Hope it helps. Thanks.

akash07k commented 2 years ago

Thanks @mayurpaghdal bro, I've cloned the repo and going through it. I hope it will be quite helpful for me. Also you mean to say that we can launch the Window in OnLaunched method only? And what if we don't Create the instance of the window and don't activate it in OnLaunch method. Also, if I'm trying to start the MainWindow after a later stage I.E: when user presses the shortcut key, that Time I'm getting error: An exception of type 'System.Runtime.InteropServices.COMException' occurred in WinRT.Runtime.dll but was not handled in user code The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD)) Any idea and fix please? Please see this related issue for more details: https://github.com/microsoft/microsoft-ui-xaml/issues/6725

akash07k commented 2 years ago

@mayurpaghdal Also, if we can't create background apps by using WinUI3 then what should we use? Winforms and WPF is quite legacy. I saw your code, trying to go through it. You wrote quite detailed code in very less time. Did you created this whole app/repo for me only?

mayurpaghdal commented 2 years ago

Also you mean to say that we can launch the Window in OnLaunched method only?

Probably yes (as that is the only method for the startup, without activating, the app shall not run). WinUI3's MainWindow is the root for the app.

Also, if we can't create background apps by using WinUI3 then what should we use?

It turns out that creating background apps is not WinUI3's forte. i suggest u go back to the Win32 App. Because WPF will anyway use the Win32 Native calls and Win32 supports WinUI (i guess).

About the code: I was working lately with similar functionality for my app and had to create a POC.

And i just saw ur post here, thought the same feature would be required by many other devs too. so created public repo of the POC then.

you're welcome to improve it if you can. :)

akash07k commented 2 years ago

@mayurpaghdal Actually as per my experience My app is running fine even though I'm not launching the main window from my App class which is derived from Application class. Obviously, in that way the app is running without a UI but able to detect keyboard commands (I've used H.Hooks lib for global keyboard hooking). So it seems that app is working in background too. I'll make the repo public, and will show you the example. It seems that I'm missing out something. But please correct me that are there any downsides to run the app in this way? without launching MainWindow?

akash07k commented 2 years ago

It seems that I'm not able to explain my point to you properly. If you are comfortable then probably we can talk on call? (obviously if you prefer it) @@mayurpaghdal

StephenLPeters commented 2 years ago

@bpulliam FYI

HavenDV commented 2 years ago

I want to note for the future that all this is already implemented in my H.NotifyIcon library. It also has an example of a Windowless application, as well as an example of a regular WinUI application with the ability to collapse. It also supports the ability to create a native context menu for TrayIcon with animation (still in preview mode) and some other features. The API is accessible from xaml and mostly inherited from hardcodet/wpf-notifyicon for easy transition to WinUI from WPF

akash07k commented 2 years ago

@HavenDV Amazing buddy! it's pretty amazing. it really solved my problem. Thanks a tons for this package.

amirvenus commented 1 year ago

Would be great if we had a universal solution i.e. for macOS as well

angelru commented 1 year ago

@HavenDV can i use it in .net maui? (Only windows)

HavenDV commented 1 year ago

@angelru Although I've added the MAUI package and removed the major hurdles, I haven't tested it in a real app yet. But I am talking about Windows support, because, as I understand it, maccatalyst does not yet support the macOS version of the tray icon

angelru commented 1 year ago

@angelru Although I've added the MAUI package and removed the major hurdles, I haven't tested it in a real app yet. But I am talking about Windows support, because, as I understand it, maccatalyst does not yet support the macOS version of the tray icon

I only want it for windows, when will there be a package?

HavenDV commented 1 year ago

I can release it soon. I see that there is a bug in Github Actions here (which prevented the release of the package) due to Package Central Management being enabled, and I need to disable this to fix it.

castorix commented 1 year ago

I only want it for windows, when will there be a package?

I had uploaded a basic class with Shell_NotifyIcon : WinUI3_NotifyIcon

angelru commented 1 year ago

Solo lo quiero para windows, cuando habrá paquete?

Había subido una clase básica con Shell_NotifyIcon : WinUI3_NotifyIcon

does it work with maui i guess?

HavenDV commented 1 year ago

@angelru I fixed some bugs and now it should work for MAUI for simple cases. Context menu and bindings are supported. Sample app here: https://github.com/HavenDV/H.NotifyIcon/tree/master/src/apps/H.NotifyIcon.Apps.Maui I want to note that the TrayIcon icon should be located in the Resources/Raw directory, and not in Resources/Images

angelru commented 12 months ago

@angelru I fixed some bugs and now it should work for MAUI for simple cases. Context menu and bindings are supported. Sample app here: https://github.com/HavenDV/H.NotifyIcon/tree/master/src/apps/H.NotifyIcon.Apps.Maui I want to note that the TrayIcon icon should be located in the Resources/Raw directory, and not in Resources/Images

Can you make a nuget? PRE

HavenDV commented 12 months ago

Already: https://www.nuget.org/packages/H.NotifyIcon.Maui

jkommeren commented 10 months ago

Already: https://www.nuget.org/packages/H.NotifyIcon.Maui

Just wanted to say thanks for this man! I'm going to use it in my Maui app. If I don't post back it means I got it working ❤️ When I tried with my own implementation it somehow meant that when restoring the appshell would no longer render and entire UI stayed blank no matter what I tried. I hope this is not affected. I vaguely remember it working for .net 6 though 🤔

I'll mention you in the credits if it works! It already took me quite some effort to just minimize the application. 😂 this is next level! Props for creating a nuget package!

hez2010 commented 9 months ago

We do can implement system tray using Win32 APIs by ourselves, but what we need is a tray with modernized context menu which can be implemented using XAML/WinUI 3. Currently even all of those 1rd party Microsoft WinUI 3 apps (PowerToys, Phone Link and etc.) don't have a modernized context menu for system tray, neither using WinUI 3 controls for menu nor theme-aware.

castorix commented 9 months ago

We do can implement system tray using Win32 APIs by ourselves, but what we need is a tray with modernized context menu which can be implemented using XAML/WinUI 3. Currently even all of those 1rd party Microsoft WinUI 3 apps (PowerToys, Phone Link and etc.) don't have a modernized context menu for system tray, neither using WinUI 3 controls for menu nor theme-aware.

What do you call exactly "modernized context menu" ? (I have only Windows 10 and I saw some images on Google from Windows 11 but they don't seem too different) In the test sample I posted above with Win32 APIs, I used SetPreferredAppMode to follow theme (or Win32 OD context menu that could be adapted to mimic Windows 11 menus)

hez2010 commented 9 months ago

What do you call exactly "modernized context menu" ?

WinUI-styled context menu with Acrylic backdrop material just like the context menu in explorer.