实现提供了完整的弹幕功能,包括多行显示、不同颜色、头像支持、防重叠、椭圆形边框、透明度渐变、点击事件、字体样式设置、暂停/继续功能、过滤功能等。还包含了批处理队列处理逻辑、速率限制、错误处理和性能监控等功能。

This commit is contained in:
yangwx01
2025-03-29 17:19:12 +08:00
parent d347357448
commit 4e178cb724
119 changed files with 2578 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,6 @@
{
"ExpandedNodes": [
""
],
"PreviewInSolutionExplorer": false
}

Binary file not shown.

Binary file not shown.

BIN
.vs/YwxAppWpfDanMu/v17/.suo Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,23 @@
{
"Version": 1,
"WorkspaceRootPath": "D:\\repos\\YwxAppWpfDanMu\\",
"Documents": [],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 323,
"SelectedChildIndex": -1,
"Children": [
{
"$type": "Bookmark",
"Name": "ST:128:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
}
]
}
]
}
]
}

View File

@@ -0,0 +1,31 @@
{
"Version": 1,
"WorkspaceRootPath": "D:\\repos\\YwxAppWpfDanMu\\",
"Documents": [],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 323,
"SelectedChildIndex": -1,
"Children": [
{
"$type": "Bookmark",
"Name": "ST:128:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
},
{
"$type": "Bookmark",
"Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}"
},
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
}
]
}
]
}
]
}

BIN
.vs/slnx.sqlite Normal file

Binary file not shown.

9
WpfApp1/App.xaml Normal file
View File

@@ -0,0 +1,9 @@
<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

13
WpfApp1/App.xaml.cs Normal file
View File

@@ -0,0 +1,13 @@
using System.Configuration;
using System.Data;
using System.Windows;
namespace WpfApp1;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}

10
WpfApp1/AssemblyInfo.cs Normal file
View File

@@ -0,0 +1,10 @@
using System.Windows;
[assembly:ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

28
WpfApp1/MainWindow.xaml Normal file
View File

@@ -0,0 +1,28 @@
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:danmu="clr-namespace:YwxAppWpfDanMu.Controls;assembly=YwxAppWpfDanMu"
mc:Ignorable="d"
Title="弹幕演示" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<danmu:DanMuControl x:Name="DanMuControl" Grid.Row="0" LineCount="10" />
</Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="暂停" Width="80" Margin="5" Click="PauseButton_Click"/>
<Button Content="继续" Width="80" Margin="5" Click="ResumeButton_Click"/>
<Button Content="清空" Width="80" Margin="5" Click="ClearButton_Click"/>
<Button Content="添加测试" Width="80" Margin="5" Click="Button_Click"/>
</StackPanel>
</Grid>
</Window>

115
WpfApp1/MainWindow.xaml.cs Normal file
View File

@@ -0,0 +1,115 @@
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using YwxAppWpfDanMu;
using YwxAppWpfDanMu.Controls;
using YwxAppWpfDanMu.Models;
namespace WpfApp1;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly Random _random = new Random();
public MainWindow()
{
InitializeComponent();
// 订阅事件
DanMuControl.DanMuClick += OnDanMuClick;
DanMuControl.DanMuAdded += OnDanMuAdded;
DanMuControl.DanMuRemoved += OnDanMuRemoved;
}
private void OnDanMuClick(object sender, DanMuEventArgs e)
{
MessageBox.Show($"点击了弹幕: {e.Message.Content}");
}
private void OnDanMuAdded(object sender, DanMuEventArgs e)
{
// 可以在这里处理弹幕添加事件
}
private void OnDanMuRemoved(object sender, DanMuEventArgs e)
{
// 可以在这里处理弹幕移除事件
}
private void PauseButton_Click(object sender, RoutedEventArgs e)
{
DanMuControl.IsPaused = true;
}
private void ResumeButton_Click(object sender, RoutedEventArgs e)
{
DanMuControl.IsPaused = false;
}
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
DanMuControl.ClearAll();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// 方法1: 添加单条弹幕
AddSingleTestDanMu();
// 方法2: 添加多条弹幕(批量)
// AddMultipleTestDanMu(5);
}
// 添加单条测试弹幕
private void AddSingleTestDanMu()
{
var colors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Yellow, Colors.White, Colors.Cyan, Colors.Magenta };
var fonts = new[] { "Microsoft YaHei", "SimSun", "Arial", "Segoe UI" };
var message = new DanMuMessage
{
// Content = $"这是单条测试弹幕 {DateTime.Now:HH:mm:ss}",
Content = $"这是单条测试弹幕 ",
Color = colors[_random.Next(colors.Length)],
FontSize = 12 + _random.Next(10),
FontFamily = new FontFamily(fonts[_random.Next(fonts.Length)]),
FontWeight = _random.Next(2) == 0 ? FontWeights.Normal : FontWeights.Bold,
FontStyle = _random.Next(2) == 0 ? FontStyles.Normal : FontStyles.Italic,
// Opacity = 0.7 + _random.NextDouble() * 0.3,
AvatarUrl = "https://unpkg.com/outeres@0.0.10/demo/avatar/1.jpg" // 使用占位图作为头像
};
DanMuControl.AddDanMu(message);
}
// 添加多条测试弹幕
private void AddMultipleTestDanMu(int count)
{
var messages = new List<DanMuMessage>();
var colors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Yellow, Colors.White, Colors.Cyan, Colors.Magenta };
var fonts = new[] { "Microsoft YaHei", "SimSun", "Arial", "Segoe UI" };
for (int i = 0; i < count; i++)
{
messages.Add(new DanMuMessage
{
Content = $"批量测试弹幕 {i + 1} - {DateTime.Now:HH:mm:ss}",
Color = colors[_random.Next(colors.Length)],
FontSize = 12 + _random.Next(10),
FontFamily = new FontFamily(fonts[_random.Next(fonts.Length)]),
FontWeight = _random.Next(2) == 0 ? FontWeights.Normal : FontWeights.Bold,
FontStyle = _random.Next(2) == 0 ? FontStyles.Normal : FontStyles.Italic,
Opacity = 0.7 + _random.NextDouble() * 0.3,
AvatarUrl = $"https://via.placeholder.com/30?text={i + 1}" // 带编号的头像
});
}
DanMuControl.AddDanMuBatch(messages);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

32
WpfApp1/WpfApp1.csproj Normal file
View File

@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\avatar1.png" />
<None Remove="Resources\avatar2.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\avatar2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\YwxAppWpfDanMu\YwxAppWpfDanMu.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\avatar1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Resource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]

View File

@@ -0,0 +1,71 @@
#pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "DCC59813AB95D23CF72F07367E2D9621042BF6D9"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
using WpfApp1;
namespace WpfApp1 {
/// <summary>
/// App
/// </summary>
public partial class App : System.Windows.Application {
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
public void InitializeComponent() {
#line 5 "..\..\..\App.xaml"
this.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative);
#line default
#line hidden
}
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
public static void Main() {
WpfApp1.App app = new WpfApp1.App();
app.InitializeComponent();
app.Run();
}
}
}

View File

@@ -0,0 +1,122 @@
#pragma checksum "..\..\..\MainWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "F66A7243C3D042690095180AF4E312C076945AB0"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
using YwxAppWpfDanMu.Controls;
namespace WpfApp1 {
/// <summary>
/// MainWindow
/// </summary>
public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
#line 19 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal YwxAppWpfDanMu.Controls.DanMuControl DanMuControl;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/WpfApp1;component/mainwindow.xaml", System.UriKind.Relative);
#line 1 "..\..\..\MainWindow.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.DanMuControl = ((YwxAppWpfDanMu.Controls.DanMuControl)(target));
return;
case 2:
#line 22 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.PauseButton_Click);
#line default
#line hidden
return;
case 3:
#line 23 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.ResumeButton_Click);
#line default
#line hidden
return;
case 4:
#line 24 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.ClearButton_Click);
#line default
#line hidden
return;
case 5:
#line 25 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.Button_Click);
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,6 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.Linq;
global using global::System.Threading;
global using global::System.Threading.Tasks;

Binary file not shown.

View File

@@ -0,0 +1,24 @@
D:\repos\WpfApp1\obj\Debug\net8.0-windows\App.g.cs
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1_MarkupCompile.cache
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.csproj.AssemblyReference.cache
D:\repos\WpfApp1\obj\Debug\net8.0-windows\MainWindow.baml
D:\repos\WpfApp1\obj\Debug\net8.0-windows\MainWindow.g.cs
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.g.resources
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.GeneratedMSBuildEditorConfig.editorconfig
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.AssemblyInfoInputs.cache
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.AssemblyInfo.cs
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.csproj.CoreCompileInputs.cache
D:\repos\WpfApp1\bin\Debug\net8.0-windows\Resources\avatar2.png
D:\repos\WpfApp1\bin\Debug\net8.0-windows\WpfApp1.exe
D:\repos\WpfApp1\bin\Debug\net8.0-windows\WpfApp1.deps.json
D:\repos\WpfApp1\bin\Debug\net8.0-windows\WpfApp1.runtimeconfig.json
D:\repos\WpfApp1\bin\Debug\net8.0-windows\WpfApp1.dll
D:\repos\WpfApp1\bin\Debug\net8.0-windows\WpfApp1.pdb
D:\repos\WpfApp1\bin\Debug\net8.0-windows\YwxAppWpfDanMu.dll
D:\repos\WpfApp1\bin\Debug\net8.0-windows\YwxAppWpfDanMu.pdb
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.csproj.Up2Date
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.dll
D:\repos\WpfApp1\obj\Debug\net8.0-windows\refint\WpfApp1.dll
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.pdb
D:\repos\WpfApp1\obj\Debug\net8.0-windows\WpfApp1.genruntimeconfig.cache
D:\repos\WpfApp1\obj\Debug\net8.0-windows\ref\WpfApp1.dll

View File

@@ -0,0 +1,11 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {}
},
"libraries": {}
}

View File

@@ -0,0 +1,25 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
{
"name": "Microsoft.WindowsDesktop.App",
"version": "8.0.0"
}
],
"additionalProbingPaths": [
"C:\\Users\\shiy7\\.dotnet\\store\\|arch|\\|tfm|",
"C:\\Users\\shiy7\\.nuget\\packages",
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": true,
"CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false,
"Microsoft.NETCore.DotNetHostPolicy.SetAppPaths": true
}
}
}

View File

@@ -0,0 +1,20 @@
WpfApp1
1.0.0.0
winexe
C#
.cs
D:\repos\YwxAppWpfDanMu\WpfApp1\obj\Debug\net8.0-windows\
WpfApp1
none
false
TRACE;DEBUG;NET;NET8_0;NETCOREAPP;WINDOWS;WINDOWS7_0;NET5_0_OR_GREATER;NET6_0_OR_GREATER;NET7_0_OR_GREATER;NET8_0_OR_GREATER;NETCOREAPP3_0_OR_GREATER;NETCOREAPP3_1_OR_GREATER;WINDOWS7_0_OR_GREATER
D:\repos\YwxAppWpfDanMu\WpfApp1\App.xaml
11407045341
6-294469655
1991235962195
MainWindow.xaml;
False

View File

@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyTitleAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")]
[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")]
// 由 MSBuild WriteCodeFragment 类生成。

View File

@@ -0,0 +1 @@
5ac7be5a9a219a310f512482b3871af9c403f9ef5ecf304e7b56289ac0d20745

View File

@@ -0,0 +1,16 @@
is_global = true
build_property.TargetFramework = net8.0-windows
build_property.TargetPlatformMinVersion = 7.0
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = WpfApp1
build_property.ProjectDir = D:\repos\WpfApp1\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,6 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.Linq;
global using global::System.Threading;
global using global::System.Threading.Tasks;

View File

@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyTitleAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")]
[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")]
// 由 MSBuild WriteCodeFragment 类生成。

View File

@@ -0,0 +1 @@
5ac7be5a9a219a310f512482b3871af9c403f9ef5ecf304e7b56289ac0d20745

View File

@@ -0,0 +1,16 @@
is_global = true
build_property.TargetFramework = net8.0-windows
build_property.TargetPlatformMinVersion = 7.0
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = WpfApp1
build_property.ProjectDir = D:\repos\WpfApp1\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,6 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.Linq;
global using global::System.Threading;
global using global::System.Threading.Tasks;

View File

@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyTitleAttribute("WpfApp1")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")]
[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")]
// 由 MSBuild WriteCodeFragment 类生成。

View File

@@ -0,0 +1 @@
5ac7be5a9a219a310f512482b3871af9c403f9ef5ecf304e7b56289ac0d20745

View File

@@ -0,0 +1,16 @@
is_global = true
build_property.TargetFramework = net8.0-windows
build_property.TargetPlatformMinVersion = 7.0
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = WpfApp1
build_property.ProjectDir = D:\repos\WpfApp1\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,6 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.Linq;
global using global::System.Threading;
global using global::System.Threading.Tasks;

Binary file not shown.

View File

@@ -0,0 +1,148 @@
{
"format": 1,
"restore": {
"D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\WpfApp1.csproj": {}
},
"projects": {
"D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\WpfApp1.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\WpfApp1.csproj",
"projectName": "WpfApp1",
"projectPath": "D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\WpfApp1.csproj",
"packagesPath": "C:\\Users\\shiy7\\.nuget\\packages\\",
"outputPath": "D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\shiy7\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net8.0-windows"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0-windows7.0": {
"targetAlias": "net8.0-windows",
"projectReferences": {
"D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\YwxAppWpfDanMu.csproj": {
"projectPath": "D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\YwxAppWpfDanMu.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.200"
},
"frameworks": {
"net8.0-windows7.0": {
"targetAlias": "net8.0-windows",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
},
"Microsoft.WindowsDesktop.App.WPF": {
"privateAssets": "none"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json"
}
}
},
"D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\YwxAppWpfDanMu.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\YwxAppWpfDanMu.csproj",
"projectName": "YwxAppWpfDanMu",
"projectPath": "D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\YwxAppWpfDanMu.csproj",
"packagesPath": "C:\\Users\\shiy7\\.nuget\\packages\\",
"outputPath": "D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\shiy7\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net8.0-windows"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0-windows7.0": {
"targetAlias": "net8.0-windows",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.200"
},
"frameworks": {
"net8.0-windows7.0": {
"targetAlias": "net8.0-windows",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
},
"Microsoft.WindowsDesktop.App.WPF": {
"privateAssets": "none"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\shiy7\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\shiy7\.nuget\packages\" />
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />

View File

@@ -0,0 +1,108 @@
{
"version": 3,
"targets": {
"net8.0-windows7.0": {
"YwxAppWpfDanMu/1.0.0": {
"type": "project",
"framework": ".NETCoreApp,Version=v8.0",
"compile": {
"bin/placeholder/YwxAppWpfDanMu.dll": {}
},
"runtime": {
"bin/placeholder/YwxAppWpfDanMu.dll": {}
},
"frameworkReferences": [
"Microsoft.WindowsDesktop.App.WPF"
]
}
}
},
"libraries": {
"YwxAppWpfDanMu/1.0.0": {
"type": "project",
"path": "../YwxAppWpfDanMu/YwxAppWpfDanMu.csproj",
"msbuildProject": "../YwxAppWpfDanMu/YwxAppWpfDanMu.csproj"
}
},
"projectFileDependencyGroups": {
"net8.0-windows7.0": [
"YwxAppWpfDanMu >= 1.0.0"
]
},
"packageFolders": {
"C:\\Users\\shiy7\\.nuget\\packages\\": {},
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {}
},
"project": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\WpfApp1.csproj",
"projectName": "WpfApp1",
"projectPath": "D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\WpfApp1.csproj",
"packagesPath": "C:\\Users\\shiy7\\.nuget\\packages\\",
"outputPath": "D:\\repos\\YwxAppWpfDanMu\\WpfApp1\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\shiy7\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net8.0-windows"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0-windows7.0": {
"targetAlias": "net8.0-windows",
"projectReferences": {
"D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\YwxAppWpfDanMu.csproj": {
"projectPath": "D:\\repos\\YwxAppWpfDanMu\\YwxAppWpfDanMu\\YwxAppWpfDanMu.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.200"
},
"frameworks": {
"net8.0-windows7.0": {
"targetAlias": "net8.0-windows",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
},
"Microsoft.WindowsDesktop.App.WPF": {
"privateAssets": "none"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json"
}
}
}
}

31
YwxAppWpfDanMu.sln Normal file
View File

@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35828.75
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YwxAppWpfDanMu", "YwxAppWpfDanMu\YwxAppWpfDanMu.csproj", "{BCBD427E-7D3C-4FE7-A49D-CE45517E84A9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfApp1", "WpfApp1\WpfApp1.csproj", "{7605DAD6-FF29-68CC-A841-EC859FB1D9DB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BCBD427E-7D3C-4FE7-A49D-CE45517E84A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BCBD427E-7D3C-4FE7-A49D-CE45517E84A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BCBD427E-7D3C-4FE7-A49D-CE45517E84A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BCBD427E-7D3C-4FE7-A49D-CE45517E84A9}.Release|Any CPU.Build.0 = Release|Any CPU
{7605DAD6-FF29-68CC-A841-EC859FB1D9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7605DAD6-FF29-68CC-A841-EC859FB1D9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7605DAD6-FF29-68CC-A841-EC859FB1D9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7605DAD6-FF29-68CC-A841-EC859FB1D9DB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {61C582F9-EA5A-40B0-8838-62C13CE58AA6}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,19 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
[assembly:ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
[assembly: AssemblyDescription("A WPF DanMu (bullet comment) control library")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View File

@@ -0,0 +1,9 @@
<UserControl x:Class="YwxAppWpfDanMu.Controls.DanMuControl"
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"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Canvas x:Name="DanMuCanvas" Background="Transparent" ClipToBounds="True"/>
</UserControl>

View File

@@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using YwxAppWpfDanMu.Models;
using YwxAppWpfDanMu.Services;
using YwxAppWpfDanMu.Utils;
namespace YwxAppWpfDanMu.Controls
{
public partial class DanMuControl : UserControl
{
private readonly DanMuPool _danMuPool;
private readonly DanMuDispatcher _dispatcher;
private readonly DanMuQueueProcessor _queueProcessor;
private readonly RateLimiter _rateLimiter;
private readonly DanMuPerformanceMonitor _performanceMonitor;
internal List<DanMuTrack> _tracks = new List<DanMuTrack>();
private readonly Dictionary<DanMuItem, DanMuTrack> _activeItems = new Dictionary<DanMuItem, DanMuTrack>();
public DanMuControl()
{
InitializeComponent();
_danMuPool = new DanMuPool(this);
_dispatcher = new DanMuDispatcher(Dispatcher);
_queueProcessor = new DanMuQueueProcessor(_dispatcher);
_rateLimiter = new RateLimiter(50); // 限制每秒50条
_performanceMonitor = new DanMuPerformanceMonitor();
Loaded += OnLoaded;
Unloaded += OnUnloaded;
SizeChanged += OnSizeChanged;
}
#region Dependency Properties
public static readonly DependencyProperty LineCountProperty = DependencyProperty.Register(
"LineCount", typeof(int), typeof(DanMuControl), new PropertyMetadata(5, OnLineCountChanged));
public int LineCount
{
get => (int)GetValue(LineCountProperty);
set => SetValue(LineCountProperty, value);
}
public static readonly DependencyProperty IsPausedProperty = DependencyProperty.Register(
"IsPaused", typeof(bool), typeof(DanMuControl), new PropertyMetadata(false));
public bool IsPaused
{
get => (bool)GetValue(IsPausedProperty);
set => SetValue(IsPausedProperty, value);
}
#endregion
#region Events
public event EventHandler<DanMuEventArgs> DanMuClick;
public event EventHandler<DanMuEventArgs> DanMuAdded;
public event EventHandler<DanMuEventArgs> DanMuRemoved;
#endregion
#region Public Methods
public void AddDanMu(DanMuMessage message)
{
if (!_rateLimiter.TryAcquire())
{
// 超出速率限制,可以记录日志或采取其他措施
return;
}
_queueProcessor.Enqueue(() =>
{
try
{
if (DanMuFilter.ShouldFilter(message))
return;
var args = new DanMuEventArgs(message);
DanMuAdded?.Invoke(this, args);
if (!args.Handled)
{
_danMuPool.AddDanMu(message);
}
_performanceMonitor.RecordAddedDanMu();
}
catch (Exception ex)
{
// 记录错误日志
_performanceMonitor.RecordError(ex);
}
});
}
public void AddDanMuBatch(IEnumerable<DanMuMessage> messages)
{
_queueProcessor.EnqueueBatch(() =>
{
foreach (var message in messages)
{
if (!_rateLimiter.TryAcquire())
continue;
try
{
if (DanMuFilter.ShouldFilter(message))
continue;
var args = new DanMuEventArgs(message);
DanMuAdded?.Invoke(this, args);
if (!args.Handled)
{
_danMuPool.AddDanMu(message);
}
_performanceMonitor.RecordAddedDanMu();
}
catch (Exception ex)
{
_performanceMonitor.RecordError(ex);
}
}
});
}
public void ClearAll()
{
_queueProcessor.Enqueue(() =>
{
_danMuPool.ClearAll();
_performanceMonitor.RecordClear();
});
}
#endregion
#region Private Methods
private void OnLoaded(object sender, RoutedEventArgs e)
{
InitializeTracks();
_danMuPool.Start();
_performanceMonitor.Start();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
_danMuPool.Stop();
_performanceMonitor.Stop();
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
InitializeTracks();
}
private void InitializeTracks()
{
_tracks.Clear();
double trackHeight = ActualHeight / LineCount;
for (int i = 0; i < LineCount; i++)
{
_tracks.Add(new DanMuTrack
{
Top = i * trackHeight,
Height = trackHeight,
Width = ActualWidth
});
}
}
private static void OnLineCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is DanMuControl control)
{
control.InitializeTracks();
}
}
internal void OnDanMuItemClick(DanMuItem item)
{
var args = new DanMuEventArgs(item.Message);
DanMuClick?.Invoke(this, args);
}
internal void OnDanMuItemRemoved(DanMuItem item)
{
var args = new DanMuEventArgs(item.Message);
DanMuRemoved?.Invoke(this, args);
}
#endregion
internal class DanMuTrack
{
public double Top { get; set; }
public double Height { get; set; }
public double Width { get; set; }
public double AvailablePosition { get; set; }
public List<DanMuItem> ActiveItems { get; } = new List<DanMuItem>();
}
}
}

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using YwxAppWpfDanMu.Models;
namespace YwxAppWpfDanMu.Controls
{
public static class DanMuFilter
{
private static readonly List<string> _blockedKeywords = new List<string>();
private static readonly List<Regex> _blockedPatterns = new List<Regex>();
public static void AddBlockedKeyword(string keyword)
{
if (!string.IsNullOrWhiteSpace(keyword) && !_blockedKeywords.Contains(keyword))
{
_blockedKeywords.Add(keyword);
}
}
public static void AddBlockedPattern(string pattern)
{
if (!string.IsNullOrWhiteSpace(pattern))
{
_blockedPatterns.Add(new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase));
}
}
public static bool ShouldFilter(DanMuMessage message)
{
if (message == null || string.IsNullOrWhiteSpace(message.Content))
return true;
// 检查关键词
foreach (var keyword in _blockedKeywords)
{
if (message.Content.Contains(keyword))
return true;
}
// 检查正则表达式
foreach (var pattern in _blockedPatterns)
{
if (pattern.IsMatch(message.Content))
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,29 @@
<UserControl x:Class="YwxAppWpfDanMu.Controls.DanMuItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="60" d:DesignWidth="200">
<Grid>
<Border x:Name="Border" CornerRadius="15" Background="#88000000" Padding="3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse Width="30" Height="30" Grid.Column="0" Margin="0,0,3,0">
<Ellipse.Fill>
<ImageBrush x:Name="AvatarBrush" Stretch="UniformToFill"/>
</Ellipse.Fill>
</Ellipse>
<TextBlock x:Name="ContentText" Grid.Column="1"
VerticalAlignment="Center"
TextWrapping="NoWrap"
TextTrimming="CharacterEllipsis"/>
</Grid>
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,57 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using YwxAppWpfDanMu.Models;
namespace YwxAppWpfDanMu.Controls
{
public partial class DanMuItem : UserControl
{
public DanMuMessage Message { get; private set; }
public DanMuItem(DanMuMessage message)
{
InitializeComponent();
Message = message;
UpdateUI();
}
private void UpdateUI()
{
ContentText.Text = Message.Content;
ContentText.Foreground = new SolidColorBrush(Message.Color);
ContentText.FontSize = Message.FontSize;
ContentText.FontFamily = Message.FontFamily;
ContentText.FontWeight = Message.FontWeight;
ContentText.FontStyle = Message.FontStyle;
Opacity = Message.Opacity;
if (!string.IsNullOrEmpty(Message.AvatarUrl))
{
// 实际项目中应该使用异步加载或缓存机制
var image = new ImageSourceConverter().ConvertFromString(Message.AvatarUrl) as ImageSource;
AvatarBrush.ImageSource = image;
}
else
{
AvatarBrush.ImageSource = null;
}
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
RaiseEvent(new RoutedEventArgs(ClickEvent));
}
public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent(
"Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DanMuItem));
public event RoutedEventHandler Click
{
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
}
}
}

View File

@@ -0,0 +1,152 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using YwxAppWpfDanMu.Models;
namespace YwxAppWpfDanMu.Controls
{
internal class DanMuPool
{
private readonly DanMuControl _parent;
private readonly Queue<DanMuMessage> _messageQueue = new Queue<DanMuMessage>();
private readonly DispatcherTimer _timer;
private readonly Random _random = new Random();
public DanMuPool(DanMuControl parent)
{
_parent = parent ?? throw new ArgumentNullException(nameof(parent));
_timer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(50)
};
_timer.Tick += OnTimerTick;
}
public void Start()
{
_timer.Start();
}
public void Stop()
{
_timer.Stop();
}
public void AddDanMu(DanMuMessage message)
{
lock (_messageQueue)
{
_messageQueue.Enqueue(message);
}
}
public void ClearAll()
{
lock (_messageQueue)
{
_messageQueue.Clear();
}
_parent.DanMuCanvas.Children.Clear();
foreach (var track in _parent._tracks)
{
track.ActiveItems.Clear();
track.AvailablePosition = 0;
}
}
private void OnTimerTick(object sender, EventArgs e)
{
if (_parent.IsPaused)
return;
lock (_messageQueue)
{
while (_messageQueue.Count > 0)
{
var message = _messageQueue.Dequeue();
DispatchDanMu(message);
}
}
}
private void DispatchDanMu(DanMuMessage message)
{
// 找到最适合的轨道
var track = FindBestTrack(message);
if (track == null)
return;
var danMuItem = new DanMuItem(message);
danMuItem.Click += (s, args) => _parent.OnDanMuItemClick(danMuItem);
// 测量弹幕宽度
danMuItem.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var itemWidth = danMuItem.DesiredSize.Width;
// 设置初始位置
Canvas.SetLeft(danMuItem, _parent.ActualWidth);
Canvas.SetTop(danMuItem, track.Top + (track.Height - danMuItem.DesiredSize.Height) / 2);
_parent.DanMuCanvas.Children.Add(danMuItem);
track.ActiveItems.Add(danMuItem);
// 创建动画
var animation = new DoubleAnimation
{
From = _parent.ActualWidth,
To = -itemWidth,
Duration = TimeSpan.FromSeconds(5 + _random.NextDouble() * 3),
FillBehavior = FillBehavior.Stop
};
animation.Completed += (s, args) =>
{
_parent.DanMuCanvas.Children.Remove(danMuItem);
track.ActiveItems.Remove(danMuItem);
_parent.OnDanMuItemRemoved(danMuItem);
};
// 添加透明度渐变效果
var opacityAnimation = new DoubleAnimation
{
From = 1.0,
To = 0.2,
Duration = animation.Duration,
BeginTime = TimeSpan.FromSeconds(animation.Duration.TimeSpan.TotalSeconds * 0.7)
};
danMuItem.BeginAnimation(Canvas.LeftProperty, animation);
danMuItem.BeginAnimation(UIElement.OpacityProperty, opacityAnimation);
// 更新轨道可用位置
track.AvailablePosition = _parent.ActualWidth + itemWidth + 10; // 10为间距
}
private DanMuControl.DanMuTrack FindBestTrack(DanMuMessage message)
{
if (_parent._tracks.Count == 0)
return null;
// 随机选择一个轨道,检查是否有足够空间
int startIndex = _random.Next(_parent._tracks.Count);
for (int i = 0; i < _parent._tracks.Count; i++)
{
int index = (startIndex + i) % _parent._tracks.Count;
var track = _parent._tracks[index];
// 如果轨道上没有弹幕,或者最后一个弹幕已经移动足够远
if (track.ActiveItems.Count == 0 ||
track.AvailablePosition < _parent.ActualWidth * 0.7)
{
return track;
}
}
// 所有轨道都满了,选择最不拥挤的轨道
return _parent._tracks.OrderBy(t => t.ActiveItems.Count).First();
}
}
}

View File

@@ -0,0 +1,13 @@
using System.Windows.Media;
namespace YwxAppWpfDanMu.Controls
{
public static class DanMuSettings
{
public static Color DefaultColor { get; set; } = Colors.White;
public static double DefaultFontSize { get; set; } = 14;
public static FontFamily DefaultFontFamily { get; set; } = new FontFamily("Microsoft YaHei");
public static double DefaultSpeed { get; set; } = 1.0;
public static double DefaultOpacity { get; set; } = 0.4;
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
namespace YwxAppWpfDanMu.Models
{
public class DanMuEventArgs : EventArgs
{
public DanMuMessage Message { get; }
public bool Handled { get; set; }
public DanMuEventArgs(DanMuMessage message)
{
Message = message;
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Windows;
using System.Windows.Media;
using static System.Net.Mime.MediaTypeNames;
namespace YwxAppWpfDanMu.Models
{
public class DanMuMessage
{
public string Content { get; set; }
public Color Color { get; set; } = Colors.Orange;
public string AvatarUrl { get; set; }
public double FontSize { get; set; } = 12;
public FontFamily FontFamily { get; set; } = new FontFamily("Microsoft YaHei");
public FontWeight FontWeight { get; set; } = FontWeights.Bold;
public FontStyle FontStyle { get; set; } = FontStyles.Normal;
public double Opacity { get; set; } = 1.0;
public object Tag { get; set; }
public DateTime Timestamp { get; set; } = DateTime.Now;
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Windows.Threading;
namespace YwxAppWpfDanMu.Services
{
public class DanMuDispatcher
{
private readonly Dispatcher _dispatcher;
public DanMuDispatcher(Dispatcher dispatcher)
{
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
}
public void Invoke(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
{
if (_dispatcher.CheckAccess())
{
action();
}
else
{
_dispatcher.Invoke(action, priority);
}
}
public void BeginInvoke(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
{
_dispatcher.BeginInvoke(action, priority);
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace YwxAppWpfDanMu.Services
{
public class DanMuPerformanceMonitor
{
private readonly Stopwatch _stopwatch = new Stopwatch();
private readonly List<Exception> _errors = new List<Exception>();
private int _totalDanMuAdded;
private int _totalDanMuFiltered;
private int _totalDanMuRemoved;
public void Start()
{
_stopwatch.Start();
}
public void Stop()
{
_stopwatch.Stop();
}
public void RecordAddedDanMu()
{
_totalDanMuAdded++;
}
public void RecordFilteredDanMu()
{
_totalDanMuFiltered++;
}
public void RecordRemovedDanMu()
{
_totalDanMuRemoved++;
}
public void RecordClear()
{
_totalDanMuRemoved += _totalDanMuAdded - _totalDanMuRemoved;
}
public void RecordError(Exception ex)
{
_errors.Add(ex);
}
public PerformanceStats GetStats()
{
return new PerformanceStats
{
TotalTime = _stopwatch.Elapsed,
TotalDanMuAdded = _totalDanMuAdded,
TotalDanMuFiltered = _totalDanMuFiltered,
TotalDanMuRemoved = _totalDanMuRemoved,
Errors = _errors.ToArray(),
DanMuPerSecond = _stopwatch.Elapsed.TotalSeconds > 0 ?
_totalDanMuAdded / _stopwatch.Elapsed.TotalSeconds : 0
};
}
public class PerformanceStats
{
public TimeSpan TotalTime { get; set; }
public int TotalDanMuAdded { get; set; }
public int TotalDanMuFiltered { get; set; }
public int TotalDanMuRemoved { get; set; }
public Exception[] Errors { get; set; }
public double DanMuPerSecond { get; set; }
}
}
}

View File

@@ -0,0 +1,13 @@
using YwxAppWpfDanMu.Models;
namespace YwxAppWpfDanMu.Services
{
public interface IDanMuService
{
void AddDanMu(DanMuMessage message);
void AddDanMuBatch(IEnumerable<DanMuMessage> messages);
void ClearAll();
void Pause();
void Resume();
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using YwxAppWpfDanMu.Services;
namespace YwxAppWpfDanMu.Utils
{
public class DanMuQueueProcessor
{
private readonly DanMuDispatcher _dispatcher;
private readonly Queue<Action> _queue = new Queue<Action>();
private bool _isProcessing;
public DanMuQueueProcessor(DanMuDispatcher dispatcher)
{
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
}
public void Enqueue(Action action)
{
lock (_queue)
{
_queue.Enqueue(action);
if (!_isProcessing)
{
_isProcessing = true;
_dispatcher.BeginInvoke(ProcessQueue);
}
}
}
public void EnqueueBatch(Action batchAction)
{
Enqueue(() =>
{
var actions = new List<Action>();
batchAction();
// 处理批处理逻辑
lock (_queue)
{
while (_queue.Count > 0)
{
actions.Add(_queue.Dequeue());
}
}
// 执行所有动作
foreach (var action in actions)
{
action();
}
});
}
private void ProcessQueue()
{
Action action = null;
lock (_queue)
{
if (_queue.Count > 0)
{
action = _queue.Dequeue();
}
else
{
_isProcessing = false;
return;
}
}
try
{
action();
}
catch (Exception ex)
{
// 记录错误日志
}
finally
{
_dispatcher.BeginInvoke(ProcessQueue);
}
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Diagnostics;
namespace YwxAppWpfDanMu.Utils
{
public class RateLimiter
{
private readonly int _maxActionsPerSecond;
private readonly Stopwatch _stopwatch;
private int _actionCount;
private long _lastResetTicks;
public RateLimiter(int maxActionsPerSecond)
{
if (maxActionsPerSecond <= 0)
throw new ArgumentOutOfRangeException(nameof(maxActionsPerSecond));
_maxActionsPerSecond = maxActionsPerSecond;
_stopwatch = Stopwatch.StartNew();
_lastResetTicks = _stopwatch.ElapsedTicks;
}
public bool TryAcquire()
{
long elapsedTicks = _stopwatch.ElapsedTicks;
long ticksPerSecond = Stopwatch.Frequency;
// 检查是否需要重置计数器
if (elapsedTicks - _lastResetTicks >= ticksPerSecond)
{
_actionCount = 0;
_lastResetTicks = elapsedTicks;
}
// 检查是否超过限制
if (_actionCount >= _maxActionsPerSecond)
{
return false;
}
_actionCount++;
return true;
}
}
}

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>YwxAppWpfDanMu</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Folder Include="Themes\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<Compile Update="Controls\DanMuControl.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Controls\DanMuItem.xaml.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
</Project>

18
YwxAppWpfDanMu/file1.md Normal file
View File

@@ -0,0 +1,18 @@
我在使用net8时 想用 WPF自定义控件库 实现一个弹幕库,
要求:根命名空间 YwxAppWpfDanMu
支持多行显示
支持不同颜色
支持头像
单行多条时不重叠
椭圆形边框
弹幕透明度渐变效果
实现弹幕点击事件
弹幕字体样式设置
弹幕暂停/继续功能
弹幕过滤功能
可以 实现 添加批处理修改队列处理逻辑一次处理多条弹幕减少Dispatcher调用次数
添加速率限制防止弹幕添加过快导致UI线程过载。
错误处理增强:可以添加更详细的错误日志记录。
性能监控:添加性能计数器,监控弹幕处理性能。
程序稳定,处理拦截异常
请问详细怎么写 请完整的列出每个文件

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]

View File

@@ -0,0 +1,89 @@
#pragma checksum "..\..\..\..\Controls\DanMuControl.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "E082544CF5C7195C2B4AAFFD01191EF13D02288E"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace YwxAppWpfDanMu.Controls {
/// <summary>
/// DanMuControl
/// </summary>
public partial class DanMuControl : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector {
#line 8 "..\..\..\..\Controls\DanMuControl.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Canvas DanMuCanvas;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/YwxAppWpfDanMu;component/controls/danmucontrol.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\Controls\DanMuControl.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.DanMuCanvas = ((System.Windows.Controls.Canvas)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,111 @@
#pragma checksum "..\..\..\..\Controls\DanMuItem.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "1250D4D6E85528DBB3B568E6B712FAF3ED68A4F5"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace YwxAppWpfDanMu.Controls {
/// <summary>
/// DanMuItem
/// </summary>
public partial class DanMuItem : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector {
#line 9 "..\..\..\..\Controls\DanMuItem.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Border;
#line default
#line hidden
#line 18 "..\..\..\..\Controls\DanMuItem.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Media.ImageBrush AvatarBrush;
#line default
#line hidden
#line 22 "..\..\..\..\Controls\DanMuItem.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock ContentText;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/YwxAppWpfDanMu;component/controls/danmuitem.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\Controls\DanMuItem.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "9.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.Border = ((System.Windows.Controls.Border)(target));
return;
case 2:
this.AvatarBrush = ((System.Windows.Media.ImageBrush)(target));
return;
case 3:
this.ContentText = ((System.Windows.Controls.TextBlock)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,6 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.Linq;
global using global::System.Threading;
global using global::System.Threading.Tasks;

View File

@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YwxAppWpfDanMu")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+7c080b159c5b893b61e005ee82d8fb0a0527b3e8")]
[assembly: System.Reflection.AssemblyProductAttribute("YwxAppWpfDanMu")]
[assembly: System.Reflection.AssemblyTitleAttribute("YwxAppWpfDanMu")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")]
[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")]
// 由 MSBuild WriteCodeFragment 类生成。

View File

@@ -0,0 +1 @@
2c1526129923d8dd40fac0b697e335e0b734b30a95c0c7dd7f4cf9f0a7248275

View File

@@ -0,0 +1,16 @@
is_global = true
build_property.TargetFramework = net8.0-windows
build_property.TargetPlatformMinVersion = 7.0
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = YwxAppWpfDanMu
build_property.ProjectDir = D:\repos\YwxAppWpfDanMu\YwxAppWpfDanMu\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,6 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.Linq;
global using global::System.Threading;
global using global::System.Threading.Tasks;

View File

@@ -0,0 +1,20 @@
YwxAppWpfDanMu
1.0.0.0
library
C#
.cs
D:\repos\YwxAppWpfDanMu\YwxAppWpfDanMu\obj\Debug\net8.0-windows\
YwxAppWpfDanMu
none
false
TRACE;DEBUG;NET;NET8_0;NETCOREAPP;WINDOWS;WINDOWS7_0;NET5_0_OR_GREATER;NET6_0_OR_GREATER;NET7_0_OR_GREATER;NET8_0_OR_GREATER;NETCOREAPP3_0_OR_GREATER;NETCOREAPP3_1_OR_GREATER;WINDOWS7_0_OR_GREATER
2-450690804
161121933939
198-344842731
Controls\DanMuControl.xaml;Controls\DanMuItem.xaml;
False

View File

@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YwxAppWpfDanMu")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+7c080b159c5b893b61e005ee82d8fb0a0527b3e8")]
[assembly: System.Reflection.AssemblyProductAttribute("YwxAppWpfDanMu")]
[assembly: System.Reflection.AssemblyTitleAttribute("YwxAppWpfDanMu")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")]
[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")]
// 由 MSBuild WriteCodeFragment 类生成。

View File

@@ -0,0 +1 @@
2c1526129923d8dd40fac0b697e335e0b734b30a95c0c7dd7f4cf9f0a7248275

View File

@@ -0,0 +1,16 @@
is_global = true
build_property.TargetFramework = net8.0-windows
build_property.TargetPlatformMinVersion = 7.0
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = YwxAppWpfDanMu
build_property.ProjectDir = D:\repos\YwxAppWpfDanMu\YwxAppWpfDanMu\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,6 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.Linq;
global using global::System.Threading;
global using global::System.Threading.Tasks;

Some files were not shown because too many files have changed in this diff Show More