WPF使用Direct2D绘制曲线

[复制链接]
发表于 2026-2-10 23:55:07 | 显示全部楼层 |阅读模式
wpf使用Direct2D绘制曲线
···
Install-Package SharpDX
Install-Package SharpDX.Direct2D1
Install-Package SharpDX.DXGI
Install-Package SharpDX.Direct3D11
···
  1. <Window x:Class="WpfApp2.MainWindow"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.         xmlns:local="clr-namespace:WpfApp2"
  7.         mc:Ignorable="d"
  8.         Title="MainWindow" Height="450" Width="800">
  9.     <Grid>
  10.         <Image Name="DxImage"/>
  11.     </Grid>
  12. </Window>
复制代码
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Interop;
  4. using SharpDX;
  5. using SharpDX.Direct2D1;
  6. using SharpDX.Direct3D11;
  7. using SharpDX.DXGI;
  8. using SharpDX.Mathematics.Interop;
  9. using Device = SharpDX.Direct3D11.Device;
  10. using Factory = SharpDX.Direct2D1.Factory;
  11. using AlphaModeD2D = SharpDX.Direct2D1.AlphaMode;
  12. using PixelFormat = SharpDX.Direct2D1.PixelFormat;
  13. using SolidColorBrush = SharpDX.Direct2D1.SolidColorBrush;
  14. using SharpDX.DirectWrite;
  15. using System.Windows.Media;
  16. using TextAlignment = SharpDX.DirectWrite.TextAlignment;
  17. using FactoryType = SharpDX.Direct2D1.FactoryType;
  18. using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
  19. using System.Numerics;
  20. using DashStyle = SharpDX.Direct2D1.DashStyle;
  21. using PathGeometry = SharpDX.Direct2D1.PathGeometry;
  22. using static System.Net.Mime.MediaTypeNames;
  23. using SharpDX.Mathematics.Interop;
  24. using SharpDX;
  25. using SharpDX.Direct2D1;
  26. using SharpDX.Mathematics.Interop;
  27. using System.Security.Cryptography.Xml;
  28. using System.Windows.Media.Media3D;
  29. namespace WpfApp2
  30. {
  31.         public partial class MainWindow : Window
  32.         {
  33.                 private Device device;
  34.                 private SwapChain swapChain;
  35.                 private RenderTarget renderTarget;
  36.                 private Factory factory;
  37.                 private SharpDX.DirectWrite.Factory writeFactory;
  38.                 private TextFormat textFormat;
  39.                 private bool isResizing = false;
  40.                 private StrokeStyle strokeStyle;
  41.                 public MainWindow()
  42.                 {
  43.                         InitializeComponent();
  44.                         Loaded += OnLoaded;
  45.                         Unloaded += OnUnloaded;
  46.                         SizeChanged += OnSizeChanged;
  47.                 }
  48.                 private void OnLoaded(object sender, RoutedEventArgs e)
  49.                 {
  50.                         InitializeSharpDX();
  51.                         CompositionTarget.Rendering += OnRendering;
  52.                 }
  53.                 private void OnUnloaded(object sender, RoutedEventArgs e)
  54.                 {
  55.                         CompositionTarget.Rendering -= OnRendering;
  56.                         DisposeResources();
  57.                 }
  58.                 private void InitializeSharpDX()
  59.                 {
  60.                         factory = new Factory(FactoryType.SingleThreaded);
  61.                         writeFactory = new SharpDX.DirectWrite.Factory();
  62.                         var swapChainDescription = new SwapChainDescription
  63.                         {
  64.                                 BufferCount = 1,
  65.                                 ModeDescription = new ModeDescription((int)ActualWidth, (int)ActualHeight, new Rational(60, 1), Format.B8G8R8A8_UNorm),
  66.                                 IsWindowed = true,
  67.                                 OutputHandle = new WindowInteropHelper(this).Handle,
  68.                                 SampleDescription = new SampleDescription(1, 0),
  69.                                 SwapEffect = SwapEffect.Discard,
  70.                                 Usage = Usage.RenderTargetOutput
  71.                         };
  72.                         Device.CreateWithSwapChain(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.BgraSupport, swapChainDescription, out device, out swapChain);
  73.                         UpdateTextFormat();
  74.                         CreateRenderTarget();
  75.                         CreateStrokeStyle();
  76.                 }
  77.                 private void UpdateTextFormat()
  78.                 {
  79.                         textFormat?.Dispose();
  80.                         float fontSize = (float)(Math.Min(ActualWidth, ActualHeight) * 0.02);
  81.                         textFormat = new TextFormat(writeFactory, "Arial", fontSize)
  82.                         {
  83.                                 TextAlignment = TextAlignment.Center,
  84.                                 ParagraphAlignment = ParagraphAlignment.Center
  85.                         };
  86.                 }
  87.                 private void CreateRenderTarget()
  88.                 {
  89.                         using (var surface = swapChain.GetBackBuffer<Surface>(0))
  90.                         {
  91.                                 var properties = new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaModeD2D.Premultiplied));
  92.                                 renderTarget = new RenderTarget(factory, surface, properties)
  93.                                 {
  94.                                         AntialiasMode = AntialiasMode.PerPrimitive,
  95.                                         TextAntialiasMode = TextAntialiasMode.Cleartype
  96.                                 };
  97.                         }
  98.                 }
  99.                 private void CreateStrokeStyle()
  100.                 {
  101.                         strokeStyle?.Dispose();
  102.                         strokeStyle = new StrokeStyle(factory, new StrokeStyleProperties
  103.                         {
  104.                                 DashStyle = DashStyle.Solid,
  105.                                 LineJoin = LineJoin.Round,
  106.                                 StartCap = CapStyle.Round,
  107.                                 EndCap = CapStyle.Round
  108.                         });
  109.                 }
  110.                 private void OnSizeChanged(object sender, SizeChangedEventArgs e)
  111.                 {
  112.                         if (swapChain != null && !isResizing)
  113.                         {
  114.                                 isResizing = true;
  115.                                 try
  116.                                 {
  117.                                         renderTarget?.Dispose();
  118.                                         swapChain.ResizeBuffers(1, (int)ActualWidth, (int)ActualHeight, Format.B8G8R8A8_UNorm, SwapChainFlags.None);
  119.                                         CreateRenderTarget();
  120.                                         UpdateTextFormat();
  121.                                 }
  122.                                 finally
  123.                                 {
  124.                                         isResizing = false;
  125.                                 }
  126.                         }
  127.                 }
  128.                 private void OnRendering(object sender, EventArgs e)
  129.                 {
  130.                         if (renderTarget == null || isResizing)
  131.                                 return;
  132.                         renderTarget.BeginDraw();
  133.                         DrawScene();
  134.                         renderTarget.EndDraw();
  135.                         swapChain.Present(1, PresentFlags.None);
  136.                 }
  137.                 private void DrawScene()
  138.                 {
  139.                         renderTarget.Clear(new RawColor4(1, 1, 1, 1));
  140.                         using (var axisBrush = new SolidColorBrush(renderTarget, new RawColor4(0, 0, 0, 1)))
  141.                         using (var lineBrush = new SolidColorBrush(renderTarget, new RawColor4(1, 0, 0, 1)))
  142.                         using (var textBrush = new SolidColorBrush(renderTarget, new RawColor4(0, 0, 0, 1)))
  143.                         {
  144.                                 float width = (float)renderTarget.Size.Width;
  145.                                 float height = (float)renderTarget.Size.Height;
  146.                                 float margin = Math.Min(width, height) * 0.1f;
  147.                                 float axisLength = Math.Min(width, height) * 0.8f;
  148.                                 float lineWidth = 1.5f;
  149.                                 // Draw X-axis
  150.                                 renderTarget.DrawLine(
  151.                                         AlignToPixel(new RawVector2(margin, height / 2)),
  152.                                         AlignToPixel(new RawVector2(width - margin, height / 2)),
  153.                                         axisBrush, lineWidth, strokeStyle);
  154.                                 // Draw Y-axis
  155.                                 renderTarget.DrawLine(
  156.                                         AlignToPixel(new RawVector2(width / 2, margin)),
  157.                                         AlignToPixel(new RawVector2(width / 2, height - margin)),
  158.                                         axisBrush, lineWidth, strokeStyle);
  159.                                 // Draw X-axis ticks and labels
  160.                                 for (int i = -4; i <= 4; i++)
  161.                                 {
  162.                                         float x = width / 2 + i * axisLength / 8;
  163.                                         renderTarget.DrawLine(
  164.                                                 AlignToPixel(new RawVector2(x, height / 2 - 5)),
  165.                                                 AlignToPixel(new RawVector2(x, height / 2 + 5)),
  166.                                                 axisBrush, 1.0f, strokeStyle);
  167.                                         using (var textLayout = new TextLayout(writeFactory, i.ToString(), textFormat, 50, 20))
  168.                                         {
  169.                                                 renderTarget.DrawTextLayout(new RawVector2(x - 25, height / 2 + 10), textLayout, textBrush);
  170.                                         }
  171.                                 }
  172.                                 // Draw Y-axis ticks and labels
  173.                                 for (int i = -4; i <= 4; i++)
  174.                                 {
  175.                                         float y = height / 2 - i * axisLength / 8;
  176.                                         renderTarget.DrawLine(
  177.                                                 AlignToPixel(new RawVector2(width / 2 - 5, y)),
  178.                                                 AlignToPixel(new RawVector2(width / 2 + 5, y)),
  179.                                                 axisBrush, 1.0f, strokeStyle);
  180.                                         using (var textLayout = new TextLayout(writeFactory, i.ToString(), textFormat, 50, 20))
  181.                                         {
  182.                                                 renderTarget.DrawTextLayout(new RawVector2(width / 2 + 10, y - 10), textLayout, textBrush);
  183.                                         }
  184.                                 }
  185.                                 // Draw a line using geometry for better quality
  186.                                 var startPoint = AlignToPixel(new RawVector2(margin, margin));
  187.                                 var endPoint = AlignToPixel(new RawVector2(width - margin, height - margin));
  188.                                 using (var lineGeometry = new PathGeometry(factory))
  189.                                 {
  190.                                         var sink = lineGeometry.Open();
  191.                                         sink.BeginFigure(startPoint, FigureBegin.Hollow);
  192.                                         sink.AddLine(endPoint);
  193.                                         sink.EndFigure(FigureEnd.Open);
  194.                                         sink.Close();
  195.                                         //        使用 SharpDX.Matrix3x2.Identity 而不是 System.Numerics.Matrix3x2.Identity
  196.                                         //var transform = SharpDX.Matrix3x2.Identity;
  197.                                         var transform = new RawMatrix3x2() { M11 = 1, M22 = 1 };
  198.                                         using (var transformedGeometry = new TransformedGeometry(factory, lineGeometry, transform))
  199.                                         {
  200.                                                 renderTarget.DrawGeometry(transformedGeometry, lineBrush, lineWidth, strokeStyle);
  201.                                         }
  202.                                 }
  203.                         }
  204.                 }
  205.                 private RawVector2 AlignToPixel(RawVector2 point)
  206.                 {
  207.                         return new RawVector2(
  208.                                 (float)Math.Round(point.X) + 0.5f,
  209.                                 (float)Math.Round(point.Y) + 0.5f
  210.                         );
  211.                 }
  212.                 private void DisposeResources()
  213.                 {
  214.                         renderTarget?.Dispose();
  215.                         swapChain?.Dispose();
  216.                         device?.Dispose();
  217.                         textFormat?.Dispose();
  218.                         writeFactory?.Dispose();
  219.                         factory?.Dispose();
  220.                         strokeStyle?.Dispose();
  221.                 }
  222.         }
  223. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表