前言&問題背景
Windows平臺上很多需要持續(xù)后臺運行的程序,都有顯示任務欄圖標的需求,主要來顯示狀態(tài)信息、提供功能菜單欄。但UWP或Windows App SDK并沒有提供對應的API,相反可能是在有意的抑制此項功能,我有理由懷疑是微軟的戰(zhàn)略布局。
但很顯然,這項功能目前并不能有其它完美的替代解決方案,所以需要借助其它手段調(diào)用Win32 API實現(xiàn)。確實如此,GitHub中H.NotifyIcon庫就幫助我們在WPF和WinUI平臺上實現(xiàn)了。我們只需使用其NuGet包即可顯示自己的任務欄圖標。
但請注意,UWP程序強調(diào)生命周期管理,在后臺期間會自動掛起。在官方的文檔中,UWP確實有“在后臺無限期運行”的解決方案,但一經(jīng)使用則不能發(fā)布到Microsoft Store。為了響應其設計理念、也因為作者確實此方面涉足不深,本篇文章不探討UWP平臺的任務欄圖標功能或后臺運行功能。
解決方案
在NuGet源中,找到H.NotifyIcon
包,根據(jù)你的需要選擇H.NotifyIcon.WinUI
或H.NotifyIcon.Uno
等包并安裝。
注意,根據(jù)項目實例和自述文件,可以有多種聲明與使用方法:
- 直接全部在
MainWindow
內(nèi)聲明
<Window
...
xmlns:tb="using:H.NotifyIcon"
>
<Grid>
<Grid.Resources>
<MenuFlyout x:Key="TrayContextFlyout">
<MenuFlyoutItem Command="{StaticResource XamlUICommand類指令}" />
<MenuFlyoutSeparator />
<MenuFlyoutItem Command="{StaticResource XamlUICommand類指令}" />
</MenuFlyout>
</Grid.Resources>
<tb:TaskbarIcon
x:Name="TrayIconView"
ToolTipText="懸停時顯示的提示語文字,如ToolTip"
IconSource="圖標文件路徑,如/Images/TrayIcons/Logo.ico"
ContextMenu="ContextMenu資源,如{StaticResource TrayMenu}"
MenuActivation="顯示菜單欄的行為,如LeftOrRightClick"
TrayPopup="彈出窗口資源,如{StaticResource TrayStatusPopup}"
PopupActivation="顯示彈出窗口的行為,如DoubleClick"
LeftClickCommand="左鍵單擊執(zhí)行的命令,如{StaticResource Command}"
ContextMenuMode="SecondWindow"
NoLeftClickDelay="True"
/>
</Grid>
</Window>
- 定義一個
UserControl
,再在MainWindow
使用
<Window
...
xmlns:views="using:UserControl所在命名空間"
>
<Grid>
...
<views:TrayIconView x:Name="TrayIconView" />
</Grid>
</Window>
<UserControl ... >
<UserControl.Resources>
<MenuFlyout x:Key="TrayContextFlyout">
<MenuFlyoutItem Command="{StaticResource XamlUICommand類指令}" />
<MenuFlyoutSeparator />
<MenuFlyoutItem Command="{StaticResource XamlUICommand類指令}" />
</MenuFlyout>
</UserControl.Resources>
<tb:TaskbarIcon
ToolTipText="懸停時顯示的提示語文字,如ToolTip"
IconSource="圖標文件路徑,如/Images/TrayIcons/Logo.ico"
ContextMenu="ContextMenu資源,如{StaticResource TrayMenu}"
MenuActivation="顯示菜單欄的行為,如LeftOrRightClick"
TrayPopup="彈出窗口資源,如{StaticResource TrayStatusPopup}"
PopupActivation="顯示彈出窗口的行為,如DoubleClick"
LeftClickCommand="左鍵單擊執(zhí)行的命令,如{StaticResource Command}"
ContextMenuMode="SecondWindow"
NoLeftClickDelay="True"
/>
</UserControl>
個人更推薦第二種方法,這樣不讓主窗口文件顯得臃腫,方便維護。
注意替換以上文字部分,要自行在Resources
部分定義XamlUICommand
指令并在MenuFlyoutItem
中使用。
注意:在退出(Window Closed
或自定義退出命令中)程序時,要調(diào)用TrayIconView.Dispose()
方法。
注意:在退出(Window Closed
或自定義退出命令中)程序時,要調(diào)用TrayIconView.Dispose()
方法。
注意:在退出(Window Closed
或自定義退出命令中)程序時,要調(diào)用TrayIconView.Dispose()
方法。
這里補充說明一下以上文字部分的注釋:
-
XamlUICommand
類指令,直接定義在菜單欄中顯示的圖標、標簽內(nèi)容等的自定義命令,可在WinUI示例代碼找到說明。 -
ContextMenuMode="SecondWindow"
指定了菜單欄顯示模式?!癝econdWindow”指創(chuàng)建新的窗口覆蓋Win32菜單欄,以使用WinUI風格設計的菜單欄。
注意:作者在指定到本模式時,在Window代碼中注冊Activated等事件會產(chǎn)生運行時錯誤,因為H.NotifyIcon也會對UI元素事件進行注冊,見issue #37。因此你需要將注冊到這些事件的代碼移動到App.xaml.cs
或刪除本項屬性,則會默認僅使用Win32風格菜單欄(不自動再創(chuàng)建窗口)。
至此,題目的問題已經(jīng)得到解決。
本篇博客有待更新,H.NotifyIcon
提供了更多實用方法和屬性,包括XAML生成托盤圖標、以效率模式隱藏窗口到后臺等,讀者可以自行從文首的GitHub鏈接到倉庫探索。
總結&反思
WinUI沒有提供系統(tǒng)托盤圖標的API,所以要調(diào)用H.NotifyIcon
這類庫來實現(xiàn)。
我本人十分欣賞這個項目,它可以用窗口覆蓋的形式,應用WinUI風格的菜單欄到托盤圖標,看起來符合Fluent Design設計語言,而不是老式的Win32風格。文章來源:http://www.zghlxwxcb.cn/news/detail-459744.html
非常感謝H.NotifyIcon
的作者,從本項目可以看見很多可以讓項目更符合Windows 11語言的新奇點子,暫時介紹不完了。文章來源地址http://www.zghlxwxcb.cn/news/detail-459744.html
到了這里,關于【W(wǎng)inUI 3】用H.NotifyIcon顯示系統(tǒng)任務欄(托盤)圖標,實現(xiàn)程序后臺運行的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!