Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Ink Canvas/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,9 @@
FontSize="14" Padding="14,4" Margin="8,0,0,0" MinWidth="65" VerticalAlignment="Center"
Click="BtnHitokotoCustomize_Click"
Visibility="Collapsed" />
<Button Name="BtnAdjustWatermarkPosition" Content="{i18n:I18n Key=Theme_AdjustPosition}" FontFamily="Microsoft YaHei UI"
FontSize="14" Padding="14,4" Margin="8,0,0,0" MinWidth="65" VerticalAlignment="Center"
Click="BtnAdjustWatermarkPosition_Click" />
</ikw:SimpleStackPanel>
</ikw:SimpleStackPanel>
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0"
Expand Down Expand Up @@ -4664,7 +4667,7 @@
Panel.ZIndex="1001"/>
</Grid>

<Canvas IsHitTestVisible="False">
<Canvas Name="WaterMarkCanvas" IsHitTestVisible="False">
<ikw:SimpleStackPanel Canvas.Left="25" Canvas.Top="15" Orientation="Vertical">
<TextBlock Text="{Binding nowTime}" Name="WaterMarkTime" Visibility="Collapsed" FontSize="30"
FontWeight="Bold" Foreground="White" Opacity="0.6" />
Expand Down
157 changes: 157 additions & 0 deletions Ink Canvas/MainWindow_cs/MW_Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,163 @@
await UpdateChickenSoupTextAsync();
}

private bool _isAdjustingWatermarkPosition = false;
private Point _watermarkDragStartPoint;
private double _watermarkStartX;
private double _watermarkStartY;

private void BtnAdjustWatermarkPosition_Click(object sender, RoutedEventArgs e)
{
// 关闭设置面板
HideSubPanelsImmediately();

// 如果名言没有显示,临时显示出来以便调整
if (BlackBoardWaterMark.Visibility != Visibility.Visible)
{
BlackBoardWaterMark.Visibility = Visibility.Visible;
}

_isAdjustingWatermarkPosition = true;
WaterMarkCanvas.IsHitTestVisible = true;
BlackBoardWaterMark.IsHitTestVisible = true;
BlackBoardWaterMark.Cursor = System.Windows.Input.Cursors.SizeAll;

// 添加视觉反馈
BlackBoardWaterMark.Background = new SolidColorBrush(Color.FromArgb(50, 255, 255, 255));

// 绑定事件
BlackBoardWaterMark.MouseDown -= BlackBoardWaterMark_MouseDown;
BlackBoardWaterMark.MouseMove -= BlackBoardWaterMark_MouseMove;
BlackBoardWaterMark.MouseUp -= BlackBoardWaterMark_MouseUp;

BlackBoardWaterMark.MouseDown += BlackBoardWaterMark_MouseDown;
BlackBoardWaterMark.MouseMove += BlackBoardWaterMark_MouseMove;
BlackBoardWaterMark.MouseUp += BlackBoardWaterMark_MouseUp;

// 提示用户
ShowNotification("进入调整模式:请拖动名言调整位置,双击或点击其他区域完成调整。");

// 绑定一个全局的点击事件来退出调整模式
inkCanvas.MouseDown += InkCanvas_EndWatermarkAdjustment;
}

private void InkCanvas_EndWatermarkAdjustment(object sender, MouseButtonEventArgs e)
{
EndWatermarkAdjustment();
inkCanvas.MouseDown -= InkCanvas_EndWatermarkAdjustment;
Comment on lines +1323 to +1326
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Mark adjustment-exit clicks as handled

The exit handler ends adjustment mode but does not set e.Handled, so the same click continues through normal canvas input processing. In this app, inkCanvas already has a MouseDown handler (inkCanvas_MouseDown) that captures input and starts interaction, so when users click the canvas to finish watermark positioning, that click can also create an unintended stroke/dot in drawing workflows. Consuming the event (or handling this in preview phase) avoids modifying the board when the user is only trying to exit adjustment mode.

Useful? React with 👍 / 👎.

}

private void EndWatermarkAdjustment()
{
if (!_isAdjustingWatermarkPosition) return;

_isAdjustingWatermarkPosition = false;
WaterMarkCanvas.IsHitTestVisible = false;
BlackBoardWaterMark.IsHitTestVisible = false;
BlackBoardWaterMark.Cursor = System.Windows.Input.Cursors.Arrow;
BlackBoardWaterMark.Background = Brushes.Transparent;

BlackBoardWaterMark.MouseDown -= BlackBoardWaterMark_MouseDown;
BlackBoardWaterMark.MouseMove -= BlackBoardWaterMark_MouseMove;
BlackBoardWaterMark.MouseUp -= BlackBoardWaterMark_MouseUp;

// 如果原本是不应该显示的,则隐藏
if (!Settings.Appearance.EnableChickenSoupInWhiteboardMode || currentMode != 1)
{
BlackBoardWaterMark.Visibility = Visibility.Collapsed;
}

ToastHelper_EndWatermarkAdjustment();

// 移除可能存在的全局点击事件
inkCanvas.MouseDown -= InkCanvas_EndWatermarkAdjustment;
}

private void ToastHelper_EndWatermarkAdjustment()
{
ShowNotification("调整完成,名言位置已保存。");
}

private void BlackBoardWaterMark_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
EndWatermarkAdjustment();
return;
}

_watermarkDragStartPoint = e.GetPosition(WaterMarkCanvas);

// 获取当前位置
_watermarkStartX = System.Windows.Controls.Canvas.GetLeft(BlackBoardWaterMark);
if (double.IsNaN(_watermarkStartX))
{
// 如果没有设置Left,可能是靠Right定位的
double right = System.Windows.Controls.Canvas.GetRight(BlackBoardWaterMark);
if (!double.IsNaN(right))
{
_watermarkStartX = WaterMarkCanvas.ActualWidth - BlackBoardWaterMark.ActualWidth - right;
// 转换为Left定位
System.Windows.Controls.Canvas.SetRight(BlackBoardWaterMark, double.NaN);
}
else
{
_watermarkStartX = 0;
}
}

_watermarkStartY = System.Windows.Controls.Canvas.GetTop(BlackBoardWaterMark);
if (double.IsNaN(_watermarkStartY))
{
_watermarkStartY = 0;
}

BlackBoardWaterMark.CaptureMouse();
e.Handled = true;
}

private void BlackBoardWaterMark_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (BlackBoardWaterMark.IsMouseCaptured)
{
Point currentPoint = e.GetPosition(WaterMarkCanvas);
double offsetX = currentPoint.X - _watermarkDragStartPoint.X;
double offsetY = currentPoint.Y - _watermarkDragStartPoint.Y;

double newLeft = _watermarkStartX + offsetX;
double newTop = _watermarkStartY + offsetY;

// 边界限制
if (newLeft < 0) newLeft = 0;
if (newTop < 0) newTop = 0;
if (newLeft + BlackBoardWaterMark.ActualWidth > WaterMarkCanvas.ActualWidth)
newLeft = WaterMarkCanvas.ActualWidth - BlackBoardWaterMark.ActualWidth;
Comment on lines +1412 to +1413
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clamp watermark position after right-edge overflow math

The boundary logic can still produce a negative newLeft when the quote text is wider than the canvas: after clamping negative values to 0, this assignment overwrites it with ActualWidth - TextWidth, which is negative. In that case the saved position becomes off-screen, so users with long quotes or narrow windows can end up with a watermark they cannot fully bring back into view.

Useful? React with 👍 / 👎.

if (newTop + BlackBoardWaterMark.ActualHeight > WaterMarkCanvas.ActualHeight)
newTop = WaterMarkCanvas.ActualHeight - BlackBoardWaterMark.ActualHeight;

System.Windows.Controls.Canvas.SetLeft(BlackBoardWaterMark, newLeft);
System.Windows.Controls.Canvas.SetTop(BlackBoardWaterMark, newTop);

// 保存位置到Settings
Settings.Appearance.WatermarkPositionX = newLeft;
Settings.Appearance.WatermarkPositionY = newTop;
Settings.Appearance.IsWatermarkPositionCustomized = true;

// 延迟保存避免频繁写盘
SaveSettingsToFile();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Defer settings persistence until drag completes

Calling SaveSettingsToFile() on every MouseMove event writes the full settings JSON synchronously for each pointer update, which can cause visible UI stutter during dragging (especially on slower disks) and unnecessary disk churn. This handler already saves again on mouse-up, so persisting only at the end of the drag (or with an actual debounce/throttle) avoids a performance regression introduced by this feature.

Useful? React with 👍 / 👎.

}
}

private void BlackBoardWaterMark_MouseUp(object sender, MouseButtonEventArgs e)
{
if (BlackBoardWaterMark.IsMouseCaptured)
{
BlackBoardWaterMark.ReleaseMouseCapture();
SaveSettingsToFile(); // 最终保存
e.Handled = true;
}
}

private async void BtnHitokotoCustomize_Click(object sender, RoutedEventArgs e)
{
var categories = new Dictionary<string, string>
Expand Down Expand Up @@ -5254,7 +5411,7 @@
MessageBoxImage.Warning);

Settings.Startup.UpdateChannel = oldChannel;
Dispatcher.BeginInvoke(new Action(() =>

Check warning on line 5414 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (AnyCPU)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 5414 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (AnyCPU)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 5414 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (x86)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 5414 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (x86)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
{
_isChangingUpdateChannelInternally = true;
try
Expand Down Expand Up @@ -5305,7 +5462,7 @@
else
{
Settings.Startup.UpdateChannel = oldChannel;
Dispatcher.BeginInvoke(new Action(() =>

Check warning on line 5465 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (AnyCPU)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 5465 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (AnyCPU)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 5465 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (x86)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 5465 in Ink Canvas/MainWindow_cs/MW_Settings.cs

View workflow job for this annotation

GitHub Actions / Build & Package (x86)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
{
_isChangingUpdateChannelInternally = true;
try
Expand Down
7 changes: 7 additions & 0 deletions Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,13 @@ private void LoadSettings(bool isStartup = false, bool skipAutoUpdateCheck = fal

ToggleSwitchEnableChickenSoupInWhiteboardMode.IsOn =
Settings.Appearance.EnableChickenSoupInWhiteboardMode;

if (Settings.Appearance.IsWatermarkPositionCustomized)
{
System.Windows.Controls.Canvas.SetLeft(BlackBoardWaterMark, Settings.Appearance.WatermarkPositionX);
System.Windows.Controls.Canvas.SetTop(BlackBoardWaterMark, Settings.Appearance.WatermarkPositionY);
Comment on lines +542 to +543
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clamp restored watermark coordinates to current canvas

When loading a customized watermark position, the code applies stored WatermarkPositionX/Y directly without validating against the current WaterMarkCanvas size. If the user saved coordinates on a larger display and later opens on a smaller one, the watermark can load off-screen and become impossible to drag back through the UI. Clamp the restored values to the canvas bounds before assigning them.

Useful? React with 👍 / 👎.

System.Windows.Controls.Canvas.SetRight(BlackBoardWaterMark, double.NaN);
}

// 浮动栏按钮显示控制开关初始化
CheckBoxUseLegacyFloatingBarUI.IsChecked = Settings.Appearance.UseLegacyFloatingBarUI;
Expand Down
9 changes: 9 additions & 0 deletions Ink Canvas/Properties/Strings.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -2583,4 +2583,13 @@ Hide</value>
<data name="Canvas_LaunchSeewoVideoShowcaseForWhiteboardBoothHint" xml:space="preserve">
<value>When enabled, the whiteboard toolbar Booth button launches Seewo Video Showcase (must be installed). When disabled, the built-in booth is used.</value>
</data>
<data name="Theme_AdjustPosition" xml:space="preserve">
<value>Adjust Position</value>
</data>
<data name="InkRecog_HandwritingBeautify" xml:space="preserve">
<value>Handwriting Beautify</value>
</data>
<data name="InkRecog_HandwritingBeautifyHint" xml:space="preserve">
<value>Automatically replace handwriting strokes with beautified font</value>
</data>
</root>
9 changes: 9 additions & 0 deletions Ink Canvas/Properties/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -2626,4 +2626,13 @@
<data name="Canvas_LaunchSeewoVideoShowcaseForWhiteboardBoothHint" xml:space="preserve">
<value>开启后,点击白板工具栏「展台」将打开希沃视频展台(需已安装);关闭则使用内置展台。</value>
</data>
<data name="Theme_AdjustPosition" xml:space="preserve">
<value>调整位置</value>
</data>
<data name="InkRecog_HandwritingBeautify" xml:space="preserve">
<value>手写体美化</value>
</data>
<data name="InkRecog_HandwritingBeautifyHint" xml:space="preserve">
<value>自动将手写字迹替换为美化字体</value>
</data>
</root>
8 changes: 7 additions & 1 deletion Ink Canvas/Resources/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,13 @@ public class Appearance
public bool EnableHotkeysInMouseMode { get; set; } = false;
[JsonProperty("language")]
public string Language { get; set; } = "";


[JsonProperty("isWatermarkPositionCustomized")]
public bool IsWatermarkPositionCustomized { get; set; } = false;
[JsonProperty("watermarkPositionX")]
public double WatermarkPositionX { get; set; } = 0;
[JsonProperty("watermarkPositionY")]
public double WatermarkPositionY { get; set; } = 0;
}

public class PowerPointSettings
Expand Down
Loading