Compare commits

..

9 Commits

Author SHA1 Message Date
Zhe Fang
2eef88523c Modify taskbar.json for layout and style changes
Updated taskbar settings including bounds, opacity, and effects.
2025-12-10 16:17:25 -05:00
Zhe Fang
220b1063ac fix: taskbar mode is not working in release mode 2025-12-10 16:15:58 -05:00
Zhe Fang
28bcd8ddfc chores: remove taskbar mode entry 2025-12-10 14:09:16 -05:00
Zhe Fang
5750bd3ad7 add: more info in thanks control 2025-12-10 11:54:03 -05:00
Zhe Fang
1667c701b0 feat: taskbar mode 2025-12-10 11:09:53 -05:00
Zhe Fang
160398f7ab fix: add null check for Window.AppWindow 2025-12-10 10:51:45 -05:00
Zhe Fang
c25ddf770f fix: when open app with window locked, then unlock the window, title bar and bottom bar will not be interactive 2025-12-10 10:42:06 -05:00
Zhe Fang
44fa3312b2 fix: docked mode ux exp 2025-12-10 07:09:08 -05:00
Zhe Fang
81f3d1f6bf fix: cannot exit app when docked mode is on 2025-12-10 06:54:21 -05:00
22 changed files with 605 additions and 284 deletions

View File

@@ -12,7 +12,7 @@
<Identity
Name="37412.BetterLyrics"
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
Version="1.1.175.0" />
Version="1.1.180.0" />
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

View File

@@ -69,14 +69,16 @@
<PackageReference Include="ComputeSharp.D2D1.WinUI" Version="3.2.0" />
<PackageReference Include="csharp-kana" Version="1.0.2" />
<PackageReference Include="csharp-pinyin" Version="1.0.1" />
<PackageReference Include="DevWinUI.Controls" Version="9.7.0" />
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
<PackageReference Include="DevWinUI.Controls" Version="9.7.1" />
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.6" />
<PackageReference Include="F23.StringSimilarity" Version="7.0.1" />
<PackageReference Include="FlaUI.UIA3" Version="5.0.0" />
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.4.1" />
<PackageReference Include="Hqub.Last.fm" Version="2.5.1" />
<PackageReference Include="Interop.UIAutomationClient" Version="10.19041.0" />
<PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.1" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7175" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
@@ -86,8 +88,8 @@
<PackageReference Include="NTextCat" Version="0.3.65" />
<PackageReference Include="Serilog.Extensions.Logging" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="System.Drawing.Common" Version="10.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.0" />
<PackageReference Include="System.Drawing.Common" Version="10.0.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.1" />
<PackageReference Include="TagLibSharp" Version="2.3.0" />
<PackageReference Include="Ude.NetStandard" Version="1.2.0" />
<PackageReference Include="Vanara.PInvoke.DwmApi" Version="4.2.1" />
@@ -115,6 +117,8 @@
</ItemGroup>
<!--Disable Trimming for Specific Packages-->
<ItemGroup>
<TrimmerRootAssembly Include="FlaUI.UIA3" />
<TrimmerRootAssembly Include="Interop.UIAutomationClient" />
<TrimmerRootAssembly Include="NAudio.Wasapi" />
<TrimmerRootAssembly Include="TagLibSharp" />
<TrimmerRootAssembly Include="Vanara.PInvoke.DwmApi" />

View File

@@ -248,7 +248,7 @@
</Hyperlink>
</Paragraph>
<!-- 打赏者 -->
<!-- 赞助 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SettingsPagePatrons" />
</Paragraph>
@@ -277,231 +277,94 @@
<Run Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="Aug 28, 2025" />
</Paragraph>
<Paragraph>
<Run x:Uid="SettingsPageYouNowUsing" FontStyle="Italic" />
<Run x:Uid="SettingsPageUserWhoPurchased" />
</Paragraph>
<!-- 依赖包 -->
<!-- 特别鸣谢 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SetingsPageSpecialThanks" />
</Paragraph>
<Paragraph>
<Run x:Uid="SettingsPageYouNowUsing" />
</Paragraph>
<!-- 代码参考 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SetingsPageDeps" />
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/3v.EvtSource">
<Run Text="3v.EvtSource" />
<Hyperlink NavigateUri="https://gist.github.com/mcworkaholic/82fbf203e3f1043bbe534b5b2974c0ce">
<Run Text="Get album artwork from ITunes (with Python3 or C#)" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView">
<Run Text="CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView" />
<Hyperlink NavigateUri="https://stackoverflow.com/a/32013610/11048731">
<Run Text="FullyObservableCollection" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.Labs.WinUI.Shimmer">
<Run Text="CommunityToolkit.Labs.WinUI.Shimmer" />
<Hyperlink NavigateUri="https://github.com/Storyteller-Studios/Impressionist">
<Run Text="Impressionist" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.Mvvm">
<Run Text="CommunityToolkit.Mvvm" />
<Hyperlink NavigateUri="https://github.com/Storyteller-Studios/ColorThief.WinUI3">
<Run Text="ColorThief.WinUI3" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Behaviors">
<Run Text="CommunityToolkit.WinUI.Behaviors" />
<Hyperlink NavigateUri="https://github.com/Johnwikix/SpectrumVisualization">
<Run Text="SpectrumVisualization" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Controls.Primitives">
<Run Text="CommunityToolkit.WinUI.Controls.Primitives" />
<Hyperlink NavigateUri="https://www.shadertoy.com/view/Mdt3Df">
<Run Text="Snow (as shown in sweden)" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Controls.Segmented">
<Run Text="CommunityToolkit.WinUI.Controls.Segmented" />
<Hyperlink NavigateUri="https://www.shadertoy.com/view/lllSR2">
<Run Text="w10" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Converters">
<Run Text="CommunityToolkit.WinUI.Converters" />
<Hyperlink NavigateUri="https://github.com/mo-jinran/Taskbar-Lyrics">
<Run Text="Taskbar-Lyrics" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Extensions">
<Run Text="CommunityToolkit.WinUI.Extensions" />
<Hyperlink NavigateUri="https://github.com/jayfunc/BetterLyrics/network/dependencies">
<Run Text="..." />
</Hyperlink>
</Paragraph>
<!-- UI/UX 设计参考 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SetingsPageUIUXRef" />
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://github.com/solstice23/refined-now-playing-netease">
<Run Text="refined-now-playing-netease" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Helpers">
<Run Text="CommunityToolkit.WinUI.Helpers" />
<Hyperlink NavigateUri="https://github.com/WXRIW/Lyricify-App">
<Run Text="Lyricify" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Media">
<Run Text="CommunityToolkit.WinUI.Media" />
<Hyperlink NavigateUri="https://moriafly.com/program/salt-player">
<Run Text="椒盐音乐 Salt Player" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Triggers">
<Run Text="CommunityToolkit.WinUI.Triggers" />
<Hyperlink NavigateUri="https://github.com/TwilightLemon/MyToolBar">
<Run Text="MyToolBar" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/ComputeSharp.D2D1.WinUI">
<Run Text="ComputeSharp.D2D1.WinUI" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/csharp-kana">
<Run Text="csharp-kana" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/csharp-pinyin">
<Run Text="csharp-pinyin" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/DevWinUI.Controls">
<Run Text="DevWinUI.Controls" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Dubya.WindowsMediaController">
<Run Text="Dubya.WindowsMediaController" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/F23.StringSimilarity">
<Run Text="F23.StringSimilarity" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/H.NotifyIcon.WinUI">
<Run Text="H.NotifyIcon.WinUI" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Hqub.Last.fm">
<Run Text="Hqub.Last.fm" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Lyricify.Lyrics.Helper-NativeAot">
<Run Text="Lyricify.Lyrics.Helper-NativeAot" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection">
<Run Text="Microsoft.Extensions.DependencyInjection" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Extensions.Logging">
<Run Text="Microsoft.Extensions.Logging" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Graphics.Win2D">
<Run Text="Microsoft.Graphics.Win2D" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Windows.SDK.BuildTools">
<Run Text="Microsoft.Windows.SDK.BuildTools" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.WindowsAppSDK">
<Run Text="Microsoft.WindowsAppSDK" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/NAudio.Wasapi">
<Run Text="NAudio.Wasapi" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Nito.AsyncEx">
<Run Text="Nito.AsyncEx" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Nito.AsyncEx.Tasks">
<Run Text="Nito.AsyncEx.Tasks" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/NTextCat">
<Run Text="NTextCat" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Serilog.Extensions.Logging">
<Run Text="Serilog.Extensions.Logging" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Serilog.Sinks.File">
<Run Text="Serilog.Sinks.File" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/System.Drawing.Common">
<Run Text="System.Drawing.Common" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/System.Text.Encoding.CodePages">
<Run Text="System.Text.Encoding.CodePages" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/TagLibSharp">
<Run Text="TagLibSharp" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Ude.NetStandard">
<Run Text="Ude.NetStandard" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.DwmApi">
<Run Text="Vanara.PInvoke.DwmApi" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.Gdi32">
<Run Text="Vanara.PInvoke.Gdi32" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.Shell32">
<Run Text="Vanara.PInvoke.Shell32" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.User32">
<Run Text="Vanara.PInvoke.User32" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.Windows.Shell">
<Run Text="Vanara.Windows.Shell" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/VCollab.DiscordRichPresence">
<Run Text="VCollab.DiscordRichPresence" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/WinUIEx">
<Run Text="WinUIEx" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/z440.atl.core">
<Run Text="z440.atl.core" />
<Hyperlink NavigateUri="">
<Run Text="" />
</Hyperlink>
</Paragraph>

View File

@@ -37,6 +37,7 @@
<MenuFlyoutItem x:Uid="SettingsPageDockedMode" Command="{x:Bind ViewModel.CreateDockedLyricsWindowStatusCommand}" />
<MenuFlyoutItem x:Uid="SettingsPageFullscreenMode" Command="{x:Bind ViewModel.CreateFullLyricsWindowStatusCommand}" />
<MenuFlyoutItem x:Uid="SettingsPageNarrowMode" Command="{x:Bind ViewModel.CreateNarrowLyricsWindowStatusCommand}" />
<MenuFlyoutItem x:Uid="SettingsPageTaskbarMode" Command="{x:Bind ViewModel.CreateTaskbarLyricsWindowStatusCommand}" />
</MenuFlyout>
</Button.Flyout>
</Button>

View File

@@ -86,6 +86,22 @@
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<dev:SettingsExpander
x:Uid="SettingsPagePinToTaskbar"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE7C4;}"
IsExpanded="{x:Bind LyricsWindowStatus.IsPinToTaskbar, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind LyricsWindowStatus.IsPinToTaskbar, Mode=TwoWay}" />
<dev:SettingsExpander.Items>
<dev:SettingsCard x:Uid="SettingsPageTaskbarPlacement">
<ComboBox SelectedIndex="{x:Bind LyricsWindowStatus.TaskbarPlacement, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
<ComboBoxItem x:Uid="SettingsPageLeft" />
<ComboBoxItem x:Uid="SettingsPageRight" />
</ComboBox>
</dev:SettingsCard>
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<dev:SettingsExpander
x:Uid="SettingsPageAOT"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BetterLyrics.WinUI3.Enums
{
public enum TaskbarPlacement
{
Left,
Right,
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Events
{
public class TaskbarFreeBoundsChangedEventArgs : EventArgs
{
public Rect TaskbarFreeBounds { get; }
public TaskbarFreeBoundsChangedEventArgs(Rect taskbarBounds)
{
TaskbarFreeBounds = taskbarBounds;
}
}
}

View File

@@ -22,9 +22,9 @@ namespace BetterLyrics.WinUI3.Extensions
Name = _resourceService.GetLocalizedString("DesktopMode"),
LyricsDisplayType = LyricsDisplayType.LyricsOnly,
WindowBounds = new Rect(100, 100, 600, 250),
IsLocked = true,
IsAlwaysOnTop = true,
IsAlwaysOnTopPolling = true,
IsLocked = true,
IsAdaptToEnvironment = true,
IsShownInSwitchers = false,
EnvironmentSampleMode = WindowPixelSampleMode.WindowEdge,
@@ -52,7 +52,6 @@ namespace BetterLyrics.WinUI3.Extensions
IsShownInSwitchers = false,
LyricsDisplayType = LyricsDisplayType.LyricsOnly,
EnvironmentSampleMode = WindowPixelSampleMode.BelowWindow,
TitleBarArea = TitleBarArea.None,
LyricsStyleSettings = new LyricsStyleSettings
{
LyricsAlignmentType = TextAlignmentType.Center,
@@ -108,5 +107,30 @@ namespace BetterLyrics.WinUI3.Extensions
LyricsLayoutOrientation = LyricsLayoutOrientation.Vertical,
};
}
public static LyricsWindowStatus TaskbarMode(Window? window = null)
{
window ??= WindowHook.GetWindow<SystemTrayWindow>();
return new LyricsWindowStatus(window)
{
Name = _resourceService.GetLocalizedString("TaskbarMode"),
LyricsDisplayType = LyricsDisplayType.LyricsOnly,
IsPinToTaskbar = true,
IsLocked = true,
IsAlwaysOnTop = true,
IsAlwaysOnTopPolling = true,
IsAdaptToEnvironment = true,
IsShownInSwitchers = false,
EnvironmentSampleMode = WindowPixelSampleMode.WindowEdge,
LyricsStyleSettings = new()
{
LyricsAlignmentType = TextAlignmentType.Center,
},
LyricsBackgroundSettings = new LyricsBackgroundSettings
{
IsFluidOverlayEnabled = false,
}
};
}
}
}

View File

@@ -1,4 +1,5 @@
using Windows.Foundation;
using Vanara.PInvoke;
using Windows.Foundation;
using Windows.Graphics;
namespace BetterLyrics.WinUI3.Extensions
@@ -77,5 +78,15 @@ namespace BetterLyrics.WinUI3.Extensions
);
}
}
extension(RECT rect)
{
public Rect ToRect() => new(
rect.Left,
rect.Top,
rect.Right - rect.Left,
rect.Bottom - rect.Top
);
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Extensions
{
public static class RectangleExtensions
{
extension(Rectangle rect)
{
public Rect ToRect() => new(
rect.Left,
rect.Top,
rect.Right - rect.Left,
rect.Bottom - rect.Top
);
}
}
}

View File

@@ -1,24 +1,213 @@
using Microsoft.UI.Xaml;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Events;
using BetterLyrics.WinUI3.Extensions;
using FlaUI.Core;
using FlaUI.Core.AutomationElements;
using FlaUI.Core.Definitions;
using FlaUI.Core.EventHandlers;
using FlaUI.UIA3;
using FlaUI.UIA3.Extensions;
using Microsoft.UI.Dispatching;
using System;
using System.Drawing;
using System.Threading;
namespace BetterLyrics.WinUI3.Hooks
{
public class TaskbarHook
public class TaskbarHook : IDisposable
{
private readonly DispatcherTimer _timer;
private readonly UIA3Automation _automation;
private AutomationElement? _taskbar;
public Action<EventArgs> OnTaskbarBoundsChanged;
private StructureChangedEventHandlerBase? _structureHandler;
private PropertyChangedEventHandlerBase? _propertyHandler;
public TaskbarHook()
private TaskbarPlacement _currentPlacement;
private readonly DispatcherQueue _dispatcherQueue;
private readonly Action<TaskbarFreeBoundsChangedEventArgs> _onLayoutChanged;
private Timer? _debounceTimer;
private const int DebounceDelay = 150;
private bool _isDisposed;
public TaskbarHook(TaskbarPlacement placement, Action<TaskbarFreeBoundsChangedEventArgs> onLayoutChanged)
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(50);
_timer.Tick += Timer_Tick;
_automation = new UIA3Automation();
_onLayoutChanged = onLayoutChanged;
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
_currentPlacement = placement;
StartHook();
}
private void Timer_Tick(object? sender, object e)
public void UpdatePlacement(TaskbarPlacement newPlacement)
{
_currentPlacement = newPlacement;
RequestUpdate(); // 立即刷新位置
}
private void StartHook()
{
try
{
var desktop = _automation.GetDesktop();
_taskbar = desktop.FindFirstChild(cf => cf.ByClassName("Shell_TrayWnd"));
if (_taskbar == null) return;
// 监听结构变化
// 这里的返回值就是一个可以 Dispose 的对象
_structureHandler = _taskbar.RegisterStructureChangedEvent(
TreeScope.Descendants,
(element, type, id) => RequestUpdate());
// 监听属性变化
_propertyHandler = _taskbar.RegisterPropertyChangedEvent(
TreeScope.Element,
(element, id, val) => RequestUpdate(),
_automation.PropertyLibrary.Element.BoundingRectangle);
RequestUpdate();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Hook Init Failed: {ex.Message}");
}
}
private void RequestUpdate()
{
if (_isDisposed) return;
_debounceTimer?.Dispose();
_debounceTimer = new Timer(_ =>
{
Rectangle voidRect = CalculateVoidRect(_currentPlacement);
_dispatcherQueue.TryEnqueue(() =>
{
if (!_isDisposed && voidRect != Rectangle.Empty)
{
_onLayoutChanged?.Invoke(new TaskbarFreeBoundsChangedEventArgs(voidRect.ToRect()));
}
});
}, null, DebounceDelay, Timeout.Infinite);
}
private Rectangle CalculateVoidRect(TaskbarPlacement placement)
{
try
{
if (_taskbar == null) return Rectangle.Empty;
try { var _ = _taskbar.BoundingRectangle; }
catch
{
var desktop = _automation.GetDesktop();
_taskbar = desktop.FindFirstChild(cf => cf.ByClassName("Shell_TrayWnd"));
if (_taskbar == null) return Rectangle.Empty;
}
Rectangle taskbarRect = _taskbar.BoundingRectangle;
// 绝对右边界:托盘
int barrierRight = taskbarRect.Right;
var tray = _taskbar.FindFirstDescendant(cf => cf.ByAutomationId("SystemTrayIcon")); // Win11
if (tray == null) tray = _taskbar.FindFirstDescendant(cf => cf.ByClassName("TrayNotifyWnd")); // Win10
if (tray != null) barrierRight = tray.BoundingRectangle.Left;
// 绝对左边界:任务栏左边缘 或 小组件(Win11)
int barrierLeft = taskbarRect.Left;
var widgets = _taskbar.FindFirstDescendant(cf => cf.ByAutomationId("WidgetsButton"));
// 只有当小组件确实在最左侧时 (Win11默认),它才构成左边界
// 如果用户把任务栏设为靠左对齐,小组件会在开始按钮右边,这时候不把它当做左边界
if (widgets != null && widgets.BoundingRectangle.Left < taskbarRect.Left + 100)
{
barrierLeft = (int)widgets.BoundingRectangle.Right;
}
// 寻找 中间内容区域 (Start + Search + Apps) 的 左右极值
int contentMinLeft = barrierRight;
int contentMaxRight = barrierLeft;
// 定义所有中间元素
string[] systemButtonIds = new[] {
"StartButton", "SearchButton", "TaskViewButton", "ChatButton"
};
// 系统按钮
foreach (var id in systemButtonIds)
{
var btn = _taskbar.FindFirstDescendant(cf => cf.ByAutomationId(id));
if (btn != null)
{
var rect = btn.BoundingRectangle;
// 排除不可见的
if (rect.Width <= 0) continue;
// 更新极值
if (rect.Left < contentMinLeft) contentMinLeft = (int)rect.Left;
if (rect.Right > contentMaxRight) contentMaxRight = (int)rect.Right;
}
}
// App 图标
var appIcons = _taskbar.FindAllDescendants(cf => cf.ByClassName("Taskbar.TaskListButtonAutomationPeer"));
foreach (var icon in appIcons)
{
var rect = icon.BoundingRectangle;
if (rect.Width <= 0) continue;
if (rect.Left < contentMinLeft) contentMinLeft = (int)rect.Left;
if (rect.Right > contentMaxRight) contentMaxRight = (int)rect.Right;
}
// 如果完全没找到内容,重置为中间
if (contentMinLeft == barrierRight) contentMinLeft = taskbarRect.Left;
if (contentMaxRight == barrierLeft) contentMaxRight = taskbarRect.Left;
int finalLeft, finalRight;
int padding = 10;
if (placement == TaskbarPlacement.Left)
{
// 【小组件】... [空隙] ...【开始按钮】
// 如果是 Win10 或 Win11左对齐contentMinLeft 几乎等于 barrierLeft空隙为0
finalLeft = barrierLeft + padding;
finalRight = contentMinLeft - padding;
}
else // Right
{
// 【最后一个图标】... [空隙] ...【托盘】
finalLeft = contentMaxRight + padding;
finalRight = barrierRight - padding;
}
int width = finalRight - finalLeft;
if (width < 20) return Rectangle.Empty;
return new Rectangle(finalLeft, taskbarRect.Top, width, taskbarRect.Height);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Calc Rect Error: {ex.Message}");
return Rectangle.Empty;
}
}
public void Dispose()
{
if (_isDisposed) return;
_isDisposed = true;
_debounceTimer?.Dispose();
_structureHandler?.Dispose();
_propertyHandler?.Dispose();
_automation?.Dispose();
}
}
}
}

View File

@@ -9,6 +9,7 @@ using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Vanara.PInvoke;
using Windows.ApplicationModel.Core;
@@ -23,8 +24,8 @@ namespace BetterLyrics.WinUI3.Hooks
private static List<object> _activeWindows = [];
private static List<object> _workAreas = [];
private static readonly Dictionary<HWND, WindowStyle> _defaultWindowStyle = [];
private static readonly Dictionary<HWND, ExtendedWindowStyle> _defaultExtendedWindowStyle = [];
private static WindowStyle? _defaultWindowStyle;
private static ExtendedWindowStyle? _defaultExtendedWindowStyle;
public static void HideWindow(this Window window)
{
@@ -81,9 +82,9 @@ namespace BetterLyrics.WinUI3.Hooks
{
return frameworkElement.XamlRoot.ContentIslandEnvironment.AppWindowId.GetWindowHandle();
}
else if (obj != null)
else if (obj is Window window)
{
return WindowNative.GetWindowHandle(obj);
return WindowNative.GetWindowHandle(window);
}
else
{
@@ -141,17 +142,19 @@ namespace BetterLyrics.WinUI3.Hooks
TrackWindow(window);
var castedWindow = (Window)window;
if (typeof(T) != typeof(SystemTrayWindow))
castedWindow.Restore();
castedWindow.Activate();
if (typeof(T) == typeof(SystemTrayWindow))
{
castedWindow.Restore();
castedWindow.Activate();
_defaultWindowStyle = castedWindow.GetWindowStyle();
_defaultExtendedWindowStyle = castedWindow.GetExtendedWindowStyle();
castedWindow.HideWindow();
}
if (typeof(T) == typeof(NowPlayingWindow))
{
var hwnd = WindowNative.GetWindowHandle(castedWindow);
_defaultWindowStyle.Add(hwnd, castedWindow.GetWindowStyle());
_defaultExtendedWindowStyle.Add(hwnd, castedWindow.GetExtendedWindowStyle());
var lyricsWindow = (NowPlayingWindow)window;
lyricsWindow.InitStatus();
@@ -225,10 +228,6 @@ namespace BetterLyrics.WinUI3.Hooks
if (_activeWindows.Contains(sender))
{
_activeWindows.Remove(sender);
var hwnd = WindowNative.GetWindowHandle(sender);
_defaultWindowStyle.Remove(hwnd);
_defaultExtendedWindowStyle.Remove(hwnd);
}
}
@@ -256,9 +255,7 @@ namespace BetterLyrics.WinUI3.Hooks
public static void SetIsClickThrough(this Window window, bool enable)
{
IntPtr hwnd = WindowNative.GetWindowHandle(window);
if (_defaultExtendedWindowStyle.TryGetValue(hwnd, out var style))
if (_defaultExtendedWindowStyle is ExtendedWindowStyle style)
{
if (enable)
{
@@ -273,9 +270,7 @@ namespace BetterLyrics.WinUI3.Hooks
public static void SetIsBorderless(this Window window, bool enable)
{
var hwnd = WindowNative.GetWindowHandle(window);
if (_defaultWindowStyle.TryGetValue(hwnd, out var style))
if (_defaultWindowStyle is WindowStyle style)
{
if (enable)
{
@@ -318,6 +313,8 @@ namespace BetterLyrics.WinUI3.Hooks
public static void SetIsShowInSwitchers(this Window window, bool enable)
{
if (window.AppWindow == null) return;
window.AppWindow.IsShownInSwitchers = enable;
}
@@ -333,6 +330,8 @@ namespace BetterLyrics.WinUI3.Hooks
public static void MoveAndResize(this Window window, Rect rect)
{
if (window.AppWindow == null) return;
window.AppWindow.Move(new Windows.Graphics.PointInt32((int)rect.X, (int)rect.Y));
window.AppWindow.Resize(new Windows.Graphics.SizeInt32((int)rect.Width, (int)rect.Height));
}

View File

@@ -22,6 +22,10 @@ namespace BetterLyrics.WinUI3.Models
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsAlwaysOnTopPolling { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsShownInSwitchers { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLocked { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsPinToTaskbar { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TaskbarPlacement TaskbarPlacement { get; set; } = TaskbarPlacement.Right;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsMaximized { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFullscreen { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsLayoutOrientation LyricsLayoutOrientation { get; set; } = LyricsLayoutOrientation.Horizontal;
@@ -137,6 +141,10 @@ namespace BetterLyrics.WinUI3.Models
IsAlwaysOnTopPolling = this.IsAlwaysOnTopPolling,
IsShownInSwitchers = this.IsShownInSwitchers,
IsLocked = this.IsLocked,
IsPinToTaskbar = this.IsPinToTaskbar,
TaskbarPlacement = this.TaskbarPlacement,
IsMaximized = this.IsMaximized,
IsFullscreen = this.IsFullscreen,

View File

@@ -544,7 +544,7 @@
<value>Contributors</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>Dependent package</value>
<value>Code Reference</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>Donation</value>
@@ -555,9 +555,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>Instructions</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>Special Thanks</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>If you like this project, please consider supporting it by donating. Your support will help keep the project alive and encourage further development.</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX Design Reference</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[Experimental] Depth effect</value>
</data>
@@ -1297,7 +1303,7 @@
<value>The path cannot be found on your computer</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>Special Thanks</value>
<value>Sponsor</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>Lyric annotation</value>
@@ -1305,6 +1311,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>Phonetic symbols</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>Pin to taskbar</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>Pinyin of Mandarin</value>
</data>
@@ -1506,6 +1515,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>Target language</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>Taskbar mode</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>Taskbar fixed position</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1578,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>Transparent</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>And buy users who support BetterLyrics</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>Version</value>
</data>
@@ -1620,6 +1638,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>Lyrics window switcher</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>Taskbar mode</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>Terms of service</value>
</data>

View File

@@ -544,7 +544,7 @@
<value>投稿者</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>依存パッケージ</value>
<value>コードリファレンス</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>寄付</value>
@@ -555,9 +555,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>手順</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>スペシャルサンクス</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>このプロジェクトが気に入っている場合は、寄付してサポートすることを検討してください。あなたのサポートは、プロジェクトを生かし続け、さらなる開発を促進するのに役立ちます。</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UXデザインリファレンス</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[実験的] 奥行き効果</value>
</data>
@@ -1297,7 +1303,7 @@
<value>パスはコンピューターでは見つかりません</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>スペシャルサンクス</value>
<value>後援しました</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>リリックアノテーション</value>
@@ -1305,6 +1311,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>発音</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>タスクバーに移動</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>マンダリンのピンイン</value>
</data>
@@ -1506,6 +1515,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>ターゲット言語</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>タスクバーモード</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>タスクバーの位置が固定されました</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1578,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>透明</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>そして、BetterLyricsをサポートするユーザーを購入しましょう</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>バージョン</value>
</data>
@@ -1620,6 +1638,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>歌詞ウィンドウスイッチャー</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>タスクバーモード</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>利用規約</value>
</data>

View File

@@ -544,7 +544,7 @@
<value>기여자</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>종속 패키지</value>
<value>코드 참조</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>기부</value>
@@ -555,9 +555,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>지침</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>특별 감사 인사</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>이 프로젝트가 마음에 들면 기부하여 지원을 고려하십시오. 귀하의 지원은 프로젝트를 계속 유지하고 추가 개발을 장려하는 데 도움이 될 것입니다.</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX 디자인 참조</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[실험] 깊이 효과</value>
</data>
@@ -1297,7 +1303,7 @@
<value>경로는 컴퓨터에서 찾을 수 없습니다</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>특별 감사 인사</value>
<value>스폰서</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>가사 주석</value>
@@ -1305,6 +1311,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>발성</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>작업 표시줄에 고정</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>만다린의 피니 인</value>
</data>
@@ -1506,6 +1515,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>대상 언어</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>작업 표시줄</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>작업 표시줄 고정 위치</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1578,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>투명한</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>그리고 BetterLyrics를 지원하는 사용자를 구입하세요</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>버전</value>
</data>
@@ -1620,6 +1638,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>가사 창 전환기</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>작업 표시줄</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>서비스 약관</value>
</data>

View File

@@ -544,7 +544,7 @@
<value>贡献者</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>依赖包</value>
<value>代码参考</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>捐贈</value>
@@ -555,9 +555,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>操作指南</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>特别鸣谢</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>如果您喜欢这个项目,请考虑通过捐赠来支持它。您的支持将有助于保持项目的生命并鼓励进一步的发展。</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX 设计参考</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[实验性] 纵深效果</value>
</data>
@@ -1297,7 +1303,7 @@
<value>无法在您的计算机中找到该路径</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>特别鸣谢</value>
<value>赞助</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>歌词注音</value>
@@ -1305,6 +1311,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>注音</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>固定到任务栏</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>普通话拼音</value>
</data>
@@ -1506,6 +1515,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>目标语言</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>任务栏模式</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>任务栏固定位置</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1578,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>透明</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>以及购买支持 BetterLyrics 的用户</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>版本号</value>
</data>
@@ -1620,6 +1638,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>歌词窗口切换器</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>任务栏模式</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>服务条款</value>
</data>

View File

@@ -544,7 +544,7 @@
<value>貢獻者</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>依賴包</value>
<value>代碼參考</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>捐贈</value>
@@ -555,9 +555,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>說明</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>特别鸣谢</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>如果您喜歡這個項目,請考慮通過捐贈來支持它。您的支持將有助於保持項目的生命並鼓勵進一步的發展。</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX 設計參考</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[實驗性] 縱深效果</value>
</data>
@@ -1297,7 +1303,7 @@
<value>無法在您的電腦中找到該路徑</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>特別鳴謝</value>
<value>贊助</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>歌詞注音</value>
@@ -1305,6 +1311,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>注音</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>釘選到任務列</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>普通話拼音</value>
</data>
@@ -1506,6 +1515,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>目標語言</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>任務列模式</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>工作列固定位置</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1578,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>透明</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>以及購買支援BetterLyrics 的用戶</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>版本號</value>
</data>
@@ -1620,6 +1638,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>歌詞視窗切換器</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>任務列模式</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>服務條款</value>
</data>

View File

@@ -69,6 +69,12 @@ namespace BetterLyrics.WinUI3.ViewModels
AppSettings.WindowBoundsRecords.Add(LyricsWindowStatusExtensions.NarrowMode());
}
[RelayCommand]
private void CreateTaskbarLyricsWindowStatus()
{
AppSettings.WindowBoundsRecords.Add(LyricsWindowStatusExtensions.TaskbarMode());
}
public void OpenConfigPanel()
{
IsConfigPanelOpened = true;

View File

@@ -22,6 +22,7 @@ using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.UI;
using WinRT.Interop;
using WinUIEx.Messaging;
namespace BetterLyrics.WinUI3.Views
{
@@ -34,10 +35,13 @@ namespace BetterLyrics.WinUI3.Views
IRecipient<PropertyChangedMessage<ElementTheme>>,
IRecipient<PropertyChangedMessage<BitmapImage?>>,
IRecipient<PropertyChangedMessage<LyricsFontColorType>>,
IRecipient<PropertyChangedMessage<Color>>
IRecipient<PropertyChangedMessage<Color>>,
IRecipient<PropertyChangedMessage<TaskbarPlacement>>
{
private ForegroundWindowHook? _fgWindowWatcher = null;
private OverlayInputHelper? _overlayInputHelper = null;
private OverlayInputHelper? _overlayInputHelper;
private TaskbarHook? _taskbarHook;
private DispatcherQueueTimer? _fgWindowWatcherTimer = null;
private Color _backdropAccentColor = Colors.Transparent;
@@ -69,6 +73,11 @@ namespace BetterLyrics.WinUI3.Views
UpdateAlbumArtThemeColors();
}
private void OnTaskbarFreeBoundsChanged(Events.TaskbarFreeBoundsChangedEventArgs obj)
{
this.MoveAndResize(obj.TaskbarFreeBounds);
}
public void InitStatus()
{
LyricsWindowStatus.UpdateMonitorBounds();
@@ -82,6 +91,7 @@ namespace BetterLyrics.WinUI3.Views
OnIsLockedChanged();
OnAutoShowOrHideWindowChanged();
OnTitleBarAreaChanged();
OnIsPinToTaskbarChanged();
LyricsWindowStatus.UpdateDemoWindowAndMonitorBounds();
}
@@ -150,6 +160,11 @@ namespace BetterLyrics.WinUI3.Views
LyricsWindowStatus.IsLocked = true;
this.MoveAndResize(LyricsWindowStatus.GetWindowBoundsWhenWorkArea());
}
else
{
// ǿ<>ƴ<EFBFBD><C6B4><EFBFBD>һ<EFBFBD>θ<EFBFBD><CEB8>£<EFBFBD>ˢ<EFBFBD>½<EFBFBD><C2BD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD>״̬
OnIsLockedChanged();
}
}
private void OnIsShownInSwitchersChanged()
@@ -165,8 +180,7 @@ namespace BetterLyrics.WinUI3.Views
private void OnIsLockedChanged()
{
this.SetIsLocked(LyricsWindowStatus.IsLocked);
if (LyricsWindowStatus.IsLocked)
if (LyricsWindowStatus.IsLocked && !LyricsWindowStatus.IsWorkArea)
{
LockToggleButtonContainer.Visibility = Visibility.Visible;
StartOverlayInputHelper();
@@ -177,6 +191,18 @@ namespace BetterLyrics.WinUI3.Views
UnlockButton.Opacity = 0;
StopOverlayInputHelper();
}
this.SetIsLocked(LyricsWindowStatus.IsLocked);
}
private void OnIsPinToTaskbarChanged()
{
_taskbarHook?.Dispose();
_taskbarHook = null;
if (LyricsWindowStatus.IsPinToTaskbar)
{
_taskbarHook = new(LyricsWindowStatus.TaskbarPlacement, OnTaskbarFreeBoundsChanged);
}
}
private void OnIsFullscreenChanged()
@@ -361,6 +387,8 @@ namespace BetterLyrics.WinUI3.Views
private void StartOverlayInputHelper()
{
if (_overlayInputHelper != null) return;
_overlayInputHelper = new(this);
_overlayInputHelper.Register(RootGrid);
_overlayInputHelper.Register(LockToggleButtonContainer);
@@ -473,6 +501,10 @@ namespace BetterLyrics.WinUI3.Views
{
OnIsAdaptToEnvironmentChanged();
}
else if (message.PropertyName == nameof(LyricsWindowStatus.IsPinToTaskbar))
{
OnIsPinToTaskbarChanged();
}
}
}
@@ -580,5 +612,15 @@ namespace BetterLyrics.WinUI3.Views
}
}
public void Receive(PropertyChangedMessage<TaskbarPlacement> message)
{
if (message.Sender == LyricsWindowStatus)
{
if (message.PropertyName == nameof(LyricsWindowStatus.TaskbarPlacement))
{
_taskbarHook?.UpdatePlacement(LyricsWindowStatus.TaskbarPlacement);
}
}
}
}
}

View File

@@ -73,6 +73,7 @@ public sealed partial class SystemTrayWindow : Window, IRecipient<PropertyChange
records.Add(LyricsWindowStatusExtensions.DockedMode(this));
records.Add(LyricsWindowStatusExtensions.NarrowMode(this));
records.Add(LyricsWindowStatusExtensions.FullscreenMode(this));
records.Add(LyricsWindowStatusExtensions.TaskbarMode(this));
}
}

View File

@@ -3,34 +3,37 @@
"IsDefault": false,
"MonitorDeviceName": "\\\\.\\DISPLAY1",
"IsWorkArea": false,
"IsBorderless": true,
"IsAlwaysOnTop": true,
"IsAlwaysOnTopPolling": true,
"IsShownInSwitchers": false,
"IsClickThrough": true,
"IsLocked": true,
"IsPinToTaskbar": true,
"TaskbarPlacement": 1,
"IsMaximized": false,
"IsFullscreen": false,
"LyricsLayoutOrientation": 0,
"LyricsDisplayType": 1,
"WindowBounds": {
"X": 0,
"Y": 1020,
"Width": 600,
"Height": 64,
"Left": 0,
"Top": 1020,
"Right": 600,
"Bottom": 1084,
"X": 100,
"Y": 100,
"Width": 800,
"Height": 500,
"Left": 100,
"Top": 100,
"Right": 900,
"Bottom": 600,
"IsEmpty": false
},
"DockHeight": 64,
"DemoWindowBounds": {
"X": 0,
"Y": 102,
"Width": 60,
"Height": 6.400000095367432,
"Left": 0,
"Top": 102,
"Right": 60,
"Bottom": 108.4000015258789,
"X": 10,
"Y": 10,
"Width": 80,
"Height": 50,
"Left": 10,
"Top": 10,
"Right": 90,
"Bottom": 60,
"IsEmpty": false
},
"MonitorBounds": {
@@ -57,12 +60,14 @@
},
"DockPlacement": 0,
"LyricsStyleSettings": {
"IsDynamicLyricsFontSize": false,
"IsDynamicLyricsFontSize": true,
"PhoneticLyricsFontSize": 12,
"OriginalLyricsFontSize": 16,
"OriginalLyricsFontSize": 24,
"TranslatedLyricsFontSize": 12,
"LyricsAlignmentType": 0,
"LyricsBgFontOpacity": 30,
"PhoneticLyricsOpacity": 60,
"OriginalLyricsOpacity": 30,
"TranslatedLyricsOpacity": 60,
"LyricsAlignmentType": 1,
"LyricsFontStrokeWidth": 0,
"LyricsCustomBgFontColor": {
"A": 255,
@@ -87,33 +92,31 @@
"LyricsStrokeFontColorType": 1,
"LyricsFontWeight": 7,
"LyricsLineSpacingFactor": 0.5,
"LyricsTranslationSeparator": "\n",
"LyricsCJKFontFamily": "Arial",
"LyricsWesternFontFamily": "Arial",
"PlayingLineTopOffset": 50,
"IsActive": false
},
"LyricsEffectSettings": {
"LyricsBlurAmount": 5,
"IsLyricsLineFadeEnabled": true,
"IsLyricsBlurEffectEnabled": true,
"IsLyricsGlowEffectEnabled": true,
"LyricsGlowEffectScope": 0,
"LyricsGlowEffectLongSyllableDuration": 700,
"IsLyricsGlowEffectAmountAutoAdjust": true,
"LyricsGlowEffectAmount": 8,
"IsLyricsShadowEnabled": false,
"LyricsShadowScope": 1,
"LyricsShadowAmount": 8,
"OriginalLyricsHighlightScope": 1,
"PhoneticLyricsHighlightAmount": 60,
"OriginalLyricsHighlightAmount": 100,
"TranslatedLyricsHighlightAmount": 60,
"IsLyricsScaleEffectEnabled": true,
"LyricsScaleEffectLongSyllableDuration": 700,
"IsLyricsScaleEffectAmountAutoAdjust": true,
"LyricsScaleEffectAmount": 115,
"IsLyricsFloatAnimationEnabled": true,
"LyricsFloatAmount": 1,
"IsLyricsFloatAnimationAmountAutoAdjust": true,
"LyricsFloatAnimationAmount": 8,
"LyricsScrollEasingType": 3,
"LyricsScrollDuration": 500,
"LyricsScrollTopDuration": 500,
"LyricsScrollBottomDuration": 500,
"LyricsScrollTopDelay": 0,
"LyricsScrollBottomDelay": 0,
"LyricsVerticalEdgeOpacity": 0,
"IsFanLyricsEnabled": false,
"FanLyricsAngle": 30,
"Is3DLyricsEnabled": false,
@@ -127,21 +130,23 @@
"LyricsBackgroundTheme": 2,
"IsPureColorOverlayEnabled": false,
"PureColorOverlayOpacity": 100,
"IsCoverOverlayEnabled": false,
"CoverOverlayBlurAmount": 100,
"CoverOverlayOpacity": 100,
"CoverOverlaySpeed": 50,
"CoverAcrylicEffectAmount": 0,
"IsFluidOverlayEnabled": false,
"FluidOverlayOpacity": 100,
"PaletteGeneratorType": 0,
"IsSpectrumOverlayEnabled": false,
"SpectrumPlacement": 1,
"SpectrumStyle": 1,
"SpectrumCount": 128,
"IsSnowFlakeOverlayEnabled": false,
"SnowFlakeOverlayAmount": 50,
"SnowFlakeOverlayAmount": 10,
"SnowFlakeOverlaySpeed": 1,
"IsFogOverlayEnabled": false,
"IsActive": false
},
"AlbumArtLayoutSettings": {
"SongInfoAlignmentType": 0,
"IsAutoCoverImageHeight": true,
"CoverImageHeight": 128,
"CoverImageRadius": 12,
"CoverImageShadowAmount": 12,
"IsAutoSongInfoFontSize": true,
@@ -149,17 +154,15 @@
"ShowTitle": true,
"ShowArtists": true,
"ShowAlbum": false,
"AlbumArtSize": 64,
"AutoAlbumArtSize": true,
"IsActive": false
},
"AlbumArtAreaEffectSettings": {
"ImageSwitchType": 1,
"IsActive": false
},
"IsAdaptToEnvironment": true,
"EnvironmentSampleMode": 3,
"AutoShowOrHideWindow": false,
"TitleBarArea": 1,
"WindowX": 0,
"WindowY": 1020,
"WindowWidth": 600,
"WindowHeight": 64,
"IsActive": false
}
}