XFEstudio/MyFirstRespo
修复部分已知问题,新增折叠块消息
d04590d
代码差异
11 个文件
+174
-222
@@ -28,7 +28,7 @@ public partial class App : Application
28
28
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
29
29
{
30
30
// 处理 UI 线程未处理的异常
31
MessageBox.Show("UI线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
31
//MessageBox.Show("UI线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
32
32
e.Handled = true; // 设置为 true 表示异常已处理,防止应用程序退出
33
33
}
34
34
@@ -42,7 +42,7 @@ public partial class App : Application
42
42
void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
43
43
{
44
44
// 处理任务调度程序未观察到的任务异常
45
MessageBox.Show("非主线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
45
//MessageBox.Show("非主线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
46
46
e.SetObserved(); // 防止程序崩溃
47
47
}
48
48
}
@@ -295,7 +295,7 @@
295
295
<Setter Property="Template">
296
296
<Setter.Value>
297
297
<ControlTemplate TargetType="Button">
298
<Grid>
298
<Grid x:Name="grid">
299
299
<Border x:Name="border" CornerRadius="5" Background="White" Opacity="0.1">
300
300
</Border>
301
301
<ContentPresenter Margin="5,3"/>
@@ -315,17 +315,43 @@
315
315
</Storyboard>
316
316
</BeginStoryboard>
317
317
</EventTrigger>
318
<EventTrigger RoutedEvent="MouseLeftButtonDown">
318
<EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="grid">
319
319
<BeginStoryboard>
320
320
<Storyboard>
321
321
<DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.1"/>
322
322
</Storyboard>
323
323
</BeginStoryboard>
324
324
</EventTrigger>
325
<EventTrigger RoutedEvent="MouseLeftButtonUp">
325
</ControlTemplate.Triggers>
326
</ControlTemplate>
327
</Setter.Value>
328
</Setter>
329
</Style.Setters>
330
<Style.Triggers>
331
<Trigger Property="IsEnabled" Value="False">
332
<Setter Property="Opacity" Value="0.5"/>
333
</Trigger>
334
</Style.Triggers>
335
</Style>
336
<Style x:Key="FoldButton" TargetType="Button">
337
<Style.Setters>
338
<Setter Property="Opacity" Value="1"/>
339
<Setter Property="Template">
340
<Setter.Value>
341
<ControlTemplate TargetType="Button">
342
<ContentPresenter x:Name="content" Margin="5,3"/>
343
<ControlTemplate.Triggers>
344
<EventTrigger RoutedEvent="MouseEnter">
326
345
<BeginStoryboard>
327
346
<Storyboard>
328
<DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:0.1"/>
347
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.8" Duration="0:0:0.1"/>
348
</Storyboard>
349
</BeginStoryboard>
350
</EventTrigger>
351
<EventTrigger RoutedEvent="MouseLeave">
352
<BeginStoryboard>
353
<Storyboard>
354
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.8" Duration="0:0:0.1"/>
329
355
</Storyboard>
330
356
</BeginStoryboard>
331
357
</EventTrigger>
@@ -2,28 +2,9 @@
2
2
3
3
namespace XFEToolBox.Utilities;
4
4
5
public class DecTextSpan
5
public class DecTextSpan(string text, Color color, Color backgroundColor)
6
6
{
7
public bool IsHyperLink { get; set; }
8
public string Text { get; set; }
9
public string? Link { get; set; }
10
public Color Color { get; set; }
11
public Color BackgroundColor { get; set; }
12
13
public DecTextSpan(string text, Color color, Color backgroundColor)
14
{
15
IsHyperLink = false;
16
Text = text;
17
Color = color;
18
BackgroundColor = backgroundColor;
19
}
20
21
public DecTextSpan(string text, string link, Color color, Color backgroundColor)
22
{
23
IsHyperLink= true;
24
Text = text;
25
Link = link;
26
Color = color;
27
BackgroundColor = backgroundColor;
28
}
7
public string Text { get; set; } = text;
8
public Color Color { get; set; } = color;
9
public Color BackgroundColor { get; set; } = backgroundColor;
29
10
}
@@ -1,5 +1,6 @@
1
1
using System.Diagnostics;
2
2
using System.Text.RegularExpressions;
3
using System.Windows;
3
4
using System.Windows.Controls;
4
5
using System.Windows.Documents;
5
6
using System.Windows.Media;
@@ -8,31 +9,37 @@ namespace XFEToolBox.Utilities;
8
9
9
10
public partial class DecoratedTextConverter
10
11
{
11
[GeneratedRegex(@"\[(?:(?:(?<type>color)\s+(?<color>\#[0-9a-fA-F]{6}|\w+)(?:\s+(?<background>\#[0-9a-fA-F]{6}|\w+))?)|(?:(?<type>hyperlink)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)(?<background>\s+\#[0-9a-fA-F]{6}|\w+)?(?:\s+))?link:\s*(?<link>.+)\s+text:\s*(?<text>.+)))\]")]
12
[GeneratedRegex(@"\[(?:(?:(?<type>color)\s+(?<color>\#[0-9a-fA-F]{6}|\w+)(?:\s+(?<background>\#[0-9a-fA-F]{6}|\w+))?)|(?:(?<type>hyperlink)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)(?<background>\s+\#[0-9a-fA-F]{6}|\w+)?(?:\s+))?link:\s*(?<link>.+)\s+text:\s*(?<text>.+))|(?:(?<type>foldblock)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)\s+(?<background>\#[0-9a-fA-F]{6}|\w+))\s+title:\s*(?<title>.+)\s+text:\s*(?<text>(?s).+)))\]")]
12
13
public static partial Regex DecorationRegex();
13
14
14
15
public static TextBlock ConvertToTextBlock(string decoratedText, Color defaultColor)
15
16
{
16
17
var results = ConvertToInlineList(decoratedText, defaultColor);
17
18
var textBlock = new TextBlock();
18
textBlock.Inlines.AddRange(results);
19
foreach (var result in results)
20
{
21
if (result is Inline inline)
22
textBlock.Inlines.Add(inline);
23
else
24
textBlock.Inlines.Add((UIElement)result);
25
}
19
26
return textBlock;
20
27
}
21
public static List<Inline> ConvertToInlineList(string decoratedText, Color defaultColor)
28
public static List<object> ConvertToInlineList(string decoratedText, Color defaultColor)
22
29
{
23
30
var results = ConvertText(decoratedText, defaultColor);
24
var inLineList = new List<Inline>();
31
var inLineList = new List<object>();
25
32
if (results.Count > 0)
26
33
{
27
34
foreach (var result in results)
28
35
{
29
if (result.IsHyperLink)
36
if (result is HyperLinkDecSpan hyperLinkDecSpan)
30
37
{
31
var hyperLink = new Hyperlink(new Run(result.Text))
38
var hyperLink = new Hyperlink(new Run(hyperLinkDecSpan.Text))
32
39
{
33
Foreground = new SolidColorBrush(result.Color),
34
NavigateUri = new Uri(result.Link!),
35
Background = new SolidColorBrush(result.BackgroundColor)
40
Foreground = new SolidColorBrush(hyperLinkDecSpan.Color),
41
NavigateUri = new Uri(hyperLinkDecSpan.Link),
42
Background = new SolidColorBrush(hyperLinkDecSpan.BackgroundColor)
36
43
};
37
44
hyperLink.RequestNavigate += (sender, e) =>
38
45
{
@@ -40,6 +47,100 @@ public partial class DecoratedTextConverter
40
47
};
41
48
inLineList.Add(hyperLink);
42
49
}
50
else if (result is FoldBlockDecSpan foldBlockDecSpan)
51
{
52
var foldGrid = new Grid
53
{
54
Margin = new Thickness(3)
55
};
56
foldGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new(220) });
57
foldGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new(20) });
58
foldGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new(1, GridUnitType.Star) });
59
foldGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
60
foldGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
61
var titleTextBlock = new TextBlock
62
{
63
Margin = new Thickness(5, 2, 5, 2),
64
Text = foldBlockDecSpan.Title,
65
TextTrimming = TextTrimming.CharacterEllipsis,
66
Foreground = new SolidColorBrush(foldBlockDecSpan.Color),
67
VerticalAlignment = VerticalAlignment.Center,
68
HorizontalAlignment = HorizontalAlignment.Center
69
};
70
var titleBorder = new Border
71
{
72
Background = new SolidColorBrush(foldBlockDecSpan.BackgroundColor),
73
CornerRadius = new CornerRadius(5, 0, 0, 5),
74
Child = titleTextBlock
75
};
76
foldGrid.Children.Add(titleBorder);
77
var buttonText = new TextBlock
78
{
79
Foreground = new SolidColorBrush(foldBlockDecSpan.BackgroundColor),
80
Background = new SolidColorBrush(foldBlockDecSpan.Color),
81
Text = "▼",
82
FontSize = 18
83
};
84
var button = new Button
85
{
86
Style = (Style)Application.Current.FindResource("FoldButton"),
87
Background = new SolidColorBrush(foldBlockDecSpan.Color),
88
Content = buttonText
89
};
90
var foldButtonBorder = new Border
91
{
92
Background = new SolidColorBrush(foldBlockDecSpan.Color),
93
CornerRadius = new CornerRadius(0, 5, 5, 0),
94
Child = button
95
};
96
Grid.SetColumn(foldButtonBorder, 1);
97
foldGrid.Children.Add(foldButtonBorder);
98
var contentTextBlock = new TextBlock
99
{
100
TextWrapping = TextWrapping.Wrap,
101
Foreground = new SolidColorBrush(foldBlockDecSpan.Color),
102
};
103
if (foldBlockDecSpan.DecTextList.Count > 0)
104
contentTextBlock.Inlines.AddRange(foldBlockDecSpan.DecTextList.Select(x => new Span(new Run(x.Text))
105
{
106
Foreground = new SolidColorBrush(x.Color),
107
Background = new SolidColorBrush(x.BackgroundColor)
108
}));
109
else
110
contentTextBlock.Text = foldBlockDecSpan.Text;
111
var contentBorder = new Border
112
{
113
Visibility = Visibility.Collapsed,
114
CornerRadius = new CornerRadius(0, 5, 5, 5),
115
Background = Brushes.Transparent,
116
BorderBrush = new SolidColorBrush(foldBlockDecSpan.BackgroundColor),
117
BorderThickness = new Thickness(3),
118
Padding = new Thickness(3),
119
Child = contentTextBlock
120
};
121
button.Click += (sender, e) =>
122
{
123
if (contentBorder.Visibility == Visibility.Visible)
124
{
125
contentBorder.Visibility = Visibility.Collapsed;
126
titleBorder.CornerRadius = new(5, 0, 0, 5);
127
buttonText.Text = "▼";
128
}
129
else
130
{
131
contentBorder.Visibility = Visibility.Visible;
132
titleBorder.CornerRadius = new(5, 0, 0, 0);
133
buttonText.Text = "▲";
134
}
135
};
136
Grid.SetColumnSpan(contentBorder, 3);
137
Grid.SetRow(contentBorder, 1);
138
Grid.SetRow(contentBorder, 1);
139
Grid.SetColumnSpan(contentBorder, 3);
140
foldGrid.Children.Add(contentBorder);
141
inLineList.Add(new Span(new Run("\n")));
142
inLineList.Add(foldGrid);
143
}
43
144
else
44
145
{
45
146
inLineList.Add(new Span(new Run(result.Text))
@@ -75,6 +176,7 @@ public partial class DecoratedTextConverter
75
176
Color backgroundColor = (Color)ColorConverter.ConvertFromString(backgroundColorText);
76
177
var link = match.Groups["link"].Value;
77
178
var text = match.Groups["text"].Value;
179
var title = match.Groups["title"].Value;
78
180
var unMatchString = "";
79
181
if (i == 0 && match.Index != 0)
80
182
{
@@ -97,7 +199,11 @@ public partial class DecoratedTextConverter
97
199
continue;
98
200
case "hyperlink":
99
201
var color = ColorConverter.ConvertFromString(colorText);
100
textSpanList.Add(new(text, link, color is null ? defaultColor : (Color)color, backgroundColor));
202
textSpanList.Add(new HyperLinkDecSpan(text, link, color is null ? defaultColor : (Color)color, backgroundColor));
203
textSpanList.Add(new(unMatchString, defaultColor, Colors.Transparent));
204
continue;
205
case "foldblock":
206
textSpanList.Add(new FoldBlockDecSpan(text, title, ConvertText(text, defaultColor), (Color)ColorConverter.ConvertFromString(colorText), backgroundColor));
101
207
textSpanList.Add(new(unMatchString, defaultColor, Colors.Transparent));
102
208
continue;
103
209
default:
@@ -0,0 +1,9 @@
1
using System.Windows.Media;
2
3
namespace XFEToolBox.Utilities;
4
5
public class FoldBlockDecSpan(string text, string title, List<DecTextSpan> decTextList, Color color, Color backgroundColor) : DecTextSpan(text, color, backgroundColor)
6
{
7
public string Title { get; set; } = title;
8
public List<DecTextSpan> DecTextList { get; set; } = decTextList;
9
}
@@ -0,0 +1,8 @@
1
using System.Windows.Media;
2
3
namespace XFEToolBox.Utilities;
4
5
public class HyperLinkDecSpan(string text, string link, Color color, Color backgroundColor) : DecTextSpan(text, color, backgroundColor)
6
{
7
public string Link { get; set; } = link;
8
}
@@ -1,30 +0,0 @@
1
using XFEExtension.NetCore.CyberComm;
2
3
namespace XFEExtension.NetCore.XFEConsole;
4
5
/// <summary>
6
/// XFE控制台客户端信息
7
/// </summary>
8
/// <param name="clientName">客户端名称</param>
9
/// <param name="clientUUID">客户端唯一标识符</param>
10
/// <param name="password">客户端连接时密码</param>
11
/// <param name="eventArgs">事件参数</param>
12
public class XFEConsoleClientInfo(string clientName, string clientUUID, string password, CyberCommServerEventArgs eventArgs)
13
{
14
/// <summary>
15
/// 客户端名称
16
/// </summary>
17
public string ClientName { get; set; } = clientName;
18
/// <summary>
19
/// 客户端唯一标识符
20
/// </summary>
21
public string ClientUUID { get; set; } = clientUUID;
22
/// <summary>
23
/// 客户端密码
24
/// </summary>
25
public string Password { get; set; } = password;
26
/// <summary>
27
/// 事件参数
28
/// </summary>
29
public CyberCommServerEventArgs EventArgs { get; set; } = eventArgs;
30
}
@@ -1,149 +0,0 @@
1
using System.Net.WebSockets;
2
using XFEExtension.NetCore.CyberComm;
3
using XFEExtension.NetCore.DelegateExtension;
4
5
namespace XFEExtension.NetCore.XFEConsole;
6
7
/// <summary>
8
/// XFE控制台终端服务器
9
/// </summary>
10
public class XFEConsoleTerminalServer
11
{
12
/// <summary>
13
/// 服务器
14
/// </summary>
15
public CyberCommServer Server { get; set; }
16
/// <summary>
17
/// 密码
18
/// </summary>
19
public string Password { get; set; }
20
/// <summary>
21
/// Socket客户端-客户端信息字典
22
/// </summary>
23
public Dictionary<WebSocket, XFEConsoleClientInfo> ClientInfoDictionary { get; set; } = [];
24
/// <summary>
25
/// 客户端连接事件
26
/// </summary>
27
public event XFEEventHandler<XFEConsoleTerminalServer, XFEConsoleClientInfo>? Connected;
28
/// <summary>
29
/// 客户端断开连接事件
30
/// </summary>
31
public event XFEEventHandler<XFEConsoleTerminalServer, XFEConsoleClientInfo>? Disconnected;
32
/// <summary>
33
/// 接收到客户端消息触发
34
/// </summary>
35
public event XFEEventHandler<XFEConsoleClientInfo, string>? MessageReceived;
36
/// <summary>
37
/// 发生错误
38
/// </summary>
39
public event XFEEventHandler<XFEConsoleClientInfo, Exception>? ErrorOccurred;
40
/// <summary>
41
/// 服务器启动事件
42
/// </summary>
43
public event XFEEventHandler<XFEConsoleTerminalServer>? ServerStarted;
44
/// <summary>
45
/// XFE控制台终端服务器
46
/// </summary>
47
/// <param name="port">端口号</param>
48
/// <param name="localOnly">是否只在本地开启</param>
49
/// <param name="password">密码(默认为空)</param>
50
public XFEConsoleTerminalServer(int port, bool localOnly = true, string password = "")
51
{
52
Password = password;
53
if (localOnly)
54
Server = new CyberCommServer($"http://localhost:{port}/");
55
else
56
Server = new CyberCommServer(port);
57
Server.ServerStarted += Server_ServerStarted;
58
Server.ClientConnected += Server_ClientConnected;
59
Server.ConnectionClosed += Server_ConnectionClosed;
60
Server.MessageReceived += Server_MessageReceived;
61
}
62
/// <summary>
63
/// XFE控制台终端服务器
64
/// </summary>
65
/// <param name="ipAddress">IP地址</param>
66
/// <param name="password">密码(默认为空)</param>
67
public XFEConsoleTerminalServer(string[] ipAddress, string password = "")
68
{
69
Password = password;
70
Server = new CyberCommServer(ipAddress);
71
Server.ServerStarted += Server_ServerStarted;
72
Server.ClientConnected += Server_ClientConnected;
73
Server.ConnectionClosed += Server_ConnectionClosed;
74
Server.MessageReceived += Server_MessageReceived;
75
}
76
77
private void Server_MessageReceived(object? sender, CyberCommServerEventArgs e)
78
{
79
switch (e.MessageType)
80
{
81
case BackMessageType.Text:
82
MessageReceived?.Invoke(ClientInfoDictionary[e.CurrentWebSocket], e.TextMessage!);
83
break;
84
case BackMessageType.Binary:
85
break;
86
case BackMessageType.Error:
87
ErrorOccurred?.Invoke(ClientInfoDictionary[e.CurrentWebSocket], e.Exception!);
88
break;
89
default:
90
break;
91
}
92
}
93
94
private void Server_ConnectionClosed(object? sender, CyberCommServerEventArgs e)
95
{
96
if (ClientInfoDictionary.TryGetValue(e.CurrentWebSocket, out XFEConsoleClientInfo? clientInfo))
97
{
98
ClientInfoDictionary.Remove(e.CurrentWebSocket);
99
Disconnected?.Invoke(this, clientInfo);
100
}
101
}
102
103
private async void Server_ClientConnected(object? sender, CyberCommServerEventArgs e)
104
{
105
try
106
{
107
if (e.WSHeader["ClientName"] is not null && e.WSHeader["ClientID"] is not null && e.WSHeader["Password"] is not null)
108
{
109
var password = e.WSHeader["Password"]!;
110
var clientName = e.WSHeader["ClientName"]!;
111
var clientUUID = e.WSHeader["ClientID"]!;
112
if (password == Password)
113
{
114
var clientInfo = new XFEConsoleClientInfo(clientName, clientUUID, password, e);
115
ClientInfoDictionary.Add(e.CurrentWebSocket, clientInfo);
116
Connected?.Invoke(this, clientInfo);
117
}
118
return;
119
}
120
}
121
catch { }
122
try
123
{
124
await e.Close();
125
}
126
catch
127
{
128
try
129
{
130
e.ForceClose();
131
}
132
catch { }
133
}
134
}
135
136
private void Server_ServerStarted(object? sender, EventArgs e)
137
{
138
ClientInfoDictionary = [];
139
ServerStarted?.Invoke(this);
140
}
141
/// <summary>
142
/// 启动服务器
143
/// </summary>
144
/// <returns></returns>
145
public async Task StartServer()
146
{
147
await Server.StartCyberCommServer();
148
}
149
}
@@ -52,7 +52,7 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
52
52
{
53
53
var code = e.InnerException?.InnerException is HttpListenerException ? (e.InnerException.InnerException as HttpListenerException)!.ErrorCode : 0;
54
54
if (code != 995)
55
ShowMessageWithTimeLine($"[color Red]发生错误:{e.Message}");
55
ShowMessageWithTimeLine($"[foldblock color: white #ff0000 title: 错误:{e.Message} text: {e}]");
56
56
}
57
57
58
58
private void TerminalServer_MessageReceived(XFEConsoleClientInfo sender, string e)
@@ -8,9 +8,9 @@
8
8
xmlns:local="clr-namespace:XFEToolBox.Views.Windows"
9
9
mc:Ignorable="d"
10
10
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel}"
11
Title="XFE工具箱" Height="450" Width="720" MinHeight="450" MinWidth="720" Background="Transparent" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Icon="/Resources/Icon/XFEToolBoxIcon.ico" Loaded="Window_Loaded">
11
Title="XFE工具箱" Height="460" Width="730" MinHeight="450" MinWidth="720" Background="Transparent" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Icon="/Resources/Icon/XFEToolBoxIcon.ico" Loaded="Window_Loaded">
12
12
13
<Border CornerRadius="19" Background="#9898e7">
13
<Border CornerRadius="19" Background="#9898e7" Margin="5">
14
14
<Grid>
15
15
<Grid.ColumnDefinitions>
16
16
<ColumnDefinition Width="180"/>
@@ -32,11 +32,12 @@
32
32
33
33
<ItemGroup>
34
34
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
35
<PackageReference Include="XFEExtension.NetCore" Version="3.0.1" />
35
<PackageReference Include="XFEExtension.NetCore" Version="3.0.2" />
36
36
<PackageReference Include="XFEExtension.NetCore.AutoConfig" Version="1.1.1" />
37
37
<PackageReference Include="XFEExtension.NetCore.AutoPath" Version="1.0.1" />
38
38
<PackageReference Include="XFEExtension.NetCore.InputSimulator" Version="2.2.0" />
39
39
<PackageReference Include="XFEExtension.NetCore.TodoHighLight" Version="1.0.0" />
40
<PackageReference Include="XFEExtension.NetCore.XFEConsole" Version="1.0.0" />
40
41
</ItemGroup>
41
42
42
43
<ItemGroup>