Files
Better-Seewo/Manager/MainWindow.xaml.cs
miao-moe 8dd1eed519 feat: Better-Seewo v2.0.0 - 希沃白板功能增强插件
- Fluent Design 风格 UI,深色/浅色主题切换
- 平滑过渡动画(页面切换、按钮交互、状态变化)
- 五大核心功能:安装管理、墨迹管理、格式转换、触摸设置、激活管理
- 基于 dotnetCampus.EasiPlugin.Sdk v2.1.1-alpha.3 插件框架
- WPF 安装向导(欢迎页 -> 安装页 -> 完成页)
2026-06-28 06:51:35 +00:00

351 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* MainWindow.xaml.cs - Better-Seewo 管理器主窗口逻辑
* 负责自定义标题栏拖动、窗口控制、页面导航、主题切换和动画效果
* 作者:雾启工作室
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Better_Seewo.Manager
{
/// <summary>
/// MainWindow 的交互逻辑 - Fluent Design 风格主窗口
/// </summary>
public partial class MainWindow : Window
{
/// <summary>
/// 导航指示条动画时长(毫秒)
/// </summary>
private const int IndicatorAnimationDuration = 200;
/// <summary>
/// 页面淡入淡出动画时长(毫秒)
/// </summary>
private const int PageTransitionDuration = 300;
/// <summary>
/// 指示条目标宽度
/// </summary>
private const double IndicatorTargetWidth = 3;
/// <summary>
/// 当前选中的导航按钮名称
/// </summary>
private string _currentNavTag = "Install";
/// <summary>
/// 构造函数,初始化窗口组件
/// </summary>
public MainWindow()
{
InitializeComponent();
// 默认选中安装页面
SetActiveNavigation("BtnInstall", "IndicatorInstall");
}
/// <summary>
/// 窗口加载完成事件处理 - 触发入场动画和初始页面加载
/// </summary>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// 入场动画已通过 XAML Trigger 触发
// 导航到默认页面
NavigateToPage("Install");
}
#region ===== =====
/// <summary>
/// 标题栏鼠标左键按下 - 实现窗口拖动
/// </summary>
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 如果点击的是按钮区域则不触发拖动
if (e.Source is Button) return;
// 调用 DragMove 实现窗口拖动
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
}
/// <summary>
/// 标题栏鼠标双击 - 切换最大化/还原
/// </summary>
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// 双击标题栏区域切换窗口状态
if (e.ClickCount == 2)
{
ToggleMaximize();
}
}
#endregion
#region ===== =====
/// <summary>
/// 最小化按钮点击
/// </summary>
private void BtnMinimize_Click(object sender, RoutedEventArgs e)
{
// 将窗口最小化到任务栏
WindowState = WindowState.Minimized;
}
/// <summary>
/// 最大化/还原按钮点击
/// </summary>
private void BtnMaximize_Click(object sender, RoutedEventArgs e)
{
ToggleMaximize();
}
/// <summary>
/// 关闭按钮点击 - 关闭应用程序
/// </summary>
private void BtnClose_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
/// <summary>
/// 切换窗口最大化/还原状态
/// </summary>
private void ToggleMaximize()
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
// 更新按钮图标为最大化图标
BtnMaximize.Content = "\uE922";
}
else
{
WindowState = WindowState.Maximized;
// 更新按钮图标为还原图标
BtnMaximize.Content = "\uE923";
}
}
#endregion
#region ===== =====
/// <summary>
/// 导航按钮点击事件 - 切换Frame页面内容
/// </summary>
private void NavButton_Click(object sender, RoutedEventArgs e)
{
if (sender is Button btn && btn.Tag is string tag)
{
// 如果点击的是当前已选中项,则忽略
if (tag == _currentNavTag) return;
// 更新当前选中项
_currentNavTag = tag;
// 根据按钮名称设置选中状态和指示条动画
SetActiveNavigation(btn.Name, GetIndicatorName(btn.Name));
// 导航到对应页面
NavigateToPage(tag);
}
}
/// <summary>
/// 根据按钮名称获取对应的指示条名称
/// </summary>
/// <param name="buttonName">按钮名称</param>
/// <returns>指示条名称</returns>
private string GetIndicatorName(string buttonName)
{
return buttonName switch
{
"BtnInstall" => "IndicatorInstall",
"BtnInk" => "IndicatorInk",
"BtnConvert" => "IndicatorConvert",
"BtnTouch" => "IndicatorTouch",
"BtnActivate" => "IndicatorActivate",
_ => "IndicatorInstall"
};
}
/// <summary>
/// 设置当前选中的导航按钮,并触发指示条动画
/// </summary>
/// <param name="activeButtonName">选中的按钮名称</param>
/// <param name="activeIndicatorName">对应的指示条名称</param>
private void SetActiveNavigation(string activeButtonName, string activeIndicatorName)
{
// 所有导航按钮列表
string[] buttonNames = { "BtnInstall", "BtnInk", "BtnConvert", "BtnTouch", "BtnActivate" };
// 所有指示条列表
string[] indicatorNames = { "IndicatorInstall", "IndicatorInk", "IndicatorConvert", "IndicatorTouch", "IndicatorActivate" };
for (int i = 0; i < buttonNames.Length; i++)
{
// 查找按钮
var btn = FindName(buttonNames[i]) as Button;
// 查找指示条
var indicator = FindName(indicatorNames[i]) as Border;
if (btn == null || indicator == null) continue;
if (buttonNames[i] == activeButtonName)
{
// 选中状态:高亮前景色,显示指示条
btn.Foreground = (Brush)FindResource("AccentBrush");
// 播放指示条展开动画宽度从0到3px
AnimateIndicatorWidth(indicator, IndicatorTargetWidth);
}
else
{
// 非选中状态:恢复默认前景色,隐藏指示条
btn.Foreground = (Brush)FindResource("TextSecondaryBrush");
// 播放指示条收缩动画宽度从当前值到0
AnimateIndicatorWidth(indicator, 0);
}
}
}
/// <summary>
/// 为导航指示条播放宽度动画
/// </summary>
/// <param name="indicator">指示条控件</param>
/// <param name="targetWidth">目标宽度</param>
private void AnimateIndicatorWidth(Border indicator, double targetWidth)
{
if (indicator == null) return;
// 创建宽度动画
var widthAnimation = new DoubleAnimation
{
From = indicator.Width,
To = targetWidth,
Duration = TimeSpan.FromMilliseconds(IndicatorAnimationDuration),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut }
};
// 应用动画到指示条的Width属性
indicator.BeginAnimation(WidthProperty, widthAnimation);
}
#endregion
#region ===== =====
/// <summary>
/// 导航到指定页面,带淡入淡出动画效果
/// </summary>
/// <param name="pageTag">页面标识Install/Ink/Convert/Touch/Activate</param>
private void NavigateToPage(string pageTag)
{
// 创建淡出动画(当前页面)
var fadeOutAnimation = new DoubleAnimation
{
From = 1.0,
To = 0.0,
Duration = TimeSpan.FromMilliseconds(PageTransitionDuration / 2),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
};
// 淡出动画完成后切换页面
fadeOutAnimation.Completed += (s, e) =>
{
// 根据页面标识加载对应页面
// TODO: 创建各个功能页面后取消注释
// switch (pageTag)
// {
// case "Install":
// ContentFrame.Navigate(new Pages.InstallPage());
// break;
// case "Ink":
// ContentFrame.Navigate(new Pages.InkPage());
// break;
// case "Convert":
// ContentFrame.Navigate(new Pages.ConvertPage());
// break;
// case "Touch":
// ContentFrame.Navigate(new Pages.TouchPage());
// break;
// case "Activate":
// ContentFrame.Navigate(new Pages.ActivatePage());
// break;
// }
// 创建淡入动画(新页面)
var fadeInAnimation = new DoubleAnimation
{
From = 0.0,
To = 1.0,
Duration = TimeSpan.FromMilliseconds(PageTransitionDuration / 2),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
// 应用淡入动画到Frame
ContentFrame.BeginAnimation(OpacityProperty, fadeInAnimation);
};
// 应用淡出动画到Frame
ContentFrame.BeginAnimation(OpacityProperty, fadeOutAnimation);
}
#endregion
#region ===== =====
/// <summary>
/// 主题切换按钮点击事件
/// </summary>
private void BtnThemeToggle_Click(object sender, RoutedEventArgs e)
{
// 切换到相反主题
bool newIsDark = !App.IsDarkTheme;
// 调用 App.SwitchTheme 切换主题资源
App.SwitchTheme(newIsDark);
// 更新主题图标
UpdateThemeIcon(newIsDark);
}
/// <summary>
/// 根据当前主题更新切换按钮的图标
/// </summary>
/// <param name="isDark">当前是否为深色主题</param>
private void UpdateThemeIcon(bool isDark)
{
if (ThemeIcon == null) return;
if (isDark)
{
// 深色主题时显示太阳图标(提示可以切换到浅色)
ThemeIcon.Data = Geometry.Parse(
"M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,2L14.39,5.42C13.73,5.14 13,5 12,5C11,5 10.27,5.14 9.61,5.42L12,2M3.34,7L7.5,6.35C7,7 6.63,7.73 6.43,8.5L3.34,7M3.36,17L6.44,15.5C6.64,16.28 7,17 7.5,17.65L3.36,17M20.64,7L17.55,8.5C17.36,7.72 17,7 16.5,6.35L20.64,7M20.65,17L16.5,17.65C17,17 17.37,16.27 17.57,15.5L20.65,17M12,22L9.61,18.58C10.27,18.86 11,19 12,19C13,19 13.73,18.86 14.39,18.58L12,22Z"
);
}
else
{
// 浅色主题时显示月亮图标(提示可以切换到深色)
ThemeIcon.Data = Geometry.Parse(
"M17.75,4.09L15.22,6.03L16.13,9.09L13.5,7.28L10.87,9.09L11.78,6.03L9.25,4.09L12.44,4L13.5,1L14.56,4L17.75,4.09M21.25,11L19.61,12.25L20.2,14.23L18.5,13.06L16.8,14.23L17.39,12.25L15.75,11L17.81,10.95L18.5,9L19.19,10.95L21.25,11M18.97,15.95C19.8,15.87 20.69,17.05 20.16,17.8C19.84,18.25 19.38,18.57 18.97,18.95C16.73,21.04 14.04,22.5 11,22.5C7.96,22.5 5.27,21.04 3.03,18.95C2.62,18.57 2.16,18.25 1.84,17.8C1.31,17.05 2.2,15.87 3.03,15.95C7.33,16.37 10.17,12.37 11,9.42C11.83,12.37 14.67,16.37 18.97,15.95Z"
);
}
}
#endregion
}
}