刚显示窗口时跳过动画 (#1040)

* feat: 初步实现启动时跳过动画

* perf: 尝试优化性能

* ui: 优化 SettingsExpander 箭头动画

* perf: 优化启动性能

* fix: 优化最大化显示窗口逻辑

* chore: 优化注释

* chore
This commit is contained in:
Xu 2024-12-26 19:25:13 +08:00 committed by GitHub
commit ed61b66537
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 161 additions and 112 deletions

View file

@ -11,7 +11,7 @@ struct CandidateWindowItem : CandidateWindowItemT<CandidateWindowItem>,
return _title;
}
Controls::IconElement Icon() const noexcept;
IconElement Icon() const noexcept;
hstring DefaultProfileName() const noexcept {
return _defaultProfileName;
@ -33,7 +33,7 @@ private:
fire_and_forget _ResolveWindow(bool resolveIcon, bool resolveName, HWND hWnd);
hstring _title;
Controls::IconElement _icon{ nullptr };
IconElement _icon{ nullptr };
hstring _defaultProfileName;
hstring _aumid;

View file

@ -3,7 +3,7 @@
namespace Magpie {
struct ContentDialogHelper {
static winrt::IAsyncOperation<winrt::Controls::ContentDialogResult> ShowAsync(winrt::Controls::ContentDialog dialog);
static winrt::IAsyncOperation<winrt::ContentDialogResult> ShowAsync(winrt::ContentDialog dialog);
static bool IsAnyDialogOpen() noexcept;
static void CloseActiveDialog();
};

View file

@ -13,7 +13,7 @@ namespace winrt::Magpie::implementation {
void HomePage::TimerSlider_Loaded(IInspectable const& sender, RoutedEventArgs const&) const {
// 修正 Slider 中 Tooltip 的主题
XamlHelper::UpdateThemeOfTooltips(sender.as<Controls::Slider>(), ActualTheme());
XamlHelper::UpdateThemeOfTooltips(sender.as<Slider>(), ActualTheme());
}
void HomePage::ComboBox_DropDownOpened(IInspectable const& sender, IInspectable const&) const {
@ -23,7 +23,7 @@ void HomePage::ComboBox_DropDownOpened(IInspectable const& sender, IInspectable
void HomePage::SimulateExclusiveFullscreenToggleSwitch_Toggled(IInspectable const& sender, RoutedEventArgs const&) {
// 如果没有启用开发者模式,模拟独占全屏选项位于页面底部,用户可能注意不到警告。
// 为了解决这个问题,打开模拟独占全屏选项时自动滚动页面。
if (_viewModel->IsDeveloperMode() || !sender.as<Controls::ToggleSwitch>().IsOn() || !IsLoaded()) {
if (_viewModel->IsDeveloperMode() || !sender.as<ToggleSwitch>().IsOn() || !IsLoaded()) {
return;
}

View file

@ -31,7 +31,7 @@ private:
winrt::Magpie::VisualType _visualType = winrt::Magpie::VisualType::Small;
bool _isError = false;
Controls::ContentPresenter _keyPresenter{ nullptr };
ContentPresenter _keyPresenter{ nullptr };
IsEnabledChanged_revoker _isEnabledChangedRevoker;
};

View file

@ -49,10 +49,7 @@ bool MainWindow::Create() noexcept {
_appThemeChangedRevoker = App::Get().ThemeChanged(winrt::auto_revoke, [this](bool) { _UpdateTheme(); });
_UpdateTheme();
const bool isMaximized = AppSettings::Get().IsMainWindowMaximized();
if (isMaximized) {
_SetInitialMaximized();
}
_SetInitialMaximized(AppSettings::Get().IsMainWindowMaximized());
// 1. 设置初始 XAML Islands 窗口的尺寸
// 2. 刷新窗口边框
@ -62,8 +59,8 @@ bool MainWindow::Create() noexcept {
(sizeToSet.cx == 0 ? (SWP_NOMOVE | SWP_NOSIZE) : 0) | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS);
// Xaml 控件加载完成后显示主窗口
Content()->Loaded([this, isMaximized](winrt::IInspectable const&, winrt::RoutedEventArgs const&) {
if (isMaximized) {
Content()->Loaded([this](winrt::IInspectable const&, winrt::RoutedEventArgs const&) {
if (AppSettings::Get().IsMainWindowMaximized()) {
// ShowWindow(Handle(), SW_SHOWMAXIMIZED) 会显示错误的动画。因此我们以窗口化显示,
// 但位置和大小都和最大化相同,显示完毕后将状态设为最大化。
//
@ -86,13 +83,15 @@ bool MainWindow::Create() noexcept {
mi.rcWork.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW
SWP_SHOWWINDOW
);
}
// 将状态设为最大化,也还原了原始的窗口化位置
wp.showCmd = SW_SHOWMAXIMIZED;
SetWindowPlacement(Handle(), &wp);
_SetInitialMaximized(false);
} else {
ShowWindow(Handle(), SW_SHOWNORMAL);
}

View file

@ -8,7 +8,6 @@
using namespace ::Magpie;
using namespace winrt;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Text;
@ -31,7 +30,7 @@ void PageFrame::Title(hstring value) {
RaisePropertyChanged(L"Title");
}
void PageFrame::Icon(Controls::IconElement value) {
void PageFrame::Icon(IconElement value) {
if (_icon == value) {
return;
}
@ -101,7 +100,7 @@ void PageFrame::ScrollViewer_ViewChanging(IInspectable const&, ScrollViewerViewC
}
void PageFrame::ScrollViewer_KeyDown(IInspectable const& sender, KeyRoutedEventArgs const& args) {
auto scrollViewer = sender.as<Controls::ScrollViewer>();
auto scrollViewer = sender.as<struct ScrollViewer>();
switch (args.Key()) {
case VirtualKey::Up:
scrollViewer.ChangeView(scrollViewer.HorizontalOffset(), scrollViewer.VerticalOffset() - 100, 1);

View file

@ -9,8 +9,8 @@ struct PageFrame : PageFrameT<PageFrame>, wil::notify_property_changed_base<Page
hstring Title() const noexcept { return _title; }
void Title(hstring value);
Controls::IconElement Icon() const { return _icon; }
void Icon(Controls::IconElement value);
IconElement Icon() const { return _icon; }
void Icon(IconElement value);
FrameworkElement HeaderAction() const { return _headerAction; }
void HeaderAction(FrameworkElement value);
@ -23,7 +23,7 @@ struct PageFrame : PageFrameT<PageFrame>, wil::notify_property_changed_base<Page
void SizeChanged(IInspectable const&, SizeChangedEventArgs const& e);
void ScrollViewer_PointerPressed(IInspectable const&, Input::PointerRoutedEventArgs const&);
void ScrollViewer_ViewChanging(IInspectable const&, Controls::ScrollViewerViewChangingEventArgs const&);
void ScrollViewer_ViewChanging(IInspectable const&, ScrollViewerViewChangingEventArgs const&);
void ScrollViewer_KeyDown(IInspectable const& sender, Input::KeyRoutedEventArgs const& args);
private:
@ -31,7 +31,7 @@ private:
void _UpdateHeaderActionPresenter();
hstring _title;
Controls::IconElement _icon{ nullptr };
IconElement _icon{ nullptr };
FrameworkElement _headerAction{ nullptr };
IInspectable _mainContent{ nullptr };
};

View file

@ -11,7 +11,6 @@
using namespace Magpie;
using namespace winrt;
using namespace Windows::Globalization::NumberFormatting;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Input;

View file

@ -15,7 +15,7 @@ struct ProfilePage : ProfilePageT<ProfilePage> {
void ComboBox_DropDownOpened(IInspectable const& sender, IInspectable const&);
void CursorScalingComboBox_SelectionChanged(IInspectable const&, Controls::SelectionChangedEventArgs const&);
void CursorScalingComboBox_SelectionChanged(IInspectable const&, SelectionChangedEventArgs const&);
static Windows::Globalization::NumberFormatting::INumberFormatter2 NumberFormatter() noexcept;

View file

@ -14,7 +14,7 @@ struct ProfileViewModel : ProfileViewModelT<ProfileViewModel>,
ProfileViewModel(int profileIdx);
~ProfileViewModel();
Controls::IconElement Icon() const noexcept {
IconElement Icon() const noexcept {
return _icon;
}
@ -164,7 +164,7 @@ private:
::Magpie::Event<uint32_t>::EventRevoker _dpiChangedRevoker;
::Magpie::Event<>::EventRevoker _adaptersChangedRevoker;
Controls::IconElement _icon{ nullptr };
IconElement _icon{ nullptr };
const bool _isDefaultProfile = true;
bool _isRenameConfirmButtonEnabled = false;

View file

@ -24,9 +24,9 @@ using namespace Windows::Graphics::Display;
using namespace Windows::Graphics::Imaging;
using namespace Windows::UI::ViewManagement;
using namespace Windows::UI;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media::Animation;
using namespace Windows::UI::Xaml::Media::Imaging;
namespace winrt::Magpie::implementation {
@ -86,6 +86,18 @@ void RootPage::InitializeComponent() {
}
}
static void SkipToggleSwitchAnimations(const DependencyObject& elem) {
FrameworkElement rootGrid = VisualTreeHelper::GetChild(elem, 0).try_as<FrameworkElement>();
for (VisualStateGroup group : VisualStateManager::GetVisualStateGroups(rootGrid)) {
for (VisualState state : group.States()) {
if (Storyboard storyboard = state.Storyboard()) {
storyboard.SkipToFill();
}
}
}
}
void RootPage::RootPage_Loaded(IInspectable const&, RoutedEventArgs const&) {
// 消除焦点框
IsTabStop(true);
@ -94,6 +106,27 @@ void RootPage::RootPage_Loaded(IInspectable const&, RoutedEventArgs const&) {
// 设置 NavigationView 内的 Tooltip 的主题
XamlHelper::UpdateThemeOfTooltips(RootNavigationView(), ActualTheme());
// 启动时跳过 ToggleSwitch 的动画
std::vector<DependencyObject> elems{ *this };
do {
std::vector<DependencyObject> temp;
for (const DependencyObject& elem : elems) {
const int count = VisualTreeHelper::GetChildrenCount(elem);
for (int i = 0; i < count; ++i) {
DependencyObject current = VisualTreeHelper::GetChild(elem, i);
if (get_class_name(current) == name_of<ToggleSwitch>()) {
SkipToggleSwitchAnimations(current);
} else {
temp.emplace_back(std::move(current));
}
}
}
elems = std::move(temp);
} while (!elems.empty());
}
void RootPage::NavigationView_SelectionChanged(

View file

@ -10,7 +10,6 @@
using namespace ::Magpie;
using namespace winrt;
using namespace Windows::Globalization::NumberFormatting;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Input;

View file

@ -36,7 +36,7 @@ private:
IInspectable _moreOptionsButton{ nullptr };
Controls::MenuFlyout _addEffectMenuFlyout;
MenuFlyout _addEffectMenuFlyout;
com_ptr<ScalingModesViewModel> _viewModel = make_self<ScalingModesViewModel>();
ScalingModeItem* _curScalingMode = nullptr;
};

View file

@ -24,11 +24,11 @@ struct SettingsCard : SettingsCardT<SettingsCard> {
IInspectable Description() const { return GetValue(_descriptionProperty); }
void Description(IInspectable const& value) const { SetValue(_descriptionProperty, value); }
Controls::IconElement HeaderIcon() const { return GetValue(_headerIconProperty).as<Controls::IconElement>(); }
void HeaderIcon(Controls::IconElement const& value) const { SetValue(_headerIconProperty, value); }
IconElement HeaderIcon() const { return GetValue(_headerIconProperty).as<IconElement>(); }
void HeaderIcon(IconElement const& value) const { SetValue(_headerIconProperty, value); }
Controls::IconElement ActionIcon() const { return GetValue(_actionIconProperty).as<Controls::IconElement>(); }
void ActionIcon(Controls::IconElement const& value) const { SetValue(_actionIconProperty, value); }
IconElement ActionIcon() const { return GetValue(_actionIconProperty).as<IconElement>(); }
void ActionIcon(IconElement const& value) const { SetValue(_actionIconProperty, value); }
hstring ActionIconToolTip() const { return GetValue(_actionIconToolTipProperty).as<hstring>(); }
void ActionIconToolTip(const hstring& value) const { SetValue(_actionIconToolTipProperty, box_value(value)); }

View file

@ -126,7 +126,7 @@
<RowDefinition x:Name="Row1"
Height="*" />
</Grid.RowDefinitions>
<ToggleButton x:Name="ExpanderHeader"
<ToggleButton x:Name="PART_ExpanderHeader"
MinHeight="{TemplateBinding MinHeight}"
Padding="{StaticResource ExpanderHeaderPadding}"
HorizontalAlignment="Stretch"
@ -171,7 +171,7 @@
<VisualStateGroup x:Name="ExpandStates">
<VisualState x:Name="ExpandDown">
<VisualState.Setters>
<Setter Target="ExpanderHeader.CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource TopCornerRadiusFilterConverter}}" />
<Setter Target="PART_ExpanderHeader.CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource TopCornerRadiusFilterConverter}}" />
</VisualState.Setters>
<VisualState.Storyboard>
<Storyboard>
@ -272,7 +272,7 @@
IsTabStop="False"
ToolTipService.ToolTip="{StaticResource SettingsExpanderChevronToolTip}"
UseSystemFocusVisuals="True">
<muxc:AnimatedIcon x:Name="ExpandCollapseChevron"
<muxc:AnimatedIcon x:Name="PART_ExpandCollapseChevron"
Width="16"
Height="16"
HorizontalAlignment="Center"
@ -304,7 +304,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SettingsCardBorderBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderChevronForeground}" />
@ -328,7 +328,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SettingsCardBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderChevronPointerOverForeground}" />
@ -340,7 +340,7 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOff" />
<Setter Target="PART_ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOff" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
@ -355,7 +355,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SettingsCardBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderChevronPressedForeground}" />
@ -367,7 +367,7 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOff" />
<Setter Target="PART_ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOff" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
@ -382,7 +382,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SettingsCardBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderHeaderDisabledForeground}" />
@ -396,7 +396,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderHeaderForeground}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderChevronForeground}" />
@ -413,7 +413,7 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
<Setter Target="PART_ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="CheckedPointerOver">
@ -423,7 +423,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderHeaderForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderChevronPointerOverForeground}" />
@ -440,7 +440,7 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
<Setter Target="PART_ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="CheckedPressed">
@ -450,7 +450,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderHeaderForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderChevronPressedForeground}" />
@ -467,7 +467,7 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
<Setter Target="PART_ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
</VisualState.Setters>
</VisualState>
@ -478,7 +478,7 @@
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderHeaderDisabledForeground}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ExpandCollapseChevron"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ExpanderHeaderDisabledForeground}" />
@ -490,7 +490,7 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
<Setter Target="PART_ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Indeterminate" />

View file

@ -12,6 +12,8 @@ using namespace Windows::UI::Xaml::Controls;
namespace winrt::Magpie::implementation {
static constexpr const wchar_t* PART_ItemsContainer = L"PART_ItemsContainer";
static constexpr const wchar_t* PART_ExpanderHeader = L"PART_ExpanderHeader";
static constexpr const wchar_t* PART_ExpandCollapseChevron = L"PART_ExpandCollapseChevron";
DependencyProperty SettingsExpander::_headerProperty{ nullptr };
DependencyProperty SettingsExpander::_descriptionProperty{ nullptr };
@ -103,7 +105,28 @@ void SettingsExpander::RegisterDependencyProperties() {
void SettingsExpander::OnApplyTemplate() {
base_type::OnApplyTemplate();
_OnItemsConnectedPropertyChanged();
auto expander = VisualTreeHelper::GetChild(*this, 0).try_as<MUXC::Expander>();
expander.ApplyTemplate();
// 跳过动画
auto expanderRoot = VisualTreeHelper::GetChild(expander, 0).try_as<Grid>();
for (VisualStateGroup group : VisualStateManager::GetVisualStateGroups(expanderRoot)) {
for (VisualState state : group.States()) {
state.Storyboard().SkipToFill();
}
}
auto header = expander.try_as<IControlProtected>()
.GetTemplateChild(PART_ExpanderHeader)
.try_as<Primitives::ToggleButton>();
header.ApplyTemplate();
_expandCollapseChevron = header.try_as<IControlProtected>()
.GetTemplateChild(PART_ExpandCollapseChevron)
.try_as<MUXC::AnimatedIcon>();
_UpdateAnimatedIcon();
}
void SettingsExpander::_OnIsExpandedChanged(DependencyObject const& sender, DependencyPropertyChangedEventArgs const& args) {
@ -114,6 +137,10 @@ void SettingsExpander::_OnIsExpandedChanged(DependencyObject const& sender, Depe
} else {
that->Collapsed.Invoke();
}
if (that->_expandCollapseChevron) {
that->_UpdateAnimatedIcon();
}
}
void SettingsExpander::_OnItemsConnectedPropertyChanged(DependencyObject const& sender, DependencyPropertyChangedEventArgs const&) {
@ -146,4 +173,9 @@ void SettingsExpander::_OnItemsConnectedPropertyChanged() {
}
}
// 防止加载后立刻展示动画
void SettingsExpander::_UpdateAnimatedIcon() {
MUXC::AnimatedIcon::SetState(_expandCollapseChevron, IsExpanded() ? L"PointerOverOn" : L"PointerOverOff");
}
}

View file

@ -25,8 +25,8 @@ struct SettingsExpander : SettingsExpanderT<SettingsExpander> {
IInspectable Description() const { return GetValue(_descriptionProperty); }
void Description(IInspectable const& value) const { SetValue(_descriptionProperty, value); }
Controls::IconElement HeaderIcon() const { return GetValue(_headerIconProperty).as<Controls::IconElement>(); }
void HeaderIcon(Controls::IconElement const& value)const { SetValue(_headerIconProperty, value); }
IconElement HeaderIcon() const { return GetValue(_headerIconProperty).as<IconElement>(); }
void HeaderIcon(IconElement const& value)const { SetValue(_headerIconProperty, value); }
IInspectable Content() const { return GetValue(_contentProperty); }
void Content(IInspectable const& value) const { SetValue(_contentProperty, value); }
@ -70,6 +70,10 @@ private:
static void _OnItemsConnectedPropertyChanged(DependencyObject const& sender, DependencyPropertyChangedEventArgs const&);
void _OnItemsConnectedPropertyChanged();
void _UpdateAnimatedIcon();
MUXC::AnimatedIcon _expandCollapseChevron{ nullptr };
};
}

View file

@ -18,7 +18,7 @@ struct ShortcutControl : ShortcutControlT<ShortcutControl>, wil::notify_property
void Title(hstring value);
private:
void _ShortcutDialog_Closing(Controls::ContentDialog const&, Controls::ContentDialogClosingEventArgs const& args);
void _ShortcutDialog_Closing(ContentDialog const&, ContentDialogClosingEventArgs const& args);
static LRESULT CALLBACK _LowLevelKeyboardProc(
int nCode,
@ -36,7 +36,7 @@ private:
::Magpie::Event<winrt::Magpie::ShortcutAction>::EventRevoker _shortcutChangedRevoker;
::Magpie::Shortcut _shortcut;
Controls::ContentDialog _shortcutDialog{ nullptr };
ContentDialog _shortcutDialog{ nullptr };
com_ptr<ShortcutDialog> _shortcutDialogContent;
wil::unique_hhook _keyboardHook;

View file

@ -4,12 +4,9 @@
#include "SimpleStackPanel.g.cpp"
#endif
using namespace winrt;
using namespace Windows::UI::Xaml::Controls;
namespace winrt::Magpie::implementation {
void SimpleStackPanel::Orientation(Controls::Orientation value) {
void SimpleStackPanel::Orientation(enum Orientation value) {
if (_orientation == value) {
return;
}

View file

@ -4,8 +4,8 @@
namespace winrt::Magpie::implementation {
struct SimpleStackPanel : SimpleStackPanelT<SimpleStackPanel>, wil::notify_property_changed_base<SimpleStackPanel> {
Controls::Orientation Orientation() const { return _orientation; }
void Orientation(Controls::Orientation value);
Orientation Orientation() const { return _orientation; }
void Orientation(enum Orientation value);
Thickness Padding() const { return _padding; }
void Padding(const Thickness& value);
@ -20,7 +20,7 @@ struct SimpleStackPanel : SimpleStackPanelT<SimpleStackPanel>, wil::notify_prope
private:
void _UpdateLayout() const;
Controls::Orientation _orientation = Controls::Orientation::Vertical;
enum Orientation _orientation = Orientation::Vertical;
Thickness _padding{};
double _spacing = 0.0;
};

View file

@ -23,7 +23,7 @@ private:
static void _OnIsAutoTooltipChanged(DependencyObject const& sender, DependencyPropertyChangedEventArgs const& args);
static void _SetTooltipBasedOnTrimmingState(const Controls::TextBlock& tb, bool isAttached);
static void _SetTooltipBasedOnTrimmingState(const TextBlock& tb, bool isAttached);
};
}

View file

@ -36,7 +36,8 @@ void TitleBarControl::TitleBarControl_Loading(FrameworkElement const&, IInspecta
MUXC::NavigationView rootNavigationView = App::Get().RootPage()->RootNavigationView();
rootNavigationView.DisplayModeChanged([this](const auto&, const auto& args) {
bool expanded = args.DisplayMode() == MUXC::NavigationViewDisplayMode::Expanded;
VisualStateManager::GoToState(*this, expanded ? L"Expanded" : L"Compact", true);
VisualStateManager::GoToState(
*this, expanded ? L"Expanded" : L"Compact", App::Get().RootPage()->IsLoaded());
});
}

View file

@ -33,7 +33,7 @@ void WrapPanel::VerticalSpacing(double value) {
_UpdateLayout();
}
void WrapPanel::Orientation(Controls::Orientation value) {
void WrapPanel::Orientation(enum Orientation value) {
if (_orientation == value) {
return;
}
@ -80,7 +80,7 @@ Size WrapPanel::MeasureOverride(const Size& availableSize) {
}
Size WrapPanel::ArrangeOverride(Size finalSize) {
Controls::Orientation orientation = Orientation();
enum Orientation orientation = Orientation();
Size desiredSize = DesiredSize();
if ((orientation == Orientation::Horizontal && finalSize.Width < desiredSize.Width) ||
@ -124,7 +124,7 @@ void WrapPanel::_UpdateLayout() const {
Size WrapPanel::_UpdateRows(Size availableSize) {
_rows.clear();
const Controls::Orientation orientation = Orientation();
const enum Orientation orientation = Orientation();
const Thickness padding = Padding();
UIElementCollection children = Children();

View file

@ -9,11 +9,11 @@ struct UvMeasure {
UvMeasure(float u_, float v_) : u(u_), v(v_) {}
UvMeasure(Controls::Orientation orientation, Size size) :
UvMeasure(Orientation orientation, Size size) :
UvMeasure(orientation, size.Width, size.Height) {}
UvMeasure(Controls::Orientation orientation, float width, float height) {
if (orientation == Controls::Orientation::Horizontal) {
UvMeasure(Orientation orientation, float width, float height) {
if (orientation == Orientation::Horizontal) {
u = width;
v = height;
} else {
@ -27,8 +27,8 @@ struct UvMeasure {
v += measure.v;
}
Size ToSize(Controls::Orientation orientation) const noexcept {
return orientation == Controls::Orientation::Horizontal ? Size(u, v) : Size(v, u);
Size ToSize(Orientation orientation) const noexcept {
return orientation == Orientation::Horizontal ? Size(u, v) : Size(v, u);
}
float u;
@ -36,8 +36,8 @@ struct UvMeasure {
};
struct UvRect {
Rect ToRect(Controls::Orientation orientation) const noexcept {
if (orientation == Controls::Orientation::Horizontal) {
Rect ToRect(Orientation orientation) const noexcept {
if (orientation == Orientation::Horizontal) {
return { position.u, position.v, size.u, size.v };
} else {
return { position.v, position.u, size.v, size.u };
@ -80,8 +80,8 @@ struct WrapPanel : WrapPanelT<WrapPanel>, wil::notify_property_changed_base<Wrap
double VerticalSpacing() const { return _verticalSpacing; }
void VerticalSpacing(double value);
Controls::Orientation Orientation() const { return _orientation; }
void Orientation(Controls::Orientation value);
Orientation Orientation() const { return _orientation; }
void Orientation(enum Orientation value);
Thickness Padding() const { return _padding; }
void Padding(const Thickness& value);
@ -100,7 +100,7 @@ private:
double _horizontalSpacing = 0.0;
double _verticalSpacing = 0.0;
Controls::Orientation _orientation = Controls::Orientation::Horizontal;
enum Orientation _orientation = Orientation::Horizontal;
Thickness _padding{};
winrt::Magpie::StretchChild _stretchChild = StretchChild::None;

View file

@ -4,11 +4,11 @@
#include "SmallVector.h"
using namespace winrt;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
namespace Magpie {
static bool IsComboBoxPopup(const Primitives::Popup& popup) {
static bool IsComboBoxPopup(const Popup& popup) {
UIElement child = popup.Child();
if (!child.try_as<Canvas>()) {
return false;
@ -39,7 +39,7 @@ static bool IsComboBoxPopup(const Primitives::Popup& popup) {
}
void XamlHelper::CloseComboBoxPopup(const XamlRoot& root) {
for (const Primitives::Popup& popup : VisualTreeHelper::GetOpenPopupsForXamlRoot(root)) {
for (const Popup& popup : VisualTreeHelper::GetOpenPopupsForXamlRoot(root)) {
if (IsComboBoxPopup(popup)) {
popup.IsOpen(false);
return;
@ -69,8 +69,8 @@ void XamlHelper::RepositionXamlPopups(const Windows::UI::Xaml::XamlRoot& root, b
for (const auto& popup : VisualTreeHelper::GetOpenPopupsForXamlRoot(root)) {
if (closeFlyoutPresenter) {
auto className = get_class_name(popup.Child());
if (className == name_of<Controls::FlyoutPresenter>() ||
className == name_of<Controls::MenuFlyoutPresenter>()) {
if (className == name_of<FlyoutPresenter>() ||
className == name_of<MenuFlyoutPresenter>()) {
popup.IsOpen(false);
continue;
}

View file

@ -3,21 +3,15 @@
namespace Magpie {
struct XamlHelper {
static void CloseComboBoxPopup(const winrt::Windows::UI::Xaml::XamlRoot& root);
static void CloseComboBoxPopup(const winrt::XamlRoot& root);
static void ClosePopups(const winrt::Windows::UI::Xaml::XamlRoot& root);
static void ClosePopups(const winrt::XamlRoot& root);
static void UpdateThemeOfXamlPopups(
const winrt::Windows::UI::Xaml::XamlRoot& root,
winrt::Windows::UI::Xaml::ElementTheme theme
);
static void UpdateThemeOfXamlPopups(const winrt::XamlRoot& root, winrt::ElementTheme theme);
static void RepositionXamlPopups(const winrt::Windows::UI::Xaml::XamlRoot& root, bool closeFlyoutPresenter);
static void RepositionXamlPopups(const winrt::XamlRoot& root, bool closeFlyoutPresenter);
static void UpdateThemeOfTooltips(
const winrt::Windows::UI::Xaml::DependencyObject& root,
winrt::Windows::UI::Xaml::ElementTheme theme
);
static void UpdateThemeOfTooltips(const winrt::DependencyObject& root, winrt::ElementTheme theme);
};
}

View file

@ -78,12 +78,6 @@ protected:
return _isMaximized;
}
// 窗口尚未显示无法最大化,通过这个方法设置 _isMaximized 使 XamlWindow 估计 XAML Islands 窗口尺寸。
// 否则在显示窗口时可能会看到 NavigationView 的导航栏的展开动画。
void _SetInitialMaximized() noexcept {
_isMaximized = true;
}
void _SetTheme(bool isLightTheme) noexcept {
_isLightTheme = isLightTheme;
@ -149,7 +143,6 @@ protected:
}
const HWND hWnd = this->Handle();
_isWindowShown = IsWindowVisible(hWnd);
NCCALCSIZE_PARAMS* params = (NCCALCSIZE_PARAMS*)lParam;
RECT& clientRect = params->rgrc[0];
@ -167,7 +160,7 @@ protected:
clientRect.top = originalTop;
// WM_NCCALCSIZE 在 WM_SIZE 前
_UpdateMaximizedState();
_isMaximized = IsMaximized(hWnd);
if (_isMaximized) {
// 最大化的窗口的实际尺寸比屏幕的工作区更大一点,这是为了将可调整窗口大小的区域隐藏在屏幕外面
@ -356,7 +349,7 @@ protected:
}
case WM_SIZE:
{
_UpdateMaximizedState();
_isMaximized = IsMaximized(this->Handle());
if (wParam != SIZE_MINIMIZED) {
_UpdateIslandPosition(LOWORD(lParam), HIWORD(lParam));
@ -388,7 +381,6 @@ protected:
_hwndXamlIsland = NULL;
_isMaximized = false;
_isWindowShown = false;
_isLightTheme = true;
_content = nullptr;
@ -426,12 +418,18 @@ protected:
GetSystemMetricsForDpi(SM_CYSIZEFRAME, _currentDpi);
}
// 以最大化显示时使 XAML Islands 窗口尺寸保持稳定,见 _UpdateIslandPosition
void _SetInitialMaximized(bool value) noexcept {
_isInitialMaximized = value;
}
private:
void _UpdateIslandPosition(int width, int height) const noexcept {
if (!IsWindowVisible(this->Handle()) && _isMaximized) {
// 初始化过程中此函数会被调用两次。如果窗口以最大化显示,则两次传入的尺寸不一致。第一次
// 调用此函数时主窗口尚未显示,因此无法最大化,我们必须估算最大化窗口的尺寸。不执行这个
// 操作可能导致窗口显示时展示 NavigationView 导航展开的动画。
// 当窗口以最大化显示时,为了修正动画,实际上是先窗口化显示然后改为最大化。这个过程中此函数
// 会被调用多次,而且传入的尺寸不一致。我们想让 XAML Islands 窗口尺寸保持稳定以避免不必要
// 的动画,因此需要估算最大化窗口的尺寸。
// 由于没考虑自动隐藏的任务栏,计算结果可能不准确,但最多相差两个像素,可以接受。
if (_isInitialMaximized && !_isMaximized) {
if (HMONITOR hMon = MonitorFromWindow(this->Handle(), MONITOR_DEFAULTTONEAREST)) {
MONITORINFO monInfo{};
monInfo.cbSize = sizeof(MONITORINFO);
@ -459,13 +457,6 @@ private:
);
}
void _UpdateMaximizedState() noexcept {
// 如果窗口尚未显示,不碰 _isMaximized
if (_isWindowShown) {
_isMaximized = IsMaximized(this->Handle());
}
}
void _UpdateFrameMargins() const noexcept {
if (Win32Helper::GetOSVersion().IsWin11()) {
return;
@ -519,7 +510,7 @@ private:
uint32_t _nativeTopBorderHeight = 1;
bool _isLightTheme = true;
bool _isWindowShown = false;
bool _isInitialMaximized = false;
bool _isMaximized = false;
};

View file

@ -85,6 +85,7 @@ using namespace Windows::Foundation::Metadata;
using namespace Windows::System;
using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Media;