alpha
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using iNKORE.UI.WPF.Modern;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
public bool isFloatingBarFolded = false;
|
||||
private bool isFloatingBarChangingHideMode = false;
|
||||
|
||||
private void CloseWhiteboardImmediately() {
|
||||
if (isDisplayingOrHidingBlackboard) return;
|
||||
isDisplayingOrHidingBlackboard = true;
|
||||
HideSubPanelsImmediately();
|
||||
if (Settings.Gesture.AutoSwitchTwoFingerGesture) // 自动启用多指书写
|
||||
ToggleSwitchEnableTwoFingerTranslate.IsOn = false;
|
||||
WaterMarkTime.Visibility = Visibility.Collapsed;
|
||||
WaterMarkDate.Visibility = Visibility.Collapsed;
|
||||
BlackBoardWaterMark.Visibility = Visibility.Collapsed;
|
||||
BtnSwitch_Click(null, null);
|
||||
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
|
||||
new Thread(new ThreadStart(() => {
|
||||
Thread.Sleep(200);
|
||||
Application.Current.Dispatcher.Invoke(() => { isDisplayingOrHidingBlackboard = false; });
|
||||
})).Start();
|
||||
}
|
||||
|
||||
public async void FoldFloatingBar_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
await FoldFloatingBar(sender);
|
||||
}
|
||||
|
||||
public async Task FoldFloatingBar(object sender)
|
||||
{
|
||||
var isShouldRejectAction = false;
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
|
||||
((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
|
||||
if (sender == Fold_Icon && lastBorderMouseDownObject != Fold_Icon) isShouldRejectAction = true;
|
||||
});
|
||||
|
||||
if (isShouldRejectAction) return;
|
||||
|
||||
// FloatingBarIcons_MouseUp_New(sender);
|
||||
if (sender == null)
|
||||
foldFloatingBarByUser = false;
|
||||
else
|
||||
foldFloatingBarByUser = true;
|
||||
unfoldFloatingBarByUser = false;
|
||||
|
||||
if (isFloatingBarChangingHideMode) return;
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
|
||||
InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
|
||||
InkCanvasGridForInkReplay.IsHitTestVisible = true;
|
||||
FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
|
||||
FloatingbarUIForInkReplay.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
|
||||
isStopInkReplay = true;
|
||||
});
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
isFloatingBarChangingHideMode = true;
|
||||
isFloatingBarFolded = true;
|
||||
if (currentMode != 0) CloseWhiteboardImmediately();
|
||||
if (StackPanelCanvasControls.Visibility == Visibility.Visible)
|
||||
if (foldFloatingBarByUser && inkCanvas.Strokes.Count > 2)
|
||||
ShowNewToast("正在清空墨迹并收纳至屏幕两边,可进入批注模式后通过 “撤销” 功能来恢复原先墨迹。",MW_Toast.ToastType.Informative, 3000);
|
||||
CursorWithDelIcon_Click(null, null);
|
||||
RectangleSelectionHitTestBorder.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
|
||||
await Task.Delay(5);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
ViewboxFloatingBarMarginAnimation(-60);
|
||||
HideSubPanels("cursor");
|
||||
// update tool selection
|
||||
SelectedMode = ICCToolsEnum.CursorMode;
|
||||
ForceUpdateToolSelection(null);
|
||||
SidePannelMarginAnimation(-10);
|
||||
|
||||
});
|
||||
isFloatingBarChangingHideMode = false;
|
||||
}
|
||||
|
||||
private async void LeftUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (Settings.Appearance.IsShowQuickPanel == true) {
|
||||
HideRightQuickPanel();
|
||||
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Visible;
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation {
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = new Thickness(-50, 0, 0, -150),
|
||||
To = new Thickness(-1, 0, 0, -150)
|
||||
};
|
||||
marginAnimation.EasingFunction = new CubicEase();
|
||||
LeftUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
await Task.Delay(100);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
LeftUnFoldButtonQuickPanel.Margin = new Thickness(-1, 0, 0, -150);
|
||||
});
|
||||
}
|
||||
else {
|
||||
UnFoldFloatingBar_MouseUp(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private async void RightUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (Settings.Appearance.IsShowQuickPanel == true) {
|
||||
HideLeftQuickPanel();
|
||||
RightUnFoldButtonQuickPanel.Visibility = Visibility.Visible;
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation {
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = new Thickness(0, 0, -50, -150),
|
||||
To = new Thickness(0, 0, -1, -150)
|
||||
};
|
||||
marginAnimation.EasingFunction = new CubicEase();
|
||||
RightUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
await Task.Delay(100);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
RightUnFoldButtonQuickPanel.Margin = new Thickness(0, 0, -1, -150);
|
||||
});
|
||||
}
|
||||
else {
|
||||
UnFoldFloatingBar_MouseUp(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private async void HideLeftQuickPanel() {
|
||||
if (LeftUnFoldButtonQuickPanel.Visibility == Visibility.Visible) {
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation {
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = new Thickness(-1, 0, 0, -150),
|
||||
To = new Thickness(-50, 0, 0, -150)
|
||||
};
|
||||
marginAnimation.EasingFunction = new CubicEase();
|
||||
LeftUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
await Task.Delay(100);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
LeftUnFoldButtonQuickPanel.Margin = new Thickness(0, 0, -50, -150);
|
||||
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async void HideRightQuickPanel() {
|
||||
if (RightUnFoldButtonQuickPanel.Visibility == Visibility.Visible) {
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation {
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = new Thickness(0, 0, -1, -150),
|
||||
To = new Thickness(0, 0, -50, -150)
|
||||
};
|
||||
marginAnimation.EasingFunction = new CubicEase();
|
||||
RightUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
await Task.Delay(100);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
RightUnFoldButtonQuickPanel.Margin = new Thickness(0, 0, -50, -150);
|
||||
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void HideQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
HideLeftQuickPanel();
|
||||
HideRightQuickPanel();
|
||||
}
|
||||
|
||||
public async void UnFoldFloatingBar_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
await UnFoldFloatingBar(sender);
|
||||
}
|
||||
|
||||
public async Task UnFoldFloatingBar(object sender)
|
||||
{
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
if (sender == null || BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible)
|
||||
unfoldFloatingBarByUser = false;
|
||||
else
|
||||
unfoldFloatingBarByUser = true;
|
||||
foldFloatingBarByUser = false;
|
||||
|
||||
if (isFloatingBarChangingHideMode) return;
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
isFloatingBarChangingHideMode = true;
|
||||
isFloatingBarFolded = false;
|
||||
});
|
||||
|
||||
await Task.Delay(0);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible)
|
||||
{
|
||||
var dops = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
|
||||
var dopsc = dops.ToCharArray();
|
||||
if (dopsc[0] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(LeftBottomPanelForPPTNavigation);
|
||||
if (dopsc[1] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(RightBottomPanelForPPTNavigation);
|
||||
if (dopsc[2] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(LeftSidePanelForPPTNavigation);
|
||||
if (dopsc[3] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(RightSidePanelForPPTNavigation);
|
||||
}
|
||||
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible)
|
||||
ViewboxFloatingBarMarginAnimation(60);
|
||||
else
|
||||
ViewboxFloatingBarMarginAnimation(100, true);
|
||||
SidePannelMarginAnimation(-50, !unfoldFloatingBarByUser);
|
||||
});
|
||||
|
||||
isFloatingBarChangingHideMode = false;
|
||||
}
|
||||
|
||||
private async void SidePannelMarginAnimation(int MarginFromEdge, bool isNoAnimation = false) // Possible value: -50, -10
|
||||
{
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
if (MarginFromEdge == -10) LeftSidePanel.Visibility = Visibility.Visible;
|
||||
|
||||
var LeftSidePanelmarginAnimation = new ThicknessAnimation {
|
||||
Duration = isNoAnimation == true ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175),
|
||||
From = LeftSidePanel.Margin,
|
||||
To = new Thickness(MarginFromEdge, 0, 0, -150)
|
||||
};
|
||||
LeftSidePanelmarginAnimation.EasingFunction = new CubicEase();
|
||||
var RightSidePanelmarginAnimation = new ThicknessAnimation {
|
||||
Duration = isNoAnimation == true ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175),
|
||||
From = RightSidePanel.Margin,
|
||||
To = new Thickness(0, 0, MarginFromEdge, -150)
|
||||
};
|
||||
RightSidePanelmarginAnimation.EasingFunction = new CubicEase();
|
||||
LeftSidePanel.BeginAnimation(MarginProperty, LeftSidePanelmarginAnimation);
|
||||
RightSidePanel.BeginAnimation(MarginProperty, RightSidePanelmarginAnimation);
|
||||
});
|
||||
|
||||
await Task.Delay(600);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
LeftSidePanel.Margin = new Thickness(MarginFromEdge, 0, 0, -150);
|
||||
RightSidePanel.Margin = new Thickness(0, 0, MarginFromEdge, -150);
|
||||
|
||||
if (MarginFromEdge == -50) LeftSidePanel.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
isFloatingBarChangingHideMode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using IWshRuntimeLibrary;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
public static bool StartAutomaticallyCreate(string exeName) {
|
||||
try {
|
||||
var shell = new WshShell();
|
||||
var shortcut = (IWshShortcut)shell.CreateShortcut(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk");
|
||||
//设置快捷方式的目标所在的位置(源程序完整路径)
|
||||
shortcut.TargetPath = System.Windows.Forms.Application.ExecutablePath;
|
||||
//应用程序的工作目录
|
||||
//当用户没有指定一个具体的目录时,快捷方式的目标应用程序将使用该属性所指定的目录来装载或保存文件。
|
||||
shortcut.WorkingDirectory = Environment.CurrentDirectory;
|
||||
//目标应用程序窗口类型(1.Normal window普通窗口,3.Maximized最大化窗口,7.Minimized最小化)
|
||||
shortcut.WindowStyle = 1;
|
||||
//快捷方式的描述
|
||||
shortcut.Description = exeName + "_Ink";
|
||||
//设置快捷键(如果有必要的话.)
|
||||
//shortcut.Hotkey = "CTRL+ALT+D";
|
||||
shortcut.Save();
|
||||
return true;
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool StartAutomaticallyDel(string exeName) {
|
||||
try {
|
||||
System.IO.File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName +
|
||||
".lnk");
|
||||
return true;
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using Microsoft.Win32;
|
||||
using iNKORE.UI.WPF.Modern;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Ink_Canvas.Helpers;
|
||||
using Application = System.Windows.Application;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
/*public partial class MainWindow : PerformanceTransparentWin {
|
||||
private Color FloatBarForegroundColor = Color.FromRgb(102, 102, 102);
|
||||
|
||||
private void SetTheme(string theme) {
|
||||
if (theme == "Light") {
|
||||
var rd1 = new ResourceDictionary()
|
||||
{ Source = new Uri("Resources/Styles/Light.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd1);
|
||||
|
||||
var rd2 = new ResourceDictionary()
|
||||
{ Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd2);
|
||||
|
||||
var rd3 = new ResourceDictionary()
|
||||
{ Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd3);
|
||||
|
||||
var rd4 = new ResourceDictionary()
|
||||
{ Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd4);
|
||||
|
||||
ThemeManager.SetRequestedTheme(window, ElementTheme.Light);
|
||||
|
||||
FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor");
|
||||
}
|
||||
else if (theme == "Dark") {
|
||||
var rd1 = new ResourceDictionary() { Source = new Uri("Resources/Styles/Dark.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd1);
|
||||
|
||||
var rd2 = new ResourceDictionary()
|
||||
{ Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd2);
|
||||
|
||||
var rd3 = new ResourceDictionary()
|
||||
{ Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd3);
|
||||
|
||||
var rd4 = new ResourceDictionary()
|
||||
{ Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) };
|
||||
Application.Current.Resources.MergedDictionaries.Add(rd4);
|
||||
|
||||
ThemeManager.SetRequestedTheme(window, ElementTheme.Dark);
|
||||
|
||||
FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor");
|
||||
}
|
||||
}
|
||||
|
||||
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) {
|
||||
switch (Settings.Appearance.Theme) {
|
||||
case 0:
|
||||
SetTheme("Light");
|
||||
break;
|
||||
case 1:
|
||||
SetTheme("Dark");
|
||||
break;
|
||||
case 2:
|
||||
if (IsSystemThemeLight()) SetTheme("Light");
|
||||
else SetTheme("Dark");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSystemThemeLight() {
|
||||
var light = false;
|
||||
try {
|
||||
var registryKey = Registry.CurrentUser;
|
||||
var themeKey =
|
||||
registryKey.OpenSubKey("software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
|
||||
var keyValue = 0;
|
||||
if (themeKey != null) keyValue = (int)themeKey.GetValue("SystemUsesLightTheme");
|
||||
if (keyValue == 1) light = true;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return light;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Xml.Linq;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
private StrokeCollection[] strokeCollections = new StrokeCollection[101];
|
||||
private bool[] whiteboadLastModeIsRedo = new bool[101];
|
||||
private StrokeCollection lastTouchDownStrokeCollection = new StrokeCollection();
|
||||
|
||||
public int CurrentWhiteboardIndex = 1;
|
||||
public int WhiteboardTotalCount = 1;
|
||||
private TimeMachineHistory[][] TimeMachineHistories = new TimeMachineHistory[101][]; //最多99页,0用来存储非白板时的墨迹以便还原
|
||||
|
||||
public Color[] BoardBackgroundColors = new Color[6] {
|
||||
Color.FromRgb(39, 39, 42),
|
||||
Color.FromRgb(23, 42, 37),
|
||||
Color.FromRgb(234, 235, 237),
|
||||
Color.FromRgb(15, 23, 42),
|
||||
Color.FromRgb(181, 230, 181),
|
||||
Color.FromRgb(0, 0, 0)
|
||||
};
|
||||
|
||||
public class BoardPageSettings {
|
||||
public BlackboardBackgroundColorEnum BackgroundColor { get; set; } = BlackboardBackgroundColorEnum.White;
|
||||
public BlackboardBackgroundPatternEnum BackgroundPattern { get; set; } = BlackboardBackgroundPatternEnum.None;
|
||||
}
|
||||
|
||||
public List<BoardPageSettings> BoardPagesSettingsList = new List<BoardPageSettings>() {
|
||||
new BoardPageSettings()
|
||||
};
|
||||
|
||||
#region Board Background
|
||||
|
||||
/// <summary>
|
||||
/// 更新白板模式下每頁的背景顏色,可以直接根據當前的<c>CurrentWhiteboardIndex</c>獲取背景配置並更新,也可以自己修改當前的背景顏色
|
||||
/// </summary>
|
||||
/// <param name="id">要修改的背景顏色的ID,傳入null會根據當前的<c>CurrentWhiteboardIndex</c>去讀取有關背景顏色的配置並更新</param>
|
||||
private void UpdateBoardBackground(int? id) {
|
||||
if (id != null) BoardPagesSettingsList[CurrentWhiteboardIndex - 1].BackgroundColor = (BlackboardBackgroundColorEnum)id;
|
||||
var bgC = BoardPagesSettingsList[CurrentWhiteboardIndex - 1].BackgroundColor;
|
||||
if (bgC == BlackboardBackgroundColorEnum.BlackBoardGreen
|
||||
|| bgC == BlackboardBackgroundColorEnum.BlueBlack
|
||||
|| bgC == BlackboardBackgroundColorEnum.GrayBlack
|
||||
|| bgC == BlackboardBackgroundColorEnum.RealBlack) {
|
||||
if (inkColor == 0) lastBoardInkColor = 5;
|
||||
} else {
|
||||
if (inkColor == 5) lastBoardInkColor = 0;
|
||||
}
|
||||
CheckColorTheme(true);
|
||||
UpdateBoardBackgroundPanelDisplayStatus();
|
||||
}
|
||||
|
||||
private void BoardBackgroundColor1Border_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
UpdateBoardBackground(0);
|
||||
}
|
||||
|
||||
private void BoardBackgroundColor2Border_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
UpdateBoardBackground(1);
|
||||
}
|
||||
|
||||
private void BoardBackgroundColor3Border_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
UpdateBoardBackground(2);
|
||||
}
|
||||
|
||||
private void BoardBackgroundColor4Border_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
UpdateBoardBackground(3);
|
||||
}
|
||||
|
||||
private void BoardBackgroundColor5Border_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
UpdateBoardBackground(4);
|
||||
}
|
||||
|
||||
private void BoardBackgroundColor6Border_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
UpdateBoardBackground(5);
|
||||
}
|
||||
|
||||
private void UpdateBoardBackgroundPanelDisplayStatus() {
|
||||
BoardBackgroundColor1Checkbox.Visibility = Visibility.Collapsed;
|
||||
BoardBackgroundColor2Checkbox.Visibility = Visibility.Collapsed;
|
||||
BoardBackgroundColor3Checkbox.Visibility = Visibility.Collapsed;
|
||||
BoardBackgroundColor4Checkbox.Visibility = Visibility.Collapsed;
|
||||
BoardBackgroundColor5Checkbox.Visibility = Visibility.Collapsed;
|
||||
BoardBackgroundColor6Checkbox.Visibility = Visibility.Collapsed;
|
||||
|
||||
if (currentMode == 1) {
|
||||
var index = CurrentWhiteboardIndex - 1;
|
||||
var bg = BoardPagesSettingsList[index];
|
||||
if (bg.BackgroundColor == (BlackboardBackgroundColorEnum)0) BoardBackgroundColor1Checkbox.Visibility = Visibility.Visible;
|
||||
else if (bg.BackgroundColor == (BlackboardBackgroundColorEnum)1) BoardBackgroundColor2Checkbox.Visibility = Visibility.Visible;
|
||||
else if (bg.BackgroundColor == (BlackboardBackgroundColorEnum)2) BoardBackgroundColor3Checkbox.Visibility = Visibility.Visible;
|
||||
else if (bg.BackgroundColor == (BlackboardBackgroundColorEnum)3) BoardBackgroundColor4Checkbox.Visibility = Visibility.Visible;
|
||||
else if (bg.BackgroundColor == (BlackboardBackgroundColorEnum)4) BoardBackgroundColor5Checkbox.Visibility = Visibility.Visible;
|
||||
else if (bg.BackgroundColor == (BlackboardBackgroundColorEnum)5) BoardBackgroundColor6Checkbox.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void SaveStrokes(bool isBackupMain = false) {
|
||||
if (isBackupMain) {
|
||||
var timeMachineHistory = timeMachine.ExportTimeMachineHistory();
|
||||
TimeMachineHistories[0] = timeMachineHistory;
|
||||
timeMachine.ClearStrokeHistory();
|
||||
} else {
|
||||
var timeMachineHistory = timeMachine.ExportTimeMachineHistory();
|
||||
TimeMachineHistories[CurrentWhiteboardIndex] = timeMachineHistory;
|
||||
timeMachine.ClearStrokeHistory();
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearStrokes(bool isErasedByCode) {
|
||||
_currentCommitType = CommitReason.ClearingCanvas;
|
||||
if (isErasedByCode) _currentCommitType = CommitReason.CodeInput;
|
||||
inkCanvas.Strokes.Clear();
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
}
|
||||
|
||||
private void RestoreStrokes(bool isBackupMain = false) {
|
||||
try {
|
||||
if (TimeMachineHistories[CurrentWhiteboardIndex] == null) return; //防止白板打开后不居中
|
||||
if (isBackupMain) {
|
||||
timeMachine.ImportTimeMachineHistory(TimeMachineHistories[0]);
|
||||
foreach (var item in TimeMachineHistories[0]) ApplyHistoryToCanvas(item);
|
||||
} else {
|
||||
timeMachine.ImportTimeMachineHistory(TimeMachineHistories[CurrentWhiteboardIndex]);
|
||||
foreach (var item in TimeMachineHistories[CurrentWhiteboardIndex]) ApplyHistoryToCanvas(item);
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private async void BtnWhiteBoardPageIndex_Click(object sender, EventArgs e) {
|
||||
if (sender == BtnLeftPageListWB) {
|
||||
if (BoardBorderLeftPageListView.Visibility == Visibility.Visible) {
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
|
||||
} else {
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
|
||||
RefreshBlackBoardSidePageListView();
|
||||
AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderLeftPageListView);
|
||||
await Task.Delay(1);
|
||||
ScrollViewToVerticalTop(
|
||||
(ListViewItem)BlackBoardLeftSidePageListView.ItemContainerGenerator.ContainerFromIndex(
|
||||
CurrentWhiteboardIndex - 1), BlackBoardLeftSidePageListScrollViewer);
|
||||
}
|
||||
} else if (sender == BtnRightPageListWB)
|
||||
{
|
||||
if (BoardBorderRightPageListView.Visibility == Visibility.Visible) {
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
|
||||
} else {
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
|
||||
RefreshBlackBoardSidePageListView();
|
||||
AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderRightPageListView);
|
||||
await Task.Delay(1);
|
||||
ScrollViewToVerticalTop(
|
||||
(ListViewItem)BlackBoardRightSidePageListView.ItemContainerGenerator.ContainerFromIndex(
|
||||
CurrentWhiteboardIndex - 1), BlackBoardRightSidePageListScrollViewer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void BtnWhiteBoardSwitchPrevious_Click(object sender, EventArgs e) {
|
||||
if (CurrentWhiteboardIndex <= 1) return;
|
||||
|
||||
SaveStrokes();
|
||||
|
||||
ClearStrokes(true);
|
||||
CurrentWhiteboardIndex--;
|
||||
|
||||
RestoreStrokes();
|
||||
|
||||
UpdateIndexInfoDisplay();
|
||||
UpdateBoardBackground(null);
|
||||
}
|
||||
|
||||
private void BtnWhiteBoardSwitchNext_Click(object sender, EventArgs e) {
|
||||
if (Settings.Automation.IsAutoSaveStrokesAtClear &&
|
||||
inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenshot(true);
|
||||
if (CurrentWhiteboardIndex >= WhiteboardTotalCount) {
|
||||
BtnWhiteBoardAdd_Click(sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
SaveStrokes();
|
||||
|
||||
ClearStrokes(true);
|
||||
CurrentWhiteboardIndex++;
|
||||
|
||||
RestoreStrokes();
|
||||
|
||||
UpdateIndexInfoDisplay();
|
||||
UpdateBoardBackground(null);
|
||||
}
|
||||
|
||||
private void BtnWhiteBoardAdd_Click(object sender, EventArgs e) {
|
||||
if (WhiteboardTotalCount >= 99) return;
|
||||
if (Settings.Automation.IsAutoSaveStrokesAtClear &&
|
||||
inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenshot(true);
|
||||
SaveStrokes();
|
||||
ClearStrokes(true);
|
||||
|
||||
BoardPagesSettingsList.Insert(CurrentWhiteboardIndex, new BoardPageSettings() {
|
||||
BackgroundColor = Settings.Canvas.UseDefaultBackgroundColorForEveryNewAddedBlackboardPage ? Settings.Canvas.BlackboardBackgroundColor : BoardPagesSettingsList[CurrentWhiteboardIndex-1].BackgroundColor,
|
||||
BackgroundPattern = Settings.Canvas.UseDefaultBackgroundPatternForEveryNewAddedBlackboardPage ? Settings.Canvas.BlackboardBackgroundPattern : BoardPagesSettingsList[CurrentWhiteboardIndex - 1].BackgroundPattern,
|
||||
});
|
||||
|
||||
WhiteboardTotalCount++;
|
||||
CurrentWhiteboardIndex++;
|
||||
|
||||
if (CurrentWhiteboardIndex != WhiteboardTotalCount)
|
||||
for (var i = WhiteboardTotalCount; i > CurrentWhiteboardIndex; i--)
|
||||
TimeMachineHistories[i] = TimeMachineHistories[i - 1];
|
||||
|
||||
UpdateIndexInfoDisplay();
|
||||
|
||||
//if (WhiteboardTotalCount >= 99) BtnWhiteBoardAdd.IsEnabled = false;
|
||||
|
||||
if (BlackBoardLeftSidePageListView.Visibility == Visibility.Visible) {
|
||||
RefreshBlackBoardSidePageListView();
|
||||
}
|
||||
|
||||
UpdateBoardBackground(null);
|
||||
}
|
||||
|
||||
private void BtnWhiteBoardDelete_Click(object sender, RoutedEventArgs e) {
|
||||
ClearStrokes(true);
|
||||
|
||||
if (CurrentWhiteboardIndex != WhiteboardTotalCount)
|
||||
for (var i = CurrentWhiteboardIndex; i <= WhiteboardTotalCount; i++)
|
||||
TimeMachineHistories[i] = TimeMachineHistories[i + 1];
|
||||
else
|
||||
CurrentWhiteboardIndex--;
|
||||
|
||||
WhiteboardTotalCount--;
|
||||
|
||||
RestoreStrokes();
|
||||
|
||||
UpdateIndexInfoDisplay();
|
||||
|
||||
//if (WhiteboardTotalCount < 99) BtnWhiteBoardAdd.IsEnabled = true;
|
||||
}
|
||||
|
||||
private bool _whiteboardModePreviousPageButtonEnabled = false;
|
||||
private bool _whiteboardModeNextPageButtonEnabled = false;
|
||||
private bool _whiteboardModeNewPageButtonEnabled = false;
|
||||
private bool _whiteboardModeNewPageButtonMerged = false;
|
||||
|
||||
public bool WhiteboardModePreviousPageButtonEnabled {
|
||||
get => _whiteboardModePreviousPageButtonEnabled;
|
||||
set {
|
||||
_whiteboardModePreviousPageButtonEnabled = value;
|
||||
var geo = new GeometryDrawing[]
|
||||
{ BtnLeftWhiteBoardSwitchPreviousGeometry, BtnRightWhiteBoardSwitchPreviousGeometry };
|
||||
var label = new TextBlock[]
|
||||
{ BtnLeftWhiteBoardSwitchPreviousLabel, BtnRightWhiteBoardSwitchPreviousLabel };
|
||||
var border = new Border[]
|
||||
{ BtnWhiteBoardSwitchPreviousL, BtnWhiteBoardSwitchPreviousR };
|
||||
foreach (var gd in geo)
|
||||
gd.Brush = new SolidColorBrush(Color.FromArgb((byte)(value ? 255 : 127), 24, 24, 27));
|
||||
foreach (var tb in label) tb.Opacity = value ? 1 : 0.5;
|
||||
foreach (var bd in border) bd.IsHitTestVisible = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WhiteboardModeNextPageButtonEnabled {
|
||||
get => _whiteboardModeNextPageButtonEnabled;
|
||||
set {
|
||||
_whiteboardModeNextPageButtonEnabled = value;
|
||||
var geo = new GeometryDrawing[]
|
||||
{ BtnLeftWhiteBoardSwitchNextGeometry, BtnRightWhiteBoardSwitchNextGeometry };
|
||||
var label = new TextBlock[]
|
||||
{ BtnLeftWhiteBoardSwitchNextLabel, BtnRightWhiteBoardSwitchNextLabel };
|
||||
var border = new Border[]
|
||||
{ BtnWhiteBoardSwitchNextL, BtnWhiteBoardSwitchNextR };
|
||||
foreach (var gd in geo)
|
||||
gd.Brush = new SolidColorBrush(Color.FromArgb((byte)(value ? 255 : 127), 24, 24, 27));
|
||||
foreach (var tb in label) tb.Opacity = value ? 1 : 0.5;
|
||||
foreach (var bd in border) bd.IsHitTestVisible = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WhiteboardModeNewPageButtonEnabled {
|
||||
get => _whiteboardModeNewPageButtonEnabled;
|
||||
set {
|
||||
_whiteboardModeNewPageButtonEnabled = value;
|
||||
var geo = new GeometryDrawing[]
|
||||
{ BtnWhiteboardAddGeometryLeft, BtnWhiteboardAddGeometryRight, BtnWhiteboardAddGeometryRightSecondary };
|
||||
var label = new TextBlock[]
|
||||
{ BtnWhiteboardAddTextBlockLeft, BtnWhiteboardAddTextBlockRight, BtnWhiteboardAddTextBlockRightSecondary };
|
||||
var border = new Border[]
|
||||
{ BtnWhiteboardAddLeft, BtnWhiteboardAddRight, BtnWhiteboardAddRightSecondary };
|
||||
foreach (var gd in geo)
|
||||
gd.Brush = new SolidColorBrush(Color.FromArgb((byte)(value ? 255 : 127), 24, 24, 27));
|
||||
foreach (var tb in label) tb.Opacity = value ? 1 : 0.5;
|
||||
foreach (var bd in border) bd.IsHitTestVisible = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WhiteboardModeNewPageButtonMerged {
|
||||
get => _whiteboardModeNewPageButtonMerged;
|
||||
set {
|
||||
_whiteboardModeNewPageButtonMerged = value;
|
||||
BtnWhiteBoardSwitchNextL.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
BtnLeftPageListWB.CornerRadius = value ? new CornerRadius(0, 5, 5, 0) : new CornerRadius(0);
|
||||
BtnWhiteBoardSwitchNextR.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
BtnRightPageListWB.CornerRadius = value ? new CornerRadius(0, 5, 5, 0) : new CornerRadius(0);
|
||||
BtnWhiteboardAddRightSecondary.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateIndexInfoDisplay() {
|
||||
BtnLeftPageListWBTextCount.Text =
|
||||
$"{CurrentWhiteboardIndex}/{WhiteboardTotalCount}";
|
||||
BtnRightPageListWBTextCount.Text =
|
||||
$"{CurrentWhiteboardIndex}/{WhiteboardTotalCount}";
|
||||
|
||||
WhiteboardModePreviousPageButtonEnabled = CurrentWhiteboardIndex > 1;
|
||||
WhiteboardModeNextPageButtonEnabled = CurrentWhiteboardIndex < WhiteboardTotalCount;
|
||||
WhiteboardModeNewPageButtonEnabled = WhiteboardTotalCount < 99;
|
||||
WhiteboardModeNewPageButtonMerged = CurrentWhiteboardIndex == WhiteboardTotalCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
private Border lastBoardToolBtnDownBorder = null;
|
||||
private Border lastBoardSideBtnDownBorder = null;
|
||||
|
||||
private void BoardToolBtnMouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder != null) return;
|
||||
lastBoardToolBtnDownBorder = (Border)sender;
|
||||
if (lastBoardToolBtnDownBorder.Name == "BoardPen") {
|
||||
BoardMouseFeedbakBorder.Margin = new Thickness(60, 0, 0, 0);
|
||||
((Border)BoardMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(0);
|
||||
} else if (lastBoardToolBtnDownBorder.Name == "BoardSelect") {
|
||||
BoardMouseFeedbakBorder.Margin = new Thickness(0);
|
||||
((Border)BoardMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(4.5,0,0,4.5);
|
||||
} else if (lastBoardToolBtnDownBorder.Name == "BoardEraser") {
|
||||
BoardMouseFeedbakBorder.Margin = new Thickness(120, 0, 0, 0);
|
||||
((Border)BoardMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(0);
|
||||
} else if (lastBoardToolBtnDownBorder.Name == "BoardGeometry") {
|
||||
BoardMouseFeedbakBorder.Margin = new Thickness(180, 0, 0, 0);
|
||||
((Border)BoardMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(0);
|
||||
} else if (lastBoardToolBtnDownBorder.Name == "BoardUndo") {
|
||||
BoardMouseFeedbakBorder.Margin = new Thickness(240, 0, 0, 0);
|
||||
((Border)BoardMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(0);
|
||||
} else if (lastBoardToolBtnDownBorder.Name == "BoardRedo") {
|
||||
BoardMouseFeedbakBorder.Margin = new Thickness(300, 0, 0, 0);
|
||||
((Border)BoardMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(0,4.5,4.5,0);
|
||||
}
|
||||
BoardMouseFeedbakBorder.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void BoardSideBtnMouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardSideBtnDownBorder != null) return;
|
||||
lastBoardSideBtnDownBorder = (Border)sender;
|
||||
if (lastBoardSideBtnDownBorder.Name == "BoardBackground") {
|
||||
BoardSideBtnMouseFeedbakBorder.Margin = new Thickness(60, 0, 0, 0);
|
||||
((Border)BoardSideBtnMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(0,4.5,4.5,0);
|
||||
BoardSideBtnMouseFeedbakBorder.Visibility = Visibility.Visible;
|
||||
} else if (lastBoardSideBtnDownBorder.Name == "BoardGesture") {
|
||||
BoardSideBtnMouseFeedbakBorder.Margin = new Thickness(0);
|
||||
((Border)BoardSideBtnMouseFeedbakBorder.Child).CornerRadius = new CornerRadius(4.5,0,0,4.5);
|
||||
BoardSideBtnMouseFeedbakBorder.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
private void BoardToolBtnMouseLeave(object sender, MouseEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder == null) return;
|
||||
lastBoardToolBtnDownBorder = null;
|
||||
BoardMouseFeedbakBorder.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void BoardSideBtnMouseLeave(object sender, MouseEventArgs e) {
|
||||
if (lastBoardSideBtnDownBorder == null) return;
|
||||
lastBoardSideBtnDownBorder = null;
|
||||
BoardSideBtnMouseFeedbakBorder.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void BoardPenMouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder == null) return;
|
||||
BoardToolBtnMouseLeave(sender, null);
|
||||
PenIcon_Click(null,null);
|
||||
}
|
||||
|
||||
private void BoardSelectMouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder == null) return;
|
||||
BoardToolBtnMouseLeave(sender, null);
|
||||
SymbolIconSelect_MouseUp(null,null);
|
||||
}
|
||||
|
||||
private void BoardGestureMouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardSideBtnDownBorder == null) return;
|
||||
BoardSideBtnMouseLeave(sender, null);
|
||||
TwoFingerGestureBorder_MouseUp(null, null);
|
||||
}
|
||||
|
||||
private void BoardChangeBackgroundColorBtn_MouseUp(object sender, RoutedEventArgs e) {
|
||||
if (lastBoardSideBtnDownBorder == null) return;
|
||||
BoardSideBtnMouseLeave(sender, null);
|
||||
UpdateBoardBackgroundPanelDisplayStatus();
|
||||
if (BoardBackgroundPopup.Visibility == Visibility.Visible) {
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBackgroundPopup);
|
||||
} else {
|
||||
AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBackgroundPopup);
|
||||
}
|
||||
}
|
||||
|
||||
private void BoardEraserMouseUp(object sender, RoutedEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder == null) return;
|
||||
BoardToolBtnMouseLeave(sender, null);
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint ||
|
||||
inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke) {
|
||||
if (BoardEraserSizePanel.Visibility == Visibility.Collapsed) {
|
||||
AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardEraserSizePanel);
|
||||
} else {
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
|
||||
}
|
||||
} else {
|
||||
EraserIcon_Click(null,null);
|
||||
}
|
||||
}
|
||||
|
||||
private void BoardGeometryMouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder == null) return;
|
||||
BoardToolBtnMouseLeave(sender, null);
|
||||
ImageDrawShape_MouseUp(null,null);
|
||||
}
|
||||
|
||||
private void BoardUndoMouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder == null) return;
|
||||
BoardToolBtnMouseLeave(sender, null);
|
||||
SymbolIconUndo_MouseUp(null,null);
|
||||
}
|
||||
|
||||
private void BoardRedoMouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBoardToolBtnDownBorder == null) return;
|
||||
BoardToolBtnMouseLeave(sender, null);
|
||||
SymbolIconRedo_MouseUp(null,null);
|
||||
}
|
||||
|
||||
private void BoardEraserIconByStrokes_Click(object sender, RoutedEventArgs e) {
|
||||
//if (BoardEraserByStrokes.Background.ToString() == "#FF679CF4") {
|
||||
// AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardDeleteIcon);
|
||||
//}
|
||||
//else {
|
||||
forceEraser = true;
|
||||
forcePointEraser = false;
|
||||
|
||||
// update tool selection
|
||||
SelectedMode = ICCToolsEnum.EraseByStrokeMode;
|
||||
ForceUpdateToolSelection(null);
|
||||
|
||||
inkCanvas.EraserShape = new EllipseStylusShape(5, 5);
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
|
||||
drawingShapeMode = 0;
|
||||
|
||||
inkCanvas_EditingModeChanged(inkCanvas, null);
|
||||
CancelSingleFingerDragMode();
|
||||
|
||||
HideSubPanels("eraserByStrokes");
|
||||
//}
|
||||
}
|
||||
|
||||
private void BoardSymbolIconDelete_MouseUp(object sender, RoutedEventArgs e) {
|
||||
PenIcon_Click(null, null);
|
||||
SymbolIconDelete_MouseUp(null, null);
|
||||
}
|
||||
private void BoardSymbolIconDeleteInkAndHistories_MouseUp(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PenIcon_Click(null, null);
|
||||
SymbolIconDelete_MouseUp(null, null);
|
||||
if (Settings.Canvas.ClearCanvasAndClearTimeMachine == false) timeMachine.ClearStrokeHistory();
|
||||
}
|
||||
|
||||
private void BoardLaunchEasiCamera_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
ImageBlackboard_MouseUp(null, null);
|
||||
SoftwareLauncher.LaunchEasiCamera("希沃视频展台");
|
||||
}
|
||||
|
||||
private void BoardLaunchDesmos_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
HideSubPanelsImmediately();
|
||||
ImageBlackboard_MouseUp(null, null);
|
||||
Process.Start("https://www.desmos.com/calculator?lang=zh-CN");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,735 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Media;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using Ink_Canvas.Popups;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
private int inkColor = 1;
|
||||
|
||||
private void ColorSwitchCheck() {
|
||||
//HideSubPanels("color");
|
||||
if (GridTransparencyFakeBackground.Background == Brushes.Transparent) {
|
||||
if (currentMode == 1) {
|
||||
currentMode = 0;
|
||||
GridBackgroundCover.Visibility = Visibility.Collapsed;
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
|
||||
}
|
||||
|
||||
BtnHideInkCanvas_Click(null, null);
|
||||
}
|
||||
|
||||
var strokes = inkCanvas.GetSelectedStrokes();
|
||||
if (strokes.Count != 0) {
|
||||
foreach (var stroke in strokes)
|
||||
try {
|
||||
stroke.DrawingAttributes.Color = inkCanvas.DefaultDrawingAttributes.Color;
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
if (DrawingAttributesHistory.Count > 0)
|
||||
{
|
||||
timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
|
||||
DrawingAttributesHistory = new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
foreach (var item in DrawingAttributesHistoryFlag)
|
||||
{
|
||||
item.Value.Clear();
|
||||
}
|
||||
}
|
||||
else {
|
||||
inkCanvas.IsManipulationEnabled = true;
|
||||
drawingShapeMode = 0;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||
CancelSingleFingerDragMode();
|
||||
forceEraser = false;
|
||||
CheckColorTheme();
|
||||
}
|
||||
|
||||
isLongPressSelected = false;
|
||||
}
|
||||
|
||||
private bool isUselightThemeColor = false, isDesktopUselightThemeColor = false;
|
||||
private int penType = 0; // 0是签字笔,1是荧光笔
|
||||
private int lastDesktopInkColor = 1, lastBoardInkColor = 5;
|
||||
private int highlighterColor = 102;
|
||||
|
||||
private void CheckColorTheme(bool changeColorTheme = false) {
|
||||
if (changeColorTheme)
|
||||
if (currentMode != 0) {
|
||||
var bgC = BoardPagesSettingsList[CurrentWhiteboardIndex - 1].BackgroundColor;
|
||||
GridBackgroundCover.Background = new SolidColorBrush(BoardBackgroundColors[(int)bgC]);
|
||||
if (bgC == BlackboardBackgroundColorEnum.BlackBoardGreen
|
||||
|| bgC == BlackboardBackgroundColorEnum.BlueBlack
|
||||
|| bgC == BlackboardBackgroundColorEnum.GrayBlack
|
||||
|| bgC == BlackboardBackgroundColorEnum.RealBlack) {
|
||||
WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
|
||||
WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
|
||||
BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
|
||||
isUselightThemeColor = true;
|
||||
} else {
|
||||
WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(22, 22,22));
|
||||
WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(22, 22, 22));
|
||||
BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(22, 22, 22));
|
||||
isUselightThemeColor = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMode == 0) {
|
||||
isUselightThemeColor = isDesktopUselightThemeColor;
|
||||
inkColor = lastDesktopInkColor;
|
||||
}
|
||||
else {
|
||||
inkColor = lastBoardInkColor;
|
||||
}
|
||||
|
||||
double alpha = inkCanvas.DefaultDrawingAttributes.Color.A;
|
||||
|
||||
if (penType == 0) {
|
||||
if (inkColor == 0) {
|
||||
// Black
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 0, 0, 0);
|
||||
}
|
||||
else if (inkColor == 5) {
|
||||
// White
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 255, 255, 255);
|
||||
}
|
||||
else if (isUselightThemeColor) {
|
||||
if (inkColor == 1)
|
||||
// Red
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 239, 68, 68);
|
||||
else if (inkColor == 2)
|
||||
// Green
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 34, 197, 94);
|
||||
else if (inkColor == 3)
|
||||
// Blue
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 59, 130, 246);
|
||||
else if (inkColor == 4)
|
||||
// Yellow
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 250, 204, 21);
|
||||
else if (inkColor == 6)
|
||||
// Pink
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 236, 72, 153);
|
||||
else if (inkColor == 7)
|
||||
// Teal (亮色)
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 20, 184, 166);
|
||||
else if (inkColor == 8)
|
||||
// Orange (亮色)
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 249, 115, 22);
|
||||
}
|
||||
else {
|
||||
if (inkColor == 1)
|
||||
// Red
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 220, 38, 38);
|
||||
else if (inkColor == 2)
|
||||
// Green
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 22, 163, 74);
|
||||
else if (inkColor == 3)
|
||||
// Blue
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 37, 99, 235);
|
||||
else if (inkColor == 4)
|
||||
// Yellow
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 234, 179, 8);
|
||||
else if (inkColor == 6)
|
||||
// Pink ( Purple )
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 147, 51, 234);
|
||||
else if (inkColor == 7)
|
||||
// Teal (暗色)
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 13, 148, 136);
|
||||
else if (inkColor == 8)
|
||||
// Orange (暗色)
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 234, 88, 12);
|
||||
}
|
||||
}
|
||||
else if (penType == 1) {
|
||||
if (highlighterColor == 100)
|
||||
// Black
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(0, 0, 0);
|
||||
else if (highlighterColor == 101)
|
||||
// White
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(250, 250, 250);
|
||||
else if (highlighterColor == 102)
|
||||
// Red
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(239, 68, 68);
|
||||
else if (highlighterColor == 103)
|
||||
// Yellow
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(253, 224, 71);
|
||||
else if (highlighterColor == 104)
|
||||
// Green
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(74, 222, 128);
|
||||
else if (highlighterColor == 105)
|
||||
// Zinc
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(113, 113, 122);
|
||||
else if (highlighterColor == 106)
|
||||
// Blue
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(59, 130, 246);
|
||||
else if (highlighterColor == 107)
|
||||
// Purple
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(168, 85, 247);
|
||||
else if (highlighterColor == 108)
|
||||
// teal
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(45, 212, 191);
|
||||
else if (highlighterColor == 109)
|
||||
// Orange
|
||||
inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(249, 115, 22);
|
||||
}
|
||||
|
||||
if (isUselightThemeColor) {
|
||||
// 亮系
|
||||
// 亮色的红色
|
||||
BorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(239, 68, 68));
|
||||
BoardBorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(239, 68, 68));
|
||||
// 亮色的绿色
|
||||
BorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(34, 197, 94));
|
||||
BoardBorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(34, 197, 94));
|
||||
// 亮色的蓝色
|
||||
BorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(59, 130, 246));
|
||||
BoardBorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(59, 130, 246));
|
||||
// 亮色的黄色
|
||||
BorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(250, 204, 21));
|
||||
BoardBorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(250, 204, 21));
|
||||
// 亮色的粉色
|
||||
BorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(236, 72, 153));
|
||||
BoardBorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(236, 72, 153));
|
||||
// 亮色的Teal
|
||||
BorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(20, 184, 166));
|
||||
BoardBorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(20, 184, 166));
|
||||
// 亮色的Orange
|
||||
BorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(249, 115, 22));
|
||||
BoardBorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(249, 115, 22));
|
||||
|
||||
var newImageSource = new BitmapImage();
|
||||
newImageSource.BeginInit();
|
||||
newImageSource.UriSource = new Uri("/Resources/Icons-Fluent/ic_fluent_weather_moon_24_regular.png",
|
||||
UriKind.RelativeOrAbsolute);
|
||||
newImageSource.EndInit();
|
||||
ColorThemeSwitchIcon.Source = newImageSource;
|
||||
BoardColorThemeSwitchIcon.Source = newImageSource;
|
||||
|
||||
ColorThemeSwitchTextBlock.Text = "暗系";
|
||||
BoardColorThemeSwitchTextBlock.Text = "暗系";
|
||||
}
|
||||
else {
|
||||
// 暗系
|
||||
// 暗色的红色
|
||||
BorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(220, 38, 38));
|
||||
BoardBorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(220, 38, 38));
|
||||
// 暗色的绿色
|
||||
BorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(22, 163, 74));
|
||||
BoardBorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(22, 163, 74));
|
||||
// 暗色的蓝色
|
||||
BorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
|
||||
BoardBorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
|
||||
// 暗色的黄色
|
||||
BorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(234, 179, 8));
|
||||
BoardBorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(234, 179, 8));
|
||||
// 暗色的紫色对应亮色的粉色
|
||||
BorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(147, 51, 234));
|
||||
BoardBorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(147, 51, 234));
|
||||
// 暗色的Teal
|
||||
BorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(13, 148, 136));
|
||||
BoardBorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(13, 148, 136));
|
||||
// 暗色的Orange
|
||||
BorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(234, 88, 12));
|
||||
BoardBorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(234, 88, 12));
|
||||
|
||||
var newImageSource = new BitmapImage();
|
||||
newImageSource.BeginInit();
|
||||
newImageSource.UriSource = new Uri("/Resources/Icons-Fluent/ic_fluent_weather_sunny_24_regular.png",
|
||||
UriKind.RelativeOrAbsolute);
|
||||
newImageSource.EndInit();
|
||||
ColorThemeSwitchIcon.Source = newImageSource;
|
||||
BoardColorThemeSwitchIcon.Source = newImageSource;
|
||||
|
||||
ColorThemeSwitchTextBlock.Text = "亮系";
|
||||
BoardColorThemeSwitchTextBlock.Text = "亮系";
|
||||
}
|
||||
|
||||
// 改变选中提示
|
||||
ViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorPinkContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
|
||||
ViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
|
||||
|
||||
BoardViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorPinkContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
|
||||
BoardViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
|
||||
|
||||
HighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Collapsed;
|
||||
|
||||
BoardHighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Collapsed;
|
||||
|
||||
switch (inkColor) {
|
||||
case 0:
|
||||
ViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
|
||||
BoardViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 1:
|
||||
ViewboxBtnColorRedContent.Visibility = Visibility.Visible;
|
||||
BoardViewboxBtnColorRedContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 2:
|
||||
ViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
|
||||
BoardViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 3:
|
||||
ViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
|
||||
BoardViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 4:
|
||||
ViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
|
||||
BoardViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 5:
|
||||
ViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
|
||||
BoardViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 6:
|
||||
ViewboxBtnColorPinkContent.Visibility = Visibility.Visible;
|
||||
BoardViewboxBtnColorPinkContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 7:
|
||||
ViewboxBtnColorTealContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 8:
|
||||
ViewboxBtnColorOrangeContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (highlighterColor) {
|
||||
case 100:
|
||||
HighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 101:
|
||||
HighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 102:
|
||||
HighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 103:
|
||||
HighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 104:
|
||||
HighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 105:
|
||||
HighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 106:
|
||||
HighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 107:
|
||||
HighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 108:
|
||||
HighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case 109:
|
||||
HighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Visible;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckLastColor(int inkColor, bool isHighlighter = false) {
|
||||
if (isHighlighter == true) {
|
||||
highlighterColor = inkColor;
|
||||
}
|
||||
else {
|
||||
if (currentMode == 0) lastDesktopInkColor = inkColor;
|
||||
else lastBoardInkColor = inkColor;
|
||||
}
|
||||
}
|
||||
|
||||
private async void CheckPenTypeUIState() {
|
||||
if (penType == 0) {
|
||||
DefaultPenPropsPanel.Visibility = Visibility.Visible;
|
||||
DefaultPenColorsPanel.Visibility = Visibility.Visible;
|
||||
HighlighterPenColorsPanel.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenPropsPanel.Visibility = Visibility.Collapsed;
|
||||
DefaultPenTabButton.Opacity = 1;
|
||||
DefaultPenTabButtonText.FontWeight = FontWeights.Bold;
|
||||
DefaultPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
|
||||
DefaultPenTabButtonText.FontSize = 9.5;
|
||||
DefaultPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
|
||||
DefaultPenTabButtonIndicator.Visibility = Visibility.Visible;
|
||||
HighlightPenTabButton.Opacity = 0.9;
|
||||
HighlightPenTabButtonText.FontWeight = FontWeights.Normal;
|
||||
HighlightPenTabButtonText.FontSize = 9;
|
||||
HighlightPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
|
||||
HighlightPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
|
||||
HighlightPenTabButtonIndicator.Visibility = Visibility.Collapsed;
|
||||
|
||||
BoardDefaultPenPropsPanel.Visibility = Visibility.Visible;
|
||||
BoardDefaultPenColorsPanel.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenColorsPanel.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenPropsPanel.Visibility = Visibility.Collapsed;
|
||||
BoardDefaultPenTabButton.Opacity = 1;
|
||||
BoardDefaultPenTabButtonText.FontWeight = FontWeights.Bold;
|
||||
BoardDefaultPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
|
||||
BoardDefaultPenTabButtonText.FontSize = 9.5;
|
||||
BoardDefaultPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
|
||||
BoardDefaultPenTabButtonIndicator.Visibility = Visibility.Visible;
|
||||
BoardHighlightPenTabButton.Opacity = 0.9;
|
||||
BoardHighlightPenTabButtonText.FontWeight = FontWeights.Normal;
|
||||
BoardHighlightPenTabButtonText.FontSize = 9;
|
||||
BoardHighlightPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
|
||||
BoardHighlightPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
|
||||
BoardHighlightPenTabButtonIndicator.Visibility = Visibility.Collapsed;
|
||||
|
||||
// PenPalette.Margin = new Thickness(-160, -200, -33, 32);
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation
|
||||
{
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = PenPalette.Margin,
|
||||
To = new Thickness(-160, -200, -33, 32),
|
||||
EasingFunction = new CubicEase()
|
||||
};
|
||||
PenPalette.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation
|
||||
{
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = PenPalette.Margin,
|
||||
To = new Thickness(-160, -200, -33, 50),
|
||||
EasingFunction = new CubicEase()
|
||||
};
|
||||
BoardPenPaletteGrid.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => { PenPalette.Margin = new Thickness(-160, -200, -33, 32); });
|
||||
|
||||
await Dispatcher.InvokeAsync(() => { BoardPenPaletteGrid.Margin = new Thickness(-160, -200, -33, 50); });
|
||||
}
|
||||
else if (penType == 1) {
|
||||
DefaultPenPropsPanel.Visibility = Visibility.Collapsed;
|
||||
DefaultPenColorsPanel.Visibility = Visibility.Collapsed;
|
||||
HighlighterPenColorsPanel.Visibility = Visibility.Visible;
|
||||
HighlighterPenPropsPanel.Visibility = Visibility.Visible;
|
||||
DefaultPenTabButton.Opacity = 0.9;
|
||||
DefaultPenTabButtonText.FontWeight = FontWeights.Normal;
|
||||
DefaultPenTabButtonText.FontSize = 9;
|
||||
DefaultPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
|
||||
DefaultPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
|
||||
DefaultPenTabButtonIndicator.Visibility = Visibility.Collapsed;
|
||||
HighlightPenTabButton.Opacity = 1;
|
||||
HighlightPenTabButtonText.FontWeight = FontWeights.Bold;
|
||||
HighlightPenTabButtonText.FontSize = 9.5;
|
||||
HighlightPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
|
||||
HighlightPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
|
||||
HighlightPenTabButtonIndicator.Visibility = Visibility.Visible;
|
||||
|
||||
BoardDefaultPenPropsPanel.Visibility = Visibility.Collapsed;
|
||||
BoardDefaultPenColorsPanel.Visibility = Visibility.Collapsed;
|
||||
BoardHighlighterPenColorsPanel.Visibility = Visibility.Visible;
|
||||
BoardHighlighterPenPropsPanel.Visibility = Visibility.Visible;
|
||||
BoardDefaultPenTabButton.Opacity = 0.9;
|
||||
BoardDefaultPenTabButtonText.FontWeight = FontWeights.Normal;
|
||||
BoardDefaultPenTabButtonText.FontSize = 9;
|
||||
BoardDefaultPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
|
||||
BoardDefaultPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
|
||||
BoardDefaultPenTabButtonIndicator.Visibility = Visibility.Collapsed;
|
||||
BoardHighlightPenTabButton.Opacity = 1;
|
||||
BoardHighlightPenTabButtonText.FontWeight = FontWeights.Bold;
|
||||
BoardHighlightPenTabButtonText.FontSize = 9.5;
|
||||
BoardHighlightPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
|
||||
BoardHighlightPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
|
||||
BoardHighlightPenTabButtonIndicator.Visibility = Visibility.Visible;
|
||||
|
||||
// PenPalette.Margin = new Thickness(-160, -157, -33, 32);
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation
|
||||
{
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = PenPalette.Margin,
|
||||
To = new Thickness(-160, -157, -33, 32),
|
||||
EasingFunction = new CubicEase()
|
||||
};
|
||||
PenPalette.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
|
||||
await Dispatcher.InvokeAsync(() => {
|
||||
var marginAnimation = new ThicknessAnimation
|
||||
{
|
||||
Duration = TimeSpan.FromSeconds(0.1),
|
||||
From = PenPalette.Margin,
|
||||
To = new Thickness(-160, -154, -33, 50),
|
||||
EasingFunction = new CubicEase()
|
||||
};
|
||||
BoardPenPaletteGrid.BeginAnimation(MarginProperty, marginAnimation);
|
||||
});
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
await Dispatcher.InvokeAsync(() => { PenPalette.Margin = new Thickness(-160, -157, -33, 32); });
|
||||
|
||||
await Dispatcher.InvokeAsync(() => { BoardPenPaletteGrid.Margin = new Thickness(-160, -154, -33, 50); });
|
||||
}
|
||||
}
|
||||
|
||||
private void SwitchToDefaultPen(object sender, MouseButtonEventArgs e) {
|
||||
penType = 0;
|
||||
CheckPenTypeUIState();
|
||||
CheckColorTheme();
|
||||
drawingAttributes.Width = Settings.Canvas.InkWidth;
|
||||
drawingAttributes.Height = Settings.Canvas.InkWidth;
|
||||
drawingAttributes.StylusTip = StylusTip.Ellipse;
|
||||
drawingAttributes.IsHighlighter = false;
|
||||
}
|
||||
|
||||
private void SwitchToHighlighterPen(object sender, MouseButtonEventArgs e) {
|
||||
penType = 1;
|
||||
CheckPenTypeUIState();
|
||||
CheckColorTheme();
|
||||
drawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2;
|
||||
drawingAttributes.Height = Settings.Canvas.HighlighterWidth;
|
||||
drawingAttributes.StylusTip = StylusTip.Rectangle;
|
||||
drawingAttributes.IsHighlighter = true;
|
||||
}
|
||||
|
||||
private void BtnColorBlack_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(0);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorRed_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(1);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorGreen_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(2);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorBlue_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(3);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorYellow_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(4);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorWhite_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(5);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorPink_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(6);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorOrange_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(8);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnColorTeal_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(7);
|
||||
forceEraser = false;
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorBlack_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(100, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorWhite_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(101, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorRed_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(102, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorYellow_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(103, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorGreen_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(104, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorZinc_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(105, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorBlue_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(106, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorPurple_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(107, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorTeal_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(108, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void BtnHighlighterColorOrange_Click(object sender, RoutedEventArgs e) {
|
||||
CheckLastColor(109, true);
|
||||
penType = 1;
|
||||
forceEraser = false;
|
||||
CheckPenTypeUIState();
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private Color StringToColor(string colorStr) {
|
||||
var argb = new byte[4];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var charArray = colorStr.Substring(i * 2 + 1, 2).ToCharArray();
|
||||
var b1 = toByte(charArray[0]);
|
||||
var b2 = toByte(charArray[1]);
|
||||
argb[i] = (byte)(b2 | (b1 << 4));
|
||||
}
|
||||
|
||||
return Color.FromArgb(argb[0], argb[1], argb[2], argb[3]); //#FFFFFFFF
|
||||
}
|
||||
|
||||
private static byte toByte(char c) {
|
||||
var b = (byte)"0123456789ABCDEF".IndexOf(c);
|
||||
return b;
|
||||
}
|
||||
|
||||
#region PenPaletteV2
|
||||
|
||||
private void PenPaletteV2Init() {
|
||||
FloatingToolBarV2.PenPaletteV2_ColorSelectionChanged += PenpaletteV2_ColorSelectionChanged;
|
||||
FloatingToolBarV2.PenPaletteV2_ColorModeChanged += PenpaletteV2_ColorModeChanged;
|
||||
FloatingToolBarV2.PenPaletteV2_CustomColorChanged += PenpaletteV2_CustomColorChanged;
|
||||
FloatingToolBarV2.PenPaletteV2_PenModeChanged += PenpaletteV2_PenModeChanged;
|
||||
FloatingToolBarV2.PenPaletteV2.SelectedColor = ColorPalette.ColorPaletteColor.ColorRed;
|
||||
}
|
||||
|
||||
private void PenpaletteV2_ColorSelectionChanged(object sender, ColorPalette.ColorSelectionChangedEventArgs e) {
|
||||
if (e.TriggerMode == ColorPalette.TriggerMode.TriggeredByCode) return;
|
||||
drawingAttributes.Color = FloatingToolBarV2.PenPaletteV2.GetColor(e.NowColor, false, null);
|
||||
}
|
||||
|
||||
private void PenpaletteV2_ColorModeChanged(object sender, ColorPalette.ColorModeChangedEventArgs e) {
|
||||
if (e.TriggerMode == ColorPalette.TriggerMode.TriggeredByCode) return;
|
||||
drawingAttributes.Color = FloatingToolBarV2.PenPaletteV2.GetColor(FloatingToolBarV2.PenPaletteV2.SelectedColor, false, null);
|
||||
}
|
||||
|
||||
private void PenpaletteV2_CustomColorChanged(object sender, ColorPalette.CustomColorChangedEventArgs e) {
|
||||
if (e.TriggerMode == ColorPalette.TriggerMode.TriggeredByCode) return;
|
||||
if (FloatingToolBarV2.PenPaletteV2.SelectedColor == ColorPalette.ColorPaletteColor.ColorCustom)
|
||||
drawingAttributes.Color = e.NowColor??new Color();
|
||||
}
|
||||
|
||||
private void PenpaletteV2_PenModeChanged(object sender, ColorPalette.PenModeChangedEventArgs e) {
|
||||
penType = e.NowMode == ColorPalette.PenMode.HighlighterMode ? 1 : 0;
|
||||
drawingAttributes.Width = e.NowMode == ColorPalette.PenMode.HighlighterMode ? Settings.Canvas.HighlighterWidth / 2 : Settings.Canvas.InkWidth;
|
||||
drawingAttributes.Height = e.NowMode == ColorPalette.PenMode.HighlighterMode ? Settings.Canvas.HighlighterWidth : Settings.Canvas.InkWidth;
|
||||
drawingAttributes.StylusTip = e.NowMode == ColorPalette.PenMode.HighlighterMode ? StylusTip.Rectangle : StylusTip.Ellipse;
|
||||
drawingAttributes.IsHighlighter = e.NowMode == ColorPalette.PenMode.HighlighterMode;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:modern="http://schemas.inkore.net/lib/ui/wpf/modern">
|
||||
<ContextMenu x:Key="StrokesSelectionMoreMenuButtonContextMenu" StaysOpen="False">
|
||||
<MenuItem Name="SSMMBCM_CopyAsISF">
|
||||
<MenuItem.Header>
|
||||
<modern:SimpleStackPanel Orientation="Horizontal" Margin="-4,0,0,0">
|
||||
<TextBlock Name="SSMMBCM_CopyAsISF_HeaderText" FontSize="14" VerticalAlignment="Center" Foreground="#18181b" Text="复制墨迹到剪切板" />
|
||||
<modern:SimpleStackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="4" Margin="16,0,0,0">
|
||||
<Border Padding="4,2,4,1" Background="#e4e4e7" BorderBrush="#a1a1aa" BorderThickness="1" CornerRadius="2.5">
|
||||
<TextBlock FontSize="8" Foreground="#3f3f46" FontWeight="Bold" Text="CTRL" />
|
||||
</Border>
|
||||
<TextBlock FontSize="10" Foreground="#3f3f46" Text="+" />
|
||||
<Border Padding="4,2,4,1" Background="#e4e4e7" BorderBrush="#a1a1aa" BorderThickness="1" CornerRadius="2.5">
|
||||
<TextBlock FontSize="8" Foreground="#3f3f46" FontWeight="Bold" Text="C" />
|
||||
</Border>
|
||||
</modern:SimpleStackPanel>
|
||||
</modern:SimpleStackPanel>
|
||||
</MenuItem.Header>
|
||||
<MenuItem.Icon>
|
||||
<Image Width="28" Height="28" Margin="-2">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#27272a" Geometry="F0 M24,24z M0,0z M4,5C4,4.45228,4.45228,4,5,4L15,4C15.1876,4 15.266,4.04268 15.3156,4.07864 15.3868,4.13032 15.4886,4.23877 15.626,4.486 15.8945,4.96868 16.5033,5.14237 16.986,4.87396 17.4687,4.60554 17.6424,3.99667 17.374,3.514 17.1694,3.14623 16.8962,2.75468 16.4904,2.46011 16.063,2.14982 15.5624,2 15,2L5,2C3.34772,2,2,3.34772,2,5L2,15 2,15.0024C2.00128,15.5315 2.1422,16.0508 2.40853,16.5079 2.67485,16.965 3.05714,17.3437 3.51674,17.6057 3.99654,17.8793 4.60722,17.7121 4.88075,17.2323 5.15427,16.7525 4.98705,16.1418 4.50726,15.8683 4.35355,15.7806 4.2257,15.654 4.13662,15.5011 4.04772,15.3485 4.0006,15.1752 4,14.9986L4,5z M8.48825,8.48825C8.80088,8.17563,9.22488,8,9.667,8L18.333,8C18.5519,8 18.7687,8.04312 18.9709,8.12689 19.1732,8.21067 19.357,8.33346 19.5117,8.48825 19.6665,8.64305 19.7893,8.82682 19.8731,9.02907 19.9569,9.23132 20,9.44808 20,9.667L20,18.333C20,18.5519 19.9569,18.7687 19.8731,18.9709 19.7893,19.1732 19.6665,19.3569 19.5117,19.5117 19.3569,19.6665 19.1732,19.7893 18.9709,19.8731 18.7687,19.9569 18.5519,20 18.333,20L9.667,20C9.44808,20 9.23132,19.9569 9.02907,19.8731 8.82682,19.7893 8.64305,19.6665 8.48825,19.5117 8.33346,19.357 8.21067,19.1732 8.12689,18.9709 8.04312,18.7687 8,18.5519 8,18.333L8,9.667C8,9.22488,8.17563,8.80088,8.48825,8.48825z M9.667,6C8.69445,6 7.76174,6.38634 7.07404,7.07404 6.38634,7.76174 6,8.69445 6,9.667L6,18.333C6,18.8146 6.09485,19.2914 6.27913,19.7363 6.46342,20.1812 6.73353,20.5854 7.07404,20.926 7.41455,21.2665 7.8188,21.5366 8.2637,21.7209 8.7086,21.9052 9.18544,22 9.667,22L18.333,22C18.8146,22 19.2914,21.9052 19.7363,21.7209 20.1812,21.5366 20.5854,21.2665 20.926,20.926 21.2665,20.5854 21.5366,20.1812 21.7209,19.7363 21.9052,19.2914 22,18.8146 22,18.333L22,9.667C22,9.18544 21.9052,8.7086 21.7209,8.2637 21.5366,7.8188 21.2665,7.41455 20.926,7.07404 20.5854,6.73353 20.1812,6.46342 19.7363,6.27913 19.2914,6.09485 18.8146,6 18.333,6L9.667,6z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Name="SSMMBCM_CopyAsPNG">
|
||||
<MenuItem.Header>
|
||||
<modern:SimpleStackPanel Orientation="Horizontal" Margin="-4,0,0,0">
|
||||
<TextBlock Name="SSMMBCM_CopyAsPNG_HeaderText" FontSize="14" VerticalAlignment="Center" Foreground="#18181b" Text="复制墨迹为PNG" />
|
||||
</modern:SimpleStackPanel>
|
||||
</MenuItem.Header>
|
||||
<MenuItem.Icon>
|
||||
<Image Width="28" Height="28" Margin="-2">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#27272a" Geometry="F0 M24,24z M0,0z M4,5C4,4.45228,4.45228,4,5,4L15,4C15.1876,4 15.266,4.04268 15.3156,4.07864 15.3868,4.13032 15.4886,4.23877 15.626,4.486 15.8945,4.96868 16.5033,5.14237 16.986,4.87396 17.4687,4.60554 17.6424,3.99667 17.374,3.514 17.1694,3.14623 16.8962,2.75468 16.4904,2.46011 16.063,2.14982 15.5624,2 15,2L5,2C3.34772,2,2,3.34772,2,5L2,15 2,15.0024C2.00128,15.5315 2.1422,16.0508 2.40853,16.5079 2.67485,16.965 3.05714,17.3437 3.51674,17.6057 3.99654,17.8793 4.60722,17.7121 4.88075,17.2323 5.15427,16.7525 4.98705,16.1418 4.50726,15.8683 4.35355,15.7806 4.2257,15.654 4.13662,15.5011 4.04772,15.3485 4.0006,15.1752 4,14.9986L4,5z M8.48825,8.48825C8.80088,8.17563,9.22488,8,9.667,8L18.333,8C18.5519,8 18.7687,8.04312 18.9709,8.12689 19.1732,8.21067 19.357,8.33346 19.5117,8.48825 19.6665,8.64305 19.7893,8.82682 19.8731,9.02907 19.9569,9.23132 20,9.44808 20,9.667L20,18.333C20,18.5519 19.9569,18.7687 19.8731,18.9709 19.7893,19.1732 19.6665,19.3569 19.5117,19.5117 19.3569,19.6665 19.1732,19.7893 18.9709,19.8731 18.7687,19.9569 18.5519,20 18.333,20L9.667,20C9.44808,20 9.23132,19.9569 9.02907,19.8731 8.82682,19.7893 8.64305,19.6665 8.48825,19.5117 8.33346,19.357 8.21067,19.1732 8.12689,18.9709 8.04312,18.7687 8,18.5519 8,18.333L8,9.667C8,9.22488,8.17563,8.80088,8.48825,8.48825z M9.667,6C8.69445,6 7.76174,6.38634 7.07404,7.07404 6.38634,7.76174 6,8.69445 6,9.667L6,18.333C6,18.8146 6.09485,19.2914 6.27913,19.7363 6.46342,20.1812 6.73353,20.5854 7.07404,20.926 7.41455,21.2665 7.8188,21.5366 8.2637,21.7209 8.7086,21.9052 9.18544,22 9.667,22L18.333,22C18.8146,22 19.2914,21.9052 19.7363,21.7209 20.1812,21.5366 20.5854,21.2665 20.926,20.926 21.2665,20.5854 21.5366,20.1812 21.7209,19.7363 21.9052,19.2914 22,18.8146 22,18.333L22,9.667C22,9.18544 21.9052,8.7086 21.7209,8.2637 21.5366,7.8188 21.2665,7.41455 20.926,7.07404 20.5854,6.73353 20.1812,6.46342 19.7363,6.27913 19.2914,6.09485 18.8146,6 18.333,6L9.667,6z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Name="SSMMBCM_CopyAsSVG">
|
||||
<MenuItem.Header>
|
||||
<modern:SimpleStackPanel Orientation="Horizontal" Margin="-4,0,0,0">
|
||||
<TextBlock Name="SSMMBCM_CopyAsSVG_HeaderText" FontSize="14" VerticalAlignment="Center" Foreground="#18181b" Text="复制墨迹为SVG" />
|
||||
</modern:SimpleStackPanel>
|
||||
</MenuItem.Header>
|
||||
<MenuItem.Icon>
|
||||
<Image Width="28" Height="28" Margin="-2">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#27272a" Geometry="F0 M24,24z M0,0z M4,5C4,4.45228,4.45228,4,5,4L15,4C15.1876,4 15.266,4.04268 15.3156,4.07864 15.3868,4.13032 15.4886,4.23877 15.626,4.486 15.8945,4.96868 16.5033,5.14237 16.986,4.87396 17.4687,4.60554 17.6424,3.99667 17.374,3.514 17.1694,3.14623 16.8962,2.75468 16.4904,2.46011 16.063,2.14982 15.5624,2 15,2L5,2C3.34772,2,2,3.34772,2,5L2,15 2,15.0024C2.00128,15.5315 2.1422,16.0508 2.40853,16.5079 2.67485,16.965 3.05714,17.3437 3.51674,17.6057 3.99654,17.8793 4.60722,17.7121 4.88075,17.2323 5.15427,16.7525 4.98705,16.1418 4.50726,15.8683 4.35355,15.7806 4.2257,15.654 4.13662,15.5011 4.04772,15.3485 4.0006,15.1752 4,14.9986L4,5z M8.48825,8.48825C8.80088,8.17563,9.22488,8,9.667,8L18.333,8C18.5519,8 18.7687,8.04312 18.9709,8.12689 19.1732,8.21067 19.357,8.33346 19.5117,8.48825 19.6665,8.64305 19.7893,8.82682 19.8731,9.02907 19.9569,9.23132 20,9.44808 20,9.667L20,18.333C20,18.5519 19.9569,18.7687 19.8731,18.9709 19.7893,19.1732 19.6665,19.3569 19.5117,19.5117 19.3569,19.6665 19.1732,19.7893 18.9709,19.8731 18.7687,19.9569 18.5519,20 18.333,20L9.667,20C9.44808,20 9.23132,19.9569 9.02907,19.8731 8.82682,19.7893 8.64305,19.6665 8.48825,19.5117 8.33346,19.357 8.21067,19.1732 8.12689,18.9709 8.04312,18.7687 8,18.5519 8,18.333L8,9.667C8,9.22488,8.17563,8.80088,8.48825,8.48825z M9.667,6C8.69445,6 7.76174,6.38634 7.07404,7.07404 6.38634,7.76174 6,8.69445 6,9.667L6,18.333C6,18.8146 6.09485,19.2914 6.27913,19.7363 6.46342,20.1812 6.73353,20.5854 7.07404,20.926 7.41455,21.2665 7.8188,21.5366 8.2637,21.7209 8.7086,21.9052 9.18544,22 9.667,22L18.333,22C18.8146,22 19.2914,21.9052 19.7363,21.7209 20.1812,21.5366 20.5854,21.2665 20.926,20.926 21.2665,20.5854 21.5366,20.1812 21.7209,19.7363 21.9052,19.2914 22,18.8146 22,18.333L22,9.667C22,9.18544 21.9052,8.7086 21.7209,8.2637 21.5366,7.8188 21.2665,7.41455 20.926,7.07404 20.5854,6.73353 20.1812,6.46342 19.7363,6.27913 19.2914,6.09485 18.8146,6 18.333,6L9.667,6z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Ink_Canvas.Helpers;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
public bool isUsingGeometryEraser = false;
|
||||
private IncrementalStrokeHitTester hitTester = null;
|
||||
|
||||
public double eraserWidth = 64;
|
||||
public bool isEraserCircleShape = false;
|
||||
public bool isUsingStrokesEraser = false;
|
||||
|
||||
private Matrix scaleMatrix = new Matrix();
|
||||
|
||||
private void EraserOverlay_Loaded(object sender, RoutedEventArgs e) {
|
||||
var bd = (Border)sender;
|
||||
bd.StylusDown += ((o, args) => {
|
||||
e.Handled = true;
|
||||
if (args.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) ((Border)o).CaptureStylus();
|
||||
EraserOverlay_PointerDown(sender);
|
||||
});
|
||||
bd.StylusUp += ((o, args) => {
|
||||
e.Handled = true;
|
||||
if (args.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) ((Border)o).ReleaseStylusCapture();
|
||||
EraserOverlay_PointerUp(sender);
|
||||
});
|
||||
bd.StylusMove += ((o, args) => {
|
||||
e.Handled = true;
|
||||
EraserOverlay_PointerMove(sender, args.GetPosition(Main_Grid));
|
||||
});
|
||||
bd.MouseDown += ((o, args) => {
|
||||
((Border)o).CaptureMouse();
|
||||
EraserOverlay_PointerDown(sender);
|
||||
});
|
||||
bd.MouseUp += ((o, args) => {
|
||||
((Border)o).ReleaseMouseCapture();
|
||||
EraserOverlay_PointerUp(sender);
|
||||
});
|
||||
bd.MouseMove += ((o, args) => {
|
||||
EraserOverlay_PointerMove(sender, args.GetPosition(Main_Grid));
|
||||
});
|
||||
bd.StylusButtonUp += (o, args) => {
|
||||
Trace.WriteLine("ButtonUp!!!!!");
|
||||
};
|
||||
}
|
||||
|
||||
private void EraserOverlay_PointerDown(object sender) {
|
||||
if (isUsingGeometryEraser) return;
|
||||
|
||||
// lock
|
||||
isUsingGeometryEraser = true;
|
||||
|
||||
// caculate height
|
||||
var _h = eraserWidth * 56 / 38;
|
||||
|
||||
// init hittester
|
||||
hitTester = inkCanvas.Strokes.GetIncrementalStrokeHitTester(new RectangleStylusShape(
|
||||
eraserWidth, _h));
|
||||
hitTester.StrokeHit += EraserGeometry_StrokeHit;
|
||||
|
||||
// eraser bitmap cache
|
||||
EraserOverlay_DrawingVisual.CacheMode = new BitmapCache();
|
||||
|
||||
// caculate scale matrix
|
||||
var scaleX = eraserWidth / 38;
|
||||
var scaleY = _h / 56;
|
||||
scaleMatrix = new Matrix();
|
||||
scaleMatrix.ScaleAt(scaleX,scaleY,0,0);
|
||||
}
|
||||
|
||||
private void EraserOverlay_PointerUp(object sender) {
|
||||
if (!isUsingGeometryEraser) return;
|
||||
|
||||
// unlock
|
||||
isUsingGeometryEraser = false;
|
||||
|
||||
// release capture
|
||||
((Border)sender).ReleaseMouseCapture();
|
||||
|
||||
// hide eraser feedback
|
||||
var ct = EraserOverlay_DrawingVisual.DrawingVisual.RenderOpen();
|
||||
ct.DrawRectangle(new SolidColorBrush(Colors.Transparent),null,new Rect(0,0,ActualWidth,ActualHeight));
|
||||
ct.Close();
|
||||
|
||||
// end hittest
|
||||
hitTester.EndHitTesting();
|
||||
|
||||
// commit stroke erased history
|
||||
// 我有受虐倾向,被这个bug硬控10秒钟,请大家嘲笑我
|
||||
if (ReplacedStroke != null || AddedStroke != null) {
|
||||
timeMachine.CommitStrokeEraseHistory(ReplacedStroke, AddedStroke);
|
||||
AddedStroke = null;
|
||||
ReplacedStroke = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void EraserGeometry_StrokeHit(object sender,
|
||||
StrokeHitEventArgs args) {
|
||||
StrokeCollection eraseResult =
|
||||
args.GetPointEraseResults();
|
||||
StrokeCollection strokesToReplace = new StrokeCollection {
|
||||
args.HitStroke
|
||||
};
|
||||
|
||||
// replace the old stroke with the new one.
|
||||
var filtered_2replace = strokesToReplace.Where(stroke => !stroke.ContainsPropertyData(IsLockGuid));
|
||||
var filtered2Replace = filtered_2replace as Stroke[] ?? filtered_2replace.ToArray();
|
||||
if (!filtered2Replace.Any()) return;
|
||||
var filtered_result = eraseResult.Where(stroke=>!stroke.ContainsPropertyData(IsLockGuid));
|
||||
var filteredResult = filtered_result as Stroke[] ?? filtered_result.ToArray();
|
||||
if (filteredResult.Any()) {
|
||||
inkCanvas.Strokes.Replace(new StrokeCollection(filtered2Replace), new StrokeCollection(filteredResult));
|
||||
} else {
|
||||
inkCanvas.Strokes.Remove(new StrokeCollection(filtered2Replace));
|
||||
}
|
||||
}
|
||||
|
||||
private void EraserOverlay_PointerMove(object sender, Point pt) {
|
||||
if (!isUsingGeometryEraser) return;
|
||||
|
||||
if (isUsingStrokesEraser) {
|
||||
var _filtered = inkCanvas.Strokes.HitTest(pt).Where(stroke => !stroke.ContainsPropertyData(IsLockGuid));
|
||||
var filtered = _filtered as Stroke[] ?? _filtered.ToArray();
|
||||
if (!filtered.Any()) return;
|
||||
inkCanvas.Strokes.Remove(new StrokeCollection(filtered));
|
||||
} else {
|
||||
// draw eraser feedback
|
||||
var ct = EraserOverlay_DrawingVisual.DrawingVisual.RenderOpen();
|
||||
var mt = scaleMatrix;
|
||||
var _h = eraserWidth * 56 / 38;
|
||||
mt.Translate(pt.X - eraserWidth / 2, pt.Y - _h / 2);
|
||||
ct.PushTransform(new MatrixTransform(mt));
|
||||
ct.DrawDrawing(FindResource(isEraserCircleShape?"EraserCircleDrawingGroup":"EraserDrawingGroup") as DrawingGroup);
|
||||
ct.Pop();
|
||||
ct.Close();
|
||||
|
||||
// add point to hittester
|
||||
hitTester.AddPoint(pt);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<DrawingGroup x:Key="EraserDrawingGroup" ClipGeometry="M0,0 V56 H38 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#FFF2EEEB" Geometry="F1 M38,56z M0,0z M0,4C0,1.79086,1.79086,0,4,0L34,0C36.2091,0,38,1.79086,38,4L38,52C38,54.2091,36.2091,56,34,56L4,56C1.79086,56,0,54.2091,0,52L0,4z" />
|
||||
<GeometryDrawing Brush="#FFCDCDCD" Geometry="F0 M38,56z M0,0z M34,1L4,1C2.34315,1,1,2.34315,1,4L1,52C1,53.6569,2.34315,55,4,55L34,55C35.6569,55,37,53.6569,37,52L37,4C37,2.34315,35.6569,1,34,1z M4,0C1.79086,0,0,1.79086,0,4L0,52C0,54.2091,1.79086,56,4,56L34,56C36.2091,56,38,54.2091,38,52L38,4C38,1.79086,36.2091,0,34,0L4,0z" />
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M38,56z M0,0z M12,19.5C12,18.1193,13.1193,17,14.5,17L14.5,17C15.8807,17,17,18.1193,17,19.5L17,36.5C17,37.8807,15.8807,39,14.5,39L14.5,39C13.1193,39,12,37.8807,12,36.5L12,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M38,56z M0,0z M11.5,19.5C11.5,17.8431 12.8431,16.5 14.5,16.5 16.1569,16.5 17.5,17.8431 17.5,19.5L17.5,36.5C17.5,38.1569 16.1569,39.5 14.5,39.5 12.8431,39.5 11.5,38.1569 11.5,36.5L11.5,19.5z M14.5,17.5C13.3954,17.5,12.5,18.3954,12.5,19.5L12.5,36.5C12.5,37.6046 13.3954,38.5 14.5,38.5 15.6046,38.5 16.5,37.6046 16.5,36.5L16.5,19.5C16.5,18.3954,15.6046,17.5,14.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M38,56z M0,0z M21,19.5C21,18.1193,22.1193,17,23.5,17L23.5,17C24.8807,17,26,18.1193,26,19.5L26,36.5C26,37.8807,24.8807,39,23.5,39L23.5,39C22.1193,39,21,37.8807,21,36.5L21,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M38,56z M0,0z M20.5,19.5C20.5,17.8431 21.8431,16.5 23.5,16.5 25.1569,16.5 26.5,17.8431 26.5,19.5L26.5,36.5C26.5,38.1569 25.1569,39.5 23.5,39.5 21.8431,39.5 20.5,38.1569 20.5,36.5L20.5,19.5z M23.5,17.5C22.3954,17.5,21.5,18.3954,21.5,19.5L21.5,36.5C21.5,37.6046 22.3954,38.5 23.5,38.5 24.6046,38.5 25.5,37.6046 25.5,36.5L25.5,19.5C25.5,18.3954,24.6046,17.5,23.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
|
||||
<DrawingGroup x:Key="EraserCircleDrawingGroup" ClipGeometry="M0,0 V56 H56 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#FFF2EEEB" Geometry="F1 M56,56z M0,0z M0,28C0,12.536,12.536,0,28,0L28,0C43.464,0,56,12.536,56,28L56,28C56,43.464,43.464,56,28,56L28,56C12.536,56,0,43.464,0,28L0,28z" />
|
||||
<GeometryDrawing Brush="#FFCDCDCD" Geometry="F0 M56,56z M0,0z M1,28C1,42.9117 13.0883,55 28,55 42.9117,55 55,42.9117 55,28 55,13.0883 42.9117,1 28,1 13.0883,1 1,13.0883 1,28z M28,0C12.536,0 0,12.536 0,28 0,43.464 12.536,56 28,56 43.464,56 56,43.464 56,28 56,12.536 43.464,0 28,0z" />
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M56,56z M0,0z M21,19.5C21,18.1193,22.1193,17,23.5,17L23.5,17C24.8807,17,26,18.1193,26,19.5L26,36.5C26,37.8807,24.8807,39,23.5,39L23.5,39C22.1193,39,21,37.8807,21,36.5L21,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M56,56z M0,0z M20.5,19.5C20.5,17.8431 21.8431,16.5 23.5,16.5 25.1569,16.5 26.5,17.8431 26.5,19.5L26.5,36.5C26.5,38.1569 25.1569,39.5 23.5,39.5 21.8431,39.5 20.5,38.1569 20.5,36.5L20.5,19.5z M23.5,17.5C22.3954,17.5,21.5,18.3954,21.5,19.5L21.5,36.5C21.5,37.6046 22.3954,38.5 23.5,38.5 24.6046,38.5 25.5,37.6046 25.5,36.5L25.5,19.5C25.5,18.3954,24.6046,17.5,23.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M56,56z M0,0z M30,19.5C30,18.1193,31.1193,17,32.5,17L32.5,17C33.8807,17,35,18.1193,35,19.5L35,36.5C35,37.8807,33.8807,39,32.5,39L32.5,39C31.1193,39,30,37.8807,30,36.5L30,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M56,56z M0,0z M29.5,19.5C29.5,17.8431 30.8431,16.5 32.5,16.5 34.1569,16.5 35.5,17.8431 35.5,19.5L35.5,36.5C35.5,38.1569 34.1569,39.5 32.5,39.5 30.8431,39.5 29.5,38.1569 29.5,36.5L29.5,19.5z M32.5,17.5C31.3954,17.5,30.5,18.3954,30.5,19.5L30.5,36.5C30.5,37.6046 31.3954,38.5 32.5,38.5 33.6046,38.5 34.5,37.6046 34.5,36.5L34.5,19.5C34.5,18.3954,33.6046,17.5,32.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</ResourceDictionary>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,170 @@
|
||||
using OSVersionExtension;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Ink_Canvas.Helpers;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
public IntPtr MagnificationWinHandle;
|
||||
public IntPtr MagnificationHostWindowHandle;
|
||||
|
||||
public bool isFreezeFrameLoaded = false;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool UpdateWindow(IntPtr hWnd);
|
||||
|
||||
/// <summary>
|
||||
/// 初始化画面定格窗口
|
||||
/// </summary>
|
||||
/// <param name="hwndsList"></param>
|
||||
public void InitFreezeWindow(HWND[] hwndsList) {
|
||||
isFreezeFrameLoaded = false;
|
||||
if (OSVersion.GetOperatingSystem() < OSVersionExtension.OperatingSystem.Windows81) return;
|
||||
if (!Magnification.MagInitialize()) return;
|
||||
// 註冊宿主窗體類名
|
||||
var wndClassEx = new WNDCLASSEX {
|
||||
cbSize = (uint)Marshal.SizeOf<WNDCLASSEX>(), style = CS_HREDRAW | CS_VREDRAW,
|
||||
lpfnWndProc = StaticWndProcDelegate, hInstance = IntPtr.Zero,
|
||||
hCursor = LoadCursor(IntPtr.Zero, IDC_ARROW), hbrBackground = (IntPtr)(1 + COLOR_BTNFACE),
|
||||
lpszClassName = "ICCMagnifierWindowHostForFreezeFrame",
|
||||
hIcon = IntPtr.Zero, hIconSm = IntPtr.Zero
|
||||
};
|
||||
RegisterClassEx(ref wndClassEx);
|
||||
// 創建宿主窗體
|
||||
var windowHostHandle = CreateWindowEx(
|
||||
WS_EX_TOPMOST | WS_EX_LAYERED, "ICCMagnifierWindowHostForFreezeFrame", "ICCMagnifierWindowHostWindowForFreezeFrame",
|
||||
WS_SIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CAPTION | WS_MAXIMIZEBOX, 0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
|
||||
IntPtr.Zero);
|
||||
// 設定分層窗體
|
||||
SetLayeredWindowAttributes(windowHostHandle, 0, 0, LWA_ALPHA);
|
||||
// 創建放大鏡窗體
|
||||
var hwndMag = CreateWindowEx(
|
||||
0, Magnification.WC_MAGNIFIER, "ICCMagnifierWindowForFreezeFrame", WS_CHILD | WS_VISIBLE | MS_CLIPAROUNDCURSOR, 0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, windowHostHandle,
|
||||
IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
|
||||
// 設定窗體樣式和排布
|
||||
int style = GetWindowLong(windowHostHandle, GWL_STYLE);
|
||||
style &= ~WS_CAPTION; // 隐藏标题栏
|
||||
style &= ~WS_THICKFRAME; // 禁止窗口拉伸
|
||||
SetWindowLong(windowHostHandle, GWL_STYLE, style);
|
||||
SetWindowPos(windowHostHandle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOSIZE | SWP_FRAMECHANGED);
|
||||
// 設定額外樣式
|
||||
int exStyle = GetWindowLong(windowHostHandle, GWL_EXSTYLE);
|
||||
exStyle |= WS_EX_TOOLWINDOW; /* <- 隐藏任务栏图标 */
|
||||
exStyle &= ~WS_EX_APPWINDOW;
|
||||
SetWindowLong(windowHostHandle, GWL_EXSTYLE, exStyle);
|
||||
// 导出成员
|
||||
MagnificationWinHandle = hwndMag;
|
||||
MagnificationHostWindowHandle = windowHostHandle;
|
||||
// 設定放大鏡工廠
|
||||
Magnification.MAGTRANSFORM matrix = new Magnification.MAGTRANSFORM();
|
||||
matrix[0, 0] = 1.0f;
|
||||
matrix[0, 1] = 0.0f;
|
||||
matrix[0, 2] = 0.0f;
|
||||
matrix[1, 0] = 0.0f;
|
||||
matrix[1, 1] = 1.0f;
|
||||
matrix[1, 2] = 0.0f;
|
||||
matrix[2, 0] = 1.0f;
|
||||
matrix[2, 1] = 0.0f;
|
||||
matrix[2, 2] = 0.0f;
|
||||
if (!Magnification.MagSetWindowTransform(hwndMag, matrix)) return;
|
||||
// 設定放大鏡轉化矩乘陣列
|
||||
Magnification.MAGCOLOREFFECT magEffect = new Magnification.MAGCOLOREFFECT();
|
||||
magEffect[0, 0] = 1.0f;
|
||||
magEffect[0, 1] = 0.0f;
|
||||
magEffect[0, 2] = 0.0f;
|
||||
magEffect[0, 3] = 0.0f;
|
||||
magEffect[0, 4] = 0.0f;
|
||||
magEffect[1, 0] = 0.0f;
|
||||
magEffect[1, 1] = 1.0f;
|
||||
magEffect[1, 2] = 0.0f;
|
||||
magEffect[1, 3] = 0.0f;
|
||||
magEffect[1, 4] = 0.0f;
|
||||
magEffect[2, 0] = 0.0f;
|
||||
magEffect[2, 1] = 0.0f;
|
||||
magEffect[2, 2] = 1.0f;
|
||||
magEffect[2, 3] = 0.0f;
|
||||
magEffect[2, 4] = 0.0f;
|
||||
magEffect[3, 0] = 0.0f;
|
||||
magEffect[3, 1] = 0.0f;
|
||||
magEffect[3, 2] = 0.0f;
|
||||
magEffect[3, 3] = 1.0f;
|
||||
magEffect[3, 4] = 0.0f;
|
||||
magEffect[4, 0] = 0.0f;
|
||||
magEffect[4, 1] = 0.0f;
|
||||
magEffect[4, 2] = 0.0f;
|
||||
magEffect[4, 3] = 0.0f;
|
||||
magEffect[4, 4] = 1.0f;
|
||||
if (!Magnification.MagSetColorEffect(hwndMag, magEffect)) return;
|
||||
// 顯示窗體
|
||||
ShowWindow(windowHostHandle, SW_SHOW);
|
||||
// 过滤窗口
|
||||
var hwnds = new List<HWND> { hwndMag };
|
||||
hwnds.AddRange(hwndsList);
|
||||
if (!Magnification.MagSetWindowFilterList(hwndMag, Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE,
|
||||
hwnds.Count, hwnds.ToArray())) return;
|
||||
// 设置窗口 Source
|
||||
if (!Magnification.MagSetWindowSource(hwndMag, new RECT(0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return;
|
||||
InvalidateRect(hwndMag, IntPtr.Zero, true);
|
||||
isFreezeFrameLoaded = true;
|
||||
}
|
||||
|
||||
public async Task<bool> InitFreezeWindowAsync(HWND[] hwndsList) {
|
||||
return await Task.Run(() => {
|
||||
InitFreezeWindow(hwndsList);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void DisposeFreezeFrame() {
|
||||
// 反注册宿主窗口
|
||||
UnregisterClass("ICCMagnifierWindowHostForFreezeFrame", IntPtr.Zero);
|
||||
// 销毁宿主窗口
|
||||
Magnification.MagUninitialize();
|
||||
DestroyWindow(MagnificationHostWindowHandle);
|
||||
}
|
||||
|
||||
public void SetFreezeFrameWindowsFilterList(HWND[] hwndsList) {
|
||||
if (!isFreezeFrameLoaded) return;
|
||||
var hwnds = new List<HWND> { MagnificationWinHandle };
|
||||
hwnds.AddRange(hwndsList);
|
||||
if (!Magnification.MagSetWindowFilterList(MagnificationWinHandle, Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE,
|
||||
hwnds.Count, hwnds.ToArray())) return;
|
||||
}
|
||||
|
||||
public Bitmap GetFreezedFrame() {
|
||||
if (!isFreezeFrameLoaded) return new Bitmap(1,1);
|
||||
if (!Magnification.MagSetWindowSource(MagnificationWinHandle, new RECT(0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return new Bitmap(1,1);
|
||||
InvalidateRect(MagnificationWinHandle, IntPtr.Zero, true);
|
||||
UpdateWindow(MagnificationHostWindowHandle);
|
||||
RECT rect;
|
||||
GetWindowRect(MagnificationWinHandle, out rect);
|
||||
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
|
||||
Graphics memoryGraphics = Graphics.FromImage(bmp);
|
||||
PrintWindow(MagnificationWinHandle, memoryGraphics.GetHdc(), PW_RENDERFULLCONTENT);
|
||||
memoryGraphics.ReleaseHdc();
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public async Task<Bitmap> GetFreezedFrameAsync() {
|
||||
if (!isFreezeFrameLoaded) return null;
|
||||
var result = await Task.Run(GetFreezedFrame);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Ink_Canvas.Helpers;
|
||||
using static Ink_Canvas.Popups.ColorPalette;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
private void Window_MouseWheel(object sender, MouseWheelEventArgs e) {
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility != Visibility.Visible || currentMode != 0) return;
|
||||
if (e.Delta >= 120)
|
||||
BtnPPTSlidesUp_Click(null, null);
|
||||
else if (e.Delta <= -120) BtnPPTSlidesDown_Click(null, null);
|
||||
}
|
||||
|
||||
private void Main_Grid_PreviewKeyDown(object sender, KeyEventArgs e) {
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible || currentMode == 0) {
|
||||
if (e.Key == Key.Down || e.Key == Key.PageDown || e.Key == Key.Right || e.Key == Key.N ||
|
||||
e.Key == Key.Space) BtnPPTSlidesDown_Click(null, null);
|
||||
if (e.Key == Key.Up || e.Key == Key.PageUp || e.Key == Key.Left || e.Key == Key.P)
|
||||
BtnPPTSlidesUp_Click(null, null);
|
||||
};
|
||||
if (e.Key == Key.LeftCtrl) {
|
||||
Trace.WriteLine("KeyDown");
|
||||
isControlKeyDown = true;
|
||||
ControlKeyDownEvent?.Invoke(this,e);
|
||||
}
|
||||
if (e.Key == Key.LeftShift) {
|
||||
Trace.WriteLine("KeyDown");
|
||||
isShiftKeyDown = true;
|
||||
ShiftKeyDownEvent?.Invoke(this,e);
|
||||
}
|
||||
}
|
||||
|
||||
public bool isControlKeyDown = false;
|
||||
public bool isShiftKeyDown = false;
|
||||
|
||||
public event EventHandler<KeyEventArgs> ControlKeyDownEvent;
|
||||
public event EventHandler<KeyEventArgs> ShiftKeyDownEvent;
|
||||
public event EventHandler<KeyEventArgs> ControlKeyUpEvent;
|
||||
public event EventHandler<KeyEventArgs> ShiftKeyUpEvent;
|
||||
|
||||
private void Main_Grid_PreviewKeyUp(object sender, KeyEventArgs e) {
|
||||
if (e.Key == Key.LeftCtrl) {
|
||||
isControlKeyDown = false;
|
||||
ControlKeyUpEvent?.Invoke(this,e);
|
||||
};
|
||||
if (e.Key == Key.LeftShift) {
|
||||
isShiftKeyDown = false;
|
||||
ShiftKeyUpEvent?.Invoke(this,e);
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_KeyDown(object sender, KeyEventArgs e) {
|
||||
if (e.Key == Key.Escape) KeyExit(null, null);
|
||||
}
|
||||
|
||||
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
|
||||
e.CanExecute = true;
|
||||
}
|
||||
|
||||
private void HotKey_Undo(object sender, ExecutedRoutedEventArgs e) {
|
||||
try {
|
||||
SymbolIconUndo_MouseUp(lastBorderMouseDownObject, null);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void HotKey_Redo(object sender, ExecutedRoutedEventArgs e) {
|
||||
try {
|
||||
SymbolIconRedo_MouseUp(lastBorderMouseDownObject, null);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void HotKey_Clear(object sender, ExecutedRoutedEventArgs e) {
|
||||
SymbolIconDelete_MouseUp(lastBorderMouseDownObject, null);
|
||||
}
|
||||
|
||||
|
||||
private void KeyExit(object sender, ExecutedRoutedEventArgs e) {
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible) BtnPPTSlideShowEnd_Click(null, null);
|
||||
}
|
||||
|
||||
private void KeyChangeToDrawTool(object sender, ExecutedRoutedEventArgs e) {
|
||||
PenIcon_Click(lastBorderMouseDownObject, null);
|
||||
}
|
||||
|
||||
private void KeyChangeToQuitDrawTool(object sender, ExecutedRoutedEventArgs e) {
|
||||
if (currentMode != 0) ImageBlackboard_MouseUp(lastBorderMouseDownObject, null);
|
||||
CursorIcon_Click(lastBorderMouseDownObject, null);
|
||||
}
|
||||
|
||||
private void KeyChangeToSelect(object sender, ExecutedRoutedEventArgs e) {
|
||||
if (StackPanelCanvasControls.Visibility == Visibility.Visible)
|
||||
SymbolIconSelect_MouseUp(lastBorderMouseDownObject, null);
|
||||
}
|
||||
|
||||
private void KeyChangeToEraser(object sender, ExecutedRoutedEventArgs e) {
|
||||
if (StackPanelCanvasControls.Visibility == Visibility.Visible) {
|
||||
if (Eraser_Icon.Background != null)
|
||||
EraserIconByStrokes_Click(lastBorderMouseDownObject, null);
|
||||
else
|
||||
EraserIcon_Click(lastBorderMouseDownObject, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void KeyChangeToBoard(object sender, ExecutedRoutedEventArgs e) {
|
||||
ImageBlackboard_MouseUp(lastBorderMouseDownObject, null);
|
||||
}
|
||||
|
||||
private void KeyCapture(object sender, ExecutedRoutedEventArgs e) {
|
||||
SaveScreenShotToDesktop();
|
||||
}
|
||||
|
||||
private void KeyDrawLine(object sender, ExecutedRoutedEventArgs e) {
|
||||
if (StackPanelCanvasControls.Visibility == Visibility.Visible) BtnDrawLine_Click(lastMouseDownSender, null);
|
||||
}
|
||||
|
||||
private void KeyHide(object sender, ExecutedRoutedEventArgs e) {
|
||||
SymbolIconEmoji_MouseUp(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public static class XamlGraphicsIconGeometries {
|
||||
public static string LinedCursorIcon =
|
||||
"F0 M24,24z M0,0z M3.85151,2.7073C3.52422,2.57095 3.147,2.64558 2.89629,2.89629 2.64558,3.147 2.57095,3.52422 2.7073,3.85151L9.7773,20.8215C9.91729,21.1575 10.2507,21.3718 10.6145,21.3595 10.9783,21.3473 11.2965,21.1111 11.4135,20.7664L13.4711,14.7085 18.8963,20.1337C19.238,20.4754 19.792,20.4754 20.1337,20.1337 20.4754,19.792 20.4754,19.238 20.1337,18.8963L14.7085,13.4711 20.7664,11.4135C21.1111,11.2965 21.3473,10.9783 21.3595,10.6145 21.3718,10.2507 21.1575,9.91729 20.8215,9.7773L3.85151,2.7073z M10.5017,18.0097L5.13984,5.13984 18.0097,10.5017 12.8136,12.2665C12.5561,12.3539,12.3539,12.5561,12.2665,12.8136L10.5017,18.0097z";
|
||||
|
||||
public static string SolidCursorIcon =
|
||||
"F0 M24,24z M0,0z M2.89629,2.89629C3.147,2.64558,3.52422,2.57095,3.85151,2.7073L20.8215,9.7773C21.1575,9.91729 21.3718,10.2507 21.3595,10.6145 21.3473,10.9783 21.1111,11.2965 20.7664,11.4135L14.7085,13.4711 20.1337,18.8963C20.4754,19.238 20.4754,19.792 20.1337,20.1337 19.792,20.4754 19.238,20.4754 18.8963,20.1337L13.4711,14.7085 11.4135,20.7664C11.2965,21.1111 10.9783,21.3473 10.6145,21.3595 10.2507,21.3718 9.91729,21.1575 9.7773,20.8215L2.7073,3.85151C2.57095,3.52422,2.64558,3.147,2.89629,2.89629z";
|
||||
|
||||
public static string LinedPenIcon =
|
||||
"F0 M24,24z M0,0z M18.7033,4.39761C18.4948,4.31644 18.2714,4.27922 18.0473,4.28846 17.8233,4.29771 17.6038,4.3532 17.403,4.4512 17.2022,4.54919 17.0246,4.68744 16.8813,4.8568 16.8665,4.87422 16.8511,4.89102 16.8349,4.90716L15.7108,6.03131 17.9591,8.27962 19.0832,7.15546C19.1021,7.13662 19.1218,7.11869 19.1424,7.10176 19.3143,6.96037 19.4543,6.7853 19.5537,6.58793 19.6531,6.39058 19.7099,6.1751 19.7207,5.95519 19.7314,5.73528 19.6959,5.51545 19.6163,5.30962 19.5367,5.10378 19.4147,4.91625 19.2576,4.75914 19.1004,4.60201 18.9117,4.47877 18.7033,4.39761z M16.7944,9.44428L14.5461,7.19597 5.47079,16.2713 4.62767,19.3627 7.7191,18.5196 16.7944,9.44428z M13.9636,5.44913L4.15148,15.2613C4.05014,15.3626,3.977,15.4886,3.93929,15.6269L2.65942,20.3198C2.58166,20.6049 2.66264,20.9098 2.87161,21.1188 3.08059,21.3277 3.38551,21.4087 3.67063,21.331L8.36347,20.0511C8.50174,20.0134,8.62777,19.9402,8.72911,19.8389L20.2217,8.34636C20.5551,8.06468 20.8283,7.71873 21.0247,7.3289 21.2275,6.92628 21.3437,6.48586 21.3658,6.03572 21.3878,5.58559 21.3151,5.13594 21.1525,4.71552 20.99,4.29512 20.7411,3.91338 20.4222,3.59447 20.1033,3.27558 19.7214,3.0265 19.3009,2.86277 18.8804,2.69905 18.4304,2.62417 17.9794,2.64278 17.5285,2.66139 17.0862,2.77308 16.6807,2.97095 16.2862,3.16344 15.9348,3.43348 15.6478,3.76494L13.9636,5.44913z";
|
||||
|
||||
public static string SolidPenIcon =
|
||||
"F1 M24,24z M0,0z M19.3332,2.85933C18.9193,2.69814 18.4762,2.62442 18.0322,2.64274 17.5882,2.66106 17.1527,2.77103 16.7535,2.96583 16.3643,3.15575 16.0177,3.42232 15.7349,3.74956L14.5672,4.91725 19.0731,9.4231 20.2373,8.25888C20.5666,7.98121 20.8364,7.63993 21.0302,7.25528 21.2298,6.85899 21.3442,6.42551 21.3659,5.98249 21.3876,5.53947 21.3161,5.09692 21.1561,4.68313 20.996,4.26934 20.7511,3.89359 20.4372,3.57966 20.1232,3.26574 19.7472,3.02052 19.3332,2.85933z M18.0085,10.4877L13.5026,5.98183 4.14128,15.3432C4.04864,15.4358,3.98179,15.551,3.94732,15.6774L2.65684,20.4091C2.58577,20.6698 2.65979,20.9485 2.8508,21.1395 3.04182,21.3305 3.32054,21.4045 3.58117,21.3335L8.3129,20.043C8.43929,20.0085,8.5545,19.9417,8.64713,19.849L18.0085,10.4877z";
|
||||
|
||||
public static string LinedEraserStrokeIcon =
|
||||
"F0 M25,24z M0,0z M7.32029,21.36L13.0098,21.36 13.0122,21.36 21.5471,21.36C21.989,21.36 22.3473,21.0017 22.3473,20.5598 22.3473,20.1179 21.989,19.7596 21.5471,19.7596L14.9429,19.7596 21.4352,13.2673C22.7372,12.0786,22.6872,10.1353,21.449,8.89707L16.1515,3.59952C14.9628,2.29751,13.0195,2.34754,11.7813,3.58572L2.68992,12.6771C1.3879,13.8657,1.43793,15.8091,2.67611,17.0473L6.75447,21.1256C6.90453,21.2757,7.10807,21.36,7.32029,21.36z M14.9771,4.68685C14.4571,4.10907,13.5664,4.06392,12.9129,4.71737L6.55503,11.0753 13.9595,18.4797 20.3174,12.1218C20.3273,12.1119 20.3375,12.1022 20.3479,12.0929 20.9257,11.5729 20.9708,10.6822 20.3174,10.0287L15.006,4.71737C14.9961,4.70745,14.9864,4.69727,14.9771,4.68685z M12.8278,19.6114L5.42338,12.2069 3.80776,13.8225C3.79784,13.8324 3.78766,13.8421 3.77724,13.8515 3.19947,14.3715 3.15431,15.2622 3.80776,15.9156L7.65174,19.7596 12.6796,19.7596 12.8278,19.6114z";
|
||||
|
||||
public static string SolidEraserStrokeIcon =
|
||||
"F1 M24,24z M0,0z M11.6199,3.61372C12.8916,2.34202,14.8995,2.2837,16.1307,3.62964L21.3433,8.84225C22.615,10.1139,22.6733,12.1218,21.3274,13.353L15.1877,19.4927 5.46434,9.76928 11.6199,3.61372z M7.33167,21.36C7.08919,21.36 6.86831,21.2676 6.70232,21.116 6.69184,21.1064 6.68155,21.0966 6.67147,21.0865L2.65671,17.0718C1.385,15.8001,1.32668,13.7922,2.67262,12.561L4.14394,11.0897 12.5469,19.4927 21.3367,19.4927C21.8523,19.4927 22.2703,19.9107 22.2703,20.4263 22.2703,20.942 21.8523,21.36 21.3367,21.36L7.33167,21.36z";
|
||||
|
||||
public static string LinedEraserCircleIcon =
|
||||
"F0 M25,24z M0,0z M2.47995,17.1206L6.56736,21.208C6.57733,21.218 6.58749,21.2277 6.59783,21.237 6.66429,21.2971 6.7405,21.3466 6.82381,21.3829L6.83712,21.3885C6.84698,21.3926 6.85693,21.3965 6.86698,21.4003 6.86818,21.4007 6.86937,21.4011 6.87057,21.4016 6.94576,21.4289 7.02412,21.4451 7.10303,21.45L7.12183,21.451 7.13076,21.4513 7.13345,21.4514 7.15549,21.4517 17.0847,21.4517C17.5973,22.3438 18.5597,22.9445 19.6624,22.9445 21.3031,22.9445 22.6332,21.6144 22.6332,19.9737 22.6332,18.3329 21.3031,17.0028 19.6624,17.0028 18.0839,17.0028 16.793,18.2338 16.6972,19.7882L14.8669,19.7882 21.3224,13.3327C22.6404,12.1289,22.5884,10.1619,21.3367,8.91021L16.0278,3.60138C14.8241,2.28336,12.8571,2.33535,11.6053,3.58706L2.49426,12.6981C1.17625,13.9019,1.22824,15.8689,2.47995,17.1206z M14.8072,4.7316C14.2984,4.16633,13.4255,4.11939,12.7816,4.76332L6.43063,11.1143 13.8094,18.4931 20.1604,12.1421C20.1707,12.1318 20.1813,12.1218 20.1921,12.112 20.7574,11.6033 20.8043,10.7304 20.1604,10.0865L14.8373,4.76332C14.8269,4.75301,14.8169,4.74243,14.8072,4.7316z M3.65621,13.8887C3.6459,13.899 3.63532,13.9091 3.62448,13.9188 3.05922,14.4276 3.01228,15.3004 3.65621,15.9444L7.50001,19.7882 12.752,19.7882 5.25437,12.2906 3.65621,13.8887z";
|
||||
|
||||
public static string SolidEraserCircleIcon =
|
||||
"F1 M24,24z M0,0z M15.0919,19.6686L21.4282,13.3322C22.7462,12.1285,22.6942,10.1616,21.4426,8.90993L16.134,3.60133C14.9303,2.28338,12.9633,2.33537,11.7117,3.58702L5.36097,9.93771 15.0919,19.6686z M6.67201,21.2053C6.82267,21.3569,7.03137,21.4508,7.26201,21.4508L17.1907,21.4508C17.7033,22.3429 18.6657,22.9437 19.7683,22.9437 21.409,22.9437 22.7391,21.6136 22.7391,19.9729 22.7391,18.3322 21.409,17.0022 19.7683,17.0022 18.19,17.0022 16.8991,18.2331 16.8033,19.7874L12.8583,19.7874 4.18476,11.1139 2.60098,12.6977C1.28303,13.9014,1.33502,15.8683,2.58667,17.12L6.67201,21.2053z";
|
||||
|
||||
public static string LinedLassoSelectIcon =
|
||||
"F0 M24,24z M0,0z M14.4715,12.7092L14.4715,18.7882 15.8291,16.7546C15.9688,16.5453,16.2038,16.4196,16.4554,16.4196L19.0106,16.4196 14.4715,12.7092z M14.6618,10.9193C14.4981,10.784 14.2733,10.6788 14.0025,10.6788 13.9951,10.6788 13.9877,10.6789 13.9803,10.6791 13.7083,10.6872 13.4502,10.8008 13.2607,10.9961 13.0712,11.1913 12.9653,11.4526 12.9653,11.7246L12.9653,20.3314C12.9653,20.3403 12.9655,20.3491 12.9658,20.358 12.9734,20.5733 13.0468,20.7811 13.176,20.9534 13.3053,21.1258 13.4842,21.2544 13.6888,21.3219 13.765,21.3471 13.8447,21.36 13.925,21.36L14.0025,21.36C14.1661,21.36 14.3276,21.3218 14.474,21.2486 14.6204,21.1754 14.7477,21.0692 14.8459,20.9382 14.8542,20.9272 14.8622,20.9159 14.8698,20.9045L16.8582,17.9258 20.3145,17.9258C20.5287,17.9281 20.7384,17.8641 20.9149,17.7424 21.0941,17.6187 21.2299,17.4417 21.3029,17.2365 21.3759,17.0313 21.3825,16.8084 21.3217,16.5993 21.262,16.3936 21.14,16.2117 20.9729,16.0782L14.6618,10.9193z M8.14548,20.0044C7.70454,19.6737 7.34665,19.2448 7.10016,18.7519 6.94658,18.4447 6.83887,18.1179 6.7795,17.7818 7.131,17.6605 7.45404,17.4604 7.72196,17.1924 7.74959,17.1648 7.7765,17.1366 7.80267,17.1078 8.5567,17.4118 9.3392,17.6365 10.1444,17.7694 10.5548,17.8372 10.9424,17.5594 11.0101,17.149 11.0779,16.7387 10.8001,16.3511 10.3897,16.2833 9.72172,16.1731 9.06686,15.9883 8.42926,15.7362 8.44084,15.6393 8.44672,15.5413 8.44672,15.4427 8.44672,14.7865 8.18602,14.1571 7.72196,13.693 7.25791,13.229 6.62852,12.9682 5.97224,12.9682 5.65536,12.9682 5.34474,13.029 5.05598,13.1441 4.47073,12.3026 4.15196,11.303 4.14328,10.2756 4.14532,7.03688 7.49758,4.1462 11.9971,4.1462 16.4941,4.1462 19.8451,7.03371 19.8508,10.2703 19.8388,10.7807 19.7549,11.2869 19.6016,11.7739 19.4767,12.1706 19.697,12.5934 20.0938,12.7183 20.4905,12.8432 20.9134,12.6228 21.0383,12.2261 21.2351,11.6008 21.3424,10.9507 21.3568,10.2952L21.357,10.2786C21.357,5.91009 16.9982,2.64 11.9971,2.64 6.9959,2.64 2.63705,5.91009 2.63705,10.2786L2.6371,10.2845C2.6479,11.6579 3.08647,12.993 3.89074,14.1047 3.63615,14.5007 3.49777,14.9646 3.49777,15.4427 3.49777,16.099 3.75847,16.7284 4.22252,17.1924 4.51465,17.4846 4.87229,17.6961 5.26092,17.8128 5.33333,18.3726 5.49917,18.9179 5.75297,19.4255 6.10404,20.1276 6.61375,20.7383 7.24176,21.2093 7.5745,21.4589 8.04654,21.3915 8.2961,21.0587 8.54566,20.726 8.47822,20.2539 8.14548,20.0044z M5.97224,14.4745C5.71544,14.4745 5.46916,14.5765 5.28757,14.7581 5.10598,14.9396 5.00397,15.1859 5.00397,15.4427 5.00397,15.6995 5.10598,15.9458 5.28757,16.1274 5.46916,16.309 5.71544,16.411 5.97224,16.411 6.22904,16.411 6.47533,16.309 6.65692,16.1274 6.8385,15.9458 6.94052,15.6995 6.94052,15.4427 6.94052,15.1859 6.8385,14.9396 6.65692,14.7581 6.47533,14.5765 6.22904,14.4745 5.97224,14.4745z";
|
||||
|
||||
public static string SolidLassoSelectIcon =
|
||||
"F1 M24,24z M0,0z M14.6618,10.9193C14.4981,10.784 14.2733,10.6788 14.0025,10.6788 13.9951,10.6788 13.9877,10.6789 13.9803,10.6791 13.7083,10.6872 13.4502,10.8008 13.2607,10.9961 13.0712,11.1913 12.9653,11.4526 12.9653,11.7246L12.9653,20.3314C12.9653,20.3403 12.9655,20.3491 12.9658,20.358 12.9734,20.5733 13.0468,20.7811 13.176,20.9534 13.3053,21.1258 13.4842,21.2544 13.6888,21.3219 13.765,21.3471 13.8447,21.36 13.925,21.36L14.0025,21.36C14.1661,21.36 14.3276,21.3218 14.474,21.2486 14.6204,21.1754 14.7477,21.0692 14.8459,20.9382 14.8542,20.9272 14.8622,20.9159 14.8698,20.9045L16.8582,17.9258 20.3145,17.9258C20.5287,17.9281 20.7384,17.8641 20.9149,17.7424 21.0941,17.6187 21.2299,17.4417 21.3029,17.2365 21.3759,17.0313 21.3825,16.8084 21.3217,16.5993 21.262,16.3936 21.14,16.2117 20.9729,16.0782L14.6618,10.9193z M8.14548,20.0044C7.70454,19.6737 7.34665,19.2448 7.10016,18.7519 6.94658,18.4447 6.83888,18.1179 6.7795,17.7818 7.131,17.6605 7.45404,17.4604 7.72196,17.1924 7.74959,17.1648 7.77649,17.1366 7.80267,17.1078 8.5567,17.4118 9.3392,17.6365 10.1444,17.7694 10.5548,17.8372 10.9424,17.5594 11.0101,17.149 11.0779,16.7387 10.8001,16.3511 10.3897,16.2833 9.72172,16.1731 9.06686,15.9883 8.42926,15.7362 8.44084,15.6393 8.44672,15.5413 8.44672,15.4427 8.44672,14.7865 8.18602,14.1571 7.72196,13.693 7.25791,13.229 6.62852,12.9682 5.97224,12.9682 5.65536,12.9682 5.34474,13.029 5.05598,13.1441 4.47073,12.3026 4.15196,11.303 4.14328,10.2756 4.14532,7.03688 7.49758,4.1462 11.9971,4.1462 16.4941,4.1462 19.8451,7.03371 19.8508,10.2703 19.8388,10.7807 19.7549,11.2869 19.6016,11.7739 19.4767,12.1706 19.697,12.5934 20.0938,12.7183 20.4905,12.8432 20.9134,12.6228 21.0383,12.2261 21.2351,11.6008 21.3424,10.9507 21.3568,10.2952L21.357,10.2786C21.357,5.91009 16.9982,2.64 11.9971,2.64 6.9959,2.64 2.63705,5.91009 2.63705,10.2786L2.6371,10.2845C2.6479,11.6579 3.08647,12.993 3.89074,14.1047 3.63615,14.5007 3.49777,14.9646 3.49777,15.4427 3.49777,16.099 3.75847,16.7284 4.22252,17.1924 4.51465,17.4846 4.87229,17.6961 5.26092,17.8128 5.33333,18.3726 5.49917,18.9178 5.75297,19.4255 6.10404,20.1276 6.61375,20.7383 7.24176,21.2093 7.5745,21.4589 8.04654,21.3915 8.2961,21.0587 8.54566,20.726 8.47822,20.2539 8.14548,20.0044z";
|
||||
|
||||
public static string DisabledGestureIcon =
|
||||
"F0 M24,24z M0,0z M7.82154,10.0753L7.82154,3.74613C7.82154,3.06603 8.08946,2.40655 8.57377,1.92224 9.05808,1.43793 9.70726,1.17001 10.3977,1.17001 11.0881,1.17001 11.7372,1.43793 12.2216,1.92224 12.7059,2.40655 12.9738,3.05573 12.9738,3.74613L12.9738,6.37308C13.1415,6.33947 13.3139,6.32225 13.489,6.32225 14.1794,6.32225 14.8286,6.59016 15.3129,7.07447 15.4484,7.21001 15.567,7.35845 15.6675,7.5171 15.9551,7.40916 16.2634,7.35269 16.5803,7.35269 17.2707,7.35269 17.9199,7.62061 18.4042,8.10492 18.5461,8.24683 18.6695,8.4029 18.7729,8.57001 19.6856,8.26338 20.7674,8.45871 21.4647,9.15599 21.949,9.6403 22.2169,10.2998 22.2169,10.9799L22.2169,15.6169C22.2169,17.5438 21.4647,19.3574 20.1045,20.7176 18.7443,22.0778 16.9307,22.83 15.0038,22.83L13.149,22.83 13.1799,22.8094 12.8398,22.8094C11.7682,22.7579 10.7068,22.4694 9.75878,21.9541 8.70773,21.3874 7.81124,20.563 7.15175,19.5738L6.94566,19.2647C6.60562,18.7494 5.49273,16.8019 3.52458,13.3087 3.19484,12.7213 3.1021,12.0412 3.27727,11.3818 3.45245,10.7326 3.86463,10.1761 4.44168,9.83608 5.00842,9.49604 5.66791,9.35177 6.31709,9.43421 6.86548,9.50385 7.39181,9.7279 7.82154,10.0753z M10.037,3.38547C10.1297,3.28243 10.2637,3.23091 10.3977,3.23091 10.5316,3.23091 10.6656,3.29273 10.7583,3.38547 10.8614,3.47821 10.9129,3.61217 10.9129,3.74613L10.9129,11.4745C10.9129,12.0412 11.3766,12.5049 11.9433,12.5049 12.5101,12.5049 12.9738,12.0412 12.9738,11.4745L12.9738,8.89836C12.9738,8.7644 13.0356,8.63045 13.1283,8.53771 13.2211,8.43466 13.355,8.38314 13.489,8.38314 13.623,8.38314 13.7569,8.44497 13.8497,8.53771 13.9527,8.63045 14.0042,8.7644 14.0042,8.89836L14.0042,11.4745C14.0042,12.0412 14.4679,12.5049 15.0347,12.5049 15.6014,12.5049 16.0651,12.0412 16.0651,11.4745L16.0651,9.92881C16.0651,9.79485 16.1269,9.66089 16.2197,9.56815 16.3124,9.46511 16.4464,9.41359 16.5803,9.41359 16.7143,9.41359 16.8483,9.47541 16.941,9.56815 17.044,9.66089 17.0956,9.79485 17.0956,9.92881L17.0956,10.5869C17.0752,10.7163 17.0646,10.8477 17.0646,10.9799 17.0646,11.0661 17.0754,11.1499 17.0956,11.2301L17.0956,11.4745C17.0956,12.0412 17.5593,12.5049 18.126,12.5049 18.6928,12.5049 19.1565,12.0412 19.1565,11.4745L19.1565,10.8128C19.1834,10.7399 19.2266,10.6727 19.2801,10.6192 19.4759,10.4234 19.8159,10.4234 20.0117,10.6192 20.1148,10.712 20.1663,10.8459 20.1663,10.9799L20.1663,15.6169C20.1663,16.9977 19.6408,18.296 18.6618,19.2647 17.6829,20.2333 16.3949,20.7691 15.0141,20.7691L13.1593,20.7691C12.3143,20.7691 11.4796,20.5527 10.7274,20.1509 9.98548,19.749 9.3363,19.1616 8.8726,18.4506L8.66651,18.1415C8.35737,17.6675 7.23419,15.7096 5.31756,12.2988 5.24543,12.1752 5.23512,12.0412 5.26604,11.9073 5.30725,11.7733 5.38969,11.6703 5.50304,11.5981 5.66791,11.4951 5.874,11.4539 6.06978,11.4745 6.26557,11.5054 6.45105,11.5878 6.59531,11.7321L8.11007,13.2469C8.49419,13.631 9.10425,13.648 9.50833,13.2978 9.73651,13.1084 9.88244,12.8229 9.88244,12.5049L9.88244,3.74613C9.88244,3.61217,9.94426,3.47821,10.037,3.38547z M2.99905,6.31195L1.78313,4.65293 2.61779,4.04497C3.46275,3.4267,4.37985,2.89087,5.33817,2.46838L6.27587,2.0459 7.12084,3.93162 6.18313,4.3541C5.35878,4.72506,4.56533,5.17846,3.83372,5.71429L2.99905,6.32225 2.99905,6.31195z M18.2806,5.20935L19.1565,5.75549 20.259,4.01404 19.3831,3.4679C18.1157,2.67446,16.7452,2.0768,15.3026,1.68523L14.303,1.41731 13.7672,3.40607 14.7667,3.67399C16.0033,4.00373,17.1883,4.51895,18.2806,5.20935z";
|
||||
|
||||
public static string EnabledGestureIcon =
|
||||
"F1 M24,24z M0,0z M7.29844,9.85586L7.29844,3.52668C7.29844,2.84658 7.56636,2.1871 8.05067,1.70279 8.53498,1.21848 9.18416,0.950562 9.87456,0.950562 10.565,0.950562 11.2141,1.21848 11.6984,1.70279 12.1828,2.1871 12.4507,2.83628 12.4507,3.52668L12.4507,6.15363C12.6184,6.12002 12.7908,6.10279 12.9659,6.10279 13.6563,6.10279 14.3055,6.37071 14.7898,6.85502 14.9253,6.99055 15.0439,7.139 15.1444,7.29765 15.432,7.18971 15.7403,7.13324 16.0572,7.13324 16.7476,7.13324 17.3968,7.40116 17.8811,7.88547 18.023,8.02738 18.1464,8.18344 18.2498,8.35055 19.1625,8.04393 20.2443,8.23925 20.9416,8.93654 21.4259,9.42085 21.6938,10.0803 21.6938,10.7604L21.6938,14.2958C21.1174,13.741,20.4192,13.3118,19.6432,13.0524L19.6432,10.7604C19.6432,10.6265 19.5917,10.4925 19.4886,10.3998 19.2928,10.204 18.9528,10.204 18.757,10.3998 18.7035,10.4532 18.6603,10.5204 18.6334,10.5934L18.6334,11.255C18.6334,11.8218 18.1697,12.2855 17.6029,12.2855 17.0362,12.2855 16.5725,11.8218 16.5725,11.255L16.5725,11.0106C16.5523,10.9304 16.5415,10.8466 16.5415,10.7604 16.5415,10.6283 16.5521,10.4969 16.5725,10.3674L16.5725,9.70936C16.5725,9.5754 16.5209,9.44144 16.4179,9.3487 16.3252,9.25596 16.1912,9.19413 16.0572,9.19413 15.9233,9.19413 15.7893,9.24566 15.6966,9.3487 15.6038,9.44144 15.542,9.5754 15.542,9.70936L15.542,11.255C15.542,11.8218 15.0783,12.2855 14.5116,12.2855 13.9448,12.2855 13.4811,11.8218 13.4811,11.255L13.4811,8.67891C13.4811,8.54495 13.4296,8.41099 13.3266,8.31825 13.2338,8.22551 13.0999,8.16369 12.9659,8.16369 12.8319,8.16369 12.698,8.21521 12.6052,8.31825 12.5125,8.41099 12.4507,8.54495 12.4507,8.67891L12.4507,11.255C12.4507,11.8218 11.987,12.2855 11.4202,12.2855 10.8535,12.2855 10.3898,11.8218 10.3898,11.255L10.3898,3.52668C10.3898,3.39272 10.3383,3.25876 10.2352,3.16602 10.1425,3.07328 10.0085,3.01145 9.87456,3.01145 9.7406,3.01145 9.60664,3.06298 9.5139,3.16602 9.42116,3.25876 9.35933,3.39272 9.35933,3.52668L9.35933,12.2855C9.35933,12.6034 9.21341,12.8889 8.98523,13.0783 8.58114,13.4285 7.97109,13.4115 7.58697,13.0274L6.07221,11.5127C5.92795,11.3684 5.74247,11.286 5.54668,11.255 5.3509,11.2344 5.14481,11.2756 4.97994,11.3787 4.86659,11.4508 4.78415,11.5539 4.74293,11.6878 4.71202,11.8218 4.72232,11.9557 4.79446,12.0794 6.71109,15.4902 7.83427,17.448 8.14341,17.922L8.3495,18.2312C8.8132,18.9422 9.46238,19.5295 10.2043,19.9314 10.9565,20.3333 11.7912,20.5497 12.6362,20.5497L12.9829,20.5497C13.3696,21.3681 13.9542,22.0748 14.6748,22.608 14.6102,22.6097 14.5455,22.6106 14.4807,22.6106L12.6258,22.6106 12.6568,22.59 12.3167,22.59C11.2451,22.5384 10.1837,22.2499 9.23568,21.7347 8.18463,21.1679 7.28814,20.3436 6.62865,19.3544L6.42256,19.0452C6.08251,18.53 4.96963,16.5824 3.00148,13.0892 2.67174,12.5019 2.579,11.8218 2.75417,11.1623 2.92935,10.5131 3.34153,9.95668 3.91858,9.61663 4.48532,9.27658 5.14481,9.13232 5.79399,9.21476 6.34238,9.28439 6.86871,9.50845 7.29844,9.85586z M2.47595,6.0925L1.26003,4.43348 2.09469,3.82551C2.93965,3.20725,3.85675,2.67141,4.81507,2.24893L5.75277,1.82645 6.59774,3.71216 5.66003,4.13465C4.83567,4.50561,4.04223,4.959,3.31061,5.49484L2.47595,6.1028 2.47595,6.0925z M17.7575,4.9899L18.6334,5.53604 19.7359,3.79458 18.86,3.24845C17.5926,2.455,16.2221,1.85734,14.7795,1.46577L13.7799,1.19786 13.2441,3.18662 14.2436,3.45454C15.4802,3.78428,16.6652,4.2995,17.7575,4.9899z";
|
||||
|
||||
public static string EnabledGestureIconBadgeCheck =
|
||||
"M22.74,18.2234C22.74,20.8888 20.5793,23.0494 17.914,23.0494 15.2487,23.0494 13.088,20.8888 13.088,18.2234 13.088,15.5581 15.2487,13.3975 17.914,13.3975 20.5793,13.3975 22.74,15.5581 22.74,18.2234z M21.1673,15.8009C21.4651,16.0889,21.473,16.5637,21.1851,16.8614L17.5425,20.6282C17.4012,20.7743 17.2066,20.8568 17.0034,20.8568 16.8001,20.8568 16.6055,20.7743 16.4642,20.6282L14.6429,18.7448C14.355,18.447 14.3629,17.9722 14.6607,17.6843 14.9585,17.3963 15.4333,17.4043 15.7212,17.7021L17.0034,19.0279 20.1068,15.8187C20.3947,15.5209,20.8695,15.513,21.1673,15.8009z";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Input.StylusPlugIns;
|
||||
using System.Windows.Media;
|
||||
using iNKORE.UI.WPF.Helpers;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
|
||||
public class IccStroke : Stroke {
|
||||
|
||||
public IccStroke(StylusPointCollection stylusPoints, DrawingAttributes drawingAttributes)
|
||||
: base(stylusPoints, drawingAttributes) { }
|
||||
|
||||
public static Guid StrokeShapeTypeGuid = new Guid("6537b29c-557f-487f-800b-cb30a8f1de78");
|
||||
public static Guid StrokeIsShapeGuid = new Guid("40eff5db-9346-4e42-bd46-7b0eb19d0018");
|
||||
|
||||
public StylusPointCollection RawStylusPointCollection { get; set; }
|
||||
|
||||
public MainWindow.ShapeDrawingHelper.ArrowLineConfig ArrowLineConfig { get; set; } =
|
||||
new MainWindow.ShapeDrawingHelper.ArrowLineConfig();
|
||||
|
||||
/// <summary>
|
||||
/// 根据这个属性判断当前 Stroke 是否是原始输入
|
||||
/// </summary>
|
||||
public bool IsRawStylusPoints = true;
|
||||
|
||||
/// <summary>
|
||||
/// 根据这个属性决定在绘制 Stroke 时是否需要在直线形状中,在两点构成直线上分布点,用于墨迹的范围框选。
|
||||
/// </summary>
|
||||
public bool IsDistributePointsOnLineShape = true;
|
||||
|
||||
/// <summary>
|
||||
/// 指示该墨迹是否来自一个完整墨迹被擦除后的一部分墨迹,仅用于形状墨迹。
|
||||
/// </summary>
|
||||
public bool IsErasedStrokePart = false;
|
||||
|
||||
// 自定义的墨迹渲染
|
||||
protected override void DrawCore(DrawingContext drawingContext,
|
||||
DrawingAttributes drawingAttributes) {
|
||||
if (!(this.ContainsPropertyData(StrokeIsShapeGuid) &&
|
||||
(bool)this.GetPropertyData(StrokeIsShapeGuid) == true)) {
|
||||
base.DrawCore(drawingContext, drawingAttributes);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DashedLine ||
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.Line ||
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine ||
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowOneSide ||
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowTwoSide) {
|
||||
if (StylusPoints.Count < 2) {
|
||||
base.DrawCore(drawingContext, drawingAttributes);
|
||||
return;
|
||||
}
|
||||
|
||||
var pts = new List<Point>(this.StylusPoints.ToPoints());
|
||||
if (IsDistributePointsOnLineShape && (
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DashedLine ||
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.Line ||
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine) && IsRawStylusPoints) {
|
||||
IsRawStylusPoints = false;
|
||||
RawStylusPointCollection = StylusPoints.Clone();
|
||||
var pointList = new List<Point> { new Point(StylusPoints[0].X, StylusPoints[0].Y) };
|
||||
pointList.AddRange(MainWindow.ShapeDrawingHelper.DistributePointsOnLine(new Point(StylusPoints[0].X, StylusPoints[0].Y),new Point(StylusPoints[1].X, StylusPoints[1].Y)));
|
||||
pointList.Add(new Point(StylusPoints[1].X, StylusPoints[1].Y));
|
||||
StylusPoints = new StylusPointCollection(pointList);
|
||||
}
|
||||
StreamGeometry geometry = new StreamGeometry();
|
||||
using (StreamGeometryContext ctx = geometry.Open()) {
|
||||
ctx.BeginFigure(pts[0], false , false);
|
||||
pts.RemoveAt(0);
|
||||
ctx.PolyLineTo(pts,true, true);
|
||||
}
|
||||
var pen = new Pen(new SolidColorBrush(DrawingAttributes.Color),
|
||||
(drawingAttributes.Width + drawingAttributes.Height) / 2) {
|
||||
DashCap = PenLineCap.Round,
|
||||
StartLineCap = PenLineCap.Round,
|
||||
EndLineCap = PenLineCap.Round,
|
||||
};
|
||||
if ((int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.Line &&
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.ArrowOneSide &&
|
||||
(int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.ArrowTwoSide)
|
||||
pen.DashStyle = (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine ? DashStyles.Dot : DashStyles.Dash;
|
||||
|
||||
if ((int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowOneSide && IsRawStylusPoints) {
|
||||
IsRawStylusPoints = false;
|
||||
pts = new List<Point>(this.StylusPoints.ToPoints());
|
||||
RawStylusPointCollection = StylusPoints.Clone();
|
||||
double w = ArrowLineConfig.ArrowWidth, h = ArrowLineConfig.ArrowHeight;
|
||||
var theta = Math.Atan2(pts[0].Y - pts[1].Y, pts[0].X - pts[1].X);
|
||||
var sint = Math.Sin(theta);
|
||||
var cost = Math.Cos(theta);
|
||||
var pointList = new List<Point> {
|
||||
new Point(pts[0].X, pts[0].Y),
|
||||
};
|
||||
if (IsDistributePointsOnLineShape) pointList.AddRange(MainWindow.ShapeDrawingHelper.DistributePointsOnLine(new Point(pts[0].X, pts[0].Y),new Point(pts[1].X, pts[1].Y)));
|
||||
pointList.AddRange(new List<Point> {
|
||||
new Point(pts[1].X, pts[1].Y),
|
||||
new Point(pts[1].X + (w * cost - h * sint), pts[1].Y + (w * sint + h * cost)),
|
||||
new Point(pts[1].X, pts[1].Y),
|
||||
new Point(pts[1].X + (w * cost + h * sint), pts[1].Y - (h * cost - w * sint)),
|
||||
});
|
||||
StylusPoints = new StylusPointCollection(pointList);
|
||||
var _pts = new List<Point>(this.StylusPoints.ToPoints());
|
||||
using (StreamGeometryContext ctx = geometry.Open()) {
|
||||
ctx.BeginFigure(_pts[0], false , false);
|
||||
_pts.RemoveAt(0);
|
||||
ctx.PolyLineTo(_pts,true, true);
|
||||
}
|
||||
drawingContext.DrawGeometry(new SolidColorBrush(DrawingAttributes.Color),pen, geometry);
|
||||
return;
|
||||
|
||||
}
|
||||
drawingContext.DrawGeometry(new SolidColorBrush(Colors.Transparent),pen, geometry);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class CustomDynamicRenderer : DynamicRenderer {
|
||||
|
||||
private Point prevPoint;
|
||||
|
||||
private List<StylusPoint> pointsList = new List<StylusPoint>();
|
||||
|
||||
private void ClearPointsList() {
|
||||
pointsList.Clear();
|
||||
}
|
||||
|
||||
private void PushPoint(StylusPoint point) {
|
||||
pointsList.Add(point);
|
||||
if (pointsList.Count > 15) {
|
||||
pointsList.RemoveRange(0,pointsList.Count - 15);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnStylusDown(RawStylusInput rawStylusInput) {
|
||||
prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
|
||||
ClearPointsList();
|
||||
var pts = rawStylusInput.GetStylusPoints();
|
||||
if (pts.Count == 1) {
|
||||
PushPoint(pts.Single());
|
||||
} else if (pts.Count > 1) {
|
||||
PushPoint(pts[pts.Count-1]);
|
||||
}
|
||||
Trace.WriteLine(pointsList.Count);
|
||||
base.OnStylusDown(rawStylusInput);
|
||||
}
|
||||
|
||||
protected override void OnStylusMove(RawStylusInput rawStylusInput) {
|
||||
base.OnStylusMove(rawStylusInput);
|
||||
var pts = rawStylusInput.GetStylusPoints();
|
||||
if (pts.Count == 1) {
|
||||
PushPoint(pts.Single());
|
||||
} else if (pts.Count > 1) {
|
||||
PushPoint(pts[pts.Count-1]);
|
||||
}
|
||||
Trace.WriteLine(pointsList.Count);
|
||||
}
|
||||
|
||||
protected override void OnDraw(DrawingContext drawingContext,
|
||||
StylusPointCollection stylusPoints,
|
||||
Geometry geometry, Brush fillBrush) {
|
||||
try {
|
||||
var sp = new StylusPointCollection();
|
||||
var n = pointsList.Count - 1;
|
||||
var pressure = 0.1;
|
||||
var x = 10;
|
||||
if (n == 1) return;
|
||||
if (n >= x) {
|
||||
for (var i = 0; i < n - x; i++) {
|
||||
var point = new StylusPoint();
|
||||
|
||||
point.PressureFactor = (float)0.5;
|
||||
point.X = pointsList[i].X;
|
||||
point.Y = pointsList[i].Y;
|
||||
sp.Add(point);
|
||||
}
|
||||
|
||||
for (var i = n - x; i <= n; i++) {
|
||||
var point = new StylusPoint();
|
||||
|
||||
point.PressureFactor = (float)((0.5 - pressure) * (n - i) / x + pressure);
|
||||
point.X = pointsList[i].X;
|
||||
point.Y = pointsList[i].Y;
|
||||
sp.Add(point);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i <= n; i++) {
|
||||
var point = new StylusPoint();
|
||||
|
||||
point.PressureFactor = (float)(0.4 * (n - i) / n + pressure);
|
||||
point.X = pointsList[i].X;
|
||||
point.Y = pointsList[i].Y;
|
||||
sp.Add(point);
|
||||
}
|
||||
}
|
||||
|
||||
var da = DrawingAttributes.Clone();
|
||||
da.Width *= 0.75;
|
||||
da.Height *= 0.75;
|
||||
var stk = new Stroke(sp,da);
|
||||
stk.Draw(drawingContext);
|
||||
}
|
||||
catch { }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class IccInkCanvas : InkCanvas {
|
||||
|
||||
CustomDynamicRenderer customDynamicRenderer = new CustomDynamicRenderer();
|
||||
|
||||
public IccInkCanvas() {
|
||||
DynamicRenderer = customDynamicRenderer;
|
||||
|
||||
// 通过反射移除InkCanvas自带的默认 Delete按键事件
|
||||
var commandBindingsField =
|
||||
typeof(CommandManager).GetField("_classCommandBindings", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var bnds = commandBindingsField.GetValue(null) as HybridDictionary;
|
||||
var inkCanvasBindings = bnds[typeof(InkCanvas)] as CommandBindingCollection;
|
||||
var enumerator = inkCanvasBindings.GetEnumerator();
|
||||
while (enumerator.MoveNext()) {
|
||||
var item = (CommandBinding)enumerator.Current;
|
||||
if (item.Command == ApplicationCommands.Delete) {
|
||||
var executedField =
|
||||
typeof(CommandBinding).GetField("Executed", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var canExecuteField =
|
||||
typeof(CommandBinding).GetField("CanExecute", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
executedField.SetValue(item, new ExecutedRoutedEventHandler((sender, args) => { }));
|
||||
canExecuteField.SetValue(item, new CanExecuteRoutedEventHandler((sender, args) => { }));
|
||||
}
|
||||
}
|
||||
|
||||
// 为IccInkCanvas注册自定义的 Delete按键Command并Invoke OnDeleteCommandFired。
|
||||
CommandManager.RegisterClassCommandBinding(typeof(IccInkCanvas), new CommandBinding(ApplicationCommands.Delete,
|
||||
(sender, args) => {
|
||||
DeleteKeyCommandFired?.Invoke(this, new RoutedEventArgs());
|
||||
}, (sender, args) => {
|
||||
args.CanExecute = GetSelectedStrokes().Count != 0;
|
||||
}));
|
||||
}
|
||||
|
||||
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e) {
|
||||
IccStroke customStroke = new IccStroke(e.Stroke.StylusPoints, e.Stroke.DrawingAttributes);
|
||||
if (e.Stroke is IccStroke) {
|
||||
this.Strokes.Add(e.Stroke);
|
||||
} else {
|
||||
this.Strokes.Remove(e.Stroke);
|
||||
this.Strokes.Add(customStroke);
|
||||
}
|
||||
|
||||
InkCanvasStrokeCollectedEventArgs args =
|
||||
new InkCanvasStrokeCollectedEventArgs(customStroke);
|
||||
base.OnStrokeCollected(args);
|
||||
}
|
||||
|
||||
public event EventHandler<RoutedEventArgs> DeleteKeyCommandFired;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Ink_Canvas.Helpers;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
private void GridInkReplayButton_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBorderMouseDownObject != sender) return;
|
||||
if (inkCanvas.Strokes.Count == 0) {
|
||||
HideSubPanels();
|
||||
return;
|
||||
};
|
||||
|
||||
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
||||
|
||||
CollapseBorderDrawShape();
|
||||
|
||||
InkCanvasForInkReplay.Visibility = Visibility.Visible;
|
||||
InkCanvasGridForInkReplay.Visibility = Visibility.Hidden;
|
||||
InkCanvasGridForInkReplay.IsHitTestVisible = false;
|
||||
FloatingbarUIForInkReplay.Visibility = Visibility.Hidden;
|
||||
FloatingbarUIForInkReplay.IsHitTestVisible = false;
|
||||
BlackboardUIGridForInkReplay.Visibility = Visibility.Hidden;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = false;
|
||||
|
||||
AnimationsHelper.ShowWithFadeIn(BorderInkReplayToolBox);
|
||||
InkReplayPanelStatusText.Text = "正在重播墨迹...";
|
||||
InkReplayPlayPauseBorder.Background = new SolidColorBrush(Colors.Transparent);
|
||||
InkReplayPlayButtonImage.Visibility = Visibility.Collapsed;
|
||||
InkReplayPauseButtonImage.Visibility = Visibility.Visible;
|
||||
|
||||
isStopInkReplay = false;
|
||||
isPauseInkReplay = false;
|
||||
isRestartInkReplay = false;
|
||||
inkReplaySpeed = 1;
|
||||
InkCanvasForInkReplay.Strokes.Clear();
|
||||
var strokes = inkCanvas.Strokes.Clone();
|
||||
if (inkCanvas.GetSelectedStrokes().Count != 0) strokes = inkCanvas.GetSelectedStrokes().Clone();
|
||||
int k = 1, i = 0;
|
||||
new Thread(() => {
|
||||
isRestartInkReplay = true;
|
||||
while (isRestartInkReplay) {
|
||||
isRestartInkReplay = false;
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
InkCanvasForInkReplay.Strokes.Clear();
|
||||
});
|
||||
foreach (var stroke in strokes) {
|
||||
|
||||
if (isRestartInkReplay) break;
|
||||
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
if (stroke.StylusPoints.Count == 629) //圆或椭圆
|
||||
{
|
||||
Stroke s = null;
|
||||
foreach (var stylusPoint in stroke.StylusPoints) {
|
||||
|
||||
if (isRestartInkReplay) break;
|
||||
|
||||
while (isPauseInkReplay) {
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
if (i++ >= 50) {
|
||||
i = 0;
|
||||
Thread.Sleep((int)(10 / inkReplaySpeed));
|
||||
if (isStopInkReplay) return;
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
try {
|
||||
InkCanvasForInkReplay.Strokes.Remove(s);
|
||||
}
|
||||
catch { }
|
||||
|
||||
stylusPoints.Add(stylusPoint);
|
||||
s = new Stroke(stylusPoints.Clone());
|
||||
s.DrawingAttributes = stroke.DrawingAttributes;
|
||||
InkCanvasForInkReplay.Strokes.Add(s);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Stroke s = null;
|
||||
foreach (var stylusPoint in stroke.StylusPoints) {
|
||||
|
||||
if (isRestartInkReplay) break;
|
||||
|
||||
while (isPauseInkReplay) {
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
if (i++ >= k) {
|
||||
i = 0;
|
||||
Thread.Sleep((int)(10 / inkReplaySpeed));
|
||||
if (isStopInkReplay) return;
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
try {
|
||||
InkCanvasForInkReplay.Strokes.Remove(s);
|
||||
}
|
||||
catch { }
|
||||
|
||||
stylusPoints.Add(stylusPoint);
|
||||
s = new Stroke(stylusPoints.Clone());
|
||||
s.DrawingAttributes = stroke.DrawingAttributes;
|
||||
InkCanvasForInkReplay.Strokes.Add(s);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(100);
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
|
||||
InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
|
||||
InkCanvasGridForInkReplay.IsHitTestVisible = true;
|
||||
AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
|
||||
FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
|
||||
FloatingbarUIForInkReplay.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
});
|
||||
}).Start();
|
||||
}
|
||||
|
||||
#region 墨迹回放(旧版,等待重构)
|
||||
|
||||
private bool isStopInkReplay = false;
|
||||
private bool isPauseInkReplay = false;
|
||||
private bool isRestartInkReplay = false;
|
||||
private double inkReplaySpeed = 1;
|
||||
|
||||
private void InkCanvasForInkReplay_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (e.ClickCount == 2) {
|
||||
InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
|
||||
InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
|
||||
InkCanvasGridForInkReplay.IsHitTestVisible = true;
|
||||
FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
|
||||
FloatingbarUIForInkReplay.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
|
||||
isStopInkReplay = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void InkReplayPlayPauseBorder_OnMouseDown(object sender, MouseButtonEventArgs e) {
|
||||
InkReplayPlayPauseBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
|
||||
}
|
||||
|
||||
private void InkReplayPlayPauseBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
InkReplayPlayPauseBorder.Background = new SolidColorBrush(Colors.Transparent);
|
||||
isPauseInkReplay = !isPauseInkReplay;
|
||||
InkReplayPanelStatusText.Text = isPauseInkReplay?"已暂停!":"正在重播墨迹...";
|
||||
InkReplayPlayButtonImage.Visibility = isPauseInkReplay ? Visibility.Visible: Visibility.Collapsed;
|
||||
InkReplayPauseButtonImage.Visibility = !isPauseInkReplay ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void InkReplayStopButtonBorder_OnMouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
InkReplayStopButtonBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
|
||||
}
|
||||
|
||||
private void InkReplayStopButtonBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
InkReplayStopButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
|
||||
InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
|
||||
InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
|
||||
InkCanvasGridForInkReplay.IsHitTestVisible = true;
|
||||
FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
|
||||
FloatingbarUIForInkReplay.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
|
||||
isStopInkReplay = true;
|
||||
}
|
||||
|
||||
private void InkReplayReplayButtonBorder_OnMouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
InkReplayReplayButtonBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
|
||||
}
|
||||
|
||||
private void InkReplayReplayButtonBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
InkReplayReplayButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
|
||||
isRestartInkReplay = true;
|
||||
isPauseInkReplay = false;
|
||||
InkReplayPanelStatusText.Text = "正在重播墨迹...";
|
||||
InkReplayPlayButtonImage.Visibility = Visibility.Collapsed;
|
||||
InkReplayPauseButtonImage.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void InkReplaySpeedButtonBorder_OnMouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
InkReplaySpeedButtonBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
|
||||
}
|
||||
|
||||
private void InkReplaySpeedButtonBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
InkReplaySpeedButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
|
||||
inkReplaySpeed = inkReplaySpeed == 0.5 ? 1 :
|
||||
inkReplaySpeed == 1 ? 2 :
|
||||
inkReplaySpeed == 2 ? 4 :
|
||||
inkReplaySpeed == 4 ? 8 : 0.5;
|
||||
InkReplaySpeedTextBlock.Text = inkReplaySpeed + "x";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Resources;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
private bool isMouseGesturing = false;
|
||||
private Point startPoint;
|
||||
|
||||
public void InkCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e) {
|
||||
if (e.StylusDevice != null) return;
|
||||
isMouseGesturing = true;
|
||||
MouseRightButtonGestureTipPopup.Visibility = Visibility.Visible;
|
||||
startPoint = e.GetPosition(inkCanvas);
|
||||
inkCanvas.CaptureMouse();
|
||||
inkCanvas.ForceCursor = true;
|
||||
StreamResourceInfo sri = Application.GetResourceStream(
|
||||
new Uri("Resources/Cursors/close-hand-cursor.cur", UriKind.Relative));
|
||||
inkCanvas.Cursor = new Cursor(sri.Stream);
|
||||
}
|
||||
|
||||
public void InkCanvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e) {
|
||||
if (e.StylusDevice != null) return;
|
||||
isMouseGesturing = false;
|
||||
inkCanvas.ReleaseMouseCapture();
|
||||
inkCanvas.ForceCursor = false;
|
||||
MouseRightButtonGestureTipPopup.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void InkCanvas_MouseGesture_MouseMove(object sender, MouseEventArgs e) {
|
||||
if (!isMouseGesturing || e.RightButton != MouseButtonState.Pressed || e.StylusDevice != null) return;
|
||||
Trace.WriteLine(e.StylusDevice == null);
|
||||
Point currentPoint = e.GetPosition(inkCanvas);
|
||||
System.Windows.Vector delta = currentPoint - startPoint;
|
||||
|
||||
foreach (Stroke stroke in inkCanvas.Strokes) {
|
||||
stroke.Transform(new Matrix(1, 0, 0, 1, delta.X, delta.Y), false);
|
||||
}
|
||||
|
||||
startPoint = currentPoint;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
public partial class MainWindow : PerformanceTransparentWin
|
||||
{
|
||||
int lastNotificationShowTime = 0;
|
||||
int notificationShowTime = 2500;
|
||||
|
||||
public static void ShowNewMessage(string notice) {
|
||||
(Application.Current?.Windows.Cast<Window>().FirstOrDefault(window => window is MainWindow) as MainWindow)?.ShowNotification(notice);
|
||||
}
|
||||
|
||||
public MW_Toast ShowNotification(string notice) {
|
||||
var notification = new MW_Toast(MW_Toast.ToastType.Informative, notice, (self) => {
|
||||
GridNotifications.Children.Remove(self);
|
||||
});
|
||||
GridNotifications.Children.Add(notification);
|
||||
notification.ShowAnimatedWithAutoDispose(3000 + notice.Length * 10);
|
||||
return notification;
|
||||
}
|
||||
|
||||
public MW_Toast ShowNewToast(string notice, MW_Toast.ToastType type, int autoCloseMs) {
|
||||
var notification = new MW_Toast(type, notice, (self) => {
|
||||
GridNotifications.Children.Remove(self);
|
||||
});
|
||||
GridNotifications.Children.Add(notification);
|
||||
notification.ShowAnimatedWithAutoDispose(autoCloseMs + notice.Length * 10);
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,961 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using Microsoft.Office.Interop.PowerPoint;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Application = System.Windows.Application;
|
||||
using File = System.IO.File;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
using iNKORE.UI.WPF.Modern;
|
||||
using Microsoft.Office.Core;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
public static Microsoft.Office.Interop.PowerPoint.Application pptApplication = null;
|
||||
public static Presentation presentation = null;
|
||||
public static Slides slides = null;
|
||||
public static Slide slide = null;
|
||||
public static int slidescount = 0;
|
||||
|
||||
private void BtnCheckPPT_Click(object sender, RoutedEventArgs e) {
|
||||
try {
|
||||
pptApplication =
|
||||
(Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("kwpp.Application");
|
||||
//pptApplication.SlideShowWindows[1].View.Next();
|
||||
if (pptApplication != null) {
|
||||
//获得演示文稿对象
|
||||
presentation = pptApplication.ActivePresentation;
|
||||
pptApplication.SlideShowBegin += PptApplication_SlideShowBegin;
|
||||
pptApplication.SlideShowNextSlide += PptApplication_SlideShowNextSlide;
|
||||
pptApplication.SlideShowEnd += PptApplication_SlideShowEnd;
|
||||
// 获得幻灯片对象集合
|
||||
slides = presentation.Slides;
|
||||
// 获得幻灯片的数量
|
||||
slidescount = slides.Count;
|
||||
memoryStreams = new MemoryStream[slidescount + 2];
|
||||
// 获得当前选中的幻灯片
|
||||
try {
|
||||
// 在普通视图下这种方式可以获得当前选中的幻灯片对象
|
||||
// 然而在阅读模式下,这种方式会出现异常
|
||||
slide = slides[pptApplication.ActiveWindow.Selection.SlideRange.SlideNumber];
|
||||
}
|
||||
catch {
|
||||
// 在阅读模式下出现异常时,通过下面的方式来获得当前选中的幻灯片对象
|
||||
slide = pptApplication.SlideShowWindows[1].View.Slide;
|
||||
}
|
||||
}
|
||||
|
||||
if (pptApplication == null) throw new Exception();
|
||||
//BtnCheckPPT.Visibility = Visibility.Collapsed;
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Visible;
|
||||
}
|
||||
catch {
|
||||
//BtnCheckPPT.Visibility = Visibility.Visible;
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Collapsed;
|
||||
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
MessageBox.Show("未找到幻灯片");
|
||||
}
|
||||
}
|
||||
|
||||
private void ToggleSwitchSupportWPS_Toggled(object sender, RoutedEventArgs e) {
|
||||
if (!isLoaded) return;
|
||||
|
||||
Settings.PowerPointSettings.IsSupportWPS = ToggleSwitchSupportWPS.IsOn;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private static bool isWPSSupportOn => Settings.PowerPointSettings.IsSupportWPS;
|
||||
|
||||
public static bool IsShowingRestoreHiddenSlidesWindow = false;
|
||||
private static bool IsShowingAutoplaySlidesWindow = false;
|
||||
|
||||
|
||||
private void TimerCheckPPT_Elapsed(object sender, ElapsedEventArgs e) {
|
||||
if (IsShowingRestoreHiddenSlidesWindow || IsShowingAutoplaySlidesWindow) return;
|
||||
try {
|
||||
//var processes = Process.GetProcessesByName("wpp");
|
||||
//if (processes.Length > 0 && !isWPSSupportOn) return;
|
||||
|
||||
//使用下方提前创建 PowerPoint 实例,将导致 PowerPoint 不再有启动界面
|
||||
//pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("91493441-5A91-11CF-8700-00AA0060263B")));
|
||||
//new ComAwareEventInfo(typeof(EApplication_Event), "SlideShowBegin").AddEventHandler(pptApplication, new EApplication_SlideShowBeginEventHandler(this.PptApplication_SlideShowBegin));
|
||||
//new ComAwareEventInfo(typeof(EApplication_Event), "SlideShowEnd").AddEventHandler(pptApplication, new EApplication_SlideShowEndEventHandler(this.PptApplication_SlideShowEnd));
|
||||
//new ComAwareEventInfo(typeof(EApplication_Event), "SlideShowNextSlide").AddEventHandler(pptApplication, new EApplication_SlideShowNextSlideEventHandler(this.PptApplication_SlideShowNextSlide));
|
||||
//ConfigHelper.Instance.IsInitApplicationSuccessful = true;
|
||||
|
||||
pptApplication =
|
||||
(Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("PowerPoint.Application");
|
||||
|
||||
if (pptApplication != null) {
|
||||
timerCheckPPT.Stop();
|
||||
//获得演示文稿对象
|
||||
presentation = pptApplication.ActivePresentation;
|
||||
|
||||
// 获得幻灯片对象集合
|
||||
slides = presentation.Slides;
|
||||
|
||||
// 获得幻灯片的数量
|
||||
slidescount = slides.Count;
|
||||
memoryStreams = new MemoryStream[slidescount + 2];
|
||||
// 获得当前选中的幻灯片
|
||||
try {
|
||||
// 在普通视图下这种方式可以获得当前选中的幻灯片对象
|
||||
// 然而在阅读模式下,这种方式会出现异常
|
||||
slide = slides[pptApplication.ActiveWindow.Selection.SlideRange.SlideNumber];
|
||||
}
|
||||
catch {
|
||||
// 在阅读模式下出现异常时,通过下面的方式来获得当前选中的幻灯片对象
|
||||
slide = pptApplication.SlideShowWindows[1].View.Slide;
|
||||
}
|
||||
|
||||
pptApplication.PresentationOpen += PptApplication_PresentationOpen;
|
||||
pptApplication.PresentationClose += PptApplication_PresentationClose;
|
||||
pptApplication.SlideShowBegin += PptApplication_SlideShowBegin;
|
||||
pptApplication.SlideShowNextSlide += PptApplication_SlideShowNextSlide;
|
||||
pptApplication.SlideShowEnd += PptApplication_SlideShowEnd;
|
||||
}
|
||||
|
||||
if (pptApplication == null) return;
|
||||
//BtnCheckPPT.Visibility = Visibility.Collapsed;
|
||||
|
||||
// 此处是已经开启了
|
||||
PptApplication_PresentationOpen(null);
|
||||
|
||||
//如果检测到已经开始放映,则立即进入画板模式
|
||||
if (pptApplication.SlideShowWindows.Count >= 1)
|
||||
PptApplication_SlideShowBegin(pptApplication.SlideShowWindows[1]);
|
||||
}
|
||||
catch {
|
||||
//StackPanelPPTControls.Visibility = Visibility.Collapsed;
|
||||
Application.Current.Dispatcher.Invoke(() => { BorderFloatingBarExitPPTBtn.Visibility = Visibility.Collapsed; });
|
||||
timerCheckPPT.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void PptApplication_PresentationOpen(Presentation Pres) {
|
||||
// 跳转到上次播放页
|
||||
if (Settings.PowerPointSettings.IsNotifyPreviousPage)
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
|
||||
var folderPath = Settings.Automation.AutoSavedStrokesLocation +
|
||||
@"\Auto Saved - Presentations\" + presentation.Name + "_" +
|
||||
presentation.Slides.Count;
|
||||
try {
|
||||
if (!File.Exists(folderPath + "/Position")) return;
|
||||
if (!int.TryParse(File.ReadAllText(folderPath + "/Position"), out var page)) return;
|
||||
if (page <= 0) return;
|
||||
new YesOrNoNotificationWindow($"上次播放到了第 {page} 页, 是否立即跳转", () => {
|
||||
if (pptApplication.SlideShowWindows.Count >= 1)
|
||||
// 如果已经播放了的话, 跳转
|
||||
presentation.SlideShowWindow.View.GotoSlide(page);
|
||||
else
|
||||
presentation.Windows[1].View.GotoSlide(page);
|
||||
}).ShowDialog();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
}), DispatcherPriority.Normal);
|
||||
|
||||
|
||||
//检查是否有隐藏幻灯片
|
||||
if (Settings.PowerPointSettings.IsNotifyHiddenPage) {
|
||||
var isHaveHiddenSlide = false;
|
||||
foreach (Slide slide in slides)
|
||||
if (slide.SlideShowTransition.Hidden == Microsoft.Office.Core.MsoTriState.msoTrue) {
|
||||
isHaveHiddenSlide = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
|
||||
if (isHaveHiddenSlide && !IsShowingRestoreHiddenSlidesWindow) {
|
||||
IsShowingRestoreHiddenSlidesWindow = true;
|
||||
new YesOrNoNotificationWindow("检测到此演示文档中包含隐藏的幻灯片,是否取消隐藏?",
|
||||
() => {
|
||||
foreach (Slide slide in slides)
|
||||
if (slide.SlideShowTransition.Hidden ==
|
||||
Microsoft.Office.Core.MsoTriState.msoTrue)
|
||||
slide.SlideShowTransition.Hidden =
|
||||
Microsoft.Office.Core.MsoTriState.msoFalse;
|
||||
IsShowingRestoreHiddenSlidesWindow = false;
|
||||
}, () => { IsShowingRestoreHiddenSlidesWindow = false; },
|
||||
() => { IsShowingRestoreHiddenSlidesWindow = false; }).ShowDialog();
|
||||
}
|
||||
}), DispatcherPriority.Normal);
|
||||
}
|
||||
|
||||
//检测是否有自动播放
|
||||
if (Settings.PowerPointSettings.IsNotifyAutoPlayPresentation
|
||||
// && presentation.SlideShowSettings.AdvanceMode == PpSlideShowAdvanceMode.ppSlideShowUseSlideTimings
|
||||
&& BorderFloatingBarExitPPTBtn.Visibility != Visibility.Visible) {
|
||||
bool hasSlideTimings = false;
|
||||
foreach (Slide slide in presentation.Slides) {
|
||||
if (slide.SlideShowTransition.AdvanceOnTime == MsoTriState.msoTrue &&
|
||||
slide.SlideShowTransition.AdvanceTime > 0) {
|
||||
hasSlideTimings = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSlideTimings) {
|
||||
Application.Current.Dispatcher.BeginInvoke((Action)(() => {
|
||||
if (hasSlideTimings && !IsShowingAutoplaySlidesWindow) {
|
||||
IsShowingAutoplaySlidesWindow = true;
|
||||
new YesOrNoNotificationWindow("检测到此演示文档中自动播放或排练计时已经启用,可能导致幻灯片自动翻页,是否取消?",
|
||||
() => {
|
||||
presentation.SlideShowSettings.AdvanceMode =
|
||||
PpSlideShowAdvanceMode.ppSlideShowManualAdvance;
|
||||
IsShowingAutoplaySlidesWindow = false;
|
||||
}, () => { IsShowingAutoplaySlidesWindow = false; },
|
||||
() => { IsShowingAutoplaySlidesWindow = false; }).ShowDialog();
|
||||
}
|
||||
}));
|
||||
presentation.SlideShowSettings.AdvanceMode = PpSlideShowAdvanceMode.ppSlideShowManualAdvance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PptApplication_PresentationClose(Presentation Pres) {
|
||||
pptApplication.PresentationOpen -= PptApplication_PresentationOpen;
|
||||
pptApplication.PresentationClose -= PptApplication_PresentationClose;
|
||||
pptApplication.SlideShowBegin -= PptApplication_SlideShowBegin;
|
||||
pptApplication.SlideShowNextSlide -= PptApplication_SlideShowNextSlide;
|
||||
pptApplication.SlideShowEnd -= PptApplication_SlideShowEnd;
|
||||
pptApplication = null;
|
||||
timerCheckPPT.Start();
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
}
|
||||
|
||||
private bool isPresentationHaveBlackSpace = false;
|
||||
|
||||
|
||||
private string pptName = null;
|
||||
int currentShowPosition = -1;
|
||||
|
||||
private void UpdatePPTBtnStyleSettingsStatus() {
|
||||
var sopt = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
|
||||
char[] soptc = sopt.ToCharArray();
|
||||
if (soptc[0] == '2')
|
||||
{
|
||||
PPTLSPageButton.Visibility = Visibility.Visible;
|
||||
PPTRSPageButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
PPTLSPageButton.Visibility = Visibility.Collapsed;
|
||||
PPTRSPageButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
if (soptc[2] == '2')
|
||||
{
|
||||
// 这里先堆一点屎山,没空用Resources了
|
||||
PPTBtnLSBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTBtnRSBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTBtnLSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
|
||||
PPTBtnRSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
|
||||
PPTLSPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTRSPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTLSNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTRSNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTLSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTRSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTLSPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTRSPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTLSNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTRSNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
TextBlock.SetForeground(PPTLSPageButton, new SolidColorBrush(Colors.White));
|
||||
TextBlock.SetForeground(PPTRSPageButton, new SolidColorBrush(Colors.White));
|
||||
}
|
||||
else
|
||||
{
|
||||
PPTBtnLSBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
|
||||
PPTBtnRSBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
|
||||
PPTBtnLSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
|
||||
PPTBtnRSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
|
||||
PPTLSPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTRSPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTLSNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTRSNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTLSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTRSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTLSPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTRSPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTLSNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTRSNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
TextBlock.SetForeground(PPTLSPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
|
||||
TextBlock.SetForeground(PPTRSPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
|
||||
}
|
||||
if (soptc[1] == '2')
|
||||
{
|
||||
PPTBtnLSBorder.Opacity = 0.5;
|
||||
PPTBtnRSBorder.Opacity = 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
PPTBtnLSBorder.Opacity = 1;
|
||||
PPTBtnRSBorder.Opacity = 1;
|
||||
}
|
||||
|
||||
var bopt = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
|
||||
char[] boptc = bopt.ToCharArray();
|
||||
if (boptc[0] == '2')
|
||||
{
|
||||
PPTLBPageButton.Visibility = Visibility.Visible;
|
||||
PPTRBPageButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
PPTLBPageButton.Visibility = Visibility.Collapsed;
|
||||
PPTRBPageButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
if (boptc[2] == '2')
|
||||
{
|
||||
// 这里先堆一点屎山,没空用Resources了
|
||||
PPTBtnLBBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTBtnRBBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTBtnLBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
|
||||
PPTBtnRBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
|
||||
PPTLBPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTRBPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTLBNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTRBNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
|
||||
PPTLBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTRBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTLBPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTRBPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTLBNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
PPTRBNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
|
||||
TextBlock.SetForeground(PPTLBPageButton, new SolidColorBrush(Colors.White));
|
||||
TextBlock.SetForeground(PPTRBPageButton, new SolidColorBrush(Colors.White));
|
||||
}
|
||||
else
|
||||
{
|
||||
PPTBtnLBBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
|
||||
PPTBtnRBBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
|
||||
PPTBtnLBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
|
||||
PPTBtnRBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
|
||||
PPTLBPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTRBPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTLBNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTRBNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
PPTLBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTRBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTLBPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTRBPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTLBNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
PPTRBNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
|
||||
TextBlock.SetForeground(PPTLBPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
|
||||
TextBlock.SetForeground(PPTRBPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
|
||||
}
|
||||
if (boptc[1] == '2')
|
||||
{
|
||||
PPTBtnLBBorder.Opacity = 0.5;
|
||||
PPTBtnRBBorder.Opacity = 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
PPTBtnLBBorder.Opacity = 1;
|
||||
PPTBtnRBBorder.Opacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePPTBtnDisplaySettingsStatus() {
|
||||
|
||||
if (!Settings.PowerPointSettings.ShowPPTButton) {
|
||||
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
return;
|
||||
}
|
||||
|
||||
var lsp = Settings.PowerPointSettings.PPTLSButtonPosition;
|
||||
LeftSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, lsp*2);
|
||||
var rsp = Settings.PowerPointSettings.PPTRSButtonPosition;
|
||||
RightSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, rsp*2);
|
||||
|
||||
var dopt = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
|
||||
char[] doptc = dopt.ToCharArray();
|
||||
|
||||
if (doptc[0] == '2') AnimationsHelper.ShowWithFadeIn(LeftBottomPanelForPPTNavigation);
|
||||
else LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
if (doptc[1] == '2') AnimationsHelper.ShowWithFadeIn(RightBottomPanelForPPTNavigation);
|
||||
else RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
if (doptc[2] == '2') AnimationsHelper.ShowWithFadeIn(LeftSidePanelForPPTNavigation);
|
||||
else LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
if (doptc[3] == '2') AnimationsHelper.ShowWithFadeIn(RightSidePanelForPPTNavigation);
|
||||
else RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private async void PptApplication_SlideShowBegin(SlideShowWindow Wn) {
|
||||
if (Settings.Automation.IsAutoFoldInPPTSlideShow && !isFloatingBarFolded)
|
||||
await FoldFloatingBar(new object());
|
||||
else if (isFloatingBarFolded) await UnFoldFloatingBar(new object());
|
||||
|
||||
isStopInkReplay = true;
|
||||
|
||||
LogHelper.WriteLogToFile("PowerPoint Application Slide Show Begin", LogHelper.LogType.Event);
|
||||
|
||||
await Application.Current.Dispatcher.InvokeAsync(() => {
|
||||
|
||||
//调整颜色
|
||||
var screenRatio = SystemParameters.PrimaryScreenWidth / SystemParameters.PrimaryScreenHeight;
|
||||
if (Math.Abs(screenRatio - 16.0 / 9) <= -0.01) {
|
||||
if (Wn.Presentation.PageSetup.SlideWidth / Wn.Presentation.PageSetup.SlideHeight < 1.65) {
|
||||
isPresentationHaveBlackSpace = true;
|
||||
}
|
||||
} else if (screenRatio == -256 / 135) { }
|
||||
|
||||
lastDesktopInkColor = 1;
|
||||
|
||||
slidescount = Wn.Presentation.Slides.Count;
|
||||
previousSlideID = 0;
|
||||
memoryStreams = new MemoryStream[slidescount + 2];
|
||||
|
||||
pptName = Wn.Presentation.Name;
|
||||
LogHelper.NewLog("Name: " + Wn.Presentation.Name);
|
||||
LogHelper.NewLog("Slides Count: " + slidescount.ToString());
|
||||
|
||||
//检查是否有已有墨迹,并加载
|
||||
if (Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint)
|
||||
if (Directory.Exists(Settings.Automation.AutoSavedStrokesLocation +
|
||||
@"\Auto Saved - Presentations\" + Wn.Presentation.Name + "_" +
|
||||
Wn.Presentation.Slides.Count)) {
|
||||
LogHelper.WriteLogToFile("Found saved strokes", LogHelper.LogType.Trace);
|
||||
var files = new DirectoryInfo(Settings.Automation.AutoSavedStrokesLocation +
|
||||
@"\Auto Saved - Presentations\" + Wn.Presentation.Name + "_" +
|
||||
Wn.Presentation.Slides.Count).GetFiles();
|
||||
var count = 0;
|
||||
foreach (var file in files)
|
||||
if (file.Name != "Position") {
|
||||
var i = -1;
|
||||
try {
|
||||
i = int.Parse(Path.GetFileNameWithoutExtension(file.Name));
|
||||
memoryStreams[i] = new MemoryStream(File.ReadAllBytes(file.FullName));
|
||||
memoryStreams[i].Position = 0;
|
||||
count++;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(
|
||||
$"Failed to load strokes on Slide {i}\n{ex.ToString()}",
|
||||
LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile($"Loaded {count.ToString()} saved strokes");
|
||||
}
|
||||
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Visible;
|
||||
|
||||
// -- old --
|
||||
//if (Settings.PowerPointSettings.IsShowBottomPPTNavigationPanel && !isFloatingBarFolded)
|
||||
// AnimationsHelper.ShowWithSlideFromBottomAndFade(BottomViewboxPPTSidesControl);
|
||||
//else
|
||||
// BottomViewboxPPTSidesControl.Visibility = Visibility.Collapsed;
|
||||
|
||||
//if (Settings.PowerPointSettings.IsShowSidePPTNavigationPanel && !isFloatingBarFolded) {
|
||||
|
||||
// AnimationsHelper.ShowWithScaleFromRight(RightSidePanelForPPTNavigation);
|
||||
//} else {
|
||||
// LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
// RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
//}
|
||||
// -- old --
|
||||
|
||||
// -- new --
|
||||
if (!isFloatingBarFolded) {
|
||||
UpdatePPTBtnDisplaySettingsStatus();
|
||||
UpdatePPTBtnStyleSettingsStatus();
|
||||
}
|
||||
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Visible;
|
||||
ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue;
|
||||
|
||||
if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
|
||||
!Settings.Automation.IsAutoFoldInPPTSlideShow &&
|
||||
GridTransparencyFakeBackground.Background == Brushes.Transparent && !isFloatingBarFolded) {
|
||||
BtnHideInkCanvas_Click(null, null);
|
||||
}
|
||||
|
||||
if (currentMode != 0)
|
||||
{
|
||||
//currentMode = 0;
|
||||
//GridBackgroundCover.Visibility = Visibility.Collapsed;
|
||||
//AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
|
||||
//AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
|
||||
//AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
|
||||
|
||||
//SaveStrokes();
|
||||
//ClearStrokes(true);
|
||||
|
||||
//BtnSwitch.Content = BtnSwitchTheme.Content.ToString() == "浅色" ? "黑板" : "白板";
|
||||
//StackPanelPPTButtons.Visibility = Visibility.Visible;
|
||||
ImageBlackboard_MouseUp(null,null);
|
||||
BtnHideInkCanvas_Click(null, null);
|
||||
}
|
||||
|
||||
//ClearStrokes(true);
|
||||
|
||||
BorderFloatingBarMainControls.Visibility = Visibility.Visible;
|
||||
|
||||
if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
|
||||
!Settings.Automation.IsAutoFoldInPPTSlideShow)
|
||||
BtnColorRed_Click(null, null);
|
||||
|
||||
isEnteredSlideShowEndEvent = false;
|
||||
PPTBtnPageNow.Text = $"{Wn.View.CurrentShowPosition}";
|
||||
PPTBtnPageTotal.Text = $"/ {Wn.Presentation.Slides.Count}";
|
||||
LogHelper.NewLog("PowerPoint Slide Show Loading process complete");
|
||||
|
||||
if (!isFloatingBarFolded) {
|
||||
new Thread(new ThreadStart(() => {
|
||||
Thread.Sleep(100);
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
ViewboxFloatingBarMarginAnimation(60);
|
||||
});
|
||||
})).Start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private bool isEnteredSlideShowEndEvent = false; //防止重复调用本函数导致墨迹保存失效
|
||||
|
||||
private async void PptApplication_SlideShowEnd(Presentation Pres) {
|
||||
if (isFloatingBarFolded) await UnFoldFloatingBar(new object());
|
||||
|
||||
LogHelper.WriteLogToFile(string.Format("PowerPoint Slide Show End"), LogHelper.LogType.Event);
|
||||
if (isEnteredSlideShowEndEvent) {
|
||||
LogHelper.WriteLogToFile("Detected previous entrance, returning");
|
||||
return;
|
||||
}
|
||||
|
||||
isEnteredSlideShowEndEvent = true;
|
||||
if (Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint) {
|
||||
var folderPath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - Presentations\" +
|
||||
Pres.Name + "_" + Pres.Slides.Count;
|
||||
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
|
||||
try {
|
||||
File.WriteAllText(folderPath + "/Position", previousSlideID.ToString());
|
||||
}
|
||||
catch { }
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
inkCanvas.Strokes.Save(ms);
|
||||
ms.Position = 0;
|
||||
memoryStreams[currentShowPosition] = ms;
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
for (var i = 1; i <= Pres.Slides.Count; i++)
|
||||
if (memoryStreams[i] != null)
|
||||
try {
|
||||
if (memoryStreams[i].Length > 8) {
|
||||
var srcBuf = new byte[memoryStreams[i].Length];
|
||||
var byteLength = memoryStreams[i].Read(srcBuf, 0, srcBuf.Length);
|
||||
File.WriteAllBytes(folderPath + @"\" + i.ToString("0000") + ".icstk", srcBuf);
|
||||
LogHelper.WriteLogToFile(string.Format(
|
||||
"Saved strokes for Slide {0}, size={1}, byteLength={2}", i.ToString(),
|
||||
memoryStreams[i].Length, byteLength));
|
||||
} else {
|
||||
File.Delete(folderPath + @"\" + i.ToString("0000") + ".icstk");
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(
|
||||
$"Failed to save strokes for Slide {i}\n{ex.ToString()}",
|
||||
LogHelper.LogType.Error);
|
||||
File.Delete(folderPath + @"\" + i.ToString("0000") + ".icstk");
|
||||
}
|
||||
}
|
||||
|
||||
await Application.Current.Dispatcher.InvokeAsync(() => {
|
||||
isPresentationHaveBlackSpace = false;
|
||||
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Collapsed;
|
||||
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
|
||||
|
||||
if (currentMode != 0) {
|
||||
ImageBlackboard_MouseUp(null,null);
|
||||
}
|
||||
|
||||
ClearStrokes(true);
|
||||
|
||||
if (GridTransparencyFakeBackground.Background != Brushes.Transparent)
|
||||
BtnHideInkCanvas_Click(null, null);
|
||||
|
||||
ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityValue;
|
||||
});
|
||||
|
||||
await Task.Delay(150);
|
||||
|
||||
Application.Current.Dispatcher.InvokeAsync(() => {
|
||||
ViewboxFloatingBarMarginAnimation(100, true);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private int previousSlideID = 0;
|
||||
private MemoryStream[] memoryStreams = new MemoryStream[50];
|
||||
|
||||
private void PptApplication_SlideShowNextSlide(SlideShowWindow Wn) {
|
||||
LogHelper.WriteLogToFile($"PowerPoint Next Slide (Slide {Wn.View.CurrentShowPosition})",
|
||||
LogHelper.LogType.Event);
|
||||
if (Wn.View.CurrentShowPosition == previousSlideID) return;
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
var ms = new MemoryStream();
|
||||
inkCanvas.Strokes.Save(ms);
|
||||
ms.Position = 0;
|
||||
memoryStreams[previousSlideID] = ms;
|
||||
|
||||
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
|
||||
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint && !_isPptClickingBtnTurned)
|
||||
SavePPTScreenshot(Wn.Presentation.Name + "/" + Wn.View.CurrentShowPosition);
|
||||
_isPptClickingBtnTurned = false;
|
||||
|
||||
ClearStrokes(true);
|
||||
timeMachine.ClearStrokeHistory();
|
||||
|
||||
try {
|
||||
if (memoryStreams[Wn.View.CurrentShowPosition] != null &&
|
||||
memoryStreams[Wn.View.CurrentShowPosition].Length > 0)
|
||||
inkCanvas.Strokes.Add(new StrokeCollection(memoryStreams[Wn.View.CurrentShowPosition]));
|
||||
|
||||
currentShowPosition = Wn.View.CurrentShowPosition;
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
|
||||
PPTBtnPageNow.Text = $"{Wn.View.CurrentShowPosition}";
|
||||
PPTBtnPageTotal.Text = $"/ {Wn.Presentation.Slides.Count}";
|
||||
|
||||
//PptNavigationTextBlock.Text = $"{Wn.View.CurrentShowPosition}/{Wn.Presentation.Slides.Count}";
|
||||
});
|
||||
previousSlideID = Wn.View.CurrentShowPosition;
|
||||
|
||||
}
|
||||
|
||||
private bool _isPptClickingBtnTurned = false;
|
||||
|
||||
private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) {
|
||||
if (currentMode == 1) {
|
||||
GridBackgroundCover.Visibility = Visibility.Collapsed;
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
|
||||
currentMode = 0;
|
||||
}
|
||||
|
||||
_isPptClickingBtnTurned = true;
|
||||
|
||||
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
|
||||
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
|
||||
SavePPTScreenshot(pptApplication.SlideShowWindows[1].Presentation.Name + "/" + pptApplication.SlideShowWindows[1].View.CurrentShowPosition);
|
||||
|
||||
try {
|
||||
new Thread(new ThreadStart(() => {
|
||||
try {
|
||||
pptApplication.SlideShowWindows[1].Activate();
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
|
||||
try {
|
||||
pptApplication.SlideShowWindows[1].View.Previous();
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
} // Without this catch{}, app will crash when click the pre-page button in the fir page in some special env.
|
||||
})).Start();
|
||||
}
|
||||
catch {
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Collapsed;
|
||||
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) {
|
||||
if (currentMode == 1) {
|
||||
GridBackgroundCover.Visibility = Visibility.Collapsed;
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
|
||||
AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
|
||||
currentMode = 0;
|
||||
}
|
||||
|
||||
_isPptClickingBtnTurned = true;
|
||||
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
|
||||
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
|
||||
SavePPTScreenshot(pptApplication.SlideShowWindows[1].Presentation.Name + "/" + pptApplication.SlideShowWindows[1].View.CurrentShowPosition);
|
||||
try {
|
||||
new Thread(new ThreadStart(() => {
|
||||
try {
|
||||
pptApplication.SlideShowWindows[1].Activate();
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
|
||||
try {
|
||||
pptApplication.SlideShowWindows[1].View.Next();
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
})).Start();
|
||||
}
|
||||
catch {
|
||||
BorderFloatingBarExitPPTBtn.Visibility = Visibility.Collapsed;
|
||||
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private async void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
lastBorderMouseDownObject = sender;
|
||||
if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
|
||||
if (sender == PPTLSPageButton)
|
||||
{
|
||||
PPTLSPageButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
else if (sender == PPTRSPageButton)
|
||||
{
|
||||
PPTRSPageButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
else if (sender == PPTLBPageButton)
|
||||
{
|
||||
PPTLBPageButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
else if (sender == PPTRBPageButton)
|
||||
{
|
||||
PPTRBPageButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
}
|
||||
|
||||
private async void PPTNavigationBtn_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
lastBorderMouseDownObject = null;
|
||||
if (sender == PPTLSPageButton)
|
||||
{
|
||||
PPTLSPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRSPageButton)
|
||||
{
|
||||
PPTRSPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTLBPageButton)
|
||||
{
|
||||
PPTLBPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRBPageButton)
|
||||
{
|
||||
PPTRBPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private async void PPTNavigationBtn_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBorderMouseDownObject != sender) return;
|
||||
|
||||
if (sender == PPTLSPageButton)
|
||||
{
|
||||
PPTLSPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRSPageButton)
|
||||
{
|
||||
PPTRSPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTLBPageButton)
|
||||
{
|
||||
PPTLBPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRBPageButton)
|
||||
{
|
||||
PPTRBPageButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
|
||||
if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
|
||||
|
||||
GridTransparencyFakeBackground.Opacity = 1;
|
||||
GridTransparencyFakeBackground.Background = new SolidColorBrush(StringToColor("#01FFFFFF"));
|
||||
CursorIcon_Click(null, null);
|
||||
try {
|
||||
pptApplication.SlideShowWindows[1].SlideNavigation.Visible = true;
|
||||
}
|
||||
catch { }
|
||||
|
||||
// 控制居中
|
||||
if (!isFloatingBarFolded) {
|
||||
await Task.Delay(100);
|
||||
ViewboxFloatingBarMarginAnimation(60);
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnPPTSlideShow_Click(object sender, RoutedEventArgs e) {
|
||||
new Thread(new ThreadStart(() => {
|
||||
try {
|
||||
presentation.SlideShowSettings.Run();
|
||||
}
|
||||
catch { }
|
||||
})).Start();
|
||||
}
|
||||
|
||||
private async void BtnPPTSlideShowEnd_Click(object sender, RoutedEventArgs e) {
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
try {
|
||||
var ms = new MemoryStream();
|
||||
inkCanvas.Strokes.Save(ms);
|
||||
ms.Position = 0;
|
||||
memoryStreams[pptApplication.SlideShowWindows[1].View.CurrentShowPosition] = ms;
|
||||
timeMachine.ClearStrokeHistory();
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
});
|
||||
new Thread(new ThreadStart(() => {
|
||||
try {
|
||||
pptApplication.SlideShowWindows[1].View.Exit();
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
})).Start();
|
||||
|
||||
HideSubPanels("cursor");
|
||||
// update tool selection
|
||||
SelectedMode = ICCToolsEnum.CursorMode;
|
||||
ForceUpdateToolSelection(null);
|
||||
await Task.Delay(150);
|
||||
ViewboxFloatingBarMarginAnimation(100, true);
|
||||
}
|
||||
|
||||
private void GridPPTControlPrevious_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
lastBorderMouseDownObject = sender;
|
||||
if (sender == PPTLSPreviousButtonBorder) {
|
||||
PPTLSPreviousButtonFeedbackBorder.Opacity = 0.15;
|
||||
} else if (sender == PPTRSPreviousButtonBorder) {
|
||||
PPTRSPreviousButtonFeedbackBorder.Opacity = 0.15;
|
||||
} else if (sender == PPTLBPreviousButtonBorder)
|
||||
{
|
||||
PPTLBPreviousButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
else if (sender == PPTRBPreviousButtonBorder)
|
||||
{
|
||||
PPTRBPreviousButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
}
|
||||
private void GridPPTControlPrevious_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
lastBorderMouseDownObject = null;
|
||||
if (sender == PPTLSPreviousButtonBorder) {
|
||||
PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTRSPreviousButtonBorder) {
|
||||
PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTLBPreviousButtonBorder)
|
||||
{
|
||||
PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRBPreviousButtonBorder)
|
||||
{
|
||||
PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
}
|
||||
private void GridPPTControlPrevious_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBorderMouseDownObject != sender) return;
|
||||
if (sender == PPTLSPreviousButtonBorder) {
|
||||
PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTRSPreviousButtonBorder) {
|
||||
PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTLBPreviousButtonBorder)
|
||||
{
|
||||
PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRBPreviousButtonBorder)
|
||||
{
|
||||
PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
BtnPPTSlidesUp_Click(null, null);
|
||||
}
|
||||
|
||||
|
||||
private void GridPPTControlNext_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||
lastBorderMouseDownObject = sender;
|
||||
if (sender == PPTLSNextButtonBorder) {
|
||||
PPTLSNextButtonFeedbackBorder.Opacity = 0.15;
|
||||
} else if (sender == PPTRSNextButtonBorder) {
|
||||
PPTRSNextButtonFeedbackBorder.Opacity = 0.15;
|
||||
} else if (sender == PPTLBNextButtonBorder)
|
||||
{
|
||||
PPTLBNextButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
else if (sender == PPTRBNextButtonBorder)
|
||||
{
|
||||
PPTRBNextButtonFeedbackBorder.Opacity = 0.15;
|
||||
}
|
||||
}
|
||||
private void GridPPTControlNext_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
lastBorderMouseDownObject = null;
|
||||
if (sender == PPTLSNextButtonBorder) {
|
||||
PPTLSNextButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTRSNextButtonBorder) {
|
||||
PPTRSNextButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTLBNextButtonBorder)
|
||||
{
|
||||
PPTLBNextButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRBNextButtonBorder)
|
||||
{
|
||||
PPTRBNextButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
}
|
||||
private void GridPPTControlNext_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBorderMouseDownObject != sender) return;
|
||||
if (sender == PPTLSNextButtonBorder) {
|
||||
PPTLSNextButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTRSNextButtonBorder) {
|
||||
PPTRSNextButtonFeedbackBorder.Opacity = 0;
|
||||
} else if (sender == PPTLBNextButtonBorder)
|
||||
{
|
||||
PPTLBNextButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
else if (sender == PPTRBNextButtonBorder)
|
||||
{
|
||||
PPTRBNextButtonFeedbackBorder.Opacity = 0;
|
||||
}
|
||||
BtnPPTSlidesDown_Click(null, null);
|
||||
}
|
||||
|
||||
private void ImagePPTControlEnd_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
BtnPPTSlideShowEnd_Click(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Ink_Canvas.Helpers;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
public partial class MainWindow : PerformanceTransparentWin
|
||||
{
|
||||
private class PageListViewItem
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public StrokeCollection Strokes { get; set; }
|
||||
}
|
||||
|
||||
ObservableCollection<PageListViewItem> blackBoardSidePageListViewObservableCollection = new ObservableCollection<PageListViewItem>();
|
||||
|
||||
/// <summary>
|
||||
/// <para>刷新白板的缩略图页面列表。</para>
|
||||
/// </summary>
|
||||
private void RefreshBlackBoardSidePageListView()
|
||||
{
|
||||
if (blackBoardSidePageListViewObservableCollection.Count == WhiteboardTotalCount) {
|
||||
foreach (int index in Enumerable.Range(1, WhiteboardTotalCount))
|
||||
{
|
||||
var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]);
|
||||
st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
|
||||
var pitem = new PageListViewItem()
|
||||
{
|
||||
Index = index,
|
||||
Strokes = st,
|
||||
};
|
||||
blackBoardSidePageListViewObservableCollection[index-1] = pitem;
|
||||
}
|
||||
} else {
|
||||
blackBoardSidePageListViewObservableCollection.Clear();
|
||||
foreach (int index in Enumerable.Range(1, WhiteboardTotalCount)) {
|
||||
var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]);
|
||||
st.Clip(new Rect(0,0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
|
||||
var pitem = new PageListViewItem()
|
||||
{
|
||||
Index = index,
|
||||
Strokes = st,
|
||||
};
|
||||
blackBoardSidePageListViewObservableCollection.Add(pitem);
|
||||
}
|
||||
}
|
||||
|
||||
var _st = inkCanvas.Strokes.Clone();
|
||||
_st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
|
||||
var _pitem = new PageListViewItem()
|
||||
{
|
||||
Index = CurrentWhiteboardIndex,
|
||||
Strokes = _st,
|
||||
};
|
||||
blackBoardSidePageListViewObservableCollection[CurrentWhiteboardIndex - 1] = _pitem;
|
||||
|
||||
BlackBoardLeftSidePageListView.SelectedIndex = CurrentWhiteboardIndex -1;
|
||||
BlackBoardRightSidePageListView.SelectedIndex = CurrentWhiteboardIndex -1;
|
||||
}
|
||||
|
||||
public static void ScrollViewToVerticalTop(FrameworkElement element, ScrollViewer scrollViewer)
|
||||
{
|
||||
var scrollViewerOffset = scrollViewer.VerticalOffset;
|
||||
var point = new Point(0, scrollViewerOffset);
|
||||
var tarPos = element.TransformToVisual(scrollViewer).Transform(point);
|
||||
scrollViewer.ScrollToVerticalOffset(tarPos.Y);
|
||||
}
|
||||
|
||||
|
||||
private void BlackBoardLeftSidePageListView_OnMouseUp(object sender, MouseButtonEventArgs e) {
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
|
||||
var item = BlackBoardLeftSidePageListView.SelectedItem;
|
||||
var index = BlackBoardLeftSidePageListView.SelectedIndex;
|
||||
if (item != null)
|
||||
{
|
||||
SaveStrokes();
|
||||
ClearStrokes(true);
|
||||
CurrentWhiteboardIndex= index+1;
|
||||
RestoreStrokes();
|
||||
UpdateIndexInfoDisplay();
|
||||
BlackBoardLeftSidePageListView.SelectedIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
private void BlackBoardRightSidePageListView_OnMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
|
||||
var item = BlackBoardRightSidePageListView.SelectedItem;
|
||||
var index = BlackBoardRightSidePageListView.SelectedIndex;
|
||||
if (item != null)
|
||||
{
|
||||
SaveStrokes();
|
||||
ClearStrokes(true);
|
||||
CurrentWhiteboardIndex = index + 1;
|
||||
RestoreStrokes();
|
||||
UpdateIndexInfoDisplay();
|
||||
BlackBoardRightSidePageListView.SelectedIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
private void SymbolIconSaveStrokes_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBorderMouseDownObject != sender || inkCanvas.Visibility != Visibility.Visible) return;
|
||||
|
||||
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
||||
|
||||
GridNotifications.Visibility = Visibility.Collapsed;
|
||||
|
||||
SaveInkCanvasStrokes(true, true);
|
||||
}
|
||||
|
||||
private void SaveInkCanvasStrokes(bool newNotice = true, bool saveByUser = false) {
|
||||
try {
|
||||
var savePath = Settings.Automation.AutoSavedStrokesLocation
|
||||
+ (saveByUser ? @"\User Saved - " : @"\Auto Saved - ")
|
||||
+ (currentMode == 0 ? "Annotation Strokes" : "BlackBoard Strokes");
|
||||
if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);
|
||||
string savePathWithName;
|
||||
if (currentMode != 0) // 黑板模式下
|
||||
savePathWithName = savePath + @"\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + " Page-" +
|
||||
CurrentWhiteboardIndex + " StrokesCount-" + inkCanvas.Strokes.Count + ".icstk";
|
||||
else
|
||||
//savePathWithName = savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".icstk";
|
||||
savePathWithName = savePath + @"\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + ".icstk";
|
||||
var fs = new FileStream(savePathWithName, FileMode.Create);
|
||||
inkCanvas.Strokes.Save(fs);
|
||||
if (newNotice) ShowNewToast("墨迹成功保存至 " + savePathWithName, MW_Toast.ToastType.Success, 2500);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ShowNewToast("墨迹保存失败!", MW_Toast.ToastType.Error, 3000);
|
||||
LogHelper.WriteLogToFile("墨迹保存失败 | " + ex.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void SymbolIconOpenStrokes_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastBorderMouseDownObject != sender) return;
|
||||
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
||||
|
||||
var openFileDialog = new OpenFileDialog();
|
||||
openFileDialog.InitialDirectory = Settings.Automation.AutoSavedStrokesLocation;
|
||||
openFileDialog.Title = "打开墨迹文件";
|
||||
openFileDialog.Filter = "Ink Canvas Strokes File (*.icstk)|*.icstk";
|
||||
if (openFileDialog.ShowDialog() != true) return;
|
||||
LogHelper.WriteLogToFile($"Strokes Insert: Name: {openFileDialog.FileName}",
|
||||
LogHelper.LogType.Event);
|
||||
try {
|
||||
var fileStreamHasNoStroke = false;
|
||||
using (var fs = new FileStream(openFileDialog.FileName, FileMode.Open, FileAccess.Read)) {
|
||||
var strokes = new StrokeCollection(fs);
|
||||
fileStreamHasNoStroke = strokes.Count == 0;
|
||||
if (!fileStreamHasNoStroke) {
|
||||
ClearStrokes(true);
|
||||
timeMachine.ClearStrokeHistory();
|
||||
inkCanvas.Strokes.Add(strokes);
|
||||
LogHelper.NewLog($"Strokes Insert: Strokes Count: {inkCanvas.Strokes.Count.ToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
if (fileStreamHasNoStroke)
|
||||
using (var ms = new MemoryStream(File.ReadAllBytes(openFileDialog.FileName))) {
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
var strokes = new StrokeCollection(ms);
|
||||
ClearStrokes(true);
|
||||
timeMachine.ClearStrokeHistory();
|
||||
inkCanvas.Strokes.Add(strokes);
|
||||
LogHelper.NewLog($"Strokes Insert (2): Strokes Count: {strokes.Count.ToString()}");
|
||||
}
|
||||
|
||||
if (inkCanvas.Visibility != Visibility.Visible) SymbolIconCursor_Click(sender, null);
|
||||
}
|
||||
catch {
|
||||
ShowNewToast("墨迹打开失败!", MW_Toast.ToastType.Error, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,745 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using OSVersionExtension;
|
||||
using Vanara.PInvoke;
|
||||
using Encoder = System.Drawing.Imaging.Encoder;
|
||||
using OperatingSystem = OSVersionExtension.OperatingSystem;
|
||||
using PixelFormat = System.Drawing.Imaging.PixelFormat;
|
||||
using System.Management;
|
||||
using System.Reflection;
|
||||
using System.Windows.Shapes;
|
||||
using Path = System.IO.Path;
|
||||
using Rectangle = System.Drawing.Rectangle;
|
||||
using Ink_Canvas.Helpers;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
#region MagnificationAPI 获取屏幕截图并过滤ICC窗口
|
||||
|
||||
#region Dubi906w 的轮子
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
|
||||
private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
|
||||
private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
|
||||
private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
#endregion Dubi906w 的轮子
|
||||
|
||||
#region Win32 窗口环境(由 AlanCRL 测试)
|
||||
|
||||
// 感謝 Alan-CRL 造的輪子
|
||||
private const int WS_EX_TOPMOST = 0x00000008;
|
||||
private const int WS_EX_LAYERED = 0x00080000;
|
||||
private const int WS_SIZEBOX = 0x00040000;
|
||||
private const int WS_SYSMENU = 0x00080000;
|
||||
private const int WS_CLIPCHILDREN = 0x02000000;
|
||||
private const int WS_CAPTION = 0x00C00000;
|
||||
private const int WS_MAXIMIZEBOX = 0x00010000;
|
||||
private const int GWL_STYLE = -16;
|
||||
private const int GWL_EXSTYLE = -20;
|
||||
private const int WS_THICKFRAME = 0x00040000;
|
||||
private const int SWP_NOSIZE = 0x0001;
|
||||
private const int SWP_FRAMECHANGED = 0x0020;
|
||||
private const int WS_EX_TOOLWINDOW = 0x00000080;
|
||||
private const int WS_EX_APPWINDOW = 0x00040000;
|
||||
private const int SW_SHOW = 5;
|
||||
private const int LWA_ALPHA = 0x00000002;
|
||||
private const int PW_RENDERFULLCONTENT = 2;
|
||||
private static IntPtr windowHostHandle;
|
||||
|
||||
// PInvoke 輪子
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern IntPtr CreateWindowEx(int dwExStyle, string lpClassName, string lpWindowName, int dwStyle,
|
||||
int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool DestroyWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern ushort RegisterClassEx(ref WNDCLASSEX lpwcx);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern short UnregisterClass(string lpClassName, IntPtr hInstance);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct WNDCLASSEX {
|
||||
public uint cbSize;
|
||||
public uint style;
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)] public WndProc lpfnWndProc;
|
||||
public int cbClsExtra;
|
||||
public int cbWndExtra;
|
||||
public IntPtr hInstance;
|
||||
public IntPtr hIcon;
|
||||
public IntPtr hCursor;
|
||||
public IntPtr hbrBackground;
|
||||
public string lpszMenuName;
|
||||
public string lpszClassName;
|
||||
public IntPtr hIconSm;
|
||||
}
|
||||
|
||||
private delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
private static readonly WndProc StaticWndProcDelegate = WndHostProc;
|
||||
|
||||
private const uint WM_DESTROY = 0x0002;
|
||||
private const uint WM_CLOSE = 0x0010;
|
||||
private const int CS_HREDRAW = 0x0002;
|
||||
private const int CS_VREDRAW = 0x0001;
|
||||
private const int IDC_ARROW = 32512;
|
||||
private static int COLOR_BTNFACE = 15;
|
||||
private const int WS_CHILD = 0x40000000;
|
||||
private const int WS_VISIBLE = 0x10000000;
|
||||
private const int MS_CLIPAROUNDCURSOR = 0x0002;
|
||||
|
||||
#endregion Win32 窗口环境(由 AlanCRL 测试)
|
||||
|
||||
public void SaveScreenshotToDesktopByMagnificationAPI(HWND[] hwndsList,
|
||||
Action<Bitmap> callbackAction, bool isUsingCallback = false) {
|
||||
if (OSVersion.GetOperatingSystem() < OperatingSystem.Windows81) return;
|
||||
if (!Magnification.MagInitialize()) return;
|
||||
// 註冊宿主窗體類名
|
||||
var wndClassEx = new WNDCLASSEX {
|
||||
cbSize = (uint)Marshal.SizeOf<WNDCLASSEX>(), style = CS_HREDRAW | CS_VREDRAW,
|
||||
lpfnWndProc = StaticWndProcDelegate, hInstance = IntPtr.Zero,
|
||||
hCursor = LoadCursor(IntPtr.Zero, IDC_ARROW), hbrBackground = (IntPtr)(1 + COLOR_BTNFACE),
|
||||
lpszClassName = "ICCMagnifierWindowHost",
|
||||
hIcon = IntPtr.Zero, hIconSm = IntPtr.Zero
|
||||
};
|
||||
RegisterClassEx(ref wndClassEx);
|
||||
// 創建宿主窗體
|
||||
windowHostHandle = CreateWindowEx(
|
||||
WS_EX_TOPMOST | WS_EX_LAYERED, "ICCMagnifierWindowHost", "ICCMagnifierWindowHostWindow",
|
||||
WS_SIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CAPTION | WS_MAXIMIZEBOX, 0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
|
||||
IntPtr.Zero);
|
||||
// 設定分層窗體
|
||||
SetLayeredWindowAttributes(windowHostHandle, 0, 0, LWA_ALPHA);
|
||||
// 創建放大鏡窗體
|
||||
var hwndMag = CreateWindowEx(
|
||||
0, Magnification.WC_MAGNIFIER, "ICCMagnifierWindow", WS_CHILD | WS_VISIBLE | MS_CLIPAROUNDCURSOR, 0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, windowHostHandle,
|
||||
IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
|
||||
// 設定窗體樣式和排布
|
||||
int style = GetWindowLong(windowHostHandle, GWL_STYLE);
|
||||
style &= ~WS_CAPTION; // 隐藏标题栏
|
||||
style &= ~WS_THICKFRAME; // 禁止窗口拉伸
|
||||
SetWindowLong(windowHostHandle, GWL_STYLE, style);
|
||||
SetWindowPos(windowHostHandle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOSIZE | SWP_FRAMECHANGED);
|
||||
// 設定額外樣式
|
||||
int exStyle = GetWindowLong(windowHostHandle, GWL_EXSTYLE);
|
||||
exStyle |= WS_EX_TOOLWINDOW; /* <- 隐藏任务栏图标 */
|
||||
exStyle &= ~WS_EX_APPWINDOW;
|
||||
SetWindowLong(windowHostHandle, GWL_EXSTYLE, exStyle);
|
||||
// 設定放大鏡工廠
|
||||
Magnification.MAGTRANSFORM matrix = new Magnification.MAGTRANSFORM();
|
||||
matrix[0, 0] = 1.0f;
|
||||
matrix[0, 1] = 0.0f;
|
||||
matrix[0, 2] = 0.0f;
|
||||
matrix[1, 0] = 0.0f;
|
||||
matrix[1, 1] = 1.0f;
|
||||
matrix[1, 2] = 0.0f;
|
||||
matrix[2, 0] = 1.0f;
|
||||
matrix[2, 1] = 0.0f;
|
||||
matrix[2, 2] = 0.0f;
|
||||
if (!Magnification.MagSetWindowTransform(hwndMag, matrix)) return;
|
||||
// 設定放大鏡轉化矩乘陣列
|
||||
Magnification.MAGCOLOREFFECT magEffect = new Magnification.MAGCOLOREFFECT();
|
||||
magEffect[0, 0] = 1.0f;
|
||||
magEffect[0, 1] = 0.0f;
|
||||
magEffect[0, 2] = 0.0f;
|
||||
magEffect[0, 3] = 0.0f;
|
||||
magEffect[0, 4] = 0.0f;
|
||||
magEffect[1, 0] = 0.0f;
|
||||
magEffect[1, 1] = 1.0f;
|
||||
magEffect[1, 2] = 0.0f;
|
||||
magEffect[1, 3] = 0.0f;
|
||||
magEffect[1, 4] = 0.0f;
|
||||
magEffect[2, 0] = 0.0f;
|
||||
magEffect[2, 1] = 0.0f;
|
||||
magEffect[2, 2] = 1.0f;
|
||||
magEffect[2, 3] = 0.0f;
|
||||
magEffect[2, 4] = 0.0f;
|
||||
magEffect[3, 0] = 0.0f;
|
||||
magEffect[3, 1] = 0.0f;
|
||||
magEffect[3, 2] = 0.0f;
|
||||
magEffect[3, 3] = 1.0f;
|
||||
magEffect[3, 4] = 0.0f;
|
||||
magEffect[4, 0] = 0.0f;
|
||||
magEffect[4, 1] = 0.0f;
|
||||
magEffect[4, 2] = 0.0f;
|
||||
magEffect[4, 3] = 0.0f;
|
||||
magEffect[4, 4] = 1.0f;
|
||||
if (!Magnification.MagSetColorEffect(hwndMag, magEffect)) return;
|
||||
// 顯示窗體
|
||||
ShowWindow(windowHostHandle, SW_SHOW);
|
||||
// 过滤窗口
|
||||
var hwnds = new List<HWND> { hwndMag };
|
||||
hwnds.AddRange(hwndsList);
|
||||
if (!Magnification.MagSetWindowFilterList(hwndMag, Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE,
|
||||
hwnds.Count, hwnds.ToArray())) return;
|
||||
// 设置窗口 Source
|
||||
if (!Magnification.MagSetWindowSource(hwndMag, new RECT(0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return;
|
||||
InvalidateRect(hwndMag, IntPtr.Zero, true);
|
||||
// 抓取屏幕圖像
|
||||
if (isUsingCallback) {
|
||||
if (!Magnification.MagSetImageScalingCallback(hwndMag,
|
||||
(hwnd, srcdata, srcheader, destdata, destheader, unclipped, clipped, dirty) => {
|
||||
Bitmap bm = new Bitmap((int)srcheader.width, (int)srcheader.height,
|
||||
(int)srcheader.width * 4, PixelFormat.Format32bppRgb, srcdata);
|
||||
callbackAction(bm);
|
||||
return true;
|
||||
})) return;
|
||||
} else {
|
||||
RECT rect;
|
||||
GetWindowRect(hwndMag, out rect);
|
||||
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
|
||||
Graphics memoryGraphics = Graphics.FromImage(bmp);
|
||||
PrintWindow(hwndMag, memoryGraphics.GetHdc(), PW_RENDERFULLCONTENT);
|
||||
memoryGraphics.ReleaseHdc();
|
||||
callbackAction(bmp);
|
||||
}
|
||||
|
||||
// 反注册宿主窗口
|
||||
UnregisterClass("ICCMagnifierWindowHost", IntPtr.Zero);
|
||||
// 销毁宿主窗口
|
||||
Magnification.MagUninitialize();
|
||||
DestroyWindow(windowHostHandle);
|
||||
}
|
||||
|
||||
public Task<Bitmap> SaveScreenshotToDesktopByMagnificationAPIAsync(HWND[] hwndsList,
|
||||
bool isUsingCallback = false) {
|
||||
return Task.Run(() => {
|
||||
var t = new TaskCompletionSource<Bitmap>();
|
||||
SaveScreenshotToDesktopByMagnificationAPI(hwndsList, bitmap => t.TrySetResult(bitmap), isUsingCallback);
|
||||
return t.Task;
|
||||
});
|
||||
}
|
||||
|
||||
private static IntPtr WndHostProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) {
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
#endregion MagnificationAPI 获取屏幕截图并过滤ICC窗口
|
||||
|
||||
#region 窗口截图(復刻Powerpoint)
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
|
||||
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
|
||||
|
||||
public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex) {
|
||||
if (IntPtr.Size > 4)
|
||||
return GetClassLongPtr64(hWnd, nIndex);
|
||||
else
|
||||
return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetClassLong")]
|
||||
public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
|
||||
public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
|
||||
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern bool EnumDesktopWindows(IntPtr hDesktop, Delegate lpEnumCallbackFunction, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsWindowVisible(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowText",
|
||||
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetWindowRect(IntPtr handle, out RECT rect);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern int GetWindowTextLength(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName,
|
||||
string windowTitle);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern IntPtr GetShellWindow();
|
||||
|
||||
[DllImport("dwmapi.dll")]
|
||||
static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out bool pvAttribute, int cbAttribute);
|
||||
[DllImport("dwmapi.dll")]
|
||||
static extern int DwmGetWindowAttribute(IntPtr hwnd, DwmWindowAttribute dwAttribute, out RECT pvAttribute, int cbAttribute);
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
static extern bool GetLayeredWindowAttributes(IntPtr hwnd, out uint crKey, out byte bAlpha, out uint dwFlags);
|
||||
public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
|
||||
[DllImport("user32.dll", SetLastError=true)]
|
||||
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern int GetDpiForWindow(IntPtr hWnd);
|
||||
|
||||
enum DwmWindowAttribute : uint {
|
||||
NCRenderingEnabled = 1,
|
||||
NCRenderingPolicy,
|
||||
TransitionsForceDisabled,
|
||||
AllowNCPaint,
|
||||
CaptionButtonBounds,
|
||||
NonClientRtlLayout,
|
||||
ForceIconicRepresentation,
|
||||
Flip3DPolicy,
|
||||
ExtendedFrameBounds,
|
||||
HasIconicBitmap,
|
||||
DisallowPeek,
|
||||
ExcludedFromPeek,
|
||||
Cloak,
|
||||
Cloaked,
|
||||
FreezeRepresentation,
|
||||
PassiveUpdateMode,
|
||||
UseHostBackdropBrush,
|
||||
UseImmersiveDarkMode = 20,
|
||||
WindowCornerPreference = 33,
|
||||
BorderColor,
|
||||
CaptionColor,
|
||||
TextColor,
|
||||
VisibleFrameBorderThickness,
|
||||
SystemBackdropType,
|
||||
Last
|
||||
}
|
||||
|
||||
public Icon GetAppIcon(IntPtr hwnd) {
|
||||
IntPtr iconHandle = SendMessage(hwnd, 0x7F, 2, 0);
|
||||
if (iconHandle == IntPtr.Zero)
|
||||
iconHandle = SendMessage(hwnd, 0x7F, 0, 0);
|
||||
if (iconHandle == IntPtr.Zero)
|
||||
iconHandle = SendMessage(hwnd, 0x7F, 1, 0);
|
||||
if (iconHandle == IntPtr.Zero)
|
||||
iconHandle = GetClassLongPtr(hwnd, -14);
|
||||
if (iconHandle == IntPtr.Zero)
|
||||
iconHandle = GetClassLongPtr(hwnd, -34);
|
||||
if (iconHandle == IntPtr.Zero)
|
||||
return null;
|
||||
Icon icn = System.Drawing.Icon.FromHandle(iconHandle);
|
||||
return icn;
|
||||
}
|
||||
|
||||
public class WindowInformation {
|
||||
public string Title { get; set; }
|
||||
public Bitmap WindowBitmap { get; set; }
|
||||
public Icon AppIcon { get; set; }
|
||||
public bool IsVisible { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public RECT Rect { get; set; }
|
||||
public WINDOWPLACEMENT Placement { get; set; }
|
||||
public HWND hwnd { get; set; }
|
||||
public RECT RealRect { get; set; }
|
||||
public Rectangle ContentRect { get; set; }
|
||||
public IntPtr Handle { get; set; }
|
||||
public int WindowDPI { get; set; }
|
||||
public int SystemDPI { get; set; }
|
||||
public double DPIScale { get; set; }
|
||||
}
|
||||
|
||||
public struct WINDOWPLACEMENT {
|
||||
public int length;
|
||||
public int flags;
|
||||
public int showCmd;
|
||||
public System.Drawing.Point ptMinPosition;
|
||||
public System.Drawing.Point ptMaxPosition;
|
||||
public System.Drawing.Rectangle rcNormalPosition;
|
||||
|
||||
public static WINDOWPLACEMENT Default {
|
||||
get {
|
||||
WINDOWPLACEMENT result = new WINDOWPLACEMENT();
|
||||
result.length = Marshal.SizeOf(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam);
|
||||
|
||||
public WindowInformation[] GetAllWindows(HWND[] excludedHwnds) {
|
||||
var windows = new List<WindowInformation>();
|
||||
IntPtr hShellWnd = GetShellWindow();
|
||||
IntPtr hDefView = FindWindowEx(hShellWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
|
||||
IntPtr folderView = FindWindowEx(hDefView, IntPtr.Zero, "SysListView32", null);
|
||||
IntPtr taskBar = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", null);
|
||||
var excluded = new List<HWND>() {
|
||||
new HWND(hShellWnd), new HWND(hDefView), new HWND(folderView), new HWND(taskBar)
|
||||
};
|
||||
var excludedWindowTitle = new string[] {
|
||||
"NVIDIA GeForce Overlay", "Ink Canvas 画板", "Ink Canvas Annotation", "Ink Canvas Artistry", "InkCanvasForClass"
|
||||
};
|
||||
excluded.AddRange(excludedHwnds);
|
||||
if (!EnumDesktopWindows(IntPtr.Zero, new EnumDesktopWindowsDelegate((hwnd, param) => {
|
||||
// 排除被過濾的窗體句柄
|
||||
if (excluded.Contains(new HWND(hwnd))) return true;
|
||||
|
||||
// 判斷窗體是否可見
|
||||
var isvisible = IsWindowVisible(hwnd);
|
||||
if (!isvisible) return true;
|
||||
|
||||
// 判斷窗體透明度和額外樣式
|
||||
var windowLong = (int)GetWindowLongPtr(hwnd, -20);
|
||||
GetLayeredWindowAttributes(hwnd, out uint crKey, out byte bAlpha, out uint dwFlags);
|
||||
if ((windowLong & 0x00000080L) != 0) return true;
|
||||
if ((windowLong & 0x00080000) != 0 && (dwFlags & 0x00000002) != 0 && bAlpha == 0) return true; //分层窗口且全透明
|
||||
|
||||
// Win8+專用,用於檢測UWP應用是否隱藏
|
||||
bool isCloacked = false;
|
||||
if (OSVersion.GetOperatingSystem() > OperatingSystem.Windows7)
|
||||
DwmGetWindowAttribute(hwnd, (int)DwmWindowAttribute.Cloaked, out isCloacked, Marshal.SizeOf(typeof(bool)));
|
||||
if (isCloacked) return true;
|
||||
|
||||
// 獲取窗體實際大小
|
||||
DwmGetWindowAttribute(hwnd, DwmWindowAttribute.ExtendedFrameBounds, out RECT realRect, Marshal.SizeOf(typeof(RECT)));
|
||||
|
||||
// 獲取窗體的進程ID
|
||||
var pidRes = GetWindowThreadProcessId(hwnd, out uint pid);
|
||||
if (pid == 0 || pidRes == 0) return true;
|
||||
|
||||
// 獲取窗體的DPI差異,scale為1則代表非DWM強制拉伸顯示窗體,實際截圖會根據窗體的DPI Awareness來截取
|
||||
var dpiForHwnd = GetDpiForWindow(hwnd);
|
||||
var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var dpiYProperty = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var dpiX = (int)dpiXProperty.GetValue(null, null);
|
||||
var dpiY = (int)dpiYProperty.GetValue(null, null);
|
||||
var dpi = (dpiX + dpiY) / 2;
|
||||
double scale = 1;
|
||||
if (dpi > dpiForHwnd) { // 说明该应用是win32应用,靠DWM的拉伸放大到高DPI
|
||||
scale = dpi / (double)dpiForHwnd;
|
||||
}
|
||||
|
||||
// 獲取窗體應用程式圖標
|
||||
var icon = GetAppIcon(hwnd);
|
||||
|
||||
// 獲取應用程式標題,這裡空標題不略過,用於後續繼續判斷獲取標題
|
||||
var length = GetWindowTextLength(hwnd) + 1;
|
||||
var title = new StringBuilder(length);
|
||||
GetWindowText(hwnd, title, length);
|
||||
// if (title.ToString().Length == 0) return true;
|
||||
|
||||
|
||||
// 窗體標題黑名單,在黑名單中的窗體不會顯示
|
||||
if (excludedWindowTitle.Equals(title.ToString())) return true;
|
||||
|
||||
// 獲取窗體狀態,如果是最小化就跳過
|
||||
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
|
||||
GetWindowPlacement(hwnd, ref placement);
|
||||
if (placement.showCmd == 2) return true;
|
||||
|
||||
// 獲取窗口Rect,用於和DwmGetWindowAttribute方法獲取到的窗體大小進行Offset計算
|
||||
RECT rect;
|
||||
GetWindowRect(hwnd, out rect);
|
||||
var w = rect.Width;
|
||||
var h = rect.Height;
|
||||
if (w == 0 || h == 0) return true;
|
||||
|
||||
// 使用PrintWindow(RENDER_FULL_CONTENT)來實現窗體圖片截取(支持D3D和DX)
|
||||
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
|
||||
Graphics memoryGraphics = Graphics.FromImage(bmp);
|
||||
IntPtr hdc = memoryGraphics.GetHdc();
|
||||
PrintWindow(hwnd, hdc, 2);
|
||||
|
||||
// 添加窗體信息
|
||||
windows.Add(new WindowInformation() {
|
||||
AppIcon = icon,
|
||||
Title = title.ToString(),
|
||||
IsVisible = isvisible,
|
||||
WindowBitmap = bmp,
|
||||
Width = w,
|
||||
Height = h,
|
||||
Rect = rect,
|
||||
Placement = placement,
|
||||
RealRect = realRect,
|
||||
Handle = hwnd,
|
||||
ContentRect = new Rectangle(realRect.X - rect.X, realRect.Y - rect.Y, (int)Math.Round(
|
||||
realRect.Width / scale ,0), (int)Math.Round(realRect.Height / scale, 0)),
|
||||
WindowDPI = dpiForHwnd,
|
||||
SystemDPI = dpi,
|
||||
DPIScale = scale
|
||||
});
|
||||
|
||||
// 釋放HDC
|
||||
memoryGraphics.ReleaseHdc(hdc);
|
||||
|
||||
// 嘗試調用GC回收叻色
|
||||
System.GC.Collect();
|
||||
System.GC.WaitForPendingFinalizers();
|
||||
return true;
|
||||
}),
|
||||
IntPtr.Zero)) return new WindowInformation[] { };
|
||||
return windows.ToArray();
|
||||
}
|
||||
|
||||
public static string GetProcessPathByPid(int processId) {
|
||||
string query = $"SELECT Name, ExecutablePath FROM Win32_Process WHERE ProcessId = {processId}";
|
||||
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
|
||||
foreach (ManagementObject obj in searcher.Get()) {
|
||||
string executablePath = obj["ExecutablePath"]?.ToString();
|
||||
if (!string.IsNullOrEmpty(executablePath)) return executablePath;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public async Task<string> GetProcessPathByPidAsync(int processId) {
|
||||
var result = await Task.Run(() => GetProcessPathByPid(processId));
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetAppFriendlyName(string filePath)
|
||||
{
|
||||
var versionInfo = FileVersionInfo.GetVersionInfo(filePath);
|
||||
return versionInfo.FileDescription;
|
||||
}
|
||||
|
||||
public async Task<WindowInformation[]> GetAllWindowsAsync(HWND[] excludedHwnds) {
|
||||
var windows = await Task.Run(() => GetAllWindows(excludedHwnds));
|
||||
var _wins = new List<WindowInformation>(){};
|
||||
foreach (var w in windows) {
|
||||
_wins.Add(w);
|
||||
}
|
||||
foreach (var windowInformation in windows) {
|
||||
if (windowInformation.Title.Length == 0) {
|
||||
GetWindowThreadProcessId(windowInformation.Handle, out uint Pid);
|
||||
if (Pid != 0) {
|
||||
var _path = Path.GetFullPath(await GetProcessPathByPidAsync((int)Pid));
|
||||
var processPath = Path.GetFullPath(Process.GetCurrentProcess().MainModule.FileName);
|
||||
if (string.Equals(_path, processPath, StringComparison.OrdinalIgnoreCase) || _path == "") {
|
||||
_wins.Remove(windowInformation);
|
||||
} else {
|
||||
var _des = GetAppFriendlyName(_path);
|
||||
Trace.WriteLine(_des);
|
||||
if (_des == null) {
|
||||
_wins.Remove(windowInformation);
|
||||
} else {
|
||||
var index = _wins.IndexOf(windowInformation);
|
||||
_wins[index].Title = _des;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_wins.Remove(windowInformation);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _wins.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 舊版全屏截圖
|
||||
|
||||
private Bitmap GetScreenshotBitmap() {
|
||||
Rectangle rc = System.Windows.Forms.SystemInformation.VirtualScreen;
|
||||
var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
|
||||
using (Graphics memoryGrahics = Graphics.FromImage(bitmap)) {
|
||||
memoryGrahics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy);
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 通用截圖API
|
||||
|
||||
private BitmapImage BitmapToImageSource(Bitmap bitmap) {
|
||||
using (MemoryStream memory = new MemoryStream()) {
|
||||
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
|
||||
memory.Position = 0;
|
||||
BitmapImage bitmapimage = new BitmapImage();
|
||||
bitmapimage.BeginInit();
|
||||
bitmapimage.StreamSource = memory;
|
||||
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapimage.EndInit();
|
||||
|
||||
return bitmapimage;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SnapshotMethod {
|
||||
Auto,
|
||||
GraphicsAPICopyFromScreen,
|
||||
MagnificationAPIWithPrintWindow,
|
||||
MagnificationAPIWithCallback
|
||||
}
|
||||
|
||||
public enum OutputImageMIMEFormat {
|
||||
Png,
|
||||
Bmp,
|
||||
Jpeg,
|
||||
}
|
||||
|
||||
public class SnapshotConfig {
|
||||
public SnapshotMethod SnapshotMethod { get; set; } = SnapshotMethod.Auto;
|
||||
public bool IsCopyToClipboard { get; set; } = false;
|
||||
public bool IsSaveToLocal { get; set; } = true;
|
||||
public DirectoryInfo BitmapSavePath { get; set; } = null;
|
||||
public string SaveBitmapFileName { get; set; } = "Screenshot-[YYYY]-[MM]-[DD]-[HH]-[mm]-[ss].png";
|
||||
public OutputImageMIMEFormat OutputMIMEType { get; set; } = OutputImageMIMEFormat.Png;
|
||||
public HWND[] ExcludedHwnds { get; set; } = new HWND[] { };
|
||||
}
|
||||
|
||||
private static ImageCodecInfo GetEncoderInfo(string mimeType) {
|
||||
foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
|
||||
if (codec.MimeType == mimeType)
|
||||
return codec;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<Bitmap> FullscreenSnapshot(SnapshotConfig config) {
|
||||
Bitmap bitmap = new Bitmap(1, 1);
|
||||
var ex = new List<HWND>() { new HWND(new WindowInteropHelper(this).Handle) };
|
||||
ex.AddRange(config.ExcludedHwnds);
|
||||
if (config.SnapshotMethod == SnapshotMethod.Auto) {
|
||||
if (OSVersion.GetOperatingSystem() >= OperatingSystem.Windows81) {
|
||||
bitmap = await SaveScreenshotToDesktopByMagnificationAPIAsync(ex.ToArray(), false);
|
||||
} else {
|
||||
if (ex.Count != 0)
|
||||
foreach (var hwnd in ex)
|
||||
ShowWindow(hwnd.DangerousGetHandle(), 0);
|
||||
bitmap = GetScreenshotBitmap();
|
||||
foreach (var hwnd in ex) ShowWindow(hwnd.DangerousGetHandle(), 5);
|
||||
}
|
||||
} else if (config.SnapshotMethod == SnapshotMethod.MagnificationAPIWithPrintWindow ||
|
||||
config.SnapshotMethod == SnapshotMethod.MagnificationAPIWithCallback) {
|
||||
if (!(OSVersion.GetOperatingSystem() >= OperatingSystem.Windows81))
|
||||
throw new Exception("您的系統版本不支持 MagnificationAPI 截圖!");
|
||||
bitmap = await SaveScreenshotToDesktopByMagnificationAPIAsync(ex.ToArray(),
|
||||
config.SnapshotMethod == SnapshotMethod.MagnificationAPIWithCallback);
|
||||
} else if (config.SnapshotMethod == SnapshotMethod.GraphicsAPICopyFromScreen) {
|
||||
if (ex.Count != 0)
|
||||
foreach (var hwnd in ex)
|
||||
ShowWindow(hwnd.DangerousGetHandle(), 0);
|
||||
bitmap = GetScreenshotBitmap();
|
||||
foreach (var hwnd in ex) ShowWindow(hwnd.DangerousGetHandle(), 5);
|
||||
}
|
||||
|
||||
if (bitmap.Width == 1 && bitmap.Height == 1) throw new Exception("截圖失敗");
|
||||
try {
|
||||
if (config.IsCopyToClipboard) Clipboard.SetImage(BitmapToImageSource(bitmap));
|
||||
}
|
||||
catch (NotSupportedException e) { }
|
||||
|
||||
if (config.IsSaveToLocal) {
|
||||
var fullPath = config.BitmapSavePath.FullName;
|
||||
if (!config.BitmapSavePath.Exists) config.BitmapSavePath.Create();
|
||||
var fileName = config.SaveBitmapFileName.Replace("[YYYY]", DateTime.Now.Year.ToString())
|
||||
.Replace("[MM]", DateTime.Now.Month.ToString()).Replace("[DD]", DateTime.Now.Day.ToString())
|
||||
.Replace("[HH]", DateTime.Now.Hour.ToString()).Replace("[mm]", DateTime.Now.Minute.ToString())
|
||||
.Replace("[ss]", DateTime.Now.Second.ToString()).Replace("[width]", bitmap.Width.ToString())
|
||||
.Replace("[height]", bitmap.Height.ToString());
|
||||
var finalPath = (fullPath.EndsWith("\\") ? fullPath.Substring(0, fullPath.Length - 1) : fullPath) +
|
||||
$"\\{fileName}";
|
||||
bitmap.Save(finalPath, config.OutputMIMEType == OutputImageMIMEFormat.Png ? ImageFormat.Png :
|
||||
config.OutputMIMEType == OutputImageMIMEFormat.Bmp ? ImageFormat.Bmp : ImageFormat.Jpeg);
|
||||
}
|
||||
bitmap.Dispose();
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void SaveScreenshot(bool isHideNotification, string fileName = null) {
|
||||
var bitmap = GetScreenshotBitmap();
|
||||
string savePath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - Screenshots";
|
||||
if (fileName == null) fileName = DateTime.Now.ToString("u").Replace(":", "-");
|
||||
if (Settings.Automation.IsSaveScreenshotsInDateFolders) {
|
||||
savePath += @"\" + DateTime.Now.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
savePath += @"\" + fileName + ".png";
|
||||
if (!Directory.Exists(Path.GetDirectoryName(savePath))) {
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
|
||||
}
|
||||
|
||||
bitmap.Save(savePath, ImageFormat.Png);
|
||||
if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) {
|
||||
SaveInkCanvasStrokes(false, false);
|
||||
}
|
||||
|
||||
if (!isHideNotification) {
|
||||
ShowNewToast("截图成功保存至 " + savePath, MW_Toast.ToastType.Success, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveScreenShotToDesktop() {
|
||||
var bitmap = GetScreenshotBitmap();
|
||||
string savePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
|
||||
bitmap.Save(savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png", ImageFormat.Png);
|
||||
ShowNewToast("截图成功保存至【桌面" + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png】",
|
||||
MW_Toast.ToastType.Success, 3000);
|
||||
if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false, false);
|
||||
}
|
||||
|
||||
private void SavePPTScreenshot(string fileName) {
|
||||
var bitmap = GetScreenshotBitmap();
|
||||
string savePath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - PPT Screenshots";
|
||||
if (Settings.Automation.IsSaveScreenshotsInDateFolders) {
|
||||
savePath += @"\" + DateTime.Now.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
if (fileName == null) fileName = DateTime.Now.ToString("u").Replace(":", "-");
|
||||
savePath += @"\" + fileName + ".png";
|
||||
if (!Directory.Exists(Path.GetDirectoryName(savePath))) {
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
|
||||
}
|
||||
|
||||
bitmap.Save(savePath, ImageFormat.Png);
|
||||
if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) {
|
||||
SaveInkCanvasStrokes(false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,878 @@
|
||||
using Hardcodet.Wpf.TaskbarNotification;
|
||||
using Ink_Canvas.Helpers;
|
||||
using Newtonsoft.Json;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using OSVersionExtension;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Microsoft.Win32;
|
||||
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
||||
using File = System.IO.File;
|
||||
using OperatingSystem = OSVersionExtension.OperatingSystem;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
private void DisplayWelcomePopup() {
|
||||
if( TaskDialog.OSSupportsTaskDialogs ) {
|
||||
var t = new Thread(() => {
|
||||
using (TaskDialog dialog = new TaskDialog()) {
|
||||
dialog.WindowTitle = "感谢使用 InkCanvasForClass!";
|
||||
dialog.MainInstruction = "感谢您使用 InkCanvasForClass!";
|
||||
dialog.Content =
|
||||
"您需要知道的是该版本正处于开发阶段,可能会有无法预测的问题出现。出现任何问题以及未捕获的异常,请及时提供日志文件然后上报给开发者。";
|
||||
dialog.Footer =
|
||||
"加入 InkCanvasForClass 交流群 <a href=\"https://qm.qq.com/q/Dgzdt7RjQQ\">825759306</a>。";
|
||||
dialog.FooterIcon = TaskDialogIcon.Information;
|
||||
dialog.EnableHyperlinks = true;
|
||||
TaskDialogButton okButton = new TaskDialogButton(ButtonType.Ok);
|
||||
dialog.Buttons.Add(okButton);
|
||||
TaskDialogButton button = dialog.Show();
|
||||
}
|
||||
});
|
||||
t.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadSettings(bool isStartup = false) {
|
||||
AppVersionTextBlock.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
try {
|
||||
if (File.Exists(App.RootPath + settingsFileName)) {
|
||||
try {
|
||||
string text = File.ReadAllText(App.RootPath + settingsFileName);
|
||||
Settings = JsonConvert.DeserializeObject<Settings>(text);
|
||||
}
|
||||
catch { }
|
||||
} else {
|
||||
BtnResetToSuggestion_Click(null, null);
|
||||
DisplayWelcomePopup();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
try {
|
||||
if (File.Exists(App.RootPath + "custom-copyright-banner.png")) {
|
||||
try {
|
||||
CustomCopyrightBanner.Visibility = Visibility.Visible;
|
||||
CustomCopyrightBanner.Source =
|
||||
new BitmapImage(new Uri($"file://{App.RootPath + "custom-copyright-banner.png"}"));
|
||||
}
|
||||
catch { }
|
||||
} else {
|
||||
CustomCopyrightBanner.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
// Startup
|
||||
if (isStartup) {
|
||||
CursorIcon_Click(null, null);
|
||||
}
|
||||
|
||||
try {
|
||||
var identity = WindowsIdentity.GetCurrent();
|
||||
var principal = new WindowsPrincipal(identity);
|
||||
if (principal.IsInRole(WindowsBuiltInRole.Administrator)) {
|
||||
AdministratorPrivilegeIndicateText.Text = "icc目前以管理员身份运行";
|
||||
RunAsAdminButton.Visibility = Visibility.Collapsed;
|
||||
RunAsUserButton.Visibility = Visibility.Visible;
|
||||
RegistryKey localKey;
|
||||
if (Environment.Is64BitOperatingSystem)
|
||||
localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
|
||||
else
|
||||
localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
|
||||
|
||||
int LUAValue = (int)(localKey.OpenSubKey("SOFTWARE").OpenSubKey("Microsoft").OpenSubKey("Windows")
|
||||
.OpenSubKey("CurrentVersion").OpenSubKey("Policies").OpenSubKey("System")
|
||||
.GetValue("EnableLUA", 1));
|
||||
CannotSwitchToUserPrivNotification.IsOpen = LUAValue == 0;
|
||||
} else {
|
||||
AdministratorPrivilegeIndicateText.Text = "icc目前以非管理员身份运行";
|
||||
RunAsAdminButton.Visibility = Visibility.Visible;
|
||||
RunAsUserButton.Visibility = Visibility.Collapsed;
|
||||
CannotSwitchToUserPrivNotification.IsOpen = false;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LogHelper.WriteLogToFile(e.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
try {
|
||||
if (File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup) +
|
||||
"\\InkCanvasForClass.lnk")) {
|
||||
ToggleSwitchRunAtStartup.IsOn = true;
|
||||
} else {
|
||||
ToggleSwitchRunAtStartup.IsOn = false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
#region Startup
|
||||
|
||||
if (Settings.Startup != null) {
|
||||
if (isStartup) {
|
||||
if (Settings.Automation.AutoDelSavedFiles) {
|
||||
DelAutoSavedFiles.DeleteFilesOlder(Settings.Automation.AutoSavedStrokesLocation,
|
||||
Settings.Automation.AutoDelSavedFilesDaysThreshold);
|
||||
}
|
||||
|
||||
if (Settings.Startup.IsFoldAtStartup) {
|
||||
FoldFloatingBar_MouseUp(Fold_Icon, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.Startup.IsEnableNibMode) {
|
||||
ToggleSwitchEnableNibMode.IsOn = true;
|
||||
BoardToggleSwitchEnableNibMode.IsOn = true;
|
||||
BoundsWidth = Settings.Advanced.NibModeBoundsWidth;
|
||||
} else {
|
||||
ToggleSwitchEnableNibMode.IsOn = false;
|
||||
BoardToggleSwitchEnableNibMode.IsOn = false;
|
||||
BoundsWidth = Settings.Advanced.FingerModeBoundsWidth;
|
||||
}
|
||||
|
||||
if (Settings.Startup.IsAutoUpdate) {
|
||||
ToggleSwitchIsAutoUpdate.IsOn = true;
|
||||
AutoUpdate();
|
||||
}
|
||||
|
||||
// ToggleSwitchIsAutoUpdateWithSilence.Visibility = Settings.Startup.IsAutoUpdate ? Visibility.Visible : Visibility.Collapsed;
|
||||
if (Settings.Startup.IsAutoUpdateWithSilence) {
|
||||
ToggleSwitchIsAutoUpdateWithSilence.IsOn = true;
|
||||
}
|
||||
|
||||
AutoUpdateTimePeriodBlock.Visibility = Settings.Startup.IsAutoUpdateWithSilence
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
|
||||
AutoUpdateWithSilenceTimeComboBox.InitializeAutoUpdateWithSilenceTimeComboBoxOptions(
|
||||
AutoUpdateWithSilenceStartTimeComboBox, AutoUpdateWithSilenceEndTimeComboBox);
|
||||
AutoUpdateWithSilenceStartTimeComboBox.SelectedItem = Settings.Startup.AutoUpdateWithSilenceStartTime;
|
||||
AutoUpdateWithSilenceEndTimeComboBox.SelectedItem = Settings.Startup.AutoUpdateWithSilenceEndTime;
|
||||
|
||||
ToggleSwitchFoldAtStartup.IsOn = Settings.Startup.IsFoldAtStartup;
|
||||
|
||||
ToggleSwitchEnableWindowChromeRendering.IsOn = Settings.Startup.EnableWindowChromeRendering;
|
||||
|
||||
} else {
|
||||
Settings.Startup = new Startup();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Appearance
|
||||
|
||||
if (Settings.Appearance != null) {
|
||||
if (!Settings.Appearance.IsEnableDisPlayNibModeToggler) {
|
||||
NibModeSimpleStackPanel.Visibility = Visibility.Collapsed;
|
||||
BoardNibModeSimpleStackPanel.Visibility = Visibility.Collapsed;
|
||||
} else {
|
||||
NibModeSimpleStackPanel.Visibility = Visibility.Visible;
|
||||
BoardNibModeSimpleStackPanel.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
//if (Settings.Appearance.IsColorfulViewboxFloatingBar) // 浮动工具栏背景色
|
||||
//{
|
||||
// LinearGradientBrush gradientBrush = new LinearGradientBrush();
|
||||
// gradientBrush.StartPoint = new Point(0, 0);
|
||||
// gradientBrush.EndPoint = new Point(1, 1);
|
||||
// GradientStop blueStop = new GradientStop(Color.FromArgb(0x95, 0x80, 0xB0, 0xFF), 0);
|
||||
// GradientStop greenStop = new GradientStop(Color.FromArgb(0x95, 0xC0, 0xFF, 0xC0), 1);
|
||||
// gradientBrush.GradientStops.Add(blueStop);
|
||||
// gradientBrush.GradientStops.Add(greenStop);
|
||||
// EnableTwoFingerGestureBorder.Background = gradientBrush;
|
||||
// BorderFloatingBarMainControls.Background = gradientBrush;
|
||||
// BorderFloatingBarMoveControls.Background = gradientBrush;
|
||||
// BorderFloatingBarExitPPTBtn.Background = gradientBrush;
|
||||
|
||||
// ToggleSwitchColorfulViewboxFloatingBar.IsOn = true;
|
||||
//} else {
|
||||
// EnableTwoFingerGestureBorder.Background = (Brush)FindResource("FloatBarBackground");
|
||||
// BorderFloatingBarMainControls.Background = (Brush)FindResource("FloatBarBackground");
|
||||
// BorderFloatingBarMoveControls.Background = (Brush)FindResource("FloatBarBackground");
|
||||
// BorderFloatingBarExitPPTBtn.Background = (Brush)FindResource("FloatBarBackground");
|
||||
|
||||
// ToggleSwitchColorfulViewboxFloatingBar.IsOn = false;
|
||||
//}
|
||||
|
||||
if (Settings.Appearance.ViewboxFloatingBarScaleTransformValue != 0) // 浮动工具栏 UI 缩放 85%
|
||||
{
|
||||
double val = Settings.Appearance.ViewboxFloatingBarScaleTransformValue;
|
||||
ViewboxFloatingBarScaleTransform.ScaleX =
|
||||
(val > 0.5 && val < 1.25) ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
|
||||
ViewboxFloatingBarScaleTransform.ScaleY =
|
||||
(val > 0.5 && val < 1.25) ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
|
||||
ViewboxFloatingBarScaleTransformValueSlider.Value = val;
|
||||
}
|
||||
|
||||
ComboBoxUnFoldBtnImg.SelectedIndex = Settings.Appearance.UnFoldButtonImageType;
|
||||
switch (Settings.Appearance.UnFoldButtonImageType) {
|
||||
case 0:
|
||||
RightUnFoldBtnImgChevron.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png"));
|
||||
RightUnFoldBtnImgChevron.Width = 14;
|
||||
RightUnFoldBtnImgChevron.Height = 14;
|
||||
RightUnFoldBtnImgChevron.RenderTransform = new RotateTransform(180);
|
||||
LeftUnFoldBtnImgChevron.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png"));
|
||||
LeftUnFoldBtnImgChevron.Width = 14;
|
||||
LeftUnFoldBtnImgChevron.Height = 14;
|
||||
LeftUnFoldBtnImgChevron.RenderTransform = null;
|
||||
break;
|
||||
case 1:
|
||||
RightUnFoldBtnImgChevron.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png"));
|
||||
RightUnFoldBtnImgChevron.Width = 18;
|
||||
RightUnFoldBtnImgChevron.Height = 18;
|
||||
RightUnFoldBtnImgChevron.RenderTransform = null;
|
||||
LeftUnFoldBtnImgChevron.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png"));
|
||||
LeftUnFoldBtnImgChevron.Width = 18;
|
||||
LeftUnFoldBtnImgChevron.Height = 18;
|
||||
LeftUnFoldBtnImgChevron.RenderTransform = null;
|
||||
break;
|
||||
}
|
||||
|
||||
ComboBoxChickenSoupSource.SelectedIndex = Settings.Appearance.ChickenSoupSource;
|
||||
|
||||
ToggleSwitchEnableQuickPanel.IsOn = Settings.Appearance.IsShowQuickPanel;
|
||||
|
||||
ToggleSwitchEnableTrayIcon.IsOn = Settings.Appearance.EnableTrayIcon;
|
||||
ICCTrayIconExampleImage.Visibility =
|
||||
Settings.Appearance.EnableTrayIcon ? Visibility.Visible : Visibility.Collapsed;
|
||||
var _taskbar = (TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"];
|
||||
_taskbar.Visibility = Settings.Appearance.EnableTrayIcon ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityValue;
|
||||
|
||||
if (Settings.Appearance.EnableViewboxBlackBoardScaleTransform) // 画板 UI 缩放 80%
|
||||
{
|
||||
ViewboxBlackboardLeftSideScaleTransform.ScaleX = 0.8;
|
||||
ViewboxBlackboardLeftSideScaleTransform.ScaleY = 0.8;
|
||||
ViewboxBlackboardCenterSideScaleTransform.ScaleX = 0.8;
|
||||
ViewboxBlackboardCenterSideScaleTransform.ScaleY = 0.8;
|
||||
ViewboxBlackboardRightSideScaleTransform.ScaleX = 0.8;
|
||||
ViewboxBlackboardRightSideScaleTransform.ScaleY = 0.8;
|
||||
|
||||
ToggleSwitchEnableViewboxBlackBoardScaleTransform.IsOn = true;
|
||||
} else {
|
||||
ViewboxBlackboardLeftSideScaleTransform.ScaleX = 1;
|
||||
ViewboxBlackboardLeftSideScaleTransform.ScaleY = 1;
|
||||
ViewboxBlackboardCenterSideScaleTransform.ScaleX = 1;
|
||||
ViewboxBlackboardCenterSideScaleTransform.ScaleY = 1;
|
||||
ViewboxBlackboardRightSideScaleTransform.ScaleX = 1;
|
||||
ViewboxBlackboardRightSideScaleTransform.ScaleY = 1;
|
||||
|
||||
ToggleSwitchEnableViewboxBlackBoardScaleTransform.IsOn = false;
|
||||
}
|
||||
|
||||
ComboBoxFloatingBarImg.SelectedIndex = Settings.Appearance.FloatingBarImg;
|
||||
if (ComboBoxFloatingBarImg.SelectedIndex == 0) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(0.5);
|
||||
} else if (ComboBoxFloatingBarImg.SelectedIndex == 1) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(
|
||||
new Uri("pack://application:,,,/Resources/Icons-png/icc-transparent-dark-small.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(1.2);
|
||||
} else if (ComboBoxFloatingBarImg.SelectedIndex == 2) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandoujiyanhuaji.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
|
||||
} else if (ComboBoxFloatingBarImg.SelectedIndex == 3) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanshounvhuaji.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
|
||||
} else if (ComboBoxFloatingBarImg.SelectedIndex == 4) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanciya.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
|
||||
} else if (ComboBoxFloatingBarImg.SelectedIndex == 5) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanneikuhuaji.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
|
||||
} else if (ComboBoxFloatingBarImg.SelectedIndex == 6) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandogeyuanliangwo.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
|
||||
} else if (ComboBoxFloatingBarImg.SelectedIndex == 7) {
|
||||
FloatingbarHeadIconImg.Source =
|
||||
new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/tiebahuaji.png"));
|
||||
FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1);
|
||||
}
|
||||
|
||||
ToggleSwitchEnableTimeDisplayInWhiteboardMode.IsOn =
|
||||
Settings.Appearance.EnableTimeDisplayInWhiteboardMode;
|
||||
|
||||
ToggleSwitchEnableChickenSoupInWhiteboardMode.IsOn =
|
||||
Settings.Appearance.EnableChickenSoupInWhiteboardMode;
|
||||
|
||||
ToggleSwitchFloatingBarButtonLabelVisibility.IsOn =
|
||||
Settings.Appearance.FloatingBarButtonLabelVisibility;
|
||||
|
||||
var items = new CheckBox[] {
|
||||
CheckboxEnableFloatingBarShapes,
|
||||
CheckboxEnableFloatingBarFreeze,
|
||||
CheckboxEnableFloatingBarHand,
|
||||
CheckboxEnableFloatingBarUndo,
|
||||
CheckboxEnableFloatingBarRedo,
|
||||
CheckboxEnableFloatingBarCAM,
|
||||
CheckboxEnableFloatingBarLasso,
|
||||
CheckboxEnableFloatingBarWhiteboard,
|
||||
CheckboxEnableFloatingBarFold,
|
||||
CheckboxEnableFloatingBarGesture
|
||||
};
|
||||
|
||||
if (Settings.Appearance.FloatingBarIconsVisibility.Length != 10) {
|
||||
Settings.Appearance.FloatingBarIconsVisibility =
|
||||
Settings.Appearance.FloatingBarIconsVisibility.PadRight(10, '1');
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
var floatingBarIconsVisibilityValue = Settings.Appearance.FloatingBarIconsVisibility;
|
||||
var fbivca = floatingBarIconsVisibilityValue.ToCharArray();
|
||||
for (var i = 0; i < fbivca.Length; i++) {
|
||||
items[i].IsChecked = fbivca[i] == '1';
|
||||
}
|
||||
|
||||
ComboBoxEraserButton.SelectedIndex = Settings.Appearance.EraserButtonsVisibility;
|
||||
ToggleSwitchOnlyDisplayEraserBtn.IsOn = Settings.Appearance.OnlyDisplayEraserBtn;
|
||||
|
||||
UpdateFloatingBarIconsVisibility();
|
||||
|
||||
FloatingBarTextVisibilityBindingLikeAPieceOfShit.Visibility = Settings.Appearance.FloatingBarButtonLabelVisibility ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
//SystemEvents_UserPreferenceChanged(null, null);
|
||||
} else {
|
||||
Settings.Appearance = new Appearance();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PowerPointSettings
|
||||
|
||||
if (Settings.PowerPointSettings != null) {
|
||||
|
||||
|
||||
if (Settings.PowerPointSettings.PowerPointSupport) {
|
||||
ToggleSwitchSupportPowerPoint.IsOn = true;
|
||||
timerCheckPPT.Start();
|
||||
} else {
|
||||
ToggleSwitchSupportPowerPoint.IsOn = false;
|
||||
timerCheckPPT.Stop();
|
||||
}
|
||||
|
||||
ToggleSwitchShowCanvasAtNewSlideShow.IsOn = Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow;
|
||||
|
||||
ToggleSwitchEnableTwoFingerGestureInPresentationMode.IsOn =
|
||||
Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode;
|
||||
|
||||
ToggleSwitchAutoSaveStrokesInPowerPoint.IsOn =
|
||||
Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
|
||||
|
||||
ToggleSwitchNotifyPreviousPage.IsOn = Settings.PowerPointSettings.IsNotifyPreviousPage;
|
||||
|
||||
// -- new --
|
||||
ToggleSwitchShowPPTButton.IsOn = Settings.PowerPointSettings.ShowPPTButton;
|
||||
|
||||
ToggleSwitchEnablePPTButtonPageClickable.IsOn =
|
||||
Settings.PowerPointSettings.EnablePPTButtonPageClickable;
|
||||
|
||||
var dops = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
|
||||
var dopsc = dops.ToCharArray();
|
||||
if ((dopsc[0] == '1' || dopsc[0] == '2') && (dopsc[1] == '1' || dopsc[1] == '2') &&
|
||||
(dopsc[2] == '1' || dopsc[2] == '2') && (dopsc[3] == '1' || dopsc[3] == '2')) {
|
||||
CheckboxEnableLBPPTButton.IsChecked = dopsc[0] == '2';
|
||||
CheckboxEnableRBPPTButton.IsChecked = dopsc[1] == '2';
|
||||
CheckboxEnableLSPPTButton.IsChecked = dopsc[2] == '2';
|
||||
CheckboxEnableRSPPTButton.IsChecked = dopsc[3] == '2';
|
||||
} else {
|
||||
Settings.PowerPointSettings.PPTButtonsDisplayOption = 2222;
|
||||
CheckboxEnableLBPPTButton.IsChecked = true;
|
||||
CheckboxEnableRBPPTButton.IsChecked = true;
|
||||
CheckboxEnableLSPPTButton.IsChecked = true;
|
||||
CheckboxEnableRSPPTButton.IsChecked = true;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
var sops = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
|
||||
var sopsc = sops.ToCharArray();
|
||||
if ((sopsc[0] == '1' || sopsc[0] == '2') && (sopsc[1] == '1' || sopsc[1] == '2') &&
|
||||
(sopsc[2] == '1' || sopsc[2] == '2'))
|
||||
{
|
||||
CheckboxSPPTDisplayPage.IsChecked = sopsc[0] == '2';
|
||||
CheckboxSPPTHalfOpacity.IsChecked = sopsc[1] == '2';
|
||||
CheckboxSPPTBlackBackground.IsChecked = sopsc[2] == '2';
|
||||
}
|
||||
else
|
||||
{
|
||||
Settings.PowerPointSettings.PPTSButtonsOption = 221;
|
||||
CheckboxSPPTDisplayPage.IsChecked = true;
|
||||
CheckboxSPPTHalfOpacity.IsChecked = true;
|
||||
CheckboxSPPTBlackBackground.IsChecked = false;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
var bops = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
|
||||
var bopsc = bops.ToCharArray();
|
||||
if ((bopsc[0] == '1' || bopsc[0] == '2') && (bopsc[1] == '1' || bopsc[1] == '2') &&
|
||||
(bopsc[2] == '1' || bopsc[2] == '2'))
|
||||
{
|
||||
CheckboxBPPTDisplayPage.IsChecked = bopsc[0] == '2';
|
||||
CheckboxBPPTHalfOpacity.IsChecked = bopsc[1] == '2';
|
||||
CheckboxBPPTBlackBackground.IsChecked = bopsc[2] == '2';
|
||||
}
|
||||
else
|
||||
{
|
||||
Settings.PowerPointSettings.PPTBButtonsOption = 121;
|
||||
CheckboxBPPTDisplayPage.IsChecked = false;
|
||||
CheckboxBPPTHalfOpacity.IsChecked = true;
|
||||
CheckboxBPPTBlackBackground.IsChecked = false;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
PPTButtonLeftPositionValueSlider.Value = Settings.PowerPointSettings.PPTLSButtonPosition;
|
||||
|
||||
PPTButtonRightPositionValueSlider.Value = Settings.PowerPointSettings.PPTRSButtonPosition;
|
||||
|
||||
UpdatePPTBtnSlidersStatus();
|
||||
|
||||
UpdatePPTBtnPreview();
|
||||
|
||||
// -- new --
|
||||
|
||||
ToggleSwitchNotifyHiddenPage.IsOn = Settings.PowerPointSettings.IsNotifyHiddenPage;
|
||||
|
||||
ToggleSwitchNotifyAutoPlayPresentation.IsOn = Settings.PowerPointSettings.IsNotifyAutoPlayPresentation;
|
||||
|
||||
ToggleSwitchSupportWPS.IsOn = Settings.PowerPointSettings.IsSupportWPS;
|
||||
|
||||
ToggleSwitchAutoSaveScreenShotInPowerPoint.IsOn =
|
||||
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint;
|
||||
} else {
|
||||
Settings.PowerPointSettings = new PowerPointSettings();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Gesture
|
||||
|
||||
if (Settings.Gesture != null) {
|
||||
ToggleSwitchEnableMultiTouchMode.IsOn = Settings.Gesture.IsEnableMultiTouchMode;
|
||||
|
||||
ToggleSwitchEnableTwoFingerZoom.IsOn = Settings.Gesture.IsEnableTwoFingerZoom;
|
||||
BoardToggleSwitchEnableTwoFingerZoom.IsOn = Settings.Gesture.IsEnableTwoFingerZoom;
|
||||
|
||||
ToggleSwitchEnableTwoFingerTranslate.IsOn = Settings.Gesture.IsEnableTwoFingerTranslate;
|
||||
BoardToggleSwitchEnableTwoFingerTranslate.IsOn = Settings.Gesture.IsEnableTwoFingerTranslate;
|
||||
|
||||
ToggleSwitchEnableTwoFingerRotation.IsOn = Settings.Gesture.IsEnableTwoFingerRotation;
|
||||
BoardToggleSwitchEnableTwoFingerRotation.IsOn = Settings.Gesture.IsEnableTwoFingerRotation;
|
||||
|
||||
ToggleSwitchAutoSwitchTwoFingerGesture.IsOn = Settings.Gesture.AutoSwitchTwoFingerGesture;
|
||||
|
||||
ToggleSwitchEnableTwoFingerRotation.IsOn = Settings.Gesture.IsEnableTwoFingerRotation;
|
||||
|
||||
ToggleSwitchEnableTwoFingerRotationOnSelection.IsOn =
|
||||
Settings.Gesture.IsEnableTwoFingerRotationOnSelection;
|
||||
|
||||
//if (Settings.Gesture.AutoSwitchTwoFingerGesture) {
|
||||
// if (Topmost) {
|
||||
// ToggleSwitchEnableTwoFingerTranslate.IsOn = false;
|
||||
// BoardToggleSwitchEnableTwoFingerTranslate.IsOn = false;
|
||||
// Settings.Gesture.IsEnableTwoFingerTranslate = false;
|
||||
// if (!isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = true;
|
||||
// } else {
|
||||
// ToggleSwitchEnableTwoFingerTranslate.IsOn = true;
|
||||
// BoardToggleSwitchEnableTwoFingerTranslate.IsOn = true;
|
||||
// Settings.Gesture.IsEnableTwoFingerTranslate = true;
|
||||
// if (isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = false;
|
||||
// }
|
||||
//}
|
||||
|
||||
ToggleSwitchDisableGestureEraser.IsOn = Settings.Gesture.DisableGestureEraser;
|
||||
|
||||
if (Settings.Gesture.DisableGestureEraser) {
|
||||
GestureEraserSettingsItemsPanel.Opacity = 0.5;
|
||||
GestureEraserSettingsItemsPanel.IsHitTestVisible = false;
|
||||
SettingsGestureEraserDisabledBorder.IsOpen = true;
|
||||
} else {
|
||||
GestureEraserSettingsItemsPanel.Opacity = 1;
|
||||
GestureEraserSettingsItemsPanel.IsHitTestVisible = true;
|
||||
SettingsGestureEraserDisabledBorder.IsOpen = false;
|
||||
}
|
||||
|
||||
ComboBoxDefaultMultiPointHandWriting.SelectedIndex = Settings.Gesture.DefaultMultiPointHandWritingMode;
|
||||
|
||||
if (Settings.Gesture.DefaultMultiPointHandWritingMode == 0) {
|
||||
ToggleSwitchEnableMultiTouchMode.IsOn = true;
|
||||
} else if (Settings.Gesture.DefaultMultiPointHandWritingMode == 1) {
|
||||
ToggleSwitchEnableMultiTouchMode.IsOn = false;
|
||||
}
|
||||
|
||||
ToggleSwitchHideCursorWhenUsingTouchDevice.IsOn = Settings.Gesture.HideCursorWhenUsingTouchDevice;
|
||||
|
||||
ToggleSwitchEnableMouseGesture.IsOn = Settings.Gesture.EnableMouseGesture;
|
||||
ToggleSwitchEnableMouseRightBtnGesture.IsOn = Settings.Gesture.EnableMouseRightBtnGesture;
|
||||
ToggleSwitchEnableMouseWheelGesture.IsOn = Settings.Gesture.EnableMouseWheelGesture;
|
||||
|
||||
ComboBoxWindowsInkEraserButtonAction.SelectedIndex = Settings.Gesture.WindowsInkEraserButtonAction;
|
||||
ComboBoxWindowsInkBarrelButtonAction.SelectedIndex = Settings.Gesture.WindowsInkBarrelButtonAction;
|
||||
|
||||
CheckEnableTwoFingerGestureBtnColorPrompt();
|
||||
} else {
|
||||
Settings.Gesture = new Gesture();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Canvas
|
||||
|
||||
if (Settings.Canvas != null) {
|
||||
drawingAttributes.Height = Settings.Canvas.InkWidth;
|
||||
drawingAttributes.Width = Settings.Canvas.InkWidth;
|
||||
|
||||
InkWidthSlider.Value = Settings.Canvas.InkWidth * 2;
|
||||
HighlighterWidthSlider.Value = Settings.Canvas.HighlighterWidth;
|
||||
|
||||
ComboBoxHyperbolaAsymptoteOption.SelectedIndex = (int)Settings.Canvas.HyperbolaAsymptoteOption;
|
||||
|
||||
var bgC = BoardPagesSettingsList[CurrentWhiteboardIndex - 1].BackgroundColor;
|
||||
GridBackgroundCover.Background = new SolidColorBrush(BoardBackgroundColors[(int)bgC]);
|
||||
if (bgC == BlackboardBackgroundColorEnum.BlackBoardGreen
|
||||
|| bgC == BlackboardBackgroundColorEnum.BlueBlack
|
||||
|| bgC == BlackboardBackgroundColorEnum.GrayBlack
|
||||
|| bgC == BlackboardBackgroundColorEnum.RealBlack)
|
||||
{
|
||||
WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
|
||||
WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
|
||||
BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
|
||||
isUselightThemeColor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(22, 22, 22));
|
||||
WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(22, 22, 22));
|
||||
BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(22, 22, 22));
|
||||
isUselightThemeColor = false;
|
||||
}
|
||||
|
||||
if (Settings.Canvas.IsShowCursor) {
|
||||
ToggleSwitchShowCursor.IsOn = true;
|
||||
inkCanvas.ForceCursor = true;
|
||||
} else {
|
||||
ToggleSwitchShowCursor.IsOn = false;
|
||||
inkCanvas.ForceCursor = false;
|
||||
}
|
||||
|
||||
ComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
||||
BoardComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
||||
|
||||
ComboBoxEraserSize.SelectedIndex = Settings.Canvas.EraserSize;
|
||||
ComboBoxEraserSizeFloatingBar.SelectedIndex = Settings.Canvas.EraserSize;
|
||||
BoardComboBoxEraserSize.SelectedIndex = Settings.Canvas.EraserSize;
|
||||
|
||||
ToggleSwitchClearCanvasAndClearTimeMachine.IsOn =
|
||||
Settings.Canvas.ClearCanvasAndClearTimeMachine == true;
|
||||
|
||||
switch (Settings.Canvas.EraserShapeType) {
|
||||
case 0: {
|
||||
double k = 1;
|
||||
switch (Settings.Canvas.EraserSize) {
|
||||
case 0:
|
||||
k = 0.5;
|
||||
break;
|
||||
case 1:
|
||||
k = 0.8;
|
||||
break;
|
||||
case 3:
|
||||
k = 1.25;
|
||||
break;
|
||||
case 4:
|
||||
k = 1.8;
|
||||
break;
|
||||
}
|
||||
|
||||
inkCanvas.EraserShape = new EllipseStylusShape(k * 90, k * 90);
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
double k = 1;
|
||||
switch (Settings.Canvas.EraserSize) {
|
||||
case 0:
|
||||
k = 0.7;
|
||||
break;
|
||||
case 1:
|
||||
k = 0.9;
|
||||
break;
|
||||
case 3:
|
||||
k = 1.2;
|
||||
break;
|
||||
case 4:
|
||||
k = 1.6;
|
||||
break;
|
||||
}
|
||||
|
||||
inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CheckEraserTypeTab();
|
||||
|
||||
ToggleSwitchHideStrokeWhenSelecting.IsOn = Settings.Canvas.HideStrokeWhenSelecting;
|
||||
|
||||
if (Settings.Canvas.FitToCurve) {
|
||||
ToggleSwitchFitToCurve.IsOn = true;
|
||||
drawingAttributes.FitToCurve = true;
|
||||
} else {
|
||||
ToggleSwitchFitToCurve.IsOn = false;
|
||||
drawingAttributes.FitToCurve = false;
|
||||
}
|
||||
|
||||
ComboBoxBlackboardBackgroundColor.SelectedIndex = (int)Settings.Canvas.BlackboardBackgroundColor;
|
||||
ComboBoxBlackboardBackgroundPattern.SelectedIndex = (int)Settings.Canvas.BlackboardBackgroundPattern;
|
||||
|
||||
BoardPagesSettingsList[0].BackgroundColor = Settings.Canvas.BlackboardBackgroundColor;
|
||||
BoardPagesSettingsList[0].BackgroundPattern = Settings.Canvas.BlackboardBackgroundPattern;
|
||||
|
||||
ToggleSwitchUseDefaultBackgroundColorForEveryNewAddedBlackboardPage.IsOn =
|
||||
Settings.Canvas.UseDefaultBackgroundColorForEveryNewAddedBlackboardPage;
|
||||
ToggleSwitchUseDefaultBackgroundPatternForEveryNewAddedBlackboardPage.IsOn =
|
||||
Settings.Canvas.UseDefaultBackgroundPatternForEveryNewAddedBlackboardPage;
|
||||
|
||||
ToggleSwitchIsEnableAutoConvertInkColorWhenBackgroundChanged.IsOn =
|
||||
Settings.Canvas.IsEnableAutoConvertInkColorWhenBackgroundChanged;
|
||||
|
||||
ComboBoxSelectionMethod.SelectedIndex = Settings.Canvas.SelectionMethod;
|
||||
ToggleSwitchAllowClickToSelectLockedStroke.IsOn = Settings.Canvas.AllowClickToSelectLockedStroke;
|
||||
ToggleSwitchOnlyHitTestFullyContainedStrokes.IsOn = Settings.Canvas.OnlyHitTestFullyContainedStrokes;
|
||||
ToggleSwitchApplyScaleToStylusTip.IsOn = Settings.Canvas.ApplyScaleToStylusTip;
|
||||
} else {
|
||||
Settings.Canvas = new Canvas();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Advanced
|
||||
|
||||
if (Settings.Advanced != null) {
|
||||
TouchMultiplierSlider.Value = Settings.Advanced.TouchMultiplier;
|
||||
FingerModeBoundsWidthSlider.Value = Settings.Advanced.FingerModeBoundsWidth;
|
||||
NibModeBoundsWidthSlider.Value = Settings.Advanced.NibModeBoundsWidth;
|
||||
FingerModeBoundsWidthThresholdValueSlider.Value = Settings.Advanced.FingerModeBoundsWidthThresholdValue;
|
||||
NibModeBoundsWidthThresholdValueSlider.Value = Settings.Advanced.NibModeBoundsWidthThresholdValue;
|
||||
FingerModeBoundsWidthEraserSizeSlider.Value = Settings.Advanced.FingerModeBoundsWidthEraserSize;
|
||||
NibModeBoundsWidthEraserSizeSlider.Value = Settings.Advanced.NibModeBoundsWidthEraserSize;
|
||||
|
||||
ToggleSwitchIsLogEnabled.IsOn = Settings.Advanced.IsLogEnabled;
|
||||
|
||||
ToggleSwitchIsSpecialScreen.IsOn = Settings.Advanced.IsSpecialScreen;
|
||||
|
||||
TouchMultiplierSlider.Visibility =
|
||||
ToggleSwitchIsSpecialScreen.IsOn ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
ToggleSwitchIsQuadIR.IsOn = Settings.Advanced.IsQuadIR;
|
||||
|
||||
ToggleSwitchIsEnableFullScreenHelper.IsOn = Settings.Advanced.IsEnableFullScreenHelper;
|
||||
if (Settings.Advanced.IsEnableFullScreenHelper) {
|
||||
FullScreenHelper.MarkFullscreenWindowTaskbarList(new WindowInteropHelper(this).Handle, true);
|
||||
}
|
||||
|
||||
ToggleSwitchIsEnableEdgeGestureUtil.IsOn = Settings.Advanced.IsEnableEdgeGestureUtil;
|
||||
if (Settings.Advanced.IsEnableEdgeGestureUtil) {
|
||||
if (OSVersion.GetOperatingSystem() >= OperatingSystem.Windows10)
|
||||
EdgeGestureUtil.DisableEdgeGestures(new WindowInteropHelper(this).Handle, true);
|
||||
}
|
||||
|
||||
ToggleSwitchIsEnableForceFullScreen.IsOn = Settings.Advanced.IsEnableForceFullScreen;
|
||||
|
||||
ToggleSwitchIsEnableDPIChangeDetection.IsOn = Settings.Advanced.IsEnableDPIChangeDetection;
|
||||
|
||||
ToggleSwitchIsEnableResolutionChangeDetection.IsOn =
|
||||
Settings.Advanced.IsEnableResolutionChangeDetection;
|
||||
|
||||
ToggleSwitchEnsureFloatingBarVisibleInScreen.IsOn = Settings.Advanced.IsEnableDPIChangeDetection &&
|
||||
Settings.Advanced.IsEnableResolutionChangeDetection;
|
||||
|
||||
ToggleSwitchIsDisableCloseWindow.IsOn = Settings.Advanced.IsDisableCloseWindow;
|
||||
ToggleSwitchEnableForceTopMost.IsOn = Settings.Advanced.EnableForceTopMost;
|
||||
} else {
|
||||
Settings.Advanced = new Advanced();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ink Recognition
|
||||
|
||||
if (Settings.InkToShape != null) {
|
||||
ToggleSwitchEnableInkToShape.IsOn = Settings.InkToShape.IsInkToShapeEnabled;
|
||||
|
||||
ToggleSwitchEnableInkToShapeNoFakePressureRectangle.IsOn =
|
||||
Settings.InkToShape.IsInkToShapeNoFakePressureRectangle;
|
||||
|
||||
ToggleSwitchEnableInkToShapeNoFakePressureTriangle.IsOn =
|
||||
Settings.InkToShape.IsInkToShapeNoFakePressureTriangle;
|
||||
|
||||
ToggleCheckboxEnableInkToShapeTriangle.IsChecked = Settings.InkToShape.IsInkToShapeTriangle;
|
||||
|
||||
ToggleCheckboxEnableInkToShapeRectangle.IsChecked = Settings.InkToShape.IsInkToShapeRectangle;
|
||||
|
||||
ToggleCheckboxEnableInkToShapeRounded.IsChecked = Settings.InkToShape.IsInkToShapeRounded;
|
||||
} else {
|
||||
Settings.InkToShape = new InkToShape();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RandSettings
|
||||
|
||||
if (Settings.RandSettings != null) {
|
||||
ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = Settings.RandSettings.DisplayRandWindowNamesInputBtn;
|
||||
RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
|
||||
RandWindowOnceMaxStudentsSlider.Value = Settings.RandSettings.RandWindowOnceMaxStudents;
|
||||
} else {
|
||||
Settings.RandSettings = new RandSettings();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Automation
|
||||
|
||||
if (Settings.Automation != null) {
|
||||
StartOrStoptimerCheckAutoFold();
|
||||
ToggleSwitchAutoFoldInEasiNote.IsOn = Settings.Automation.IsAutoFoldInEasiNote;
|
||||
|
||||
ToggleSwitchAutoFoldInEasiCamera.IsOn = Settings.Automation.IsAutoFoldInEasiCamera;
|
||||
|
||||
ToggleSwitchAutoFoldInEasiNote3C.IsOn = Settings.Automation.IsAutoFoldInEasiNote3C;
|
||||
|
||||
ToggleSwitchAutoFoldInEasiNote3.IsOn = Settings.Automation.IsAutoFoldInEasiNote3;
|
||||
|
||||
ToggleSwitchAutoFoldInEasiNote5C.IsOn = Settings.Automation.IsAutoFoldInEasiNote5C;
|
||||
|
||||
ToggleSwitchAutoFoldInSeewoPincoTeacher.IsOn = Settings.Automation.IsAutoFoldInSeewoPincoTeacher;
|
||||
|
||||
ToggleSwitchAutoFoldInHiteTouchPro.IsOn = Settings.Automation.IsAutoFoldInHiteTouchPro;
|
||||
|
||||
ToggleSwitchAutoFoldInHiteLightBoard.IsOn = Settings.Automation.IsAutoFoldInHiteLightBoard;
|
||||
|
||||
ToggleSwitchAutoFoldInHiteCamera.IsOn = Settings.Automation.IsAutoFoldInHiteCamera;
|
||||
|
||||
ToggleSwitchAutoFoldInWxBoardMain.IsOn = Settings.Automation.IsAutoFoldInWxBoardMain;
|
||||
|
||||
ToggleSwitchAutoFoldInOldZyBoard.IsOn = Settings.Automation.IsAutoFoldInOldZyBoard;
|
||||
|
||||
ToggleSwitchAutoFoldInMSWhiteboard.IsOn = Settings.Automation.IsAutoFoldInMSWhiteboard;
|
||||
|
||||
ToggleSwitchAutoFoldInAdmoxWhiteboard.IsOn = Settings.Automation.IsAutoFoldInAdmoxWhiteboard;
|
||||
|
||||
ToggleSwitchAutoFoldInAdmoxBooth.IsOn = Settings.Automation.IsAutoFoldInAdmoxBooth;
|
||||
|
||||
ToggleSwitchAutoFoldInQPoint.IsOn = Settings.Automation.IsAutoFoldInQPoint;
|
||||
|
||||
ToggleSwitchAutoFoldInYiYunVisualPresenter.IsOn = Settings.Automation.IsAutoFoldInYiYunVisualPresenter;
|
||||
|
||||
ToggleSwitchAutoFoldInMaxHubWhiteboard.IsOn = Settings.Automation.IsAutoFoldInMaxHubWhiteboard;
|
||||
|
||||
SettingsPPTInkingAndAutoFoldExplictBorder.IsOpen = false;
|
||||
if (Settings.Automation.IsAutoFoldInPPTSlideShow) {
|
||||
SettingsPPTInkingAndAutoFoldExplictBorder.IsOpen = true;
|
||||
SettingsShowCanvasAtNewSlideShowStackPanel.Opacity = 0.5;
|
||||
SettingsShowCanvasAtNewSlideShowStackPanel.IsHitTestVisible = false;
|
||||
}
|
||||
|
||||
ToggleSwitchAutoFoldInPPTSlideShow.IsOn = Settings.Automation.IsAutoFoldInPPTSlideShow;
|
||||
|
||||
if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService ||
|
||||
Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas
|
||||
|| Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT ||
|
||||
Settings.Automation.IsAutoKillVComYouJiao
|
||||
|| Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) {
|
||||
timerKillProcess.Start();
|
||||
} else {
|
||||
timerKillProcess.Stop();
|
||||
}
|
||||
|
||||
ToggleSwitchAutoKillEasiNote.IsOn = Settings.Automation.IsAutoKillEasiNote;
|
||||
|
||||
ToggleSwitchAutoKillHiteAnnotation.IsOn = Settings.Automation.IsAutoKillHiteAnnotation;
|
||||
|
||||
ToggleSwitchAutoKillPptService.IsOn = Settings.Automation.IsAutoKillPptService;
|
||||
|
||||
ToggleSwitchAutoKillVComYouJiao.IsOn = Settings.Automation.IsAutoKillVComYouJiao;
|
||||
|
||||
ToggleSwitchAutoKillInkCanvas.IsOn = Settings.Automation.IsAutoKillInkCanvas;
|
||||
|
||||
ToggleSwitchAutoKillICA.IsOn = Settings.Automation.IsAutoKillICA;
|
||||
|
||||
//ToggleSwitchAutoKillIDT.IsOn = Settings.Automation.IsAutoKillIDT;
|
||||
|
||||
ToggleSwitchAutoKillSeewoLauncher2DesktopAnnotation.IsOn =
|
||||
Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation;
|
||||
|
||||
ToggleSwitchAutoSaveStrokesAtClear.IsOn = Settings.Automation.IsAutoSaveStrokesAtClear;
|
||||
|
||||
ToggleSwitchSaveScreenshotsInDateFolders.IsOn = Settings.Automation.IsSaveScreenshotsInDateFolders;
|
||||
|
||||
ToggleSwitchAutoSaveStrokesAtScreenshot.IsOn = Settings.Automation.IsAutoSaveStrokesAtScreenshot;
|
||||
|
||||
SideControlMinimumAutomationSlider.Value = Settings.Automation.MinimumAutomationStrokeNumber;
|
||||
|
||||
ToggleSwitchAutoDelSavedFiles.IsOn = Settings.Automation.AutoDelSavedFiles;
|
||||
ComboBoxAutoDelSavedFilesDaysThreshold.Text =
|
||||
Settings.Automation.AutoDelSavedFilesDaysThreshold.ToString();
|
||||
|
||||
ToggleSwitchLimitAutoSaveAmount.IsOn = Settings.Automation.IsEnableLimitAutoSaveAmount;
|
||||
ComboBoxLimitAutoSaveAmount.SelectedIndex = Settings.Automation.LimitAutoSaveAmount;
|
||||
|
||||
} else {
|
||||
Settings.Automation = new Automation();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Snapshot
|
||||
|
||||
if (Settings.Snapshot != null) {
|
||||
ToggleSwitchScreenshotUsingMagnificationAPI.IsOn = Settings.Snapshot.ScreenshotUsingMagnificationAPI;
|
||||
ToggleSwitchCopyScreenshotToClipboard.IsOn = Settings.Snapshot.CopyScreenshotToClipboard;
|
||||
ToggleSwitchHideMainWinWhenScreenshot.IsOn = Settings.Snapshot.HideMainWinWhenScreenshot;
|
||||
ToggleSwitchAttachInkWhenScreenshot.IsOn = Settings.Snapshot.AttachInkWhenScreenshot;
|
||||
ToggleSwitchOnlySnapshotMaximizeWindow.IsOn = Settings.Snapshot.OnlySnapshotMaximizeWindow;
|
||||
ScreenshotFileName.Text = Settings.Snapshot.ScreenshotFileName;
|
||||
} else {
|
||||
Settings.Snapshot = new Snapshot();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// auto align
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible) {
|
||||
ViewboxFloatingBarMarginAnimation(60);
|
||||
} else {
|
||||
ViewboxFloatingBarMarginAnimation(100, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
public StrokeCollection DrawShapeCore(PointCollection pts, ShapeDrawingType type, bool doNotDisturbutePoints, bool isPreview) {
|
||||
// 线
|
||||
if (type == MainWindow.ShapeDrawingType.Line ||
|
||||
type == MainWindow.ShapeDrawingType.DashedLine ||
|
||||
type == MainWindow.ShapeDrawingType.DottedLine ||
|
||||
type == MainWindow.ShapeDrawingType.ArrowOneSide ||
|
||||
type == MainWindow.ShapeDrawingType.ArrowTwoSide) {
|
||||
if (pts.Count != 2) throw new Exception("传入的点个数不是2个");
|
||||
var stk = new IccStroke(new StylusPointCollection() {
|
||||
new StylusPoint(pts[0].X, pts[0].Y),
|
||||
new StylusPoint(pts[1].X, pts[1].Y),
|
||||
}, inkCanvas.DefaultDrawingAttributes.Clone()) {
|
||||
IsDistributePointsOnLineShape = !doNotDisturbutePoints,
|
||||
};
|
||||
stk.AddPropertyData(IccStroke.StrokeIsShapeGuid, true);
|
||||
stk.AddPropertyData(IccStroke.StrokeShapeTypeGuid, (int)type);
|
||||
return new StrokeCollection() { stk };
|
||||
}
|
||||
|
||||
return new StrokeCollection();
|
||||
}
|
||||
|
||||
public static class ShapeDrawingHelper {
|
||||
|
||||
/// <summary>
|
||||
/// 根据给定的两个点计算角度
|
||||
/// </summary>
|
||||
/// <param name="firstPoint"></param>
|
||||
/// <param name="lastPoint"></param>
|
||||
/// <returns></returns>
|
||||
public static double CaculateRotateAngleByGivenTwoPoints(Point firstPoint, Point lastPoint) {
|
||||
var vec1 = new double[] {
|
||||
lastPoint.X - firstPoint.X ,
|
||||
lastPoint.Y - firstPoint.Y
|
||||
};
|
||||
var vec_base = new double[] { 0, firstPoint.Y };
|
||||
var cosine = (vec_base[0] * vec1[0] + vec_base[1] * vec1[1]) /
|
||||
(Math.Sqrt(Math.Pow(vec_base[0],2) + Math.Pow(vec_base[1],2)) *
|
||||
Math.Sqrt(Math.Pow(vec1[0],2) + Math.Pow(vec1[1],2)));
|
||||
var angle = Math.Acos(cosine);
|
||||
var isIn2And3Quadrant = lastPoint.X <= firstPoint.X;
|
||||
var rotateAngle = Math.Round(180 + 180 * (angle / Math.PI) * (isIn2And3Quadrant ? 1 : -1), 0);
|
||||
return rotateAngle;
|
||||
}
|
||||
|
||||
|
||||
public static List<Point> DistributePointsOnLine(Point start, Point end, double interval=16) {
|
||||
List<Point> points = new List<Point>();
|
||||
|
||||
double dx = end.X - start.X;
|
||||
double dy = end.Y - start.Y;
|
||||
double distance = Math.Sqrt(dx * dx + dy * dy);
|
||||
int numPoints = (int)(distance / interval);
|
||||
|
||||
for (int i = 0; i <= numPoints; i++) {
|
||||
double ratio = (interval * i) / distance;
|
||||
double x = start.X + ratio * dx;
|
||||
double y = start.Y + ratio * dy;
|
||||
points.Add(new Point(x, y));
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
public class ArrowLineConfig {
|
||||
public int ArrowWidth { get; set; } = 20;
|
||||
public int ArrowHeight { get; set; } = 7;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
<UserControl x:Class="Ink_Canvas.ShapeDrawingLayer"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Ink_Canvas"
|
||||
xmlns:modern="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:helpers="clr-namespace:Ink_Canvas.Helpers"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="1920" d:DesignHeight="1080">
|
||||
<Grid>
|
||||
<helpers:DrawingVisualCanvas IsHitTestVisible="False" x:Name="DrawingVisualCanvas"/>
|
||||
<Grid Name="FullscreenGrid"/>
|
||||
<Border Name="Toolbar" Height="48" Width="728" Background="#fafafa" BorderBrush="#e4e4e7" BorderThickness="1" CornerRadius="6" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,36">
|
||||
<Grid>
|
||||
<Border Name="ToolbarMoveHandle" Width="24" Height="48" Background="#d4d4d8" BorderBrush="#88a1a1aa" Margin="-1,-1,0,-1" CornerRadius="6,0,0,6" HorizontalAlignment="Left" BorderThickness="1">
|
||||
<Image Width="12" Margin="2,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V37 H16 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#a1a1aa" Geometry="F0 M16,37z M0,0z M13,6C14.6567,6 16,4.65686 16,3 16,1.34314 14.6567,0 13,0 11.3433,0 10,1.34314 10,3 10,4.65686 11.3433,6 13,6z M3,6.11261C4.65674,6.11261 6,4.76947 6,3.11261 6,1.45575 4.65674,0.11261 3,0.11261 1.34326,0.11261 0,1.45575 0,3.11261 0,4.76947 1.34326,6.11261 3,6.11261z M6,13.1126C6,14.7695 4.65674,16.1126 3,16.1126 1.34326,16.1126 0,14.7695 0,13.1126 0,11.4557 1.34326,10.1126 3,10.1126 4.65674,10.1126 6,11.4557 6,13.1126z M13,16C14.6567,16 16,14.6569 16,13 16,11.3431 14.6567,10 13,10 11.3433,10 10,11.3431 10,13 10,14.6569 11.3433,16 13,16z M6,23.1126C6,24.7695 4.65674,26.1126 3,26.1126 1.34326,26.1126 0,24.7695 0,23.1126 0,21.4557 1.34326,20.1126 3,20.1126 4.65674,20.1126 6,21.4557 6,23.1126z M13,26C14.6567,26 16,24.6569 16,23 16,21.3431 14.6567,20 13,20 11.3433,20 10,21.3431 10,23 10,24.6569 11.3433,26 13,26z M6,33.1126C6,34.7695 4.65674,36.1126 3,36.1126 1.34326,36.1126 0,34.7695 0,33.1126 0,31.4557 1.34326,30.1126 3,30.1126 4.65674,30.1126 6,31.4557 6,33.1126z M13,36C14.6567,36 16,34.6569 16,33 16,31.3431 14.6567,30 13,30 11.3433,30 10,31.3431 10,33 10,34.6569 11.3433,36 13,36z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</Border>
|
||||
<Button Foreground="White" Content="完成" Padding="16,6" FontSize="16" Click="DoneButtonClicked"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,8,0">
|
||||
<Button.Resources>
|
||||
<SolidColorBrush
|
||||
x:Key="{x:Static modern:ThemeKeys.ButtonBackgroundKey}"
|
||||
Color="#2563eb" />
|
||||
<SolidColorBrush
|
||||
x:Key="{x:Static modern:ThemeKeys.ButtonBackgroundPointerOverKey}"
|
||||
Color="#2563eb" />
|
||||
<SolidColorBrush
|
||||
x:Key="{x:Static modern:ThemeKeys.ButtonBackgroundPressedKey}"
|
||||
Color="#1e40af" />
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
<modern:SimpleStackPanel Margin="30,0,82,0" Spacing="4" Orientation="Horizontal">
|
||||
<Border Name="CursorButton" Padding="9,0" Height="36" Width="36" CornerRadius="5">
|
||||
<Image Width="23" Height="23" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V16 H16 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F1 M16,16z M0,0z M4.22929,10.3892C4.37895,11.3606 4.5047,12.1768 4.58442,12.6882 4.65533,13.1234 5.12214,13.1723 5.35668,12.7448 5.7484,12.0468 6.45109,10.826 6.94285,9.97433L9.65754,13.8513C9.768,14.009,9.98544,14.0474,10.1432,13.9369L11.2857,13.1369C11.4435,13.0265,11.4817,12.809,11.3713,12.6513L8.83296,9.02618C10.0101,9.02604 11.6711,9.02597 12.5766,9.02632 13.0884,9.00839 13.1289,8.5242 12.7521,8.23186 10.7514,6.84664 6.03382,3.63789 3.75702,2.14093 3.36741,1.86634 2.89582,1.9778 3.01682,2.60989 3.34465,4.64736 3.85981,7.99113 4.22929,10.3892z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</Border>
|
||||
<Border Name="UndoButton" Padding="9,0" Height="36" Width="36" CornerRadius="5">
|
||||
<Image Width="24" Height="24" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V16 H16 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F1 M16,16z M0,0z M7.04202,4.02051C7.04757,3.43213 6.47012,3.28587 6.18416,3.57018 5.10859,4.63952 3.1937,6.53764 2.26671,7.45928 1.92345,7.80055 1.91016,8.21537 2.23474,8.53802 3.14903,9.44705 5.09052,11.2748 6.17629,12.3543 6.46488,12.6412 7.04227,12.7032 7.04202,11.9083 7.04202,11.1775 7.06964,9.7887 7.06964,9.7887 8.87951,9.79135 11.9537,10.7495 13.4887,12.437 13.7194,12.6906 14.0567,12.2934 13.9919,11.9491 13.37,8.64627 10.2122,6.48714 7.06391,6.07519 7.06391,6.07519 7.04202,4.75251 7.04202,4.02051z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</Border>
|
||||
<Border Name="RedoButton" Padding="9,0" Height="36" Width="36" CornerRadius="5">
|
||||
<Image Width="24" Height="24" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V16 H16 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F1 M16,16z M0,0z M8.95798,4.02051C8.95243,3.43213 9.52988,3.28587 9.81584,3.57018 10.8914,4.63952 12.8063,6.53764 13.7333,7.45928 14.0766,7.80055 14.0898,8.21537 13.7653,8.53802 12.851,9.44705 10.9095,11.2748 9.82371,12.3543 9.53512,12.6412 8.95773,12.7032 8.95798,11.9083 8.95798,11.1775 8.93036,9.7887 8.93036,9.7887 7.12049,9.79135 4.04627,10.7495 2.51129,12.437 2.28061,12.6906 1.94328,12.2934 2.00813,11.9491 2.63002,8.64627 5.78777,6.48714 8.93609,6.07519 8.93609,6.07519 8.95798,4.75251 8.95798,4.02051z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</Border>
|
||||
<Border Name="ClearButton" Padding="9,0" Height="36" Width="36" CornerRadius="5">
|
||||
<Image Width="23" Height="23" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V16 H16 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F0 M16,16z M0,0z M6.24025,2C6.09677,2,5.96939,2.09181,5.92403,2.22793L5.55555,3.33333 2.33333,3.33333C2.14924,3.33333,2,3.48257,2,3.66667L2,4.33333C2,4.51743,2.14924,4.66667,2.33333,4.66667L13.6667,4.66667C13.8507,4.66667,14,4.51743,14,4.33333L14,3.66667C14,3.48257,13.8507,3.33333,13.6667,3.33333L10.4445,3.33333 10.076,2.22793C10.0306,2.09181,9.9032,2,9.75973,2L6.24025,2z M3.33333,5.66667L12.6667,5.66667 12.0491,13.3865C12.0213,13.7329,11.7321,14,11.3845,14L4.61546,14C4.26789,14,3.97864,13.7329,3.95092,13.3865L3.33333,5.66667z M6.33333,8C6.14924,8,6,8.14927,6,8.33333L6,11C6,11.1841,6.14924,11.3333,6.33333,11.3333L6.66667,11.3333C6.85073,11.3333,7,11.1841,7,11L7,8.33333C7,8.14927,6.85073,8,6.66667,8L6.33333,8z M9,8.33333C9,8.14927,9.14927,8,9.33333,8L9.66667,8C9.85073,8,10,8.14927,10,8.33333L10,11C10,11.1841,9.85073,11.3333,9.66667,11.3333L9.33333,11.3333C9.14927,11.3333,9,11.1841,9,11L9,8.33333z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</Border>
|
||||
<Line X1="0" Y1="0" X2="0" Y2="36" VerticalAlignment="Center" StrokeThickness="1" Stroke="#a1a1aa"/>
|
||||
<Border Name="GridLineButton" Padding="9,0" Height="36" CornerRadius="5">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Width="20" Height="20" VerticalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F0 M24,24z M0,0z M7,3C7,2.44772 6.55228,2 6,2 5.44772,2 5,2.44772 5,3L5,5 3,5C2.44772,5 2,5.44772 2,6 2,6.55228 2.44772,7 3,7L5,7 5,11 3,11C2.44772,11 2,11.4477 2,12 2,12.5523 2.44772,13 3,13L5,13 5,17 3,17C2.44772,17 2,17.4477 2,18 2,18.5523 2.44772,19 3,19L5,19 5,21C5,21.5523 5.44772,22 6,22 6.55228,22 7,21.5523 7,21L7,19 11,19 11,21C11,21.5523 11.4477,22 12,22 12.5523,22 13,21.5523 13,21L13,19 17,19 17,21C17,21.5523 17.4477,22 18,22 18.5523,22 19,21.5523 19,21L19,19 21,19C21.5523,19 22,18.5523 22,18 22,17.4477 21.5523,17 21,17L19,17 19,13 21,13C21.5523,13 22,12.5523 22,12 22,11.4477 21.5523,11 21,11L19,11 19,7 21,7C21.5523,7 22,6.55228 22,6 22,5.44772 21.5523,5 21,5L19,5 19,3C19,2.44772 18.5523,2 18,2 17.4477,2 17,2.44772 17,3L17,5 13,5 13,3C13,2.44772 12.5523,2 12,2 11.4477,2 11,2.44772 11,3L11,5 7,5 7,3z M17,7L13,7 13,11 17,11 17,7z M17,13L13,13 13,17 17,17 17,13z M11,13L11,17 7,17 7,13 11,13z M11,7L11,11 7,11 7,7 11,7z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<TextBlock FontSize="14" Margin="4,0,0,0" Text="网格辅助线" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Name="SnapButton" Padding="9,0" Height="36" CornerRadius="5">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Width="20" Height="20" VerticalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F0 M24,24z M0,0z M4,4C3.46957,4 2.96086,4.21071 2.58579,4.58579 2.21071,4.96086 2,5.46957 2,6L2,18C2,18.5304 2.21071,19.0391 2.58579,19.4142 2.96086,19.7893 3.46957,20 4,20L20,20C20.5304,20 21.0391,19.7893 21.4142,19.4142 21.7893,19.0391 22,18.5304 22,18L22,13C22,12.4477 21.5523,12 21,12 20.4477,12 20,12.4477 20,13L20,18 4,18 4,6 13,6C13.5523,6 14,5.55228 14,5 14,4.44772 13.5523,4 13,4L4,4z M17.5858,8.41421C17.2107,8.03914 17,7.53043 17,7 17,6.46957 17.2107,5.96086 17.5858,5.58579 17.9609,5.21071 18.4696,5 19,5 19.5304,5 20.0391,5.21071 20.4142,5.58579 20.7893,5.96086 21,6.46957 21,7 21,7.53043 20.7893,8.03914 20.4142,8.41421 20.0391,8.78929 19.5304,9 19,9 18.4696,9 17.9609,8.78929 17.5858,8.41421z M10,12C9.44772,12 9,11.5523 9,11 9,10.4477 9.44772,10 10,10L14,10C14.2751,10 14.5242,10.1111 14.705,10.2908 14.7064,10.2922 14.7078,10.2936 14.7092,10.295 14.804,10.3904 14.8757,10.5001 14.9241,10.6172 14.9727,10.7343 14.9996,10.8625 15,10.997 15,10.998 15,10.999 15,11L15,11.0007 15,15C15,15.5523 14.5523,16 14,16 13.4477,16 13,15.5523 13,15L13,13.4142 10.7071,15.7071C10.3166,16.0976 9.68342,16.0976 9.29289,15.7071 8.90237,15.3166 8.90237,14.6834 9.29289,14.2929L11.5858,12 10,12z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<TextBlock FontSize="14" Margin="4,0,0,0" Text="顶点吸附" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Name="MultiPointButton" Padding="9,0" Height="36" CornerRadius="5">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Width="20" Height="20" VerticalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F1 M24,24z M0,0z M20.5023,9.22252C19.8223,8.53252 18.7423,8.35252 17.8523,8.67252 17.7523,8.51252 17.6423,8.36252 17.5023,8.22252 16.8223,7.53252 15.7423,7.35252 14.8523,7.67252 14.7523,7.51252 14.6423,7.35252 14.5023,7.22252 14.2723,6.99252 13.9923,6.80252 13.6923,6.68252 13.2323,6.49252 12.7223,6.44252 12.2323,6.54252L12.2323,3.99252C12.2323,3.32252 11.9723,2.69252 11.5023,2.22252 10.5623,1.28252 8.90226,1.28252 7.96226,2.22252 7.49226,2.69252 7.23226,3.32252 7.23226,3.99252L7.23226,10.1125C6.82226,9.78252 6.32226,9.56252 5.79226,9.49252 5.16226,9.41252 4.51226,9.55252 3.97226,9.88252 3.41226,10.2225 3.01226,10.7525 2.84226,11.3825 2.67226,12.0125 2.76226,12.6825 3.08226,13.2525 4.98226,16.6325 6.07226,18.5325 6.40226,19.0325L6.60226,19.3425C7.23226,20.3025 8.11226,21.1025 9.13226,21.6525 10.0523,22.1425 11.0723,22.4325 12.1123,22.4825 12.1523,22.4825 12.1923,22.4825 12.2423,22.4825L14.2423,22.4825C16.1123,22.4825 17.8723,21.7525 19.1923,20.4325 20.4923,19.1325 21.2423,17.3225 21.2423,15.4825L21.2423,10.9825C21.2423,10.3125,20.9823,9.68252,20.5123,9.21252L20.5023,9.22252z M19.2323,15.4925C19.2323,16.8125 18.7023,18.0925 17.7723,19.0325 16.8423,19.9725 15.5723,20.4925 14.2323,20.4925L12.4423,20.4925C11.6223,20.4925 10.7923,20.2825 10.0723,19.8925 9.34226,19.5025 8.72226,18.9325 8.27226,18.2425L8.08226,17.9425C7.87226,17.6225 7.14226,16.3825 4.83226,12.2725 4.77226,12.1625 4.75226,12.0225 4.78226,11.9025 4.81226,11.7725 4.89226,11.6725 5.01226,11.6025 5.17226,11.5025 5.37226,11.4625 5.56226,11.4825 5.75226,11.5025 5.93226,11.5925 6.07226,11.7325L7.54226,13.2025C7.63226,13.2925 7.74226,13.3725 7.87226,13.4225 8.11226,13.5225 8.39226,13.5225 8.63226,13.4225 8.87226,13.3225 9.07226,13.1225 9.17226,12.8825 9.22226,12.7625 9.25226,12.6325 9.25226,12.5025L9.25226,3.99252C9.25226,3.86252 9.30226,3.73252 9.40226,3.64252 9.59226,3.45252 9.92226,3.45252 10.1123,3.64252 10.2023,3.73252 10.2623,3.86252 10.2623,3.99252L10.2623,11.4925C10.2623,12.0425 10.7123,12.4925 11.2623,12.4925 11.8123,12.4925 12.2623,12.0425 12.2623,11.4925L12.2623,8.99252C12.2623,8.92252 12.2723,8.86252 12.3023,8.80252 12.3323,8.74252 12.3623,8.68252 12.4123,8.64252 12.4623,8.60252 12.5123,8.56252 12.5723,8.53252 12.6923,8.48252 12.8323,8.48252 12.9523,8.53252 13.0123,8.55252 13.0623,8.59252 13.1123,8.64252 13.1623,8.69252 13.1923,8.74252 13.2223,8.80252 13.2523,8.86252 13.2623,8.93252 13.2623,8.99252L13.2623,11.4925C13.2623,12.0425 13.7123,12.4925 14.2623,12.4925 14.8123,12.4925 15.2623,12.0425 15.2623,11.4925L15.2623,9.99252C15.2623,9.86252 15.3123,9.73252 15.4123,9.64252 15.6023,9.45252 15.9323,9.45252 16.1223,9.64252 16.2123,9.73252 16.2723,9.86252 16.2723,9.99252L16.2723,11.4925C16.2723,12.0425 16.7223,12.4925 17.2723,12.4925 17.8223,12.4925 18.2723,12.0425 18.2723,11.4925L18.2723,10.9925C18.2723,10.8625 18.3223,10.7325 18.4223,10.6425 18.6123,10.4525 18.9423,10.4525 19.1323,10.6425 19.2223,10.7325 19.2823,10.8625 19.2823,10.9925L19.2823,15.4925 19.2323,15.4925z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<TextBlock FontSize="14" Margin="4,0,0,0" Text="多指绘制" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Name="InfoButton" Padding="9,0" Height="36" CornerRadius="5">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Width="20" Height="20" VerticalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F0 M24,24z M0,0z M4.92893,4.92893C6.8043,3.05357 9.34784,2 12,2 14.6522,2 17.1957,3.05357 19.0711,4.92893 20.9464,6.8043 22,9.34784 22,12 22,13.3132 21.7413,14.6136 21.2388,15.8268 20.7362,17.0401 19.9997,18.1425 19.0711,19.0711 18.1425,19.9997 17.0401,20.7362 15.8268,21.2388 14.6136,21.7413 13.3132,22 12,22 10.6868,22 9.38642,21.7413 8.17317,21.2388 6.95991,20.7362 5.85752,19.9997 4.92893,19.0711 4.00035,18.1425 3.26375,17.0401 2.7612,15.8268 2.25866,14.6136 2,13.3132 2,12 2,9.34784 3.05357,6.8043 4.92893,4.92893z M12,4C9.87827,4 7.84344,4.84285 6.34315,6.34315 4.84285,7.84344 4,9.87827 4,12 4,13.0506 4.20693,14.0909 4.60896,15.0615 5.011,16.0321 5.60028,16.914 6.34315,17.6569 7.08601,18.3997 7.96793,18.989 8.93853,19.391 9.90914,19.7931 10.9494,20 12,20 13.0506,20 14.0909,19.7931 15.0615,19.391 16.0321,18.989 16.914,18.3997 17.6569,17.6569 18.3997,16.914 18.989,16.0321 19.391,15.0615 19.7931,14.0909 20,13.0506 20,12 20,9.87827 19.1571,7.84344 17.6569,6.34315 16.1566,4.84285 14.1217,4 12,4z M11,9C11,8.44772,11.4477,8,12,8L12.01,8C12.5623,8 13.01,8.44772 13.01,9 13.01,9.55228 12.5623,10 12.01,10L12,10C11.4477,10,11,9.55228,11,9z M11,11C10.4477,11 10,11.4477 10,12 10,12.5523 10.4477,13 11,13L11,16C11,16.5523,11.4477,17,12,17L13,17C13.5523,17 14,16.5523 14,16 14,15.4477 13.5523,15 13,15L13,12C13,11.4477,12.5523,11,12,11L11,11z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<TextBlock FontSize="14" Margin="4,0,0,0" Text="信息" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Name="MoreButton" Padding="9,0" Height="36" Width="36" CornerRadius="5">
|
||||
<Image Width="24" Height="24" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Image.Source>
|
||||
<DrawingImage>
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#18181b" Geometry="F0 M24,24z M0,0z M3.58579,10.5858C3.96086,10.2107 4.46957,10 5,10 5.53043,10 6.03914,10.2107 6.41421,10.5858 6.78929,10.9609 7,11.4696 7,12 7,12.5304 6.78929,13.0391 6.41421,13.4142 6.03914,13.7893 5.53043,14 5,14 4.46957,14 3.96086,13.7893 3.58579,13.4142 3.21071,13.0391 3,12.5304 3,12 3,11.4696 3.21071,10.9609 3.58579,10.5858z M10.5858,10.5858C10.9609,10.2107 11.4696,10 12,10 12.5304,10 13.0391,10.2107 13.4142,10.5858 13.7893,10.9609 14,11.4696 14,12 14,12.5304 13.7893,13.0391 13.4142,13.4142 13.0391,13.7893 12.5304,14 12,14 11.4696,14 10.9609,13.7893 10.5858,13.4142 10.2107,13.0391 10,12.5304 10,12 10,11.4696 10.2107,10.9609 10.5858,10.5858z M19,10C18.4696,10 17.9609,10.2107 17.5858,10.5858 17.2107,10.9609 17,11.4696 17,12 17,12.5304 17.2107,13.0391 17.5858,13.4142 17.9609,13.7893 18.4696,14 19,14 19.5304,14 20.0391,13.7893 20.4142,13.4142 20.7893,13.0391 21,12.5304 21,12 21,11.4696 20.7893,10.9609 20.4142,10.5858 20.0391,10.2107 19.5304,10 19,10z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</Border>
|
||||
</modern:SimpleStackPanel>
|
||||
<modern:SimpleStackPanel Spacing="8" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,-42,0,48">
|
||||
<Border Padding="12,0" Height="32" Background="#bb450a0a" CornerRadius="4">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock FontSize="14" Foreground="White" FontWeight="Bold" Text="形状绘制模式 : "/>
|
||||
<TextBlock Name="ShapeDrawingTypeText" FontSize="14" Foreground="White" Text="直线"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Name="AngleTooltip" Padding="12,0" Height="32" Background="#bb422006" CornerRadius="4">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock FontSize="14" Foreground="White" Text="角度 : "/>
|
||||
<TextBlock FontSize="14" Foreground="White" Name="AngleText" FontWeight="Bold" Text="0°"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Name="LengthTooltip" Padding="12,0" Height="32" Background="#bb052e16" CornerRadius="4">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock FontSize="14" Foreground="White" Text="长度 : "/>
|
||||
<TextBlock FontSize="14" Foreground="White" Name="LengthText" FontWeight="Bold" Text="0.00 px"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Padding="12,0" Height="32" Background="#bb172554" CornerRadius="4">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock FontSize="14" Foreground="White" Text="粗细 : "/>
|
||||
<TextBlock FontSize="14" Foreground="White" FontWeight="Bold" Name="PenSizeText" Text="4 像素"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</modern:SimpleStackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class ShapeDrawingLayer : UserControl {
|
||||
|
||||
public ShapeDrawingLayer() {
|
||||
InitializeComponent();
|
||||
|
||||
// ToolbarMoveHandle
|
||||
ToolbarMoveHandle.MouseDown += ToolbarMoveHandle_MouseDown;
|
||||
ToolbarMoveHandle.MouseUp += ToolbarMoveHandle_MouseUp;
|
||||
ToolbarMoveHandle.MouseMove += ToolbarMoveHandle_MouseMove;
|
||||
UpdateToolbarPosition(ToolbarNowPosition);
|
||||
|
||||
// Update ToolBtns
|
||||
ToolButtons = new Border[] {
|
||||
CursorButton,
|
||||
UndoButton,
|
||||
RedoButton,
|
||||
ClearButton,
|
||||
GridLineButton,
|
||||
SnapButton,
|
||||
MultiPointButton,
|
||||
InfoButton,
|
||||
MoreButton,
|
||||
};
|
||||
foreach (var tb in ToolButtons) {
|
||||
tb.MouseDown += ToolButton_MouseDown;
|
||||
tb.MouseUp += ToolButton_MouseUp;
|
||||
tb.MouseLeave += ToolButton_MouseLeave;
|
||||
}
|
||||
|
||||
Toolbar.Visibility = Visibility.Collapsed;
|
||||
AngleTooltip.Visibility = Visibility.Collapsed;
|
||||
LengthTooltip.Visibility = Visibility.Collapsed;
|
||||
|
||||
FullscreenGrid.MouseDown += FullscreenGrid_MouseDown;
|
||||
FullscreenGrid.MouseUp += FullscreenGrid_MouseUp;
|
||||
FullscreenGrid.MouseMove += FullscreenGrid_MouseMove;
|
||||
}
|
||||
|
||||
private Point CaculateCenteredToolbarPosition() {
|
||||
var aw = Toolbar.Width;
|
||||
var ah = Toolbar.Height;
|
||||
var left = (MainWindow.ActualWidth - aw) / 2;
|
||||
var top = MainWindow.ActualHeight - ah - 128;
|
||||
return new Point(left, top);
|
||||
}
|
||||
|
||||
public MainWindow MainWindow { get; set; }
|
||||
|
||||
public Border[] ToolButtons = new Border[] { };
|
||||
public Point ToolbarNowPosition = new Point(0, 0);
|
||||
public bool IsToolbarMoveHandleDown = false;
|
||||
public Point MouseDownPointInHandle;
|
||||
public Border ToolButtonMouseDownBorder = null;
|
||||
|
||||
public void UpdateToolbarPosition(Point? position) {
|
||||
if (position == null) {
|
||||
Toolbar.RenderTransform = null;
|
||||
return;
|
||||
}
|
||||
Toolbar.RenderTransform = new TranslateTransform(((Point)position).X, ((Point)position).Y);
|
||||
}
|
||||
|
||||
private void ToolbarMoveHandle_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (IsToolbarMoveHandleDown) return;
|
||||
MouseDownPointInHandle = FullscreenGrid.TranslatePoint(e.GetPosition(null),ToolbarMoveHandle);
|
||||
IsToolbarMoveHandleDown = true;
|
||||
ToolbarMoveHandle.CaptureMouse();
|
||||
}
|
||||
|
||||
private void ToolbarMoveHandle_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (!IsToolbarMoveHandleDown) return;
|
||||
IsToolbarMoveHandleDown = false;
|
||||
ToolbarMoveHandle.ReleaseMouseCapture();
|
||||
}
|
||||
|
||||
private void ToolbarMoveHandle_MouseMove(object sender, MouseEventArgs e) {
|
||||
if (!IsToolbarMoveHandleDown) return;
|
||||
var ptInScreen = e.GetPosition(null);
|
||||
ToolbarNowPosition = new Point(ptInScreen.X - MouseDownPointInHandle.X, ptInScreen.Y - MouseDownPointInHandle.Y);
|
||||
UpdateToolbarPosition(ToolbarNowPosition);
|
||||
}
|
||||
|
||||
private MainWindow.ShapeDrawingType? _shapeType;
|
||||
|
||||
public bool IsInShapeDrawingMode {
|
||||
get => _shapeType != null;
|
||||
}
|
||||
|
||||
public void StartShapeDrawing(MainWindow.ShapeDrawingType type, string name) {
|
||||
_shapeType = type;
|
||||
FullscreenGrid.Background = new SolidColorBrush(Color.FromArgb(1,0,0,0));
|
||||
FullscreenGrid.Visibility = Visibility.Visible;
|
||||
Toolbar.Visibility = Visibility.Visible;
|
||||
var pt = CaculateCenteredToolbarPosition();
|
||||
ToolbarNowPosition = pt;
|
||||
UpdateToolbarPosition(pt);
|
||||
ShapeDrawingTypeText.Text = name ?? "未知形状";
|
||||
PenSizeText.Text = $"{(MainWindow.inkCanvas.DefaultDrawingAttributes.Width + MainWindow.inkCanvas.DefaultDrawingAttributes.Height) / 2} 像素";
|
||||
}
|
||||
|
||||
private void DoneButtonClicked(object sender, RoutedEventArgs e) {
|
||||
EndShapeDrawing();
|
||||
}
|
||||
|
||||
public void EndShapeDrawing() {
|
||||
_shapeType = null;
|
||||
FullscreenGrid.Background = null;
|
||||
FullscreenGrid.Visibility = Visibility.Collapsed;
|
||||
Toolbar.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void ToolButton_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (ToolButtonMouseDownBorder != null) return;
|
||||
ToolButtonMouseDownBorder = (Border)sender;
|
||||
ToolButtonMouseDownBorder.Background = new SolidColorBrush(Color.FromRgb(228, 228, 231));
|
||||
}
|
||||
|
||||
private void ToolButton_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (ToolButtonMouseDownBorder == null || ToolButtonMouseDownBorder != sender) return;
|
||||
|
||||
ToolButton_MouseLeave(sender, null);
|
||||
}
|
||||
|
||||
private void ToolButton_MouseLeave(object sender, MouseEventArgs e) {
|
||||
if (ToolButtonMouseDownBorder == null || ToolButtonMouseDownBorder != sender) return;
|
||||
ToolButtonMouseDownBorder.Background = new SolidColorBrush(Colors.Transparent);
|
||||
ToolButtonMouseDownBorder = null;
|
||||
}
|
||||
|
||||
private bool isFullscreenGridDown = false;
|
||||
public PointCollection points = new PointCollection();
|
||||
|
||||
private void FullscreenGrid_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (isFullscreenGridDown) return;
|
||||
points.Clear();
|
||||
points.Add(e.GetPosition(null));
|
||||
isFullscreenGridDown = true;
|
||||
FullscreenGrid.CaptureMouse();
|
||||
}
|
||||
|
||||
private void FullscreenGrid_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (!isFullscreenGridDown) return;
|
||||
FullscreenGrid.ReleaseMouseCapture();
|
||||
isFullscreenGridDown = false;
|
||||
if (_shapeType == null) return;
|
||||
using (DrawingContext dc = DrawingVisualCanvas.DrawingVisual.RenderOpen()) {}
|
||||
|
||||
if (points.Count >= 2)
|
||||
MainWindow.inkCanvas.Strokes.Add(MainWindow.DrawShapeCore(points, (MainWindow.ShapeDrawingType)_shapeType,false,false));
|
||||
points.Clear();
|
||||
AngleTooltip.Visibility = Visibility.Collapsed;
|
||||
LengthTooltip.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void FullscreenGrid_MouseMove(object sender, MouseEventArgs e) {
|
||||
if (!isFullscreenGridDown) return;
|
||||
if (_shapeType == null) return;
|
||||
if (points.Count >= 2) points[1] = e.GetPosition(null);
|
||||
else points.Add(e.GetPosition(null));
|
||||
|
||||
using (DrawingContext dc = DrawingVisualCanvas.DrawingVisual.RenderOpen()) {
|
||||
if ((_shapeType == MainWindow.ShapeDrawingType.Line ||
|
||||
_shapeType == MainWindow.ShapeDrawingType.DashedLine ||
|
||||
_shapeType == MainWindow.ShapeDrawingType.DottedLine ||
|
||||
_shapeType == MainWindow.ShapeDrawingType.ArrowOneSide ||
|
||||
_shapeType == MainWindow.ShapeDrawingType.ArrowTwoSide) && points.Count >= 2) {
|
||||
MainWindow.DrawShapeCore(points, (MainWindow.ShapeDrawingType)_shapeType,true,true).Draw(dc);
|
||||
var angle = MainWindow.ShapeDrawingHelper.CaculateRotateAngleByGivenTwoPoints(points[0], points[1]);
|
||||
if (AngleTooltip.Visibility == Visibility.Collapsed) AngleTooltip.Visibility = Visibility.Visible;
|
||||
AngleText.Text = $"{angle}°";
|
||||
if (LengthTooltip.Visibility == Visibility.Collapsed) LengthTooltip.Visibility = Visibility.Visible;
|
||||
LengthText.Text = $"{Math.Round(Math.Sqrt(Math.Pow((points[1].Y - points[0].Y), 2) + Math.Pow((points[1].X - points[0].X), 2)),2)} 像素";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,579 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
private StrokeCollection newStrokes = new StrokeCollection();
|
||||
private List<Circle> circles = new List<Circle>();
|
||||
|
||||
private void inkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) {
|
||||
if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false;
|
||||
|
||||
try {
|
||||
inkCanvas.Opacity = 1;
|
||||
if (Settings.InkToShape.IsInkToShapeEnabled && !Environment.Is64BitProcess) {
|
||||
void InkToShapeProcess() {
|
||||
try {
|
||||
newStrokes.Add(e.Stroke);
|
||||
if (newStrokes.Count > 4) newStrokes.RemoveAt(0);
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
for (var i = 0; i < newStrokes.Count; i++)
|
||||
if (!inkCanvas.Strokes.Contains(newStrokes[i]))
|
||||
newStrokes.RemoveAt(i--);
|
||||
|
||||
for (var i = 0; i < circles.Count; i++)
|
||||
if (!inkCanvas.Strokes.Contains(circles[i].Stroke))
|
||||
circles.RemoveAt(i);
|
||||
});
|
||||
var strokeReco = new StrokeCollection();
|
||||
var result = InkRecognizeHelper.RecognizeShape(newStrokes);
|
||||
for (var i = newStrokes.Count - 1; i >= 0; i--) {
|
||||
strokeReco.Add(newStrokes[i]);
|
||||
var newResult = InkRecognizeHelper.RecognizeShape(strokeReco);
|
||||
if (newResult.InkDrawingNode.GetShapeName() == "Circle" ||
|
||||
newResult.InkDrawingNode.GetShapeName() == "Ellipse") {
|
||||
result = newResult;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.InkDrawingNode.GetShapeName() == "Circle" &&
|
||||
Settings.InkToShape.IsInkToShapeRounded == true) {
|
||||
var shapeWidth = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Width);
|
||||
var shapeHeight = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Height);
|
||||
if (shapeWidth > 75) {
|
||||
foreach (var circle in circles)
|
||||
//判断是否画同心圆
|
||||
if (Math.Abs(result.Centroid.X - circle.Centroid.X) / shapeWidth < 0.12 &&
|
||||
Math.Abs(result.Centroid.Y - circle.Centroid.Y) / shapeWidth < 0.12) {
|
||||
result.Centroid = circle.Centroid;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
var d = (result.Centroid.X - circle.Centroid.X) *
|
||||
(result.Centroid.X - circle.Centroid.X) +
|
||||
(result.Centroid.Y - circle.Centroid.Y) *
|
||||
(result.Centroid.Y - circle.Centroid.Y);
|
||||
d = Math.Sqrt(d);
|
||||
//判断是否画外切圆
|
||||
var x = shapeWidth / 2.0 + circle.R - d;
|
||||
if (Math.Abs(x) / shapeWidth < 0.1) {
|
||||
var sinTheta = (result.Centroid.Y - circle.Centroid.Y) / d;
|
||||
var cosTheta = (result.Centroid.X - circle.Centroid.X) / d;
|
||||
var newX = result.Centroid.X + x * cosTheta;
|
||||
var newY = result.Centroid.Y + x * sinTheta;
|
||||
result.Centroid = new Point(newX, newY);
|
||||
}
|
||||
|
||||
//判断是否画外切圆
|
||||
x = Math.Abs(circle.R - shapeWidth / 2.0) - d;
|
||||
if (Math.Abs(x) / shapeWidth < 0.1) {
|
||||
var sinTheta = (result.Centroid.Y - circle.Centroid.Y) / d;
|
||||
var cosTheta = (result.Centroid.X - circle.Centroid.X) / d;
|
||||
var newX = result.Centroid.X + x * cosTheta;
|
||||
var newY = result.Centroid.Y + x * sinTheta;
|
||||
result.Centroid = new Point(newX, newY);
|
||||
}
|
||||
}
|
||||
|
||||
var iniP = new Point(result.Centroid.X - shapeWidth / 2,
|
||||
result.Centroid.Y - shapeHeight / 2);
|
||||
var endP = new Point(result.Centroid.X + shapeWidth / 2,
|
||||
result.Centroid.Y + shapeHeight / 2);
|
||||
var pointList = GenerateEllipseGeometry(iniP, endP);
|
||||
var point = new StylusPointCollection(pointList);
|
||||
var stroke = new Stroke(point) {
|
||||
DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone())
|
||||
};
|
||||
circles.Add(new Circle(result.Centroid, shapeWidth / 2.0, stroke));
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
SetNewBackupOfStroke();
|
||||
_currentCommitType = CommitReason.ShapeRecognition;
|
||||
inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
|
||||
inkCanvas.Strokes.Add(stroke);
|
||||
});
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
newStrokes = new StrokeCollection();
|
||||
}
|
||||
}
|
||||
else if (result.InkDrawingNode.GetShapeName().Contains("Ellipse") &&
|
||||
Settings.InkToShape.IsInkToShapeRounded == true) {
|
||||
var shapeWidth = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Width);
|
||||
var shapeHeight = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Height);
|
||||
PointCollection p = new PointCollection();
|
||||
Point[] _p = new Point[]{};
|
||||
Dispatcher.Invoke(() => {
|
||||
var arr = result.InkDrawingNode.HotPoints.ToArray();
|
||||
_p = arr;
|
||||
});
|
||||
p = new PointCollection(_p);
|
||||
var a = GetDistance(p[0], p[2]) / 2; //长半轴
|
||||
var b = GetDistance(p[1], p[3]) / 2; //短半轴
|
||||
if (a < b) {
|
||||
var t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
result.Centroid = new Point((p[0].X + p[2].X) / 2, (p[0].Y + p[2].Y) / 2);
|
||||
var needRotation = true;
|
||||
|
||||
if (shapeWidth > 75 || (shapeHeight > 75 && p.Count == 4)) {
|
||||
var iniP = new Point(result.Centroid.X - shapeWidth / 2,
|
||||
result.Centroid.Y - shapeHeight / 2);
|
||||
var endP = new Point(result.Centroid.X + shapeWidth / 2,
|
||||
result.Centroid.Y + shapeHeight / 2);
|
||||
|
||||
foreach (var circle in circles)
|
||||
//判断是否画同心椭圆
|
||||
if (Math.Abs(result.Centroid.X - circle.Centroid.X) / a < 0.2 &&
|
||||
Math.Abs(result.Centroid.Y - circle.Centroid.Y) / a < 0.2) {
|
||||
result.Centroid = circle.Centroid;
|
||||
iniP = new Point(result.Centroid.X - shapeWidth / 2,
|
||||
result.Centroid.Y - shapeHeight / 2);
|
||||
endP = new Point(result.Centroid.X + shapeWidth / 2,
|
||||
result.Centroid.Y + shapeHeight / 2);
|
||||
|
||||
//再判断是否与圆相切
|
||||
if (Math.Abs(a - circle.R) / a < 0.2) {
|
||||
if (shapeWidth >= shapeHeight) {
|
||||
iniP.X = result.Centroid.X - circle.R;
|
||||
endP.X = result.Centroid.X + circle.R;
|
||||
iniP.Y = result.Centroid.Y - b;
|
||||
endP.Y = result.Centroid.Y + b;
|
||||
}
|
||||
else {
|
||||
iniP.Y = result.Centroid.Y - circle.R;
|
||||
endP.Y = result.Centroid.Y + circle.R;
|
||||
iniP.X = result.Centroid.X - a;
|
||||
endP.X = result.Centroid.X + a;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (Math.Abs(result.Centroid.X - circle.Centroid.X) / a < 0.2) {
|
||||
var sinTheta = Math.Abs(circle.Centroid.Y - result.Centroid.Y) /
|
||||
circle.R;
|
||||
var cosTheta = Math.Sqrt(1 - sinTheta * sinTheta);
|
||||
var newA = circle.R * cosTheta;
|
||||
if (circle.R * sinTheta / circle.R < 0.9 && a / b > 2 &&
|
||||
Math.Abs(newA - a) / newA < 0.3) {
|
||||
iniP.X = circle.Centroid.X - newA;
|
||||
endP.X = circle.Centroid.X + newA;
|
||||
iniP.Y = result.Centroid.Y - newA / 5;
|
||||
endP.Y = result.Centroid.Y + newA / 5;
|
||||
|
||||
var topB = endP.Y - iniP.Y;
|
||||
|
||||
SetNewBackupOfStroke();
|
||||
_currentCommitType = CommitReason.ShapeRecognition;
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
|
||||
});
|
||||
newStrokes = new StrokeCollection();
|
||||
|
||||
var _pointList = GenerateEllipseGeometry(iniP, endP, false, true);
|
||||
var _point = new StylusPointCollection(_pointList);
|
||||
var _stroke = new Stroke(_point) {
|
||||
DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone())
|
||||
};
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
var _dashedLineStroke =
|
||||
GenerateDashedLineEllipseStrokeCollection(iniP, endP, true,
|
||||
false);
|
||||
var strokes = new StrokeCollection() {
|
||||
_stroke,
|
||||
_dashedLineStroke
|
||||
};
|
||||
inkCanvas.Strokes.Add(strokes);
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Math.Abs(result.Centroid.Y - circle.Centroid.Y) / a < 0.2) {
|
||||
var cosTheta = Math.Abs(circle.Centroid.X - result.Centroid.X) /
|
||||
circle.R;
|
||||
var sinTheta = Math.Sqrt(1 - cosTheta * cosTheta);
|
||||
var newA = circle.R * sinTheta;
|
||||
if (circle.R * sinTheta / circle.R < 0.9 && a / b > 2 &&
|
||||
Math.Abs(newA - a) / newA < 0.3) {
|
||||
iniP.X = result.Centroid.X - newA / 5;
|
||||
endP.X = result.Centroid.X + newA / 5;
|
||||
iniP.Y = circle.Centroid.Y - newA;
|
||||
endP.Y = circle.Centroid.Y + newA;
|
||||
needRotation = false;
|
||||
}
|
||||
}
|
||||
|
||||
//纠正垂直与水平关系
|
||||
var newPoints = FixPointsDirection(p[0], p[2]);
|
||||
p[0] = newPoints[0];
|
||||
p[2] = newPoints[1];
|
||||
newPoints = FixPointsDirection(p[1], p[3]);
|
||||
p[1] = newPoints[0];
|
||||
p[3] = newPoints[1];
|
||||
|
||||
var pointList = GenerateEllipseGeometry(iniP, endP);
|
||||
var point = new StylusPointCollection(pointList);
|
||||
var stroke = new Stroke(point) {
|
||||
DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone())
|
||||
};
|
||||
|
||||
if (needRotation) {
|
||||
var m = new Matrix();
|
||||
var fe = e.Source as FrameworkElement;
|
||||
var tanTheta = (p[2].Y - p[0].Y) / (p[2].X - p[0].X);
|
||||
var theta = Math.Atan(tanTheta);
|
||||
m.RotateAt(theta * 180.0 / Math.PI, result.Centroid.X, result.Centroid.Y);
|
||||
stroke.Transform(m, false);
|
||||
}
|
||||
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
SetNewBackupOfStroke();
|
||||
_currentCommitType = CommitReason.ShapeRecognition;
|
||||
inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
|
||||
inkCanvas.Strokes.Add(stroke);
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
|
||||
newStrokes = new StrokeCollection();
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (result.InkDrawingNode.GetShapeName().Contains("Triangle") &&
|
||||
Settings.InkToShape.IsInkToShapeTriangle == true) {
|
||||
PointCollection p = new PointCollection();
|
||||
Point[] _p = new Point[]{};
|
||||
Dispatcher.Invoke(() => {
|
||||
var arr = result.InkDrawingNode.HotPoints.ToArray();
|
||||
_p = arr;
|
||||
});
|
||||
p = new PointCollection(_p);
|
||||
if ((Math.Max(Math.Max(p[0].X, p[1].X), p[2].X) -
|
||||
Math.Min(Math.Min(p[0].X, p[1].X), p[2].X) >= 100 ||
|
||||
Math.Max(Math.Max(p[0].Y, p[1].Y), p[2].Y) -
|
||||
Math.Min(Math.Min(p[0].Y, p[1].Y), p[2].Y) >= 100) &&
|
||||
result.InkDrawingNode.HotPoints.Count == 3) {
|
||||
//纠正垂直与水平关系
|
||||
var newPoints = FixPointsDirection(p[0], p[1]);
|
||||
p[0] = newPoints[0];
|
||||
p[1] = newPoints[1];
|
||||
newPoints = FixPointsDirection(p[0], p[2]);
|
||||
p[0] = newPoints[0];
|
||||
p[2] = newPoints[1];
|
||||
newPoints = FixPointsDirection(p[1], p[2]);
|
||||
p[1] = newPoints[0];
|
||||
p[2] = newPoints[1];
|
||||
|
||||
var pointList = p.ToList();
|
||||
//pointList.Add(p[0]);
|
||||
var point = new StylusPointCollection(pointList);
|
||||
var stroke = new Stroke(GenerateFakePressureTriangle(point)) {
|
||||
DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone())
|
||||
};
|
||||
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
SetNewBackupOfStroke();
|
||||
_currentCommitType = CommitReason.ShapeRecognition;
|
||||
inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
|
||||
inkCanvas.Strokes.Add(stroke);
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
|
||||
newStrokes = new StrokeCollection();
|
||||
});
|
||||
}
|
||||
}
|
||||
else if ((result.InkDrawingNode.GetShapeName().Contains("Rectangle") ||
|
||||
result.InkDrawingNode.GetShapeName().Contains("Diamond") ||
|
||||
result.InkDrawingNode.GetShapeName().Contains("Parallelogram") ||
|
||||
result.InkDrawingNode.GetShapeName().Contains("Square") ||
|
||||
result.InkDrawingNode.GetShapeName().Contains("Trapezoid")) &&
|
||||
Settings.InkToShape.IsInkToShapeRectangle == true) {
|
||||
PointCollection p = new PointCollection();
|
||||
Point[] _p = new Point[]{};
|
||||
Dispatcher.Invoke(() => {
|
||||
var arr = result.InkDrawingNode.HotPoints.ToArray();
|
||||
_p = arr;
|
||||
});
|
||||
p = new PointCollection(_p);
|
||||
if ((Math.Max(Math.Max(Math.Max(p[0].X, p[1].X), p[2].X), p[3].X) -
|
||||
Math.Min(Math.Min(Math.Min(p[0].X, p[1].X), p[2].X), p[3].X) >= 100 ||
|
||||
Math.Max(Math.Max(Math.Max(p[0].Y, p[1].Y), p[2].Y), p[3].Y) -
|
||||
Math.Min(Math.Min(Math.Min(p[0].Y, p[1].Y), p[2].Y), p[3].Y) >= 100) &&
|
||||
result.InkDrawingNode.HotPoints.Count == 4) {
|
||||
//纠正垂直与水平关系
|
||||
var newPoints = FixPointsDirection(p[0], p[1]);
|
||||
p[0] = newPoints[0];
|
||||
p[1] = newPoints[1];
|
||||
newPoints = FixPointsDirection(p[1], p[2]);
|
||||
p[1] = newPoints[0];
|
||||
p[2] = newPoints[1];
|
||||
newPoints = FixPointsDirection(p[2], p[3]);
|
||||
p[2] = newPoints[0];
|
||||
p[3] = newPoints[1];
|
||||
newPoints = FixPointsDirection(p[3], p[0]);
|
||||
p[3] = newPoints[0];
|
||||
p[0] = newPoints[1];
|
||||
|
||||
var pointList = p.ToList();
|
||||
pointList.Add(p[0]);
|
||||
var point = new StylusPointCollection(pointList);
|
||||
var stroke = new Stroke(GenerateFakePressureRectangle(point)) {
|
||||
DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone())
|
||||
};
|
||||
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
SetNewBackupOfStroke();
|
||||
_currentCommitType = CommitReason.ShapeRecognition;
|
||||
inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
|
||||
inkCanvas.Strokes.Add(stroke);
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
|
||||
newStrokes = new StrokeCollection();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
var _t = new Thread(InkToShapeProcess);
|
||||
_t.Start();
|
||||
}
|
||||
|
||||
foreach (var stylusPoint in e.Stroke.StylusPoints)
|
||||
//LogHelper.WriteLogToFile(stylusPoint.PressureFactor.ToString(), LogHelper.LogType.Info);
|
||||
// 检查是否是压感笔书写
|
||||
//if (stylusPoint.PressureFactor != 0.5 && stylusPoint.PressureFactor != 0)
|
||||
if ((stylusPoint.PressureFactor > 0.501 || stylusPoint.PressureFactor < 0.5) &&
|
||||
stylusPoint.PressureFactor != 0)
|
||||
return;
|
||||
|
||||
try {
|
||||
if (e.Stroke.StylusPoints.Count > 3) {
|
||||
var random = new Random();
|
||||
var _speed = GetPointSpeed(
|
||||
e.Stroke.StylusPoints[random.Next(0, e.Stroke.StylusPoints.Count - 1)].ToPoint(),
|
||||
e.Stroke.StylusPoints[random.Next(0, e.Stroke.StylusPoints.Count - 1)].ToPoint(),
|
||||
e.Stroke.StylusPoints[random.Next(0, e.Stroke.StylusPoints.Count - 1)].ToPoint());
|
||||
|
||||
RandWindow.randSeed = (int)(_speed * 100000 * 1000);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
switch (Settings.Canvas.InkStyle) {
|
||||
case 1:
|
||||
if (penType == 0)
|
||||
try {
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
var n = e.Stroke.StylusPoints.Count - 1;
|
||||
var s = "";
|
||||
|
||||
for (var i = 0; i <= n; i++) {
|
||||
var speed = GetPointSpeed(e.Stroke.StylusPoints[Math.Max(i - 1, 0)].ToPoint(),
|
||||
e.Stroke.StylusPoints[i].ToPoint(),
|
||||
e.Stroke.StylusPoints[Math.Min(i + 1, n)].ToPoint());
|
||||
s += speed.ToString() + "\t";
|
||||
var point = new StylusPoint();
|
||||
if (speed >= 0.25)
|
||||
point.PressureFactor = (float)(0.5 - 0.3 * (Math.Min(speed, 1.5) - 0.3) / 1.2);
|
||||
else if (speed >= 0.05)
|
||||
point.PressureFactor = (float)0.5;
|
||||
else
|
||||
point.PressureFactor = (float)(0.5 + 0.4 * (0.05 - speed) / 0.05);
|
||||
|
||||
point.X = e.Stroke.StylusPoints[i].X;
|
||||
point.Y = e.Stroke.StylusPoints[i].Y;
|
||||
stylusPoints.Add(point);
|
||||
}
|
||||
|
||||
e.Stroke.StylusPoints = stylusPoints;
|
||||
}
|
||||
catch { }
|
||||
|
||||
break;
|
||||
case 0:
|
||||
if (penType == 0)
|
||||
try {
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
var n = e.Stroke.StylusPoints.Count - 1;
|
||||
var pressure = 0.1;
|
||||
var x = 10;
|
||||
if (n == 1) return;
|
||||
if (n >= x) {
|
||||
for (var i = 0; i < n - x; i++) {
|
||||
var point = new StylusPoint();
|
||||
|
||||
point.PressureFactor = (float)0.5;
|
||||
point.X = e.Stroke.StylusPoints[i].X;
|
||||
point.Y = e.Stroke.StylusPoints[i].Y;
|
||||
stylusPoints.Add(point);
|
||||
}
|
||||
|
||||
for (var i = n - x; i <= n; i++) {
|
||||
var point = new StylusPoint();
|
||||
|
||||
point.PressureFactor = (float)((0.5 - pressure) * (n - i) / x + pressure);
|
||||
point.X = e.Stroke.StylusPoints[i].X;
|
||||
point.Y = e.Stroke.StylusPoints[i].Y;
|
||||
stylusPoints.Add(point);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i <= n; i++) {
|
||||
var point = new StylusPoint();
|
||||
|
||||
point.PressureFactor = (float)(0.4 * (n - i) / n + pressure);
|
||||
point.X = e.Stroke.StylusPoints[i].X;
|
||||
point.Y = e.Stroke.StylusPoints[i].Y;
|
||||
stylusPoints.Add(point);
|
||||
}
|
||||
}
|
||||
|
||||
e.Stroke.StylusPoints = stylusPoints;
|
||||
}
|
||||
catch { }
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = true;
|
||||
}
|
||||
|
||||
private void SetNewBackupOfStroke() {
|
||||
lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone();
|
||||
var whiteboardIndex = CurrentWhiteboardIndex;
|
||||
if (currentMode == 0) whiteboardIndex = 0;
|
||||
|
||||
strokeCollections[whiteboardIndex] = lastTouchDownStrokeCollection;
|
||||
}
|
||||
|
||||
public double GetDistance(Point point1, Point point2) {
|
||||
return Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) +
|
||||
(point1.Y - point2.Y) * (point1.Y - point2.Y));
|
||||
}
|
||||
|
||||
public double GetPointSpeed(Point point1, Point point2, Point point3) {
|
||||
return (Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) +
|
||||
(point1.Y - point2.Y) * (point1.Y - point2.Y))
|
||||
+ Math.Sqrt((point3.X - point2.X) * (point3.X - point2.X) +
|
||||
(point3.Y - point2.Y) * (point3.Y - point2.Y)))
|
||||
/ 20;
|
||||
}
|
||||
|
||||
public Point[] FixPointsDirection(Point p1, Point p2) {
|
||||
if (Math.Abs(p1.X - p2.X) / Math.Abs(p1.Y - p2.Y) > 8) {
|
||||
//水平
|
||||
var x = Math.Abs(p1.Y - p2.Y) / 2;
|
||||
if (p1.Y > p2.Y) {
|
||||
p1.Y -= x;
|
||||
p2.Y += x;
|
||||
}
|
||||
else {
|
||||
p1.Y += x;
|
||||
p2.Y -= x;
|
||||
}
|
||||
}
|
||||
else if (Math.Abs(p1.Y - p2.Y) / Math.Abs(p1.X - p2.X) > 8) {
|
||||
//垂直
|
||||
var x = Math.Abs(p1.X - p2.X) / 2;
|
||||
if (p1.X > p2.X) {
|
||||
p1.X -= x;
|
||||
p2.X += x;
|
||||
}
|
||||
else {
|
||||
p1.X += x;
|
||||
p2.X -= x;
|
||||
}
|
||||
}
|
||||
|
||||
return new Point[2] { p1, p2 };
|
||||
}
|
||||
|
||||
public StylusPointCollection GenerateFakePressureTriangle(StylusPointCollection points) {
|
||||
if (Settings.InkToShape.IsInkToShapeNoFakePressureTriangle == true || penType == 1) {
|
||||
var newPoint = new StylusPointCollection();
|
||||
newPoint.Add(new StylusPoint(points[0].X, points[0].Y));
|
||||
var cPoint = GetCenterPoint(points[0], points[1]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y));
|
||||
newPoint.Add(new StylusPoint(points[1].X, points[1].Y));
|
||||
newPoint.Add(new StylusPoint(points[1].X, points[1].Y));
|
||||
cPoint = GetCenterPoint(points[1], points[2]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y));
|
||||
newPoint.Add(new StylusPoint(points[2].X, points[2].Y));
|
||||
newPoint.Add(new StylusPoint(points[2].X, points[2].Y));
|
||||
cPoint = GetCenterPoint(points[2], points[0]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y));
|
||||
newPoint.Add(new StylusPoint(points[0].X, points[0].Y));
|
||||
return newPoint;
|
||||
}
|
||||
else {
|
||||
var newPoint = new StylusPointCollection();
|
||||
newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
|
||||
var cPoint = GetCenterPoint(points[0], points[1]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
|
||||
newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
|
||||
newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
|
||||
cPoint = GetCenterPoint(points[1], points[2]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
|
||||
newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
|
||||
newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
|
||||
cPoint = GetCenterPoint(points[2], points[0]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
|
||||
newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
|
||||
return newPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public StylusPointCollection GenerateFakePressureRectangle(StylusPointCollection points) {
|
||||
if (Settings.InkToShape.IsInkToShapeNoFakePressureRectangle == true || penType == 1) {
|
||||
return points;
|
||||
}
|
||||
else {
|
||||
var newPoint = new StylusPointCollection();
|
||||
newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
|
||||
var cPoint = GetCenterPoint(points[0], points[1]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
|
||||
newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
|
||||
newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
|
||||
cPoint = GetCenterPoint(points[1], points[2]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
|
||||
newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
|
||||
newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
|
||||
cPoint = GetCenterPoint(points[2], points[3]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
|
||||
newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4));
|
||||
newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4));
|
||||
cPoint = GetCenterPoint(points[3], points[0]);
|
||||
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
|
||||
newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
|
||||
return newPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public Point GetCenterPoint(Point point1, Point point2) {
|
||||
return new Point((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
|
||||
}
|
||||
|
||||
public StylusPoint GetCenterPoint(StylusPoint point1, StylusPoint point2) {
|
||||
return new StylusPoint((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using Ink_Canvas.Helpers;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
public class StorageLocationItem {
|
||||
public string Path { get; set; }
|
||||
public ImageSource Icon { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool IsDrive { get; set; }
|
||||
public DriveType DriveType { get; set; }
|
||||
public string SelectItem { get; set; }
|
||||
}
|
||||
|
||||
public static long GetDirectorySize(System.IO.DirectoryInfo directoryInfo, bool recursive = true)
|
||||
{
|
||||
var startDirectorySize = default(long);
|
||||
if (directoryInfo == null || !directoryInfo.Exists)
|
||||
return startDirectorySize; //Return 0 while Directory does not exist.
|
||||
|
||||
//Add size of files in the Current Directory to main size.
|
||||
foreach (var fileInfo in directoryInfo.GetFiles())
|
||||
System.Threading.Interlocked.Add(ref startDirectorySize, fileInfo.Length);
|
||||
|
||||
if (recursive) //Loop on Sub Direcotries in the Current Directory and Calculate it's files size.
|
||||
System.Threading.Tasks.Parallel.ForEach(directoryInfo.GetDirectories(), (subDirectory) =>
|
||||
System.Threading.Interlocked.Add(ref startDirectorySize, GetDirectorySize(subDirectory, recursive)));
|
||||
|
||||
return startDirectorySize;
|
||||
}
|
||||
|
||||
public async Task<long> GetDirectorySizeAsync(System.IO.DirectoryInfo directoryInfo, bool recursive = true) {
|
||||
var size = await Task.Run(()=> GetDirectorySize(directoryInfo, recursive));
|
||||
return size;
|
||||
}
|
||||
|
||||
private static string FormatBytes(long bytes) {
|
||||
string[] Suffix = { "B", "KB", "MB", "GB", "TB" };
|
||||
int i; double dblSByte = bytes;
|
||||
for (i = 0; i < Suffix.Length && bytes >= 1024; i++, bytes /= 1024) {
|
||||
dblSByte = bytes / 1024.0;
|
||||
}
|
||||
return String.Format("{0:0.##} {1}", dblSByte, Suffix[i]);
|
||||
}
|
||||
|
||||
private ObservableCollection<StorageLocationItem> storageLocationItems =
|
||||
new ObservableCollection<StorageLocationItem>() { };
|
||||
|
||||
private void UpdateStorageLocations() {
|
||||
DriveInfo[] allDrives = DriveInfo.GetDrives();
|
||||
var fixedDrives = new List<StorageLocationItem>() { };
|
||||
var integratedFolders = new List<StorageLocationItem>() { };
|
||||
storageLocationItems.Clear();
|
||||
foreach (var driveInfo in allDrives) {
|
||||
if (driveInfo.DriveType == DriveType.Fixed) {
|
||||
if (driveInfo.Name.Contains("C") || !driveInfo.IsReady) continue;
|
||||
fixedDrives.Add(new StorageLocationItem() {
|
||||
Path = driveInfo.Name + "InkCanvasForClass",
|
||||
Title = driveInfo.Name.Substring(0,1) + "盘 ",
|
||||
Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/classic-icons/disk-drive.png")),
|
||||
DriveType = driveInfo.DriveType,
|
||||
IsDrive = true,
|
||||
SelectItem = "d"+driveInfo.Name.Substring(0,1).ToLower()
|
||||
});
|
||||
}
|
||||
}
|
||||
var docfolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
integratedFolders.Add(new StorageLocationItem() {
|
||||
Path = (docfolder.EndsWith("\\") ? docfolder.Substring(0, docfolder.Length - 1) : docfolder) + "\\InkCanvasForClass",
|
||||
Title = "“文档”文件夹 ",
|
||||
IsDrive = false,
|
||||
Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/classic-icons/documents-folder.png")),
|
||||
SelectItem = "fw"
|
||||
});
|
||||
var runfolder = AppDomain.CurrentDomain.BaseDirectory;
|
||||
integratedFolders.Add(new StorageLocationItem() {
|
||||
Path = (runfolder.EndsWith("\\") ? runfolder.Substring(0, runfolder.Length - 1) : runfolder) + "\\InkCanvasForClass",
|
||||
Title = "icc安装目录 ",
|
||||
IsDrive = false,
|
||||
Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/classic-icons/folder.png")),
|
||||
SelectItem = "fr"
|
||||
});
|
||||
var usrfolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
integratedFolders.Add(new StorageLocationItem() {
|
||||
Path = (usrfolder.EndsWith("\\") ? usrfolder.Substring(0, usrfolder.Length - 1) : usrfolder) + "\\InkCanvasForClass",
|
||||
Title = "当前用户目录 ",
|
||||
IsDrive = false,
|
||||
Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/classic-icons/user-folder.png")),
|
||||
SelectItem = "fu"
|
||||
});
|
||||
var dskfolder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
|
||||
integratedFolders.Add(new StorageLocationItem() {
|
||||
Path = (dskfolder.EndsWith("\\") ? dskfolder.Substring(0, dskfolder.Length - 1) : dskfolder) + "\\InkCanvasForClass",
|
||||
Title = "“桌面”文件夹 ",
|
||||
IsDrive = false,
|
||||
Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/classic-icons/desktop-folder.png")),
|
||||
SelectItem = "fd"
|
||||
});
|
||||
|
||||
foreach (var i in fixedDrives) storageLocationItems.Add(i);
|
||||
foreach (var i in integratedFolders) storageLocationItems.Add(i);
|
||||
storageLocationItems.Add(new StorageLocationItem() {
|
||||
Path = "",
|
||||
Title = "自定义... ",
|
||||
IsDrive = false,
|
||||
Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/classic-icons/folder.png")),
|
||||
SelectItem = "c-"
|
||||
});
|
||||
}
|
||||
|
||||
private bool isChangingUserStorageSelectionProgramically = false;
|
||||
|
||||
private void UpdateUserStorageSelection() {
|
||||
// 先获取磁盘信息
|
||||
DriveInfo[] allDrives = DriveInfo.GetDrives();
|
||||
var fixedDrives = new List<string>() { };
|
||||
foreach (var driveInfo in allDrives) {
|
||||
if (driveInfo.Name.Contains("C") || !driveInfo.IsReady) continue;
|
||||
fixedDrives.Add("d"+driveInfo.Name.Substring(0,1).ToLower());
|
||||
}
|
||||
|
||||
var integratedFolders = new List<string>() {
|
||||
"fw", "fr", "fu", "fd" // fw - folder wendang ; fd - folder desktop ; fu - folder user ; fr - folder running
|
||||
};
|
||||
if (Settings.Storage.StorageLocation.Substring(0, 1) == "d") {
|
||||
if (fixedDrives.Count == 0) {
|
||||
Settings.Storage.StorageLocation = "fw";
|
||||
SaveSettingsToFile();
|
||||
ComboBoxStoragePath.SelectedIndex = 0;
|
||||
} else if (fixedDrives.Contains(Settings.Storage.StorageLocation)) {
|
||||
ComboBoxStoragePath.SelectedIndex = fixedDrives.IndexOf(Settings.Storage.StorageLocation);
|
||||
} else {
|
||||
ComboBoxStoragePath.SelectedIndex = 0;
|
||||
Settings.Storage.StorageLocation = fixedDrives[0];
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
} else if (Settings.Storage.StorageLocation.Substring(0, 1) == "f") {
|
||||
if (integratedFolders.Contains(Settings.Storage.StorageLocation)) {
|
||||
ComboBoxStoragePath.SelectedIndex = fixedDrives.Count + integratedFolders.IndexOf(Settings.Storage.StorageLocation);
|
||||
} else {
|
||||
ComboBoxStoragePath.SelectedIndex = fixedDrives.Count;
|
||||
Settings.Storage.StorageLocation = "fw";
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
} else if (Settings.Storage.StorageLocation.Substring(0, 1) == "c") {
|
||||
ComboBoxStoragePath.SelectedIndex = storageLocationItems.Count - 1;
|
||||
}
|
||||
|
||||
if (isLoaded) CustomStorageLocationGroup.Visibility = Settings.Storage.StorageLocation == "c-" ? Visibility.Visible : Visibility.Collapsed;
|
||||
if (isLoaded) CustomStorageLocation.Text = Settings.Storage.UserStorageLocation;
|
||||
}
|
||||
|
||||
private void ComboBoxStoragePath_DropDownOpened(object sender, EventArgs e) {
|
||||
isChangingUserStorageSelectionProgramically = true;
|
||||
UpdateStorageLocations();
|
||||
UpdateUserStorageSelection();
|
||||
isChangingUserStorageSelectionProgramically = false;
|
||||
}
|
||||
|
||||
private async Task<int> GetDirectoryFilesCount(string path) {
|
||||
var count = await Task.Run(() => Directory.GetFiles(path, "*", SearchOption.AllDirectories).Length);
|
||||
return count;
|
||||
}
|
||||
|
||||
private void InitStorageFoldersStructure(string dirPath) {
|
||||
string path;
|
||||
if (storageLocationItems[ComboBoxStoragePath.SelectedIndex].SelectItem == "c-") {
|
||||
if (Settings.Storage.StorageLocation != "c-") {
|
||||
var si = Settings.Storage.StorageLocation;
|
||||
var item = storageLocationItems.Where(i => i.SelectItem == si).ToArray()[0];
|
||||
path = item.Path;
|
||||
} else {
|
||||
if (Settings.Storage.UserStorageLocation != "") {
|
||||
path = new DirectoryInfo(Settings.Storage.UserStorageLocation).FullName;
|
||||
} else {
|
||||
var item = storageLocationItems.Where(i => i.SelectItem == "fr").ToArray()[0];
|
||||
path = item.Path;
|
||||
Settings.Storage.StorageLocation = "fr";
|
||||
SaveSettingsToFile();
|
||||
UpdateStorageLocations();
|
||||
UpdateUserStorageSelection();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dirPath == null) {
|
||||
var si = Settings.Storage.StorageLocation;
|
||||
var item = storageLocationItems.Where(i => i.SelectItem == si).ToArray()[0];
|
||||
path = item.Path;
|
||||
} else path = dirPath;
|
||||
}
|
||||
var basePath = new DirectoryInfo(path);
|
||||
var autoSavedInkPath = new DirectoryInfo(path+"\\AutoSavedInk");
|
||||
var autoSavedSnapshotPath = new DirectoryInfo(path+"\\AutoSavedSnapshot");
|
||||
var exportedInkPath = new DirectoryInfo(path+"\\ExportedInk");
|
||||
var quotedPhotosPath = new DirectoryInfo(path+"\\QuotedPhotos");
|
||||
var cachesPath = new DirectoryInfo(path+"\\caches");
|
||||
var paths = new DirectoryInfo[] {
|
||||
basePath, autoSavedInkPath, autoSavedSnapshotPath, exportedInkPath, quotedPhotosPath, cachesPath
|
||||
};
|
||||
foreach (var di in paths) {
|
||||
if (!di.Exists) di.Create();
|
||||
}
|
||||
}
|
||||
|
||||
private bool isAnalyzingStorageInfo = false;
|
||||
|
||||
private async void StartAnalyzeStorage(bool forceAnalyze = false) {
|
||||
if (isAnalyzingStorageInfo && !forceAnalyze) return;
|
||||
isAnalyzingStorageInfo = true;
|
||||
var item = storageLocationItems[ComboBoxStoragePath.SelectedIndex];
|
||||
StorageAnalazeWaitingGroup.Visibility = Visibility.Visible;
|
||||
StorageAnalazeGroup.Visibility = Visibility.Collapsed;
|
||||
|
||||
string path;
|
||||
var runfolder = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
if (item.SelectItem != "c-") {
|
||||
path = item.Path;
|
||||
} else if (Settings.Storage.UserStorageLocation != "") {
|
||||
path = Settings.Storage.UserStorageLocation;
|
||||
} else {
|
||||
path = (runfolder.EndsWith("\\") ? runfolder.Substring(0, runfolder.Length - 1) : runfolder) +
|
||||
"\\InkCanvasForClass";
|
||||
}
|
||||
|
||||
StorageNowLocationTextBlock.Text = $"当前位置:{path}";
|
||||
DriveInfo[] allDrives = DriveInfo.GetDrives();
|
||||
var driveArr = allDrives.Where((info, i) => info.Name.Substring(0,1)==path.Substring(0,1)).ToArray();
|
||||
if (driveArr.Length > 0) {
|
||||
StorageDiskUsageTextBlock.Visibility = Visibility.Visible;
|
||||
var freeSpace = driveArr[0].TotalFreeSpace;
|
||||
var usedSpace = driveArr[0].TotalSize - driveArr[0].TotalFreeSpace;
|
||||
StorageDiskUsageTextBlock.Text = $"磁盘使用情况:已用 {FormatBytes(usedSpace)}、剩余 {FormatBytes(freeSpace)}";
|
||||
var dirsize = await GetDirectorySizeAsync(new DirectoryInfo(path));
|
||||
var formatedDirSize = FormatBytes(dirsize);
|
||||
var dirFilecount = await GetDirectoryFilesCount(path);
|
||||
StorageDirectoryUsageTextBlock.Text = $"目录占用情况:已用 {formatedDirSize},共 {dirFilecount} 个文件";
|
||||
var usedBorderWidth = Math.Round(388 * ((double)usedSpace / (double)(driveArr[0].TotalSize)), 1);
|
||||
var ICCUsedBorderWidth = Math.Round(usedBorderWidth * ((double)dirsize / (double)usedSpace), 1);
|
||||
usedBorderWidth = usedBorderWidth - ICCUsedBorderWidth;
|
||||
ICCDirectoryStorageAnalyzeGroup.Visibility = dirsize == 0 ? Visibility.Collapsed : Visibility.Visible;
|
||||
DiskUsageUsedSpaceBorder.Width = usedBorderWidth;
|
||||
DiskUsageICCSpaceBorder.Width = ICCUsedBorderWidth;
|
||||
var asiSize = await GetDirectorySizeAsync(new DirectoryInfo(path + "\\AutoSavedInk"));
|
||||
var assSize = await GetDirectorySizeAsync(new DirectoryInfo(path + "\\AutoSavedSnapshot"));
|
||||
var eiSize = await GetDirectorySizeAsync(new DirectoryInfo(path + "\\ExportedInk"));
|
||||
var qpSize = await GetDirectorySizeAsync(new DirectoryInfo(path + "\\QuotedPhotos"));
|
||||
var cachesSize = await GetDirectorySizeAsync(new DirectoryInfo(path + "\\caches"));
|
||||
ClearCacheFilesButton.IsEnabled = cachesSize != 0;
|
||||
ClearAutoSavedSnapshotButton.IsEnabled = assSize != 0;
|
||||
StorageDirectoryAutoSavedInkUsageBorder.Width =
|
||||
Math.Round(388 * ((double)asiSize / (double)dirsize), 1);
|
||||
StorageDirectoryAutoSavedSnapshotUsageBorder.Width =
|
||||
Math.Round(388 * ((double)assSize / (double)dirsize), 1);
|
||||
StorageDirectoryExportedInkUsageBorder.Width = Math.Round(388 * ((double)eiSize / (double)dirsize), 1);
|
||||
StorageDirectoryQuotedPhotoUsageBorder.Width = Math.Round(388 * ((double)qpSize / (double)dirsize), 1);
|
||||
StorageDirectoryCachesUsageBorder.Width = Math.Round(388 * ((double)cachesSize / (double)dirsize), 1);
|
||||
StorageAutoSavedInkDescription.Text =
|
||||
$"{Math.Round(100 * ((double)asiSize / (double)dirsize), 1)}% 、{FormatBytes(asiSize)}";
|
||||
StorageAutoSavedSnapshotDescription.Text =
|
||||
$"{Math.Round(100 * ((double)assSize / (double)dirsize), 1)}% 、{FormatBytes(assSize)}";
|
||||
StorageExportedInkDescription.Text =
|
||||
$"{Math.Round(100 * ((double)eiSize / (double)dirsize), 1)}% 、{FormatBytes(eiSize)}";
|
||||
StorageQuotedPhotosDescription.Text =
|
||||
$"{Math.Round(100 * ((double)qpSize / (double)dirsize), 1)}% 、{FormatBytes(qpSize)}";
|
||||
StorageCachesDescription.Text =
|
||||
$"{Math.Round(100 * ((double)cachesSize / (double)dirsize), 1)}% 、{FormatBytes(cachesSize)}";
|
||||
StorageAnalazeWaitingGroup.Visibility = Visibility.Collapsed;
|
||||
StorageAnalazeGroup.Visibility = Visibility.Visible;
|
||||
isAnalyzingStorageInfo = false;
|
||||
} else isAnalyzingStorageInfo = false;
|
||||
}
|
||||
|
||||
private void ClearCacheFilesButton_Clicked(object sender, RoutedEventArgs e) {
|
||||
var di = new DirectoryInfo(storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path+"\\caches");
|
||||
try {
|
||||
Directory.Delete(di.FullName, true);
|
||||
ShowNewToast("清理缓存成功!", MW_Toast.ToastType.Success, 2000);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ShowNewToast($"清理缓存失败!{ex.Message}", MW_Toast.ToastType.Error, 2000);
|
||||
}
|
||||
InitStorageFoldersStructure(storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path);
|
||||
StartAnalyzeStorage();
|
||||
}
|
||||
|
||||
private void ClearAutoSavedSnapshotButton_Clicked(object sender, RoutedEventArgs e) {
|
||||
var di = new DirectoryInfo(storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path+"\\AutoSavedSnapshot");
|
||||
try {
|
||||
Directory.Delete(di.FullName, true);
|
||||
ShowNewToast("清理自动保存的截图成功!", MW_Toast.ToastType.Success, 2000);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ShowNewToast($"清理自动保存的截图失败!{ex.Message}", MW_Toast.ToastType.Error, 2000);
|
||||
}
|
||||
InitStorageFoldersStructure(storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path);
|
||||
StartAnalyzeStorage();
|
||||
}
|
||||
|
||||
|
||||
private DirectoryInfo GetDirectory(string type) {
|
||||
var path = "";
|
||||
if (Settings.Storage.StorageLocation == "c-" && Settings.Storage.UserStorageLocation != "")
|
||||
path = Settings.Storage.UserStorageLocation;
|
||||
else path = storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path;
|
||||
var autoSavedInkPath = new DirectoryInfo(path+"\\AutoSavedInk");
|
||||
var autoSavedSnapshotPath = new DirectoryInfo(path+"\\AutoSavedSnapshot");
|
||||
var exportedInkPath = new DirectoryInfo(path +"\\ExportedInk");
|
||||
var quotedPhotosPath = new DirectoryInfo(path +"\\QuotedPhotos");
|
||||
var cachesPath = new DirectoryInfo(path +"\\caches");
|
||||
if (type == "autosaveink") return autoSavedInkPath;
|
||||
if (type == "autosavesnapshot") return autoSavedSnapshotPath;
|
||||
if (type == "exportedink") return exportedInkPath;
|
||||
if (type == "quotedphotos") return quotedPhotosPath;
|
||||
if (type == "caches") return cachesPath;
|
||||
return new DirectoryInfo("");
|
||||
}
|
||||
|
||||
private DirectoryInfo GetDirectoryInfoByIndex(int index) {
|
||||
var path = "";
|
||||
if (Settings.Storage.StorageLocation == "c-" && Settings.Storage.UserStorageLocation != "")
|
||||
path = Settings.Storage.UserStorageLocation;
|
||||
else path = storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path;
|
||||
var autoSavedInkPath = new DirectoryInfo(path +"\\AutoSavedInk");
|
||||
var autoSavedSnapshotPath = new DirectoryInfo(path +"\\AutoSavedSnapshot");
|
||||
var exportedInkPath = new DirectoryInfo(path +"\\ExportedInk");
|
||||
var quotedPhotosPath = new DirectoryInfo(path +"\\QuotedPhotos");
|
||||
var cachesPath = new DirectoryInfo(path +"\\caches");
|
||||
return (new DirectoryInfo[]
|
||||
{ autoSavedInkPath, quotedPhotosPath, exportedInkPath, cachesPath, autoSavedSnapshotPath })[index];
|
||||
}
|
||||
|
||||
private Border lastStorageJumpToFolderBorderDown = null;
|
||||
|
||||
private void StorageJumpToFolderBtn_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (lastStorageJumpToFolderBorderDown != null) return;
|
||||
lastStorageJumpToFolderBorderDown = (Border)sender;
|
||||
lastStorageJumpToFolderBorderDown.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
|
||||
}
|
||||
|
||||
private void StorageJumpToFolderBtn_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (lastStorageJumpToFolderBorderDown == null || lastStorageJumpToFolderBorderDown != (Border)sender) return;
|
||||
var bd = (Border)sender;
|
||||
StorageJumpToFolderBtn_MouseLeave(sender,null);
|
||||
var di = GetDirectoryInfoByIndex(Int32.Parse(bd.Name[bd.Name.Length - 1].ToString()));
|
||||
Process.Start("explorer.exe", di.FullName);
|
||||
}
|
||||
|
||||
private void StorageJumpToFolderBtn_MouseLeave(object sender, MouseEventArgs e) {
|
||||
if (lastStorageJumpToFolderBorderDown == null || lastStorageJumpToFolderBorderDown != (Border)sender) return;
|
||||
lastStorageJumpToFolderBorderDown.Background = new SolidColorBrush(Colors.Transparent);
|
||||
lastStorageJumpToFolderBorderDown = null;
|
||||
}
|
||||
|
||||
private void InitStorageManagementModule() {
|
||||
ComboBoxStoragePath.ItemsSource = storageLocationItems;
|
||||
ComboBoxStoragePath.DropDownOpened += ComboBoxStoragePath_DropDownOpened;
|
||||
ComboBoxStoragePath.SelectionChanged += ComboBoxStoragePath_OnSelectionChanged;
|
||||
isChangingUserStorageSelectionProgramically = true;
|
||||
UpdateStorageLocations();
|
||||
UpdateUserStorageSelection();
|
||||
isChangingUserStorageSelectionProgramically = false;
|
||||
HandleUserCustomStorageLocation();
|
||||
InitStorageFoldersStructure(storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path);
|
||||
StartAnalyzeStorage();
|
||||
var sb = new Border[] {
|
||||
StorageJumpToFolderBtn1, StorageJumpToFolderBtn2, StorageJumpToFolderBtn3, StorageJumpToFolderBtn4,
|
||||
StorageJumpToFolderBtn5,
|
||||
};
|
||||
foreach (var btn in sb) {
|
||||
btn.MouseUp += StorageJumpToFolderBtn_MouseUp;
|
||||
btn.MouseDown += StorageJumpToFolderBtn_MouseDown;
|
||||
btn.MouseLeave += StorageJumpToFolderBtn_MouseLeave;
|
||||
}
|
||||
CustomStorageLocationGroup.Visibility = ((StorageLocationItem)ComboBoxStoragePath.SelectedItem).SelectItem == "c-" ? Visibility.Visible : Visibility.Collapsed;
|
||||
CustomStorageLocationCheckPanel.Visibility = ((StorageLocationItem)ComboBoxStoragePath.SelectedItem).SelectItem == "c-" ? Visibility.Visible : Visibility.Collapsed;
|
||||
CustomStorageLocation.Text = Settings.Storage.UserStorageLocation;
|
||||
}
|
||||
|
||||
private async void HandleUserCustomStorageLocation([CanBeNull] string dirPath = null) {
|
||||
var path = dirPath ?? (Settings.Storage.UserStorageLocation != ""
|
||||
? Settings.Storage.UserStorageLocation
|
||||
: null);
|
||||
if (path != null) {
|
||||
CustomStorageLocationGroup.Visibility = Visibility.Visible;
|
||||
CustomStorageLocationCheckPanel.Visibility = Visibility.Visible;
|
||||
CustomStorageNonRemovableDriveTip.Visibility = Visibility.Visible;
|
||||
CustomStorageWritableTip.Visibility = Visibility.Collapsed;
|
||||
CustomStorageLocation.Text = "";
|
||||
|
||||
CustomStorageLocation.Text = new DirectoryInfo(path).FullName;
|
||||
|
||||
// 加载动画
|
||||
((Image)CustomStorageNonRemovableDriveTip.Children[0]).Source =
|
||||
CustomStorageLocationCheckPanel.FindResource("LoadingIcon") as DrawingImage;
|
||||
((Image)CustomStorageNonRemovableDriveTip.Children[0]).RenderTransformOrigin = new Point(0.5, 0.5);
|
||||
((Image)CustomStorageNonRemovableDriveTip.Children[0]).RenderTransform = new RotateTransform(0, 8, 8);
|
||||
var tg = new EventTrigger(LoadedEvent);
|
||||
var sb = new Storyboard();
|
||||
var da = new DoubleAnimation {
|
||||
To = -360,
|
||||
Duration = new Duration(new TimeSpan(0, 0, 1)),
|
||||
RepeatBehavior = RepeatBehavior.Forever,
|
||||
};
|
||||
sb.Children.Add(da);
|
||||
Storyboard.SetTargetProperty(da, new PropertyPath("(Image.RenderTransform).(RotateTransform.Angle)"));
|
||||
tg.Actions.Add(new BeginStoryboard() {
|
||||
Storyboard = sb
|
||||
});
|
||||
((Image)CustomStorageNonRemovableDriveTip.Children[0]).Triggers.Add(tg);
|
||||
|
||||
// 检测是否在非可移动存储上
|
||||
var drive = new DirectoryInfo(path).FullName.Substring(0, 1);
|
||||
var allDrives = DriveInfo.GetDrives();
|
||||
var ds = allDrives.Where(info => info.Name.StartsWith(drive) && info.DriveType == DriveType.Fixed);
|
||||
if (ds.Any()) {
|
||||
((Image)CustomStorageNonRemovableDriveTip.Children[0]).Source =
|
||||
CustomStorageLocationCheckPanel.FindResource("SuccessIcon") as DrawingImage;
|
||||
((TextBlock)CustomStorageNonRemovableDriveTip.Children[1]).Text = "非可移动存储介质";
|
||||
} else {
|
||||
((Image)CustomStorageNonRemovableDriveTip.Children[0]).Source =
|
||||
CustomStorageLocationCheckPanel.FindResource("FailedIcon") as DrawingImage;
|
||||
((TextBlock)CustomStorageNonRemovableDriveTip.Children[1]).Text = "路径在可移动存储介质上";
|
||||
}
|
||||
sb.Stop();
|
||||
((Image)CustomStorageNonRemovableDriveTip.Children[0]).Triggers.Remove(tg);
|
||||
|
||||
// 加载动画2
|
||||
CustomStorageWritableTip.Visibility = Visibility.Visible;
|
||||
((Image)CustomStorageWritableTip.Children[0]).Source =
|
||||
CustomStorageLocationCheckPanel.FindResource("LoadingIcon") as DrawingImage;
|
||||
((Image)CustomStorageWritableTip.Children[0]).RenderTransformOrigin = new Point(0.5, 0.5);
|
||||
((Image)CustomStorageWritableTip.Children[0]).RenderTransform = new RotateTransform(0, 8, 8);
|
||||
var tg2 = new EventTrigger(LoadedEvent);
|
||||
var sb2 = new Storyboard();
|
||||
var da2 = new DoubleAnimation {
|
||||
To = -360,
|
||||
Duration = new Duration(new TimeSpan(0, 0, 1)),
|
||||
RepeatBehavior = RepeatBehavior.Forever,
|
||||
};
|
||||
sb.Children.Add(da2);
|
||||
Storyboard.SetTargetProperty(da2, new PropertyPath("(Image.RenderTransform).(RotateTransform.Angle)"));
|
||||
tg.Actions.Add(new BeginStoryboard() {
|
||||
Storyboard = sb2
|
||||
});
|
||||
((Image)CustomStorageWritableTip.Children[0]).Triggers.Add(tg2);
|
||||
|
||||
// 检查是否可写
|
||||
var result = await DirectoryUtils.IsWritableAsync(path);
|
||||
if (result) {
|
||||
((Image)CustomStorageWritableTip.Children[0]).Source =
|
||||
CustomStorageLocationCheckPanel.FindResource("SuccessIcon") as DrawingImage;
|
||||
((TextBlock)CustomStorageWritableTip.Children[1]).Text = "目录可写";
|
||||
} else {
|
||||
((Image)CustomStorageWritableTip.Children[0]).Source =
|
||||
CustomStorageLocationCheckPanel.FindResource("FailedIcon") as DrawingImage;
|
||||
((TextBlock)CustomStorageWritableTip.Children[1]).Text = "目录权限错误";
|
||||
}
|
||||
sb2.Stop();
|
||||
((Image)CustomStorageWritableTip.Children[0]).Triggers.Remove(tg2);
|
||||
|
||||
if (ds.Any() && result) {
|
||||
Settings.Storage.StorageLocation = storageLocationItems[ComboBoxStoragePath.SelectedIndex].SelectItem;
|
||||
Settings.Storage.UserStorageLocation = new DirectoryInfo(path).FullName;
|
||||
SaveSettingsToFile();
|
||||
InitStorageFoldersStructure(null);
|
||||
StartAnalyzeStorage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboBoxStoragePath_OnSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (isChangingUserStorageSelectionProgramically) return;
|
||||
if (!isLoaded) return;
|
||||
if (storageLocationItems[ComboBoxStoragePath.SelectedIndex].SelectItem == "c-") {
|
||||
if (Settings.Storage.UserStorageLocation == "") {
|
||||
var folderBrowser = new System.Windows.Forms.FolderBrowserDialog();
|
||||
folderBrowser.Description = "请选择ICC的自定义存储目录。不支持存储到固定硬盘除外的设备和网络地址上!";
|
||||
folderBrowser.ShowDialog();
|
||||
if (folderBrowser.SelectedPath.Length > 0)
|
||||
HandleUserCustomStorageLocation(folderBrowser.SelectedPath);
|
||||
else {
|
||||
var si = Settings.Storage.StorageLocation;
|
||||
var item = storageLocationItems.Where(i => i.SelectItem == si).ToArray()[0];
|
||||
var index = storageLocationItems.IndexOf(item);
|
||||
ComboBoxStoragePath.SelectedIndex = index;
|
||||
}
|
||||
} else HandleUserCustomStorageLocation();
|
||||
} else {
|
||||
if (isLoaded) CustomStorageLocationGroup.Visibility = ((StorageLocationItem)ComboBoxStoragePath.SelectedItem).SelectItem == "c-" ? Visibility.Visible : Visibility.Collapsed;
|
||||
if (isLoaded) CustomStorageLocation.Text = Settings.Storage.UserStorageLocation;
|
||||
Settings.Storage.StorageLocation = storageLocationItems[ComboBoxStoragePath.SelectedIndex].SelectItem;
|
||||
SaveSettingsToFile();
|
||||
InitStorageFoldersStructure(storageLocationItems[ComboBoxStoragePath.SelectedIndex].Path);
|
||||
StartAnalyzeStorage();
|
||||
}
|
||||
}
|
||||
|
||||
private void CustomStorageLocationButton_Click(object sender, RoutedEventArgs e) {
|
||||
var folderBrowser = new System.Windows.Forms.FolderBrowserDialog();
|
||||
folderBrowser.Description = "请选择ICC的自定义存储目录。不支持存储到固定硬盘除外的设备和网络地址上!";
|
||||
folderBrowser.ShowDialog();
|
||||
if (folderBrowser.SelectedPath.Length > 0) HandleUserCustomStorageLocation(folderBrowser.SelectedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
private enum CommitReason {
|
||||
UserInput,
|
||||
CodeInput,
|
||||
ShapeDrawing,
|
||||
ShapeRecognition,
|
||||
ClearingCanvas,
|
||||
Manipulation
|
||||
}
|
||||
|
||||
private CommitReason _currentCommitType = CommitReason.UserInput;
|
||||
private bool IsEraseByPoint => SelectedMode == ICCToolsEnum.EraseByGeometryMode;
|
||||
private StrokeCollection ReplacedStroke;
|
||||
private StrokeCollection AddedStroke;
|
||||
private StrokeCollection CuboidStrokeCollection;
|
||||
private Dictionary<Stroke, Tuple<StylusPointCollection, StylusPointCollection>> StrokeManipulationHistory;
|
||||
|
||||
private Dictionary<Stroke, StylusPointCollection> StrokeInitialHistory =
|
||||
new Dictionary<Stroke, StylusPointCollection>();
|
||||
|
||||
private Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>> DrawingAttributesHistory =
|
||||
new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
|
||||
private Dictionary<Guid, List<Stroke>> DrawingAttributesHistoryFlag = new Dictionary<Guid, List<Stroke>>() {
|
||||
{ DrawingAttributeIds.Color, new List<Stroke>() },
|
||||
{ DrawingAttributeIds.DrawingFlags, new List<Stroke>() },
|
||||
{ DrawingAttributeIds.IsHighlighter, new List<Stroke>() },
|
||||
{ DrawingAttributeIds.StylusHeight, new List<Stroke>() },
|
||||
{ DrawingAttributeIds.StylusTip, new List<Stroke>() },
|
||||
{ DrawingAttributeIds.StylusTipTransform, new List<Stroke>() },
|
||||
{ DrawingAttributeIds.StylusWidth, new List<Stroke>() }
|
||||
};
|
||||
|
||||
private TimeMachine timeMachine = new TimeMachine();
|
||||
|
||||
private void ApplyHistoryToCanvas(TimeMachineHistory item, IccInkCanvas applyCanvas = null) {
|
||||
_currentCommitType = CommitReason.CodeInput;
|
||||
var canvas = inkCanvas;
|
||||
if (applyCanvas != null && applyCanvas is IccInkCanvas) {
|
||||
canvas = applyCanvas;
|
||||
}
|
||||
|
||||
if (item.CommitType == TimeMachineHistoryType.UserInput) {
|
||||
if (!item.StrokeHasBeenCleared) {
|
||||
foreach (var strokes in item.CurrentStroke)
|
||||
if (!canvas.Strokes.Contains(strokes))
|
||||
canvas.Strokes.Add(strokes);
|
||||
} else {
|
||||
foreach (var strokes in item.CurrentStroke)
|
||||
if (canvas.Strokes.Contains(strokes))
|
||||
canvas.Strokes.Remove(strokes);
|
||||
}
|
||||
} else if (item.CommitType == TimeMachineHistoryType.ShapeRecognition) {
|
||||
if (item.StrokeHasBeenCleared) {
|
||||
foreach (var strokes in item.CurrentStroke)
|
||||
if (canvas.Strokes.Contains(strokes))
|
||||
canvas.Strokes.Remove(strokes);
|
||||
|
||||
foreach (var strokes in item.ReplacedStroke)
|
||||
if (!canvas.Strokes.Contains(strokes))
|
||||
canvas.Strokes.Add(strokes);
|
||||
} else {
|
||||
foreach (var strokes in item.CurrentStroke)
|
||||
if (!canvas.Strokes.Contains(strokes))
|
||||
canvas.Strokes.Add(strokes);
|
||||
|
||||
foreach (var strokes in item.ReplacedStroke)
|
||||
if (canvas.Strokes.Contains(strokes))
|
||||
canvas.Strokes.Remove(strokes);
|
||||
}
|
||||
} else if (item.CommitType == TimeMachineHistoryType.Manipulation) {
|
||||
if (!item.StrokeHasBeenCleared) {
|
||||
foreach (var currentStroke in item.StylusPointDictionary) {
|
||||
if (canvas.Strokes.Contains(currentStroke.Key)) {
|
||||
currentStroke.Key.StylusPoints = currentStroke.Value.Item2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (var currentStroke in item.StylusPointDictionary) {
|
||||
if (canvas.Strokes.Contains(currentStroke.Key)) {
|
||||
currentStroke.Key.StylusPoints = currentStroke.Value.Item1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (item.CommitType == TimeMachineHistoryType.DrawingAttributes) {
|
||||
if (!item.StrokeHasBeenCleared) {
|
||||
foreach (var currentStroke in item.DrawingAttributes) {
|
||||
if (canvas.Strokes.Contains(currentStroke.Key)) {
|
||||
currentStroke.Key.DrawingAttributes = currentStroke.Value.Item2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (var currentStroke in item.DrawingAttributes) {
|
||||
if (canvas.Strokes.Contains(currentStroke.Key)) {
|
||||
currentStroke.Key.DrawingAttributes = currentStroke.Value.Item1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (item.CommitType == TimeMachineHistoryType.Clear) {
|
||||
if (!item.StrokeHasBeenCleared) {
|
||||
if (item.CurrentStroke != null)
|
||||
foreach (var currentStroke in item.CurrentStroke)
|
||||
if (!canvas.Strokes.Contains(currentStroke))
|
||||
canvas.Strokes.Add(currentStroke);
|
||||
|
||||
if (item.ReplacedStroke != null)
|
||||
foreach (var replacedStroke in item.ReplacedStroke)
|
||||
if (canvas.Strokes.Contains(replacedStroke))
|
||||
canvas.Strokes.Remove(replacedStroke);
|
||||
} else {
|
||||
if (item.ReplacedStroke != null)
|
||||
foreach (var replacedStroke in item.ReplacedStroke)
|
||||
if (!canvas.Strokes.Contains(replacedStroke))
|
||||
canvas.Strokes.Add(replacedStroke);
|
||||
|
||||
if (item.CurrentStroke != null)
|
||||
foreach (var currentStroke in item.CurrentStroke)
|
||||
if (canvas.Strokes.Contains(currentStroke))
|
||||
canvas.Strokes.Remove(currentStroke);
|
||||
}
|
||||
}
|
||||
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
}
|
||||
|
||||
private StrokeCollection ApplyHistoriesToNewStrokeCollection(TimeMachineHistory[] items) {
|
||||
IccInkCanvas fakeInkCanv = new IccInkCanvas() {
|
||||
Width = inkCanvas.ActualWidth,
|
||||
Height = inkCanvas.ActualHeight,
|
||||
EditingMode = InkCanvasEditingMode.None,
|
||||
};
|
||||
|
||||
if (items != null && items.Length > 0) {
|
||||
foreach (var timeMachineHistory in items) {
|
||||
ApplyHistoryToCanvas(timeMachineHistory, fakeInkCanv);
|
||||
}
|
||||
}
|
||||
|
||||
return fakeInkCanv.Strokes;
|
||||
}
|
||||
|
||||
private void TimeMachine_OnUndoStateChanged(bool status) {
|
||||
SymbolIconUndo.IsEnabled = status;
|
||||
}
|
||||
|
||||
private void TimeMachine_OnRedoStateChanged(bool status) {
|
||||
SymbolIconRedo.IsEnabled = status;
|
||||
}
|
||||
|
||||
private bool _mouseGesturingPrevious = false;
|
||||
|
||||
private void StrokesOnStrokesChanged(object sender, StrokeCollectionChangedEventArgs e) {
|
||||
if (!isHidingSubPanelsWhenInking) {
|
||||
isHidingSubPanelsWhenInking = true;
|
||||
HideSubPanels(); // 书写时自动隐藏二级菜单
|
||||
}
|
||||
|
||||
|
||||
foreach (var stroke in e?.Removed) {
|
||||
stroke.StylusPointsChanged -= Stroke_StylusPointsChanged;
|
||||
stroke.StylusPointsReplaced -= Stroke_StylusPointsReplaced;
|
||||
stroke.DrawingAttributesChanged -= Stroke_DrawingAttributesChanged;
|
||||
StrokeInitialHistory.Remove(stroke);
|
||||
}
|
||||
|
||||
foreach (var stroke in e?.Added) {
|
||||
stroke.StylusPointsChanged += Stroke_StylusPointsChanged;
|
||||
stroke.StylusPointsReplaced += Stroke_StylusPointsReplaced;
|
||||
stroke.DrawingAttributesChanged += Stroke_DrawingAttributesChanged;
|
||||
StrokeInitialHistory[stroke] = stroke.StylusPoints.Clone();
|
||||
}
|
||||
|
||||
if (_currentCommitType == CommitReason.CodeInput || _currentCommitType == CommitReason.ShapeDrawing) return;
|
||||
|
||||
if ((e.Added.Count != 0 || e.Removed.Count != 0) && IsEraseByPoint) {
|
||||
if (AddedStroke == null) AddedStroke = new StrokeCollection();
|
||||
if (ReplacedStroke == null) ReplacedStroke = new StrokeCollection();
|
||||
AddedStroke.Add(e.Added);
|
||||
ReplacedStroke.Add(e.Removed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Added.Count != 0) {
|
||||
if (_currentCommitType == CommitReason.ShapeRecognition) {
|
||||
timeMachine.CommitStrokeShapeHistory(ReplacedStroke, e.Added);
|
||||
ReplacedStroke = null;
|
||||
return;
|
||||
} else {
|
||||
timeMachine.CommitStrokeUserInputHistory(e.Added);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Removed.Count != 0) {
|
||||
if (_currentCommitType == CommitReason.ShapeRecognition) {
|
||||
ReplacedStroke = e.Removed;
|
||||
return;
|
||||
} else if (!IsEraseByPoint || _currentCommitType == CommitReason.ClearingCanvas) {
|
||||
timeMachine.CommitStrokeEraseHistory(e.Removed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Stroke_DrawingAttributesChanged(object sender, PropertyDataChangedEventArgs e) {
|
||||
var key = sender as Stroke;
|
||||
var currentValue = key.DrawingAttributes.Clone();
|
||||
DrawingAttributesHistory.TryGetValue(key, out var previousTuple);
|
||||
var previousValue = previousTuple?.Item1 ?? currentValue.Clone();
|
||||
var needUpdateValue = !DrawingAttributesHistoryFlag[e.PropertyGuid].Contains(key);
|
||||
if (needUpdateValue) {
|
||||
DrawingAttributesHistoryFlag[e.PropertyGuid].Add(key);
|
||||
Debug.Write(e.PreviousValue.ToString());
|
||||
}
|
||||
|
||||
if (e.PropertyGuid == DrawingAttributeIds.Color && needUpdateValue) {
|
||||
previousValue.Color = (Color)e.PreviousValue;
|
||||
}
|
||||
|
||||
if (e.PropertyGuid == DrawingAttributeIds.IsHighlighter && needUpdateValue) {
|
||||
previousValue.IsHighlighter = (bool)e.PreviousValue;
|
||||
}
|
||||
|
||||
if (e.PropertyGuid == DrawingAttributeIds.StylusHeight && needUpdateValue) {
|
||||
previousValue.Height = (double)e.PreviousValue;
|
||||
}
|
||||
|
||||
if (e.PropertyGuid == DrawingAttributeIds.StylusWidth && needUpdateValue) {
|
||||
previousValue.Width = (double)e.PreviousValue;
|
||||
}
|
||||
|
||||
if (e.PropertyGuid == DrawingAttributeIds.StylusTip && needUpdateValue) {
|
||||
previousValue.StylusTip = (StylusTip)e.PreviousValue;
|
||||
}
|
||||
|
||||
if (e.PropertyGuid == DrawingAttributeIds.StylusTipTransform && needUpdateValue) {
|
||||
previousValue.StylusTipTransform = (Matrix)e.PreviousValue;
|
||||
}
|
||||
|
||||
if (e.PropertyGuid == DrawingAttributeIds.DrawingFlags && needUpdateValue) {
|
||||
previousValue.IgnorePressure = (bool)e.PreviousValue;
|
||||
}
|
||||
|
||||
DrawingAttributesHistory[key] =
|
||||
new Tuple<DrawingAttributes, DrawingAttributes>(previousValue, currentValue);
|
||||
}
|
||||
|
||||
private void Stroke_StylusPointsReplaced(object sender, StylusPointsReplacedEventArgs e) {
|
||||
if (isMouseGesturing) return;
|
||||
StrokeInitialHistory[sender as Stroke] = e.NewStylusPoints.Clone();
|
||||
}
|
||||
|
||||
private void Stroke_StylusPointsChanged(object sender, EventArgs e) {
|
||||
if (isMouseGesturing) return;
|
||||
var selectedStrokes = inkCanvas.GetSelectedStrokes();
|
||||
var count = selectedStrokes.Count;
|
||||
if (count == 0) count = inkCanvas.Strokes.Count;
|
||||
if (StrokeManipulationHistory == null) {
|
||||
StrokeManipulationHistory =
|
||||
new Dictionary<Stroke, Tuple<StylusPointCollection, StylusPointCollection>>();
|
||||
}
|
||||
|
||||
StrokeManipulationHistory[sender as Stroke] =
|
||||
new Tuple<StylusPointCollection, StylusPointCollection>(StrokeInitialHistory[sender as Stroke],
|
||||
(sender as Stroke).StylusPoints.Clone());
|
||||
if ((StrokeManipulationHistory.Count == count || sender == null) && dec.Count == 0) {
|
||||
timeMachine.CommitStrokeManipulationHistory(StrokeManipulationHistory);
|
||||
foreach (var item in StrokeManipulationHistory) {
|
||||
StrokeInitialHistory[item.Key] = item.Value.Item2;
|
||||
}
|
||||
|
||||
StrokeManipulationHistory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public class TimeViewModel : INotifyPropertyChanged {
|
||||
private string _nowTime;
|
||||
private string _nowDate;
|
||||
|
||||
public string nowTime {
|
||||
get => _nowTime;
|
||||
set {
|
||||
if (_nowTime != value) {
|
||||
_nowTime = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string nowDate {
|
||||
get => _nowDate;
|
||||
set {
|
||||
if (_nowDate != value) {
|
||||
_nowDate = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
private Timer timerCheckPPT = new Timer();
|
||||
private Timer timerKillProcess = new Timer();
|
||||
private Timer timerCheckAutoFold = new Timer();
|
||||
private string AvailableLatestVersion = null;
|
||||
private Timer timerCheckAutoUpdateWithSilence = new Timer();
|
||||
private bool isHidingSubPanelsWhenInking = false; // 避免书写时触发二次关闭二级菜单导致动画不连续
|
||||
|
||||
private Timer timerDisplayTime = new Timer();
|
||||
private Timer timerDisplayDate = new Timer();
|
||||
|
||||
private TimeViewModel nowTimeVM = new TimeViewModel();
|
||||
|
||||
private void InitTimers() {
|
||||
timerCheckPPT.Elapsed += TimerCheckPPT_Elapsed;
|
||||
timerCheckPPT.Interval = 500;
|
||||
timerKillProcess.Elapsed += TimerKillProcess_Elapsed;
|
||||
timerKillProcess.Interval = 2000;
|
||||
timerCheckAutoFold.Elapsed += timerCheckAutoFold_Elapsed;
|
||||
timerCheckAutoFold.Interval = 500;
|
||||
timerCheckAutoUpdateWithSilence.Elapsed += timerCheckAutoUpdateWithSilence_Elapsed;
|
||||
timerCheckAutoUpdateWithSilence.Interval = 1000 * 60 * 10;
|
||||
WaterMarkTime.DataContext = nowTimeVM;
|
||||
WaterMarkDate.DataContext = nowTimeVM;
|
||||
timerDisplayTime.Elapsed += TimerDisplayTime_Elapsed;
|
||||
timerDisplayTime.Interval = 1000;
|
||||
timerDisplayTime.Start();
|
||||
timerDisplayDate.Elapsed += TimerDisplayDate_Elapsed;
|
||||
timerDisplayDate.Interval = 1000 * 60 * 60 * 1;
|
||||
timerDisplayDate.Start();
|
||||
timerKillProcess.Start();
|
||||
nowTimeVM.nowDate = DateTime.Now.ToShortDateString().ToString();
|
||||
nowTimeVM.nowTime = DateTime.Now.ToShortTimeString().ToString();
|
||||
}
|
||||
|
||||
private void TimerDisplayTime_Elapsed(object sender, ElapsedEventArgs e) {
|
||||
nowTimeVM.nowTime = DateTime.Now.ToShortTimeString().ToString();
|
||||
}
|
||||
|
||||
private void TimerDisplayDate_Elapsed(object sender, ElapsedEventArgs e) {
|
||||
nowTimeVM.nowDate = DateTime.Now.ToShortDateString().ToString();
|
||||
}
|
||||
|
||||
private void TimerKillProcess_Elapsed(object sender, ElapsedEventArgs e) {
|
||||
try {
|
||||
// 希沃相关: easinote swenserver RemoteProcess EasiNote.MediaHttpService smartnote.cloud EasiUpdate smartnote EasiUpdate3 EasiUpdate3Protect SeewoP2P CefSharp.BrowserSubprocess SeewoUploadService
|
||||
var arg = "/F";
|
||||
if (Settings.Automation.IsAutoKillPptService) {
|
||||
var processes = Process.GetProcessesByName("PPTService");
|
||||
if (processes.Length > 0) arg += " /IM PPTService.exe";
|
||||
processes = Process.GetProcessesByName("SeewoIwbAssistant");
|
||||
if (processes.Length > 0) arg += " /IM SeewoIwbAssistant.exe" + " /IM Sia.Guard.exe";
|
||||
}
|
||||
|
||||
if (Settings.Automation.IsAutoKillEasiNote) {
|
||||
var processes = Process.GetProcessesByName("EasiNote");
|
||||
if (processes.Length > 0) arg += " /IM EasiNote.exe";
|
||||
}
|
||||
|
||||
if (Settings.Automation.IsAutoKillHiteAnnotation) {
|
||||
var processes = Process.GetProcessesByName("HiteAnnotation");
|
||||
if (processes.Length > 0) arg += " /IM HiteAnnotation.exe";
|
||||
}
|
||||
|
||||
if (Settings.Automation.IsAutoKillVComYouJiao)
|
||||
{
|
||||
var processes = Process.GetProcessesByName("VcomTeach");
|
||||
if (processes.Length > 0) arg += " /IM VcomTeach.exe" + " /IM VcomDaemon.exe" + " /IM VcomRender.exe";
|
||||
}
|
||||
|
||||
if (Settings.Automation.IsAutoKillICA) {
|
||||
var processesAnnotation = Process.GetProcessesByName("Ink Canvas Annotation");
|
||||
var processesArtistry = Process.GetProcessesByName("Ink Canvas Artistry");
|
||||
if (processesAnnotation.Length > 0) arg += " /IM \"Ink Canvas Annotation.exe\"";
|
||||
if (processesArtistry.Length > 0) arg += " /IM \"Ink Canvas Artistry.exe\"";
|
||||
}
|
||||
|
||||
if (Settings.Automation.IsAutoKillInkCanvas) {
|
||||
var processes = Process.GetProcessesByName("Ink Canvas");
|
||||
if (processes.Length > 0) arg += " /IM \"Ink Canvas.exe\"";
|
||||
}
|
||||
|
||||
// 移除了IDT的查殺
|
||||
//if (Settings.Automation.IsAutoKillIDT) {
|
||||
// var processes = Process.GetProcessesByName("智绘教");
|
||||
// if (processes.Length > 0) arg += " /IM \"智绘教.exe\"";
|
||||
//}
|
||||
|
||||
//if (Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) {
|
||||
//由于希沃桌面2.0提供的桌面批注是64位应用程序,32位程序无法访问,目前暂不做精准匹配,只匹配进程名称,后面会考虑封装一套基于P/Invoke和WMI的综合进程识别方案。
|
||||
// var processes = Process.GetProcessesByName("DesktopAnnotation");
|
||||
// if (processes.Length > 0) arg += " /IM DesktopAnnotation.exe";
|
||||
//}
|
||||
|
||||
if (arg != "/F") {
|
||||
var p = new Process();
|
||||
p.StartInfo = new ProcessStartInfo("taskkill", arg);
|
||||
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
p.Start();
|
||||
|
||||
if (arg.Contains("EasiNote")) {
|
||||
Dispatcher.Invoke(() => {
|
||||
ShowNewToast("“希沃白板 5”已自动关闭", MW_Toast.ToastType.Warning, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
if (arg.Contains("HiteAnnotation")) {
|
||||
Dispatcher.Invoke(() => {
|
||||
ShowNewToast("“鸿合屏幕书写”已自动关闭", MW_Toast.ToastType.Warning, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
if (arg.Contains("Ink Canvas Annotation") || arg.Contains("Ink Canvas Artistry")) {
|
||||
Dispatcher.Invoke(() => {
|
||||
ShowNewToast("“ICA”已自动关闭", MW_Toast.ToastType.Warning, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
if (arg.Contains("\"Ink Canvas.exe\"")) {
|
||||
Dispatcher.Invoke(() => {
|
||||
ShowNewToast("“Ink Canvas”已自动关闭", MW_Toast.ToastType.Warning, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
//if (arg.Contains("智绘教")) {
|
||||
// Dispatcher.Invoke(() => {
|
||||
// ShowNotification("“智绘教”已自动关闭");
|
||||
// });
|
||||
//}
|
||||
|
||||
if (arg.Contains("VcomTeach"))
|
||||
{
|
||||
Dispatcher.Invoke(() => {
|
||||
ShowNewToast("“优教授课端”已自动关闭", MW_Toast.ToastType.Warning, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
//if (arg.Contains("DesktopAnnotation"))
|
||||
//{
|
||||
// Dispatcher.Invoke(() => {
|
||||
// ShowNotification("“DesktopAnnotation”已自动关闭");
|
||||
// });
|
||||
//}
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
|
||||
private bool foldFloatingBarByUser = false, // 保持收纳操作不受自动收纳的控制
|
||||
unfoldFloatingBarByUser = false; // 允许用户在希沃软件内进行展开操作
|
||||
|
||||
private void timerCheckAutoFold_Elapsed(object sender, ElapsedEventArgs e) {
|
||||
if (isFloatingBarChangingHideMode) return;
|
||||
try {
|
||||
var windowProcessName = ForegroundWindowInfo.ProcessName();
|
||||
Trace.WriteLine(windowProcessName);
|
||||
var windowTitle = ForegroundWindowInfo.WindowTitle();
|
||||
Trace.WriteLine(windowTitle);
|
||||
//LogHelper.WriteLogToFile("windowTitle | " + windowTitle + " | windowProcessName | " + windowProcessName);
|
||||
|
||||
if (windowProcessName == "EasiNote") {
|
||||
// 检测到有可能是EasiNote5或者EasiNote3/3C
|
||||
if (ForegroundWindowInfo.ProcessPath() != "Unknown") {
|
||||
var versionInfo = FileVersionInfo.GetVersionInfo(ForegroundWindowInfo.ProcessPath());
|
||||
string version = versionInfo.FileVersion;
|
||||
string prodName = versionInfo.ProductName;
|
||||
Trace.WriteLine(ForegroundWindowInfo.ProcessPath());
|
||||
Trace.WriteLine(version);
|
||||
Trace.WriteLine(prodName);
|
||||
if (version.StartsWith("5.") && Settings.Automation.IsAutoFoldInEasiNote ) { // EasiNote5
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
} else if (version.StartsWith("3.") && Settings.Automation.IsAutoFoldInEasiNote3) { // EasiNote3
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
} else if (prodName.Contains("3C") && Settings.Automation.IsAutoFoldInEasiNote3C &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) { // EasiNote3C
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
}
|
||||
}
|
||||
// EasiCamera
|
||||
} else if (Settings.Automation.IsAutoFoldInEasiCamera && windowProcessName == "EasiCamera" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// EasiNote5C
|
||||
} else if (Settings.Automation.IsAutoFoldInEasiNote5C && windowProcessName == "EasiNote5C" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// SeewoPinco
|
||||
} else if (Settings.Automation.IsAutoFoldInSeewoPincoTeacher && (windowProcessName == "BoardService" || windowProcessName == "seewoPincoTeacher")) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// HiteCamera
|
||||
} else if (Settings.Automation.IsAutoFoldInHiteCamera && windowProcessName == "HiteCamera" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// HiteTouchPro
|
||||
} else if (Settings.Automation.IsAutoFoldInHiteTouchPro && windowProcessName == "HiteTouchPro" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// WxBoardMain
|
||||
} else if (Settings.Automation.IsAutoFoldInWxBoardMain && windowProcessName == "WxBoardMain" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// MSWhiteboard
|
||||
} else if (Settings.Automation.IsAutoFoldInMSWhiteboard && (windowProcessName == "MicrosoftWhiteboard" ||
|
||||
windowProcessName == "msedgewebview2")) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// OldZyBoard
|
||||
} else if (Settings.Automation.IsAutoFoldInOldZyBoard && // 中原旧白板
|
||||
(WinTabWindowsChecker.IsWindowExisted("WhiteBoard - DrawingWindow")
|
||||
|| WinTabWindowsChecker.IsWindowExisted("InstantAnnotationWindow"))) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// HiteLightBoard
|
||||
} else if (Settings.Automation.IsAutoFoldInHiteLightBoard && windowProcessName == "HiteLightBoard" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// AdmoxWhiteboard
|
||||
} else if (Settings.Automation.IsAutoFoldInAdmoxWhiteboard && windowProcessName == "Amdox.WhiteBoard" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// AdmoxBooth
|
||||
} else if (Settings.Automation.IsAutoFoldInAdmoxBooth && windowProcessName == "Amdox.Booth" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// QPoint
|
||||
} else if (Settings.Automation.IsAutoFoldInQPoint && windowProcessName == "QPoint" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// YiYunVisualPresenter
|
||||
} else if (Settings.Automation.IsAutoFoldInYiYunVisualPresenter && windowProcessName == "YiYunVisualPresenter" &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
// MaxHubWhiteboard
|
||||
} else if (Settings.Automation.IsAutoFoldInMaxHubWhiteboard && windowProcessName == "WhiteBoard" &&
|
||||
WinTabWindowsChecker.IsWindowExisted("白板书写") &&
|
||||
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
|
||||
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
|
||||
if (ForegroundWindowInfo.ProcessPath() != "Unknown") {
|
||||
var versionInfo = FileVersionInfo.GetVersionInfo(ForegroundWindowInfo.ProcessPath());
|
||||
var version = versionInfo.FileVersion; var prodName = versionInfo.ProductName;
|
||||
if (version.StartsWith("6.") && prodName=="WhiteBoard") if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
|
||||
}
|
||||
} else if (WinTabWindowsChecker.IsWindowExisted("幻灯片放映", false)) {
|
||||
// 处于幻灯片放映状态
|
||||
if (!Settings.Automation.IsAutoFoldInPPTSlideShow && isFloatingBarFolded && !foldFloatingBarByUser)
|
||||
UnFoldFloatingBar_MouseUp(new object(), null);
|
||||
} else {
|
||||
if (isFloatingBarFolded && !foldFloatingBarByUser) UnFoldFloatingBar_MouseUp(new object(), null);
|
||||
unfoldFloatingBarByUser = false;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void timerCheckAutoUpdateWithSilence_Elapsed(object sender, ElapsedEventArgs e) {
|
||||
Dispatcher.Invoke(() => {
|
||||
try {
|
||||
if (!Topmost || inkCanvas.Strokes.Count > 0) return;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
});
|
||||
try {
|
||||
if (AutoUpdateWithSilenceTimeComboBox.CheckIsInSilencePeriod(
|
||||
Settings.Startup.AutoUpdateWithSilenceStartTime,
|
||||
Settings.Startup.AutoUpdateWithSilenceEndTime)) {
|
||||
AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, true);
|
||||
timerCheckAutoUpdateWithSilence.Stop();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<UserControl x:Class="Ink_Canvas.MW_Toast"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Ink_Canvas"
|
||||
xmlns:modern="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<DrawingImage x:Key="ErrorIcon">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Geometry="F1 M24,24z M0,0z M0,12C0,6.34315 0,3.51472 1.75736,1.75736 3.51472,0 6.34315,0 12,0 17.6569,0 20.4853,0 22.2426,1.75736 24,3.51472 24,6.34315 24,12 24,17.6569 24,20.4853 22.2426,22.2426 20.4853,24 17.6569,24 12,24 6.34315,24 3.51472,24 1.75736,22.2426 0,20.4853 0,17.6569 0,12z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF000000" Opacity="0.3" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F0 M24,24z M0,0z M8.46967,8.46967C8.76256,8.17678,9.23744,8.17678,9.53033,8.46967L12,10.9394 14.4697,8.46969C14.7626,8.1768 15.2374,8.1768 15.5303,8.46969 15.8232,8.76259 15.8232,9.23746 15.5303,9.53035L13.0607,12 15.5303,14.4696C15.8232,14.7625 15.8232,15.2374 15.5303,15.5303 15.2374,15.8232 14.7625,15.8232 14.4696,15.5303L12,13.0607 9.53036,15.5303C9.23746,15.8232 8.76259,15.8232 8.4697,15.5303 8.1768,15.2374 8.1768,14.7626 8.4697,14.4697L10.9394,12 8.46967,9.53033C8.17678,9.23744,8.17678,8.76256,8.46967,8.46967z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
<DrawingImage x:Key="WarningIcon">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Geometry="F1 M24,24z M0,0z M0,12C0,6.34315 0,3.51472 1.75736,1.75736 3.51472,0 6.34315,0 12,0 17.6569,0 20.4853,0 22.2426,1.75736 24,3.51472 24,6.34315 24,12 24,17.6569 24,20.4853 22.2426,22.2426 20.4853,24 17.6569,24 12,24 6.34315,24 3.51472,24 1.75736,22.2426 0,20.4853 0,17.6569 0,12z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF000000" Opacity="0.3" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F0 M24,24z M0,0z M12.75,7.5C12.75,7.08579 12.4142,6.75 12,6.75 11.5858,6.75 11.25,7.08579 11.25,7.5L11.25,12.5C11.25,12.9142 11.5858,13.25 12,13.25 12.4142,13.25 12.75,12.9142 12.75,12.5L12.75,7.5z M12,16.5C12.5523,16.5 13,16.0523 13,15.5 13,14.9477 12.5523,14.5 12,14.5 11.4477,14.5 11,14.9477 11,15.5 11,16.0523 11.4477,16.5 12,16.5z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
<DrawingImage x:Key="InfoIcon">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Geometry="F1 M24,24z M0,0z M0,12C0,6.34315 0,3.51472 1.75736,1.75736 3.51472,0 6.34315,0 12,0 17.6569,0 20.4853,0 22.2426,1.75736 24,3.51472 24,6.34315 24,12 24,17.6569 24,20.4853 22.2426,22.2426 20.4853,24 17.6569,24 12,24 6.34315,24 3.51472,24 1.75736,22.2426 0,20.4853 0,17.6569 0,12z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF000000" Opacity="0.3" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F0 M24,24z M0,0z M12,7C12.5523,7 13,7.44772 13,8 13,8.55229 12.5523,9 12,9 11.4477,9 11,8.55229 11,8 11,7.44772 11.4477,7 12,7z M12.75,16C12.75,16.4142 12.4142,16.75 12,16.75 11.5858,16.75 11.25,16.4142 11.25,16L11.25,11C11.25,10.5858 11.5858,10.25 12,10.25 12.4142,10.25 12.75,10.5858 12.75,11L12.75,16z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
<DrawingImage x:Key="SuccessIcon">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
||||
<GeometryDrawing Geometry="F1 M24,24z M0,0z M0,12C0,6.34315 0,3.51472 1.75736,1.75736 3.51472,0 6.34315,0 12,0 17.6569,0 20.4853,0 22.2426,1.75736 24,3.51472 24,6.34315 24,12 24,17.6569 24,20.4853 22.2426,22.2426 20.4853,24 17.6569,24 12,24 6.34315,24 3.51472,24 1.75736,22.2426 0,20.4853 0,17.6569 0,12z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF000000" Opacity="0.3" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F0 M24,24z M0,0z M16.0303,8.96967C16.3232,9.26256,16.3232,9.73744,16.0303,10.0303L11.0303,15.0303C10.7374,15.3232,10.2626,15.3232,9.96967,15.0303L7.96967,13.0303C7.67678,12.7374 7.67678,12.2626 7.96967,11.9697 8.26256,11.6768 8.73744,11.6768 9.03033,11.9697L10.5,13.4393 14.9697,8.96967C15.2626,8.67678,15.7374,8.67678,16.0303,8.96967z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</UserControl.Resources>
|
||||
<Grid Name="ToastGrid" IsHitTestVisible="False" Opacity="1">
|
||||
<Border Name="ToastBorder" BorderBrush="#F0863A" BorderThickness="1.5" CornerRadius="8" Padding="28,10" Height="56">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="-1,-1" EndPoint="2,2" >
|
||||
<GradientStop x:Name="GradientStop1" Color="#F6743E" Offset="0"/>
|
||||
<GradientStop x:Name="GradientStop2" Color="#D42525" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<modern:SimpleStackPanel Orientation="Horizontal" Spacing="14">
|
||||
<Image Name="ToastIconImage" Width="32" Height="32" VerticalAlignment="Center" Source="{StaticResource ErrorIcon}"/>
|
||||
<TextBlock Name="ToastTextBlock" Foreground="White" VerticalAlignment="Center" Margin="0,-1,0,0" FontSize="17" Text="這是 InkCanvasForClass 新版Toast控件測試"></TextBlock>
|
||||
</modern:SimpleStackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
|
||||
public partial class MW_Toast : UserControl {
|
||||
|
||||
private Tuple<Color, Color>[] gradientTuples = new Tuple<Color, Color>[] {
|
||||
new Tuple<Color, Color>(Color.FromRgb(246, 116, 62),Color.FromRgb(212, 37, 37)),
|
||||
new Tuple<Color, Color>(Color.FromRgb(248, 184, 6), Color.FromRgb(255, 140, 4)),
|
||||
new Tuple<Color, Color>(Color.FromRgb(45, 130, 178), Color.FromRgb(50, 154, 187)),
|
||||
new Tuple<Color, Color>(Color.FromRgb(50, 187, 113), Color.FromRgb(42, 157, 143))
|
||||
};
|
||||
|
||||
private Color[] borderColors = new Color[] {
|
||||
Color.FromRgb(240, 134, 58),
|
||||
Color.FromRgb(255, 223, 141),
|
||||
Color.FromRgb(123, 207, 237),
|
||||
Color.FromRgb(67, 213, 144),
|
||||
};
|
||||
|
||||
public enum ToastType {
|
||||
Error,
|
||||
Warning,
|
||||
Informative,
|
||||
Success
|
||||
}
|
||||
|
||||
public DrawingImage[] tipIconDrawingImages;
|
||||
|
||||
private void UpdateToastStyle(ToastType type) {
|
||||
ToastBorder.BorderBrush = new SolidColorBrush(borderColors[(int)type]);
|
||||
GradientStop1.Color = gradientTuples[(int)type].Item1;
|
||||
GradientStop2.Color = gradientTuples[(int)type].Item2;
|
||||
ToastIconImage.Source = tipIconDrawingImages[(int)type];
|
||||
}
|
||||
|
||||
private string _toastText = "InkCanvasForClass";
|
||||
public string ToastText {
|
||||
get => _toastText;
|
||||
set {
|
||||
_toastText = value;
|
||||
ToastTextBlock.Text = _toastText;
|
||||
}
|
||||
}
|
||||
|
||||
private ToastType _toastType = ToastType.Error;
|
||||
|
||||
public ToastType Type {
|
||||
get => _toastType;
|
||||
set {
|
||||
_toastType = value;
|
||||
UpdateToastStyle(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void Animate(double opacityFrom, double opacityTo, int durationMs, Action complete, EasingFunctionBase easing = null) {
|
||||
var sb = new Storyboard();
|
||||
|
||||
var fadeInAnimation = new DoubleAnimation {
|
||||
From = opacityFrom,
|
||||
To = opacityTo,
|
||||
Duration = TimeSpan.FromMilliseconds(durationMs)
|
||||
};
|
||||
Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(UIElement.OpacityProperty));
|
||||
if (easing != null) fadeInAnimation.EasingFunction = easing;
|
||||
sb.Children.Add(fadeInAnimation);
|
||||
sb.Completed += (sender, args) => {
|
||||
if (complete != null) complete();
|
||||
};
|
||||
|
||||
ToastGrid.Opacity = opacityFrom;
|
||||
sb.Begin(ToastGrid);
|
||||
}
|
||||
|
||||
public void ShowImmediately() {
|
||||
ToastGrid.Opacity = 1;
|
||||
}
|
||||
|
||||
public void ShowAnimated() {
|
||||
HideImmediately();
|
||||
Animate(0, 1, 200, null ,new CubicEase());
|
||||
}
|
||||
|
||||
public void ShowAnimatedWithAutoDispose(int autoCloseMs=3000) {
|
||||
var t = new Thread(() => {
|
||||
_isDisplay = true;
|
||||
Dispatcher.InvokeAsync(() => { ShowAnimated(); });
|
||||
Thread.Sleep(autoCloseMs);
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
Animate(1, 0, 200, (() => {
|
||||
ShouldDisposeAction(this);
|
||||
}), new CubicEase());
|
||||
});
|
||||
_isDisplay = false;
|
||||
});
|
||||
t.Start();
|
||||
}
|
||||
|
||||
public void ShowImmediatelyWithAutoDispose(int autoCloseMs=3000) {
|
||||
var t = new Thread(() => {
|
||||
_isDisplay = true;
|
||||
Dispatcher.InvokeAsync(() => { ToastGrid.Opacity = 1; });
|
||||
Thread.Sleep(autoCloseMs);
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
Animate(1, 0, 200, (() => {
|
||||
ShouldDisposeAction(this);
|
||||
}), new CubicEase());
|
||||
});
|
||||
_isDisplay = false;
|
||||
});
|
||||
t.Start();
|
||||
}
|
||||
|
||||
public void HideImmediately() {
|
||||
ToastGrid.Opacity = 0;
|
||||
}
|
||||
|
||||
public void HideAnimated() {
|
||||
Animate(1, 0, 200, null, new CubicEase());
|
||||
}
|
||||
|
||||
public Action<MW_Toast> ShouldDisposeAction;
|
||||
|
||||
private bool _isDisplay = false;
|
||||
public bool IsDisplay {
|
||||
get => _isDisplay;
|
||||
}
|
||||
|
||||
public MW_Toast(ToastType type, string text, Action<MW_Toast> shouldDisposeAction) {
|
||||
InitializeComponent();
|
||||
|
||||
tipIconDrawingImages = new DrawingImage[] {
|
||||
this.FindResource("ErrorIcon") as DrawingImage,
|
||||
this.FindResource("WarningIcon") as DrawingImage,
|
||||
this.FindResource("InfoIcon") as DrawingImage,
|
||||
this.FindResource("SuccessIcon") as DrawingImage,
|
||||
};
|
||||
|
||||
Type = type;
|
||||
ToastText = text;
|
||||
|
||||
ToastGrid.Opacity = 0;
|
||||
ShouldDisposeAction = shouldDisposeAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
#region Multi-Touch
|
||||
|
||||
private bool isInMultiTouchMode = false;
|
||||
|
||||
private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
if (isInMultiTouchMode) {
|
||||
inkCanvas.StylusDown -= MainWindow_StylusDown;
|
||||
inkCanvas.StylusMove -= MainWindow_StylusMove;
|
||||
inkCanvas.StylusUp -= MainWindow_StylusUp;
|
||||
inkCanvas.TouchDown -= MainWindow_TouchDown;
|
||||
inkCanvas.TouchDown += Main_Grid_TouchDown;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||
inkCanvas.Children.Clear();
|
||||
isInMultiTouchMode = false;
|
||||
} else {
|
||||
inkCanvas.StylusDown += MainWindow_StylusDown;
|
||||
inkCanvas.StylusMove += MainWindow_StylusMove;
|
||||
inkCanvas.StylusUp += MainWindow_StylusUp;
|
||||
inkCanvas.TouchDown += MainWindow_TouchDown;
|
||||
inkCanvas.TouchDown -= Main_Grid_TouchDown;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
inkCanvas.Children.Clear();
|
||||
isInMultiTouchMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void MainWindow_TouchDown(object sender, TouchEventArgs e) {
|
||||
if (!isCursorHidden && Settings.Gesture.HideCursorWhenUsingTouchDevice) {
|
||||
System.Windows.Forms.Cursor.Hide();
|
||||
isCursorHidden = true;
|
||||
}
|
||||
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint
|
||||
|| inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke
|
||||
|| inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
|
||||
|
||||
if (!isHidingSubPanelsWhenInking) {
|
||||
isHidingSubPanelsWhenInking = true;
|
||||
HideSubPanels(); // 书写时自动隐藏二级菜单
|
||||
}
|
||||
|
||||
// 不禁用手势橡皮
|
||||
if (!Settings.Gesture.DisableGestureEraser) {
|
||||
double boundWidth = e.GetTouchPoint(null).Bounds.Width;
|
||||
if ((Settings.Advanced.TouchMultiplier != 0 ||
|
||||
!Settings.Advanced.IsSpecialScreen) //启用特殊屏幕且触摸倍数为 0 时禁用橡皮
|
||||
&& (boundWidth > BoundsWidth)) {
|
||||
if (drawingShapeMode == 0 && forceEraser) return;
|
||||
double EraserThresholdValue = Settings.Startup.IsEnableNibMode
|
||||
? Settings.Advanced.NibModeBoundsWidthThresholdValue
|
||||
: Settings.Advanced.FingerModeBoundsWidthThresholdValue;
|
||||
if (boundWidth > BoundsWidth * EraserThresholdValue) {
|
||||
boundWidth *= (Settings.Startup.IsEnableNibMode
|
||||
? Settings.Advanced.NibModeBoundsWidthEraserSize
|
||||
: Settings.Advanced.FingerModeBoundsWidthEraserSize);
|
||||
if (Settings.Advanced.IsSpecialScreen) boundWidth *= Settings.Advanced.TouchMultiplier;
|
||||
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.EraseByPoint;
|
||||
eraserWidth = boundWidth;
|
||||
isEraserCircleShape = Settings.Canvas.EraserShapeType == 0;
|
||||
isUsingStrokesEraser = false;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
|
||||
} else {
|
||||
isUsingStrokesEraser = true;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
|
||||
}
|
||||
} else {
|
||||
inkCanvas.EraserShape =
|
||||
forcePointEraser ? new EllipseStylusShape(50, 50) : new EllipseStylusShape(5, 5);
|
||||
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MainWindow_StylusDown(object sender, StylusDownEventArgs e) {
|
||||
if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Touch) {
|
||||
if (!isCursorHidden && Settings.Gesture.HideCursorWhenUsingTouchDevice &&
|
||||
e.StylusDevice.TabletDevice.Type == TabletDeviceType.Touch) {
|
||||
System.Windows.Forms.Cursor.Hide();
|
||||
isCursorHidden = true;
|
||||
}
|
||||
|
||||
ViewboxFloatingBar.IsHitTestVisible = false;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = false;
|
||||
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint
|
||||
|| inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke
|
||||
|| inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
|
||||
|
||||
TouchDownPointsList[e.StylusDevice.Id] = InkCanvasEditingMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
private async void MainWindow_StylusUp(object sender, StylusEventArgs e) {
|
||||
if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Touch) {
|
||||
try {
|
||||
inkCanvas.Strokes.Add(GetStrokeVisual(e.StylusDevice.Id).Stroke);
|
||||
await Task.Delay(5); // 避免渲染墨迹完成前预览墨迹被删除导致墨迹闪烁
|
||||
inkCanvas.Children.Remove(GetVisualCanvas(e.StylusDevice.Id));
|
||||
inkCanvas_StrokeCollected(inkCanvas,
|
||||
new InkCanvasStrokeCollectedEventArgs(GetStrokeVisual(e.StylusDevice.Id).Stroke));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Label.Content = ex.ToString();
|
||||
}
|
||||
|
||||
try {
|
||||
StrokeVisualList.Remove(e.StylusDevice.Id);
|
||||
VisualCanvasList.Remove(e.StylusDevice.Id);
|
||||
TouchDownPointsList.Remove(e.StylusDevice.Id);
|
||||
if (StrokeVisualList.Count == 0 || VisualCanvasList.Count == 0 || TouchDownPointsList.Count == 0) {
|
||||
inkCanvas.Children.Clear();
|
||||
StrokeVisualList.Clear();
|
||||
VisualCanvasList.Clear();
|
||||
TouchDownPointsList.Clear();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
ViewboxFloatingBar.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void MainWindow_StylusMove(object sender, StylusEventArgs e) {
|
||||
if (!isCursorHidden && Settings.Gesture.HideCursorWhenUsingTouchDevice &&
|
||||
e.StylusDevice.TabletDevice.Type == TabletDeviceType.Touch) {
|
||||
System.Windows.Forms.Cursor.Hide();
|
||||
isCursorHidden = true;
|
||||
}
|
||||
|
||||
if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Touch) {
|
||||
try {
|
||||
if (GetTouchDownPointsList(e.StylusDevice.Id) != InkCanvasEditingMode.None) return;
|
||||
try {
|
||||
if (e.StylusDevice.StylusButtons[1].StylusButtonState == StylusButtonState.Down) return;
|
||||
}
|
||||
catch { }
|
||||
|
||||
var strokeVisual = GetStrokeVisual(e.StylusDevice.Id);
|
||||
var stylusPointCollection = e.GetStylusPoints(this);
|
||||
foreach (var stylusPoint in stylusPointCollection)
|
||||
strokeVisual.Add(new StylusPoint(stylusPoint.X, stylusPoint.Y, stylusPoint.PressureFactor));
|
||||
strokeVisual.Redraw();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private StrokeVisual GetStrokeVisual(int id) {
|
||||
if (StrokeVisualList.TryGetValue(id, out var visual)) return visual;
|
||||
|
||||
var strokeVisual = new StrokeVisual(inkCanvas.DefaultDrawingAttributes.Clone());
|
||||
StrokeVisualList[id] = strokeVisual;
|
||||
StrokeVisualList[id] = strokeVisual;
|
||||
var visualCanvas = new VisualCanvas(strokeVisual);
|
||||
VisualCanvasList[id] = visualCanvas;
|
||||
inkCanvas.Children.Add(visualCanvas);
|
||||
|
||||
return strokeVisual;
|
||||
}
|
||||
|
||||
private VisualCanvas GetVisualCanvas(int id) {
|
||||
return VisualCanvasList.TryGetValue(id, out var visualCanvas) ? visualCanvas : null;
|
||||
}
|
||||
|
||||
private InkCanvasEditingMode GetTouchDownPointsList(int id) {
|
||||
return TouchDownPointsList.TryGetValue(id, out var inkCanvasEditingMode)
|
||||
? inkCanvasEditingMode
|
||||
: inkCanvas.EditingMode;
|
||||
}
|
||||
|
||||
private Dictionary<int, InkCanvasEditingMode> TouchDownPointsList { get; } =
|
||||
new Dictionary<int, InkCanvasEditingMode>();
|
||||
|
||||
private Dictionary<int, StrokeVisual> StrokeVisualList { get; } = new Dictionary<int, StrokeVisual>();
|
||||
private Dictionary<int, VisualCanvas> VisualCanvasList { get; } = new Dictionary<int, VisualCanvas>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Touch Pointer Hide
|
||||
|
||||
public bool isCursorHidden = false;
|
||||
|
||||
private void MainWindow_OnMouseMove(object sender, MouseEventArgs e) {
|
||||
if (e.StylusDevice == null) {
|
||||
if (isCursorHidden) {
|
||||
System.Windows.Forms.Cursor.Show();
|
||||
isCursorHidden = false;
|
||||
}
|
||||
} else if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) {
|
||||
if (isCursorHidden) {
|
||||
System.Windows.Forms.Cursor.Show();
|
||||
isCursorHidden = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private int lastTouchDownTime = 0, lastTouchUpTime = 0;
|
||||
|
||||
private Point iniP = new Point(0, 0);
|
||||
private bool isLastTouchEraser = false;
|
||||
private bool forcePointEraser = true;
|
||||
|
||||
private void Main_Grid_TouchDown(object sender, TouchEventArgs e) {
|
||||
if (!isCursorHidden && Settings.Gesture.HideCursorWhenUsingTouchDevice) {
|
||||
System.Windows.Forms.Cursor.Hide();
|
||||
isCursorHidden = true;
|
||||
}
|
||||
|
||||
inkCanvas.CaptureTouch(e.TouchDevice);
|
||||
ViewboxFloatingBar.IsHitTestVisible = false;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = false;
|
||||
|
||||
if (!isHidingSubPanelsWhenInking) {
|
||||
isHidingSubPanelsWhenInking = true;
|
||||
HideSubPanels(); // 书写时自动隐藏二级菜单
|
||||
}
|
||||
|
||||
if (NeedUpdateIniP()) iniP = e.GetTouchPoint(inkCanvas).Position;
|
||||
if (drawingShapeMode == 9 && isFirstTouchCuboid == false) MouseTouchMove(iniP);
|
||||
inkCanvas.Opacity = 1;
|
||||
|
||||
if (!Settings.Gesture.DisableGestureEraser) {
|
||||
double boundsWidth = GetTouchBoundWidth(e);
|
||||
if ((Settings.Advanced.TouchMultiplier != 0 ||
|
||||
!Settings.Advanced.IsSpecialScreen) //启用特殊屏幕且触摸倍数为 0 时禁用橡皮
|
||||
&& (boundsWidth > BoundsWidth)) {
|
||||
isLastTouchEraser = true;
|
||||
if (drawingShapeMode == 0 && forceEraser) return;
|
||||
double EraserThresholdValue = Settings.Startup.IsEnableNibMode
|
||||
? Settings.Advanced.NibModeBoundsWidthThresholdValue
|
||||
: Settings.Advanced.FingerModeBoundsWidthThresholdValue;
|
||||
if (boundsWidth > BoundsWidth * EraserThresholdValue) {
|
||||
boundsWidth *= (Settings.Startup.IsEnableNibMode
|
||||
? Settings.Advanced.NibModeBoundsWidthEraserSize
|
||||
: Settings.Advanced.FingerModeBoundsWidthEraserSize);
|
||||
if (Settings.Advanced.IsSpecialScreen) boundsWidth *= Settings.Advanced.TouchMultiplier;
|
||||
eraserWidth = boundsWidth;
|
||||
isEraserCircleShape = Settings.Canvas.EraserShapeType == 0;
|
||||
isUsingStrokesEraser = false;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
|
||||
} else {
|
||||
isUsingStrokesEraser = true;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
|
||||
}
|
||||
} else {
|
||||
isLastTouchEraser = false;
|
||||
inkCanvas.EraserShape =
|
||||
forcePointEraser ? new EllipseStylusShape(50, 50) : new EllipseStylusShape(5, 5);
|
||||
if (forceEraser) return;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double GetTouchBoundWidth(TouchEventArgs e) {
|
||||
var args = e.GetTouchPoint(null).Bounds;
|
||||
if (!Settings.Advanced.IsQuadIR) return args.Width;
|
||||
else return Math.Sqrt(args.Width * args.Height); //四边红外
|
||||
}
|
||||
|
||||
//记录触摸设备ID
|
||||
private List<int> dec = new List<int>();
|
||||
|
||||
//中心点
|
||||
private Point centerPoint;
|
||||
private InkCanvasEditingMode lastInkCanvasEditingMode = InkCanvasEditingMode.Ink;
|
||||
private bool isSingleFingerDragMode = false;
|
||||
|
||||
private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) {
|
||||
inkCanvas.CaptureTouch(e.TouchDevice);
|
||||
ViewboxFloatingBar.IsHitTestVisible = false;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = false;
|
||||
|
||||
dec.Add(e.TouchDevice.Id);
|
||||
//设备1个的时候,记录中心点
|
||||
if (dec.Count == 1) {
|
||||
var touchPoint = e.GetTouchPoint(inkCanvas);
|
||||
centerPoint = touchPoint.Position;
|
||||
|
||||
//记录第一根手指点击时的 StrokeCollection
|
||||
lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone();
|
||||
}
|
||||
|
||||
//设备两个及两个以上,将画笔功能关闭
|
||||
if (dec.Count > 1 || isSingleFingerDragMode || !Settings.Gesture.IsEnableTwoFingerGesture) {
|
||||
if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return;
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.None ||
|
||||
inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
|
||||
lastInkCanvasEditingMode = inkCanvas.EditingMode;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
private void inkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) {
|
||||
inkCanvas.ReleaseAllTouchCaptures();
|
||||
ViewboxFloatingBar.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
|
||||
//手势完成后切回之前的状态
|
||||
if (dec.Count > 1)
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.None)
|
||||
inkCanvas.EditingMode = lastInkCanvasEditingMode;
|
||||
dec.Remove(e.TouchDevice.Id);
|
||||
inkCanvas.Opacity = 1;
|
||||
if (dec.Count == 0)
|
||||
if (lastTouchDownStrokeCollection.Count() != inkCanvas.Strokes.Count() &&
|
||||
!(drawingShapeMode == 9 && !isFirstTouchCuboid)) {
|
||||
var whiteboardIndex = CurrentWhiteboardIndex;
|
||||
if (currentMode == 0) whiteboardIndex = 0;
|
||||
strokeCollections[whiteboardIndex] = lastTouchDownStrokeCollection;
|
||||
}
|
||||
}
|
||||
|
||||
private void inkCanvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e) {
|
||||
e.Mode = ManipulationModes.All;
|
||||
}
|
||||
|
||||
private void inkCanvas_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e) { }
|
||||
|
||||
private void Main_Grid_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
|
||||
if (e.Manipulators.Count() != 0) return;
|
||||
if (forceEraser) return;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||
}
|
||||
|
||||
|
||||
//private void inkCanvas_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
|
||||
//{
|
||||
// if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture || inkCanvas.Strokes.Count == 0 || dec.Count() < 2) return;
|
||||
// _currentCommitType = CommitReason.Manipulation;
|
||||
// StrokeCollection strokes = inkCanvas.GetSelectedStrokes();
|
||||
// if (strokes.Count != 0)
|
||||
// {
|
||||
// inkCanvas.Strokes.Replace(strokes, strokes.Clone());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var originalStrokes = inkCanvas.Strokes;
|
||||
// var targetStrokes = originalStrokes.Clone();
|
||||
// originalStrokes.Replace(originalStrokes, targetStrokes);
|
||||
// }
|
||||
// _currentCommitType = CommitReason.UserInput;
|
||||
//}
|
||||
|
||||
private void Main_Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) {
|
||||
if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return;
|
||||
if ((dec.Count >= 2 && (Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode ||
|
||||
BorderFloatingBarExitPPTBtn.Visibility != Visibility.Visible)) ||
|
||||
isSingleFingerDragMode) {
|
||||
var md = e.DeltaManipulation;
|
||||
var trans = md.Translation; // 获得位移矢量
|
||||
|
||||
var m = new Matrix();
|
||||
|
||||
if (Settings.Gesture.IsEnableTwoFingerTranslate)
|
||||
m.Translate(trans.X, trans.Y); // 移动
|
||||
|
||||
if (Settings.Gesture.IsEnableTwoFingerGestureTranslateOrRotation) {
|
||||
var rotate = md.Rotation; // 获得旋转角度
|
||||
var scale = md.Scale; // 获得缩放倍数
|
||||
|
||||
// Find center of element and then transform to get current location of center
|
||||
var fe = e.Source as FrameworkElement;
|
||||
var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
|
||||
center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
|
||||
|
||||
if (Settings.Gesture.IsEnableTwoFingerRotation)
|
||||
m.RotateAt(rotate, center.X, center.Y); // 旋转
|
||||
if (Settings.Gesture.IsEnableTwoFingerZoom)
|
||||
m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
|
||||
}
|
||||
|
||||
var strokes = inkCanvas.GetSelectedStrokes();
|
||||
if (strokes.Count != 0) {
|
||||
foreach (var stroke in strokes) {
|
||||
stroke.Transform(m, false);
|
||||
|
||||
foreach (var circle in circles)
|
||||
if (stroke == circle.Stroke) {
|
||||
circle.R = GetDistance(circle.Stroke.StylusPoints[0].ToPoint(),
|
||||
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].ToPoint()) / 2;
|
||||
circle.Centroid = new Point(
|
||||
(circle.Stroke.StylusPoints[0].X +
|
||||
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].X) / 2,
|
||||
(circle.Stroke.StylusPoints[0].Y +
|
||||
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].Y) / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Settings.Gesture.IsEnableTwoFingerZoom) continue;
|
||||
try {
|
||||
stroke.DrawingAttributes.Width *= md.Scale.X;
|
||||
stroke.DrawingAttributes.Height *= md.Scale.Y;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
} else {
|
||||
if (Settings.Gesture.IsEnableTwoFingerZoom) {
|
||||
foreach (var stroke in inkCanvas.Strokes) {
|
||||
stroke.Transform(m, false);
|
||||
try {
|
||||
stroke.DrawingAttributes.Width *= md.Scale.X;
|
||||
stroke.DrawingAttributes.Height *= md.Scale.Y;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
;
|
||||
} else {
|
||||
foreach (var stroke in inkCanvas.Strokes) stroke.Transform(m, false);
|
||||
;
|
||||
}
|
||||
|
||||
foreach (var circle in circles) {
|
||||
circle.R = GetDistance(circle.Stroke.StylusPoints[0].ToPoint(),
|
||||
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].ToPoint()) / 2;
|
||||
circle.Centroid = new Point(
|
||||
(circle.Stroke.StylusPoints[0].X +
|
||||
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].X) / 2,
|
||||
(circle.Stroke.StylusPoints[0].Y +
|
||||
circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].Y) / 2
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using iNKORE.UI.WPF.Modern.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Forms.VisualStyles;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Animation;
|
||||
using Hardcodet.Wpf.TaskbarNotification;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
public partial class App : Application {
|
||||
|
||||
private void SysTrayMenu_Opened(object sender, RoutedEventArgs e) {
|
||||
var s = (ContextMenu)sender;
|
||||
var FoldFloatingBarTrayIconMenuItemIconEyeOff =
|
||||
(Image)((Grid)((MenuItem)s.Items[s.Items.Count-5]).Icon).Children[0];
|
||||
var FoldFloatingBarTrayIconMenuItemIconEyeOn =
|
||||
(Image)((Grid)((MenuItem)s.Items[s.Items.Count - 5]).Icon).Children[1];
|
||||
var FoldFloatingBarTrayIconMenuItemHeaderText =
|
||||
(TextBlock)((SimpleStackPanel)((MenuItem)s.Items[s.Items.Count - 5]).Header).Children[0];
|
||||
var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
|
||||
var HideICCMainWindowTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 9];
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded) {
|
||||
// 判斷是否在收納模式中
|
||||
if (mainWin.isFloatingBarFolded) {
|
||||
FoldFloatingBarTrayIconMenuItemIconEyeOff.Visibility = Visibility.Hidden;
|
||||
FoldFloatingBarTrayIconMenuItemIconEyeOn.Visibility = Visibility.Visible;
|
||||
FoldFloatingBarTrayIconMenuItemHeaderText.Text = "退出收纳模式";
|
||||
if (!HideICCMainWindowTrayIconMenuItem.IsChecked) {
|
||||
ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = false;
|
||||
ResetFloatingBarPositionTrayIconMenuItem.Opacity = 0.5;
|
||||
}
|
||||
} else {
|
||||
FoldFloatingBarTrayIconMenuItemIconEyeOff.Visibility = Visibility.Visible;
|
||||
FoldFloatingBarTrayIconMenuItemIconEyeOn.Visibility = Visibility.Hidden;
|
||||
FoldFloatingBarTrayIconMenuItemHeaderText.Text = "切换为收纳模式";
|
||||
if (!HideICCMainWindowTrayIconMenuItem.IsChecked) {
|
||||
ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = true;
|
||||
ResetFloatingBarPositionTrayIconMenuItem.Opacity = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded) mainWin.BtnExit_Click(null,null);
|
||||
}
|
||||
|
||||
private void RestartAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded) mainWin.BtnRestart_Click(null,null);
|
||||
}
|
||||
|
||||
private void ForceFullScreenTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded) {
|
||||
Ink_Canvas.MainWindow.MoveWindow(new WindowInteropHelper(mainWin).Handle, 0, 0,
|
||||
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, true);
|
||||
Ink_Canvas.MainWindow.ShowNewMessage($"已强制全屏化:{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}(缩放比例为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight})");
|
||||
}
|
||||
}
|
||||
|
||||
private void FoldFloatingBarTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded)
|
||||
if (mainWin.isFloatingBarFolded) mainWin.UnFoldFloatingBar_MouseUp(new object(),null);
|
||||
else mainWin.FoldFloatingBar_MouseUp(new object(),null);
|
||||
}
|
||||
|
||||
private void ResetFloatingBarPositionTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded) {
|
||||
var isInPPTPresentationMode = false;
|
||||
Dispatcher.Invoke(() => {
|
||||
isInPPTPresentationMode = mainWin.BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible;
|
||||
});
|
||||
if (!mainWin.isFloatingBarFolded) {
|
||||
if (!isInPPTPresentationMode) mainWin.PureViewboxFloatingBarMarginAnimationInDesktopMode();
|
||||
else mainWin.PureViewboxFloatingBarMarginAnimationInPPTMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HideICCMainWindowTrayIconMenuItem_Checked(object sender, RoutedEventArgs e) {
|
||||
var mi = (MenuItem)sender;
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded) {
|
||||
mainWin.Hide();
|
||||
var s = ((TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"]).ContextMenu;
|
||||
var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
|
||||
var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5];
|
||||
var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6];
|
||||
ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = false;
|
||||
FoldFloatingBarTrayIconMenuItem.IsEnabled = false;
|
||||
ForceFullScreenTrayIconMenuItem.IsEnabled = false;
|
||||
ResetFloatingBarPositionTrayIconMenuItem.Opacity = 0.5;
|
||||
FoldFloatingBarTrayIconMenuItem.Opacity = 0.5;
|
||||
ForceFullScreenTrayIconMenuItem.Opacity = 0.5;
|
||||
} else {
|
||||
mi.IsChecked = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void HideICCMainWindowTrayIconMenuItem_UnChecked(object sender, RoutedEventArgs e) {
|
||||
var mi = (MenuItem)sender;
|
||||
var mainWin = (MainWindow)Application.Current.MainWindow;
|
||||
if (mainWin.IsLoaded) {
|
||||
mainWin.Show();
|
||||
var s = ((TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"]).ContextMenu;
|
||||
var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
|
||||
var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5];
|
||||
var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6];
|
||||
ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = true;
|
||||
FoldFloatingBarTrayIconMenuItem.IsEnabled = true;
|
||||
ForceFullScreenTrayIconMenuItem.IsEnabled = true;
|
||||
ResetFloatingBarPositionTrayIconMenuItem.Opacity = 1;
|
||||
FoldFloatingBarTrayIconMenuItem.Opacity = 1;
|
||||
ForceFullScreenTrayIconMenuItem.Opacity = 1;
|
||||
} else {
|
||||
mi.IsChecked = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Ink_Canvas {
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
public FloatingToolBarV2 FloatingToolBarV2;
|
||||
|
||||
private void InitFloatingToolbarV2() {
|
||||
FloatingToolBarV2 = new FloatingToolBarV2();
|
||||
FloatingToolBarV2.Topmost = false;
|
||||
FloatingToolBarV2.Show();
|
||||
FloatingToolBarV2.Owner = this;
|
||||
|
||||
FloatingToolBarV2.FloatingBarToolSelectionChanged += FloatingToolBarV2_ToolSelectionChanged;
|
||||
FloatingToolBarV2.FloatingBarToolButtonClicked += FloatingToolBarV2_ToolButtonClicked;
|
||||
}
|
||||
|
||||
#region 工具切换
|
||||
|
||||
private void SwitchToCursorMode() {
|
||||
// 结束未完成的形状绘制
|
||||
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
|
||||
|
||||
// 切换前自动截图保存墨迹
|
||||
if (inkCanvas.Strokes.Count > 0 &&
|
||||
inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) {
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible) SavePPTScreenshot($"{pptName}/{previousSlideID}_{DateTime.Now:HH-mm-ss}");
|
||||
else SaveScreenshot(true);
|
||||
}
|
||||
|
||||
|
||||
inkCanvas.Visibility = Settings.Canvas.HideStrokeWhenSelecting ? Visibility.Collapsed : Visibility.Visible;
|
||||
inkCanvas.IsHitTestVisible = false;
|
||||
SetTransparentHitThrough();
|
||||
|
||||
GridBackgroundCoverHolder.Visibility = Visibility.Collapsed;
|
||||
inkCanvas.Select(new StrokeCollection());
|
||||
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
|
||||
|
||||
RectangleSelectionHitTestBorder.Visibility = Visibility.Collapsed;
|
||||
|
||||
if (currentMode != 0) {
|
||||
SaveStrokes();
|
||||
RestoreStrokes(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SwitchToPenMode() {
|
||||
// 结束未完成的形状绘制
|
||||
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
|
||||
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||
|
||||
SetTransparentNotHitThrough();
|
||||
inkCanvas.IsHitTestVisible = true;
|
||||
inkCanvas.Visibility = Visibility.Visible;
|
||||
|
||||
GridBackgroundCoverHolder.Visibility = Visibility.Visible;
|
||||
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
|
||||
|
||||
ColorSwitchCheck();
|
||||
}
|
||||
|
||||
private void ClearInkCanvasStrokes(bool isClearTimeMachineHistory, bool isErasedByCode) {
|
||||
if (inkCanvas.GetSelectedStrokes().Count > 0) {
|
||||
inkCanvas.Strokes.Remove(inkCanvas.GetSelectedStrokes());
|
||||
// cancel
|
||||
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
|
||||
inkCanvas.Opacity = 1;
|
||||
InkSelectionStrokesOverlay.Visibility = Visibility.Collapsed;
|
||||
InkSelectionStrokesBackgroundInkCanvas.Visibility = Visibility.Collapsed;
|
||||
InkSelectionStrokesOverlay.DrawStrokes(new StrokeCollection(), new Matrix());
|
||||
UpdateStrokeSelectionBorder(false, null);
|
||||
RectangleSelectionHitTestBorder.Visibility = Visibility.Visible;
|
||||
} else if (inkCanvas.Strokes.Count > 0) {
|
||||
if (Settings.Automation.IsAutoSaveStrokesAtClear &&
|
||||
inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) {
|
||||
if (BorderFloatingBarExitPPTBtn.Visibility == Visibility.Visible)
|
||||
SavePPTScreenshot($"{pptName}/{previousSlideID}_{DateTime.Now:HH-mm-ss}");
|
||||
else
|
||||
SaveScreenshot(true);
|
||||
}
|
||||
|
||||
forceEraser = false;
|
||||
|
||||
if (currentMode == 0) {
|
||||
// 先回到画笔再清屏,避免 TimeMachine 的相关 bug 影响
|
||||
if (Pen_Icon.Background == null && StackPanelCanvasControls.Visibility == Visibility.Visible) SwitchToPenMode();
|
||||
} else if (Pen_Icon.Background == null) SwitchToPenMode();
|
||||
|
||||
if (inkCanvas.Strokes.Count != 0) {
|
||||
var whiteboardIndex = CurrentWhiteboardIndex;
|
||||
if (currentMode == 0) whiteboardIndex = 0;
|
||||
strokeCollections[whiteboardIndex] = inkCanvas.Strokes.Clone();
|
||||
}
|
||||
|
||||
ClearStrokes(false);
|
||||
inkCanvas.Children.Clear();
|
||||
|
||||
CancelSingleFingerDragMode();
|
||||
|
||||
if (isClearTimeMachineHistory) {
|
||||
inkCanvas.Strokes.Clear();
|
||||
timeMachine.ClearStrokeHistory();
|
||||
} else {
|
||||
_currentCommitType = CommitReason.ClearingCanvas;
|
||||
if (isErasedByCode) _currentCommitType = CommitReason.CodeInput;
|
||||
inkCanvas.Strokes.Clear();
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void FloatingToolBarV2_ToolSelectionChanged(object sender, EventArgs e) {
|
||||
var item = (FloatingBarItem)sender;
|
||||
if (item.ToolType == ICCToolsEnum.CursorMode) SwitchToCursorMode();
|
||||
if (item.ToolType == ICCToolsEnum.PenMode) SwitchToPenMode();
|
||||
}
|
||||
|
||||
private void FloatingToolBarV2_ToolButtonClicked(object sender, EventArgs e) {
|
||||
var item = (FloatingBarItem)sender;
|
||||
if (item.Name == "Clear") ClearInkCanvasStrokes(Settings.Canvas.ClearCanvasAndClearTimeMachine,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
public partial class MainWindow : PerformanceTransparentWin {
|
||||
|
||||
private bool _stylusInverted = false;
|
||||
private int _stylusInvertedInit = 0;
|
||||
|
||||
private bool IsStylusInverted {
|
||||
get => _stylusInverted;
|
||||
set {
|
||||
if (value && !_stylusInverted) {
|
||||
StylusInverted?.Invoke(this,new RoutedEventArgs());
|
||||
} else if (!value && _stylusInverted) {
|
||||
StylusUnInverted?.Invoke(this,new RoutedEventArgs());
|
||||
}
|
||||
_stylusInverted = value;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<RoutedEventArgs> StylusInverted;
|
||||
public event EventHandler<RoutedEventArgs> StylusUnInverted;
|
||||
|
||||
public void UpdateStylusPenInvertedStatus(bool isInverted) {
|
||||
if (_stylusInvertedInit == 0) {
|
||||
_stylusInverted = isInverted;
|
||||
_stylusInvertedInit = 1;
|
||||
} else {
|
||||
IsStylusInverted = isInverted;
|
||||
}
|
||||
}
|
||||
|
||||
#region 托管StylusInAirMove和StylusMove事件
|
||||
|
||||
public void mainWin_StylusInAirMove(object sender, StylusEventArgs e) {
|
||||
UpdateStylusPenInvertedStatus(e.Inverted);
|
||||
}
|
||||
|
||||
public void mainWin_StylusMove(object sender, StylusEventArgs e) {
|
||||
UpdateStylusPenInvertedStatus(e.Inverted);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Windows Ink 橡皮按钮自定义适配
|
||||
|
||||
public void StylusInvertedListenerInit() {
|
||||
StylusInverted += StylusInvertedEvent;
|
||||
StylusUnInverted += StylusUnInvertedEvent;
|
||||
}
|
||||
|
||||
private void StylusInvertedEvent(object sender, RoutedEventArgs e) {
|
||||
if (Settings.Gesture.WindowsInkEraserButtonAction != 0) {
|
||||
if (SelectedMode != ICCToolsEnum.EraseByGeometryMode &&
|
||||
SelectedMode != ICCToolsEnum.EraseByStrokeMode) {
|
||||
GridEraserOverlay.Visibility = Visibility.Visible;
|
||||
isUsingStrokesEraser = Settings.Gesture.WindowsInkEraserButtonAction == 1;
|
||||
} else if (SelectedMode == (Settings.Gesture.WindowsInkEraserButtonAction == 2
|
||||
? ICCToolsEnum.EraseByStrokeMode
|
||||
: ICCToolsEnum.EraseByGeometryMode)) {
|
||||
isUsingStrokesEraser = Settings.Gesture.WindowsInkEraserButtonAction == 1;
|
||||
}
|
||||
ForceUpdateToolSelection((Settings.Gesture.WindowsInkEraserButtonAction == 2
|
||||
? ICCToolsEnum.EraseByGeometryMode
|
||||
: ICCToolsEnum.EraseByStrokeMode));
|
||||
}
|
||||
}
|
||||
|
||||
private void StylusUnInvertedEvent(object sender, RoutedEventArgs e) {
|
||||
if (Settings.Gesture.WindowsInkEraserButtonAction != 0) {
|
||||
if (SelectedMode != ICCToolsEnum.EraseByGeometryMode &&
|
||||
SelectedMode != ICCToolsEnum.EraseByStrokeMode) {
|
||||
GridEraserOverlay.Visibility = Visibility.Collapsed;
|
||||
} else if (SelectedMode == (Settings.Gesture.WindowsInkEraserButtonAction == 2
|
||||
? ICCToolsEnum.EraseByStrokeMode
|
||||
: ICCToolsEnum.EraseByGeometryMode)) {
|
||||
isUsingStrokesEraser = Settings.Gesture.WindowsInkEraserButtonAction == 2;
|
||||
}
|
||||
}
|
||||
ForceUpdateToolSelection(null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Windows Ink 筒形按钮自定义适配
|
||||
|
||||
private void mainWin_StylusButtonUp(object sender, StylusButtonEventArgs e) {
|
||||
if (e.StylusButton.Guid == StylusPointProperties.BarrelButton.Id) {
|
||||
if (Settings.Gesture.WindowsInkBarrelButtonAction == 0) return;
|
||||
if (Settings.Gesture.WindowsInkBarrelButtonAction == 1) SelectIcon_MouseUp(null,null);
|
||||
else if (Settings.Gesture.WindowsInkBarrelButtonAction == 2) {
|
||||
SymbolIconSelect_MouseUp(null,null);
|
||||
inkCanvas.Select(inkCanvas.Strokes);
|
||||
}
|
||||
else if (Settings.Gesture.WindowsInkBarrelButtonAction == 3) SymbolIconUndo_MouseUp(null,null);
|
||||
}
|
||||
}
|
||||
|
||||
private void mainWin_StylusButtonDown(object sender, StylusButtonEventArgs e) {
|
||||
if (e.StylusButton.Guid == StylusPointProperties.BarrelButton.Id) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user