Merge branch 'net6' into net462

This commit is contained in:
doudou0720
2026-05-02 12:42:54 +08:00
8 changed files with 142 additions and 61 deletions
@@ -722,64 +722,60 @@ namespace Ink_Canvas.Helpers
var m = new Matrix(scale, 0, 0, scale, tx, ty);
geom.Transform = new MatrixTransform(m);
return StrokesFromOutlinedGeometry(geom, templateDa, 0.35);
var filled = FilledGlyphStroke.TryCreate(geom, templateDa);
if (filled == null)
return list;
list.Add(filled);
return list;
}
}
/// <summary>
/// 把字形几何作为「实心填充」绘制的笔画。仍是 WPF <see cref="Stroke"/>,可被 InkCanvas 选择/移动/删除,
/// 但渲染时直接 DrawGeometry(brush, null, geom),不再走 StylusPoints 描边路径。
/// </summary>
internal sealed class FilledGlyphStroke : Stroke
{
private readonly Geometry _geometry;
private FilledGlyphStroke(StylusPointCollection pts, Geometry geometry, DrawingAttributes da)
: base(pts)
{
_geometry = geometry;
if (da != null)
DrawingAttributes = da.Clone();
}
private static List<Stroke> StrokesFromOutlinedGeometry(Geometry geometry, DrawingAttributes da, double tolerance)
public static FilledGlyphStroke TryCreate(Geometry geometry, DrawingAttributes templateDa)
{
var list = new List<Stroke>();
if (geometry == null || geometry.IsEmpty() || da == null)
return list;
if (geometry == null || geometry.IsEmpty())
return null;
Geometry outlined;
try
var b = geometry.Bounds;
if (b.IsEmpty || b.Width < 0.5 || b.Height < 0.5)
return null;
// StylusPoints 用 bounds 四角,保证命中测试 / 选区 / 包围盒计算正常。
var pts = new StylusPointCollection
{
outlined = geometry.GetOutlinedPathGeometry(tolerance, ToleranceType.Absolute);
}
catch
{
return list;
}
new StylusPoint(b.Left, b.Top, 0.5f),
new StylusPoint(b.Right, b.Top, 0.5f),
new StylusPoint(b.Right, b.Bottom, 0.5f),
new StylusPoint(b.Left, b.Bottom, 0.5f),
};
if (outlined == null || outlined.IsEmpty())
return list;
return new FilledGlyphStroke(pts, geometry, templateDa);
}
Geometry flat;
try
{
flat = outlined.GetFlattenedPathGeometry(tolerance, ToleranceType.Absolute);
}
catch
{
return list;
}
protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
{
if (drawingContext == null || _geometry == null)
return;
if (!(flat is PathGeometry pg))
return list;
foreach (var fig in pg.Figures)
{
var pts = new StylusPointCollection();
pts.Add(new StylusPoint(fig.StartPoint.X, fig.StartPoint.Y, 0.5f));
foreach (var seg in fig.Segments)
{
switch (seg)
{
case LineSegment ls:
pts.Add(new StylusPoint(ls.Point.X, ls.Point.Y, 0.5f));
break;
case PolyLineSegment pls:
foreach (var p in pls.Points)
pts.Add(new StylusPoint(p.X, p.Y, 0.5f));
break;
}
}
if (pts.Count >= 2)
list.Add(new Stroke(pts) { DrawingAttributes = da.Clone() });
}
return list;
var color = drawingAttributes != null ? drawingAttributes.Color : Colors.Black;
drawingContext.DrawGeometry(new SolidColorBrush(color), null, _geometry);
}
}
+5 -1
View File
@@ -3419,7 +3419,11 @@
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelBlackboardIcon}" Label="{i18n:I18n Key=QuickPanel_Whiteboard}" ButtonMouseUp="ImageBlackboard_MouseUp" />
<controls:QuickPanelButton x:Name="BtnExitPptFromSidebarRight" IconSource="{DynamicResource QuickPanelEndSlideshowIcon}" Label="{i18n:I18n Key=QuickPanel_ExitShow}" LabelFontSize="7" Visibility="Collapsed" ButtonMouseUp="ExitPPTSlideShow_MouseUp" />
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelEyeIcon}" Label="{i18n:I18n Key=QuickPanel_Show}" ButtonMouseUp="UnFoldFloatingBar_MouseUp" />
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelChevronLeftIcon}" ButtonMouseUp="HideQuickPanel_MouseUp" />
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelChevronLeftIcon}" ButtonMouseUp="HideQuickPanel_MouseUp" RenderTransformOrigin="0.5,0.5">
<controls:QuickPanelButton.RenderTransform>
<RotateTransform Angle="180" />
</controls:QuickPanelButton.RenderTransform>
</controls:QuickPanelButton>
</ikw:SimpleStackPanel>
</Border>
</Viewbox>
+40 -5
View File
@@ -2269,9 +2269,15 @@ namespace Ink_Canvas
if (Settings.PowerPointSettings.EnablePPTButtonEnhancedPreview && bar != null)
{
if (bar.IsPreviewExpanded)
// 侧边条点击时,把增强预览重定向到同侧的底部条上展开
var targetBar = ResolvePreviewTargetBar(bar);
if (targetBar == null)
{
bar.IsPreviewExpanded = false;
_pptManager.TryShowSlideNavigation();
}
else if (targetBar.IsPreviewExpanded)
{
targetBar.IsPreviewExpanded = false;
}
else
{
@@ -2292,9 +2298,9 @@ namespace Ink_Canvas
Thumbnail = s.Thumbnail
});
}
bar.PreviewItems = items;
bar.CurrentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
bar.IsPreviewExpanded = true;
targetBar.PreviewItems = items;
targetBar.CurrentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
targetBar.IsPreviewExpanded = true;
}
}
}
@@ -2332,6 +2338,35 @@ namespace Ink_Canvas
finally { if (bar != null) bar.IsPreviewExpanded = false; }
}
/// <summary>
/// 选择承载增强预览的底部条:
/// - 来自侧边条的点击重定向到同侧底部条;
/// - 若同侧底部条不可用,退化到任意可用的底部条;
/// - 来自底部条的点击保持原行为。
/// </summary>
private Controls.PptNavBar ResolvePreviewTargetBar(Controls.PptNavBar source)
{
if (source == null) return null;
switch (source.Direction)
{
case Controls.PptNavBar.NavDirection.LeftSide:
return PickVisibleBar(LeftBottomPanelForPPTNavigation, RightBottomPanelForPPTNavigation) ?? source;
case Controls.PptNavBar.NavDirection.RightSide:
return PickVisibleBar(RightBottomPanelForPPTNavigation, LeftBottomPanelForPPTNavigation) ?? source;
default:
return source;
}
}
private static Controls.PptNavBar PickVisibleBar(params Controls.PptNavBar[] candidates)
{
foreach (var c in candidates)
{
if (c != null && c.Visibility == Visibility.Visible) return c;
}
return null;
}
private sealed class PptEnhancedPreviewItem
{
public int SlideNumber { get; set; }
+1 -1
View File
@@ -1864,7 +1864,7 @@
<value>Finger mode BoundsWidth</value>
</data>
<data name="Advanced_EdgeGestureUtilHint_Part1" xml:space="preserve">
<value>EdgeGestureUtil is newly introduced in ICC to temporarily block edge gestures when using touch (e.g., on Windows 10: swipe from the left edge to Task View, from the right edge to Action Center; on Windows 11: swipe up from the bottom to open Start). It works by using</value>
<value>EdgeGestureUtil is newly introduced in ICC to temporarily block edge gestures when using touch (e.g., on Windows 10: swipe from the left edge to Task View, from the right edge to Action Center; on Windows 11: swipe up from the bottom to open Start). It works by using System.EdgeGesture.DisableTouchWhenFullscreen (When the app window is active and in full-screen mode (or an owned window is active), prevents edge gesture behavior.) If anything is abnormal, turn this option off; it should take effect immediately. (Not available on Windows 7/8.)</value>
</data>
<data name="Advanced_EdgeGestureUtilHint_Part2" xml:space="preserve">
<value>(When the app window is active and in full-screen mode (or an owned window is active), prevents edge gesture behavior.) If anything is abnormal, turn this option off; it should take effect immediately. (Not available on Windows 7/8.)</value>
+2 -2
View File
@@ -1907,7 +1907,7 @@
<value>手指模式 BoundsWidth</value>
</data>
<data name="Advanced_EdgeGestureUtilHint_Part1" xml:space="preserve">
<value>EdgeGestureUtil是icc最新引入的可以暂时阻止在使用触摸时触发边缘手势(如Windows10环境下,屏幕左边缘滑动进入任务视图,右边缘滑动弹出通知中心;Windows11环境下,底部向上滑动打开开始菜单),其原理是使用了</value>
<value>EdgeGestureUtil是icc最新引入的可以暂时阻止在使用触摸时触发边缘手势(如Windows10环境下,屏幕左边缘滑动进入任务视图,右边缘滑动弹出通知中心;Windows11环境下,底部向上滑动打开开始菜单),其原理是使用了 System.EdgeGesture.DisableTouchWhenFullscreen (当应用程序窗口处于活动状态且处于全屏模式 (或拥有的窗口) 处于活动状态时,防止边缘手势行为。)来实现的。如果有异常,请关闭该选项,该选项应该能够实时生效。(Win7和Win8用户该选项无法使用)</value>
</data>
<data name="Advanced_EdgeGestureUtilHint_Part2" xml:space="preserve">
<value>(当应用程序窗口处于活动状态且处于全屏模式 (或拥有的窗口) 处于活动状态时,防止边缘手势行为。)来实现的。如果有异常,请关闭该选项,该选项应该能够实时生效。(Win7和Win8用户该选项无法使用)</value>
@@ -2831,7 +2831,7 @@
<value>自动更新</value>
</data>
<data name="Storage_Update_Desc" xml:space="preserve">
<value>AutoUpdate 目录中的安装包与下载缓存,每次新版本发布或更新时会被刷新</value>
<value>AutoUpdate 目录中的安装包与下载缓存,每次更新完成后会被清理</value>
</data>
<data name="Storage_Other_Header" xml:space="preserve">
<value>其他</value>
@@ -302,7 +302,7 @@
<TextBlock Text="{i18n:I18n Key=AutoSave_Title}" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"/>
<controls:LabeledSettingsCard x:Name="CardSaveScreenshotsInDateFolders"
Header="{i18n:I18n Key=Storage_AutoSaveInkOnScreenshot}"
Header="{i18n:I18n Key=Storage_ScreenshotsByDateFolder}"
Icon="{x:Static ui:SegoeFluentIcons.Folder}"
Toggled="ToggleSwitchSaveScreenshotsInDateFolders_Toggled"/>
@@ -59,9 +59,18 @@
</Grid>
<!-- 横向占比柱状图 -->
<Border Height="14" CornerRadius="7"
<Border x:Name="UsageBarBorder" Height="14" CornerRadius="2"
Background="{DynamicResource ControlStrokeColorDefaultBrush}"
ClipToBounds="True">
<Border.OpacityMask>
<VisualBrush>
<VisualBrush.Visual>
<Border Background="Black" CornerRadius="2"
Width="{Binding ActualWidth, ElementName=UsageBarBorder}"
Height="{Binding ActualHeight, ElementName=UsageBarBorder}"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.OpacityMask>
<Grid x:Name="UsageStackedBar">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="BarCoreCol" Width="0*"/>
@@ -78,6 +78,7 @@ namespace Ink_Canvas.Windows.SettingsViews
RegisterDpiChangedListener();
LoadPluginSettingsPages();
UpdateUpdateBadgeVisibility();
_ = PreloadAllPagesAsync();
};
this.Closed += (sender, e) =>
@@ -690,6 +691,42 @@ namespace Ink_Canvas.Windows.SettingsViews
return NavigationViewControl;
}
private async System.Threading.Tasks.Task PreloadAllPagesAsync()
{
try
{
var tags = _pageTypes.Keys.ToList();
foreach (var tag in tags)
{
if (_pages.ContainsKey(tag))
continue;
if (!_pageTypes.TryGetValue(tag, out var type))
continue;
if (type == typeof(PluginSettingsPage))
continue;
await Dispatcher.InvokeAsync(() =>
{
try
{
if (_pages.ContainsKey(tag))
return;
var page = Activator.CreateInstance(type);
_pages[tag] = page;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"预加载设置页面 {tag} 失败: {ex.Message}");
}
}, System.Windows.Threading.DispatcherPriority.Background);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"异步预加载设置页面时出错: {ex.Message}");
}
}
public void UpdateUpdateBadgeVisibility()
{
try