使用 D2D 绘制界面以及使用 AOT 发布的应用

这是我用不到 370 行代码,从零开始控制台创建 Win32 窗口,再挂上交换链,在窗口上使用 D2D 绘制界面内容。最后使用 AOT 方式发布的测试应用。成品文件体积不超过 10MB 且运行内存稳定在 60MB 以内,满帧率运行但 CPU 近乎不动

整个测试应用采用了 .NET 8 的框架,用于更好的支持 AOT 发布

使用了 Vortice 系列库用于对 DirectX 的封装,方便让编写调用 DirectX 的代码

使用了 Microsoft.Windows.CsWin32 方便进行 Win32 方法的调用

所有的代码都写在 Program.cs 文件里面,代码长度不到 370 行,更有趣的是,可以强行算是都写在 Main 方法里面,由 Main 方法以及放在 Main 方法里面的局部方法构成。整体实现非常简单。我将会在本文末尾告诉大家本文的代码的下载方法

本文仅仅是分享我的开发经验,不包含 DirectX 的前置知识。如果不熟悉 D2D 和 DirectX 还请以看着玩的心态阅读本文

一开始采用了 DirectX 使用 Vortice 从零开始控制台创建 Direct2D1 窗口修改颜色 和 dotnet DirectX 通过 Vortice 控制台使用 ID2D1DeviceContext 绘制画面 博客提供的方法搭建了基础的应用框架

为了让界面更加的丰富,我准备在界面添加多个圆形。然后为了让界面动起来,我添加了名为 DrawingInfo 的结构体,用于存放每个圆形的坐标和大小等信息

readonly record struct DrawingInfo(System.Numerics.Vector2 Offset, Size Size, D2D.ID2D1SolidColorBrush Brush);

先在绘制的循环外对 DrawingInfo 进行随机设置值

var ellipseInfoList = new List<DrawingInfo>();
            for (int i = 0; i < 3000; i++)
            {
                // 随意创建颜色
                var color = new Color4((byte) Random.Shared.Next(255), (byte) Random.Shared.Next(255), (byte) Random.Shared.Next(255));
                D2D.ID2D1SolidColorBrush brush = renderTarget.CreateSolidColorBrush(color);
                ellipseInfoList.Add(new DrawingInfo(new System.Numerics.Vector2(Random.Shared.Next(clientSize.Width), Random.Shared.Next(clientSize.Height)), new Size(Random.Shared.Next(10, 100)), brush));
            }

进入循环之后,再每次修改 Offset 的值,这样就可以让每次绘制的圆形动起来

while (true)
            {
                // 开始绘制逻辑
                renderTarget.BeginDraw();

                // 清空画布
                renderTarget.Clear(new Color4(0xFF, 0xFF, 0xFF));

                // 在下面绘制漂亮的界面

                for (var i = 0; i < ellipseInfoList.Count; i++)
                {
                    var drawingInfo = ellipseInfoList[i];
                    var vector2 = drawingInfo.Offset;
                    vector2.X += Random.Shared.Next(200) - 100;
                    vector2.Y += Random.Shared.Next(200) - 100;

                    while (vector2.X < 100 || vector2.X > clientSize.Width - 100)
                    {
                        vector2.X = Random.Shared.Next(clientSize.Width);
                    }

                    while (vector2.Y < 100 || vector2.Y > clientSize.Height - 100)
                    {
                        vector2.Y = Random.Shared.Next(clientSize.Height);
                    }

                    ellipseInfoList[i] = drawingInfo with { Offset = vector2 };
                    
                    // 忽略其他代码
                }

                // 忽略其他代码
            }

以上的修改坐标代码只是为了让圆形每次都在其附近移动

附带就在里层循环将每个圆形绘制,代码如下

// 在下面绘制漂亮的界面

                for (var i = 0; i < ellipseInfoList.Count; i++)
                {
                    // 忽略其他代码
                    renderTarget.FillEllipse(new D2D.Ellipse(vector2, drawingInfo.Size.Width, drawingInfo.Size.Height), drawingInfo.Brush);
                }

大概的改动如此,接下来咱需要改造一下 csproj 项目文件,让此项目可以构建出 AOT 版本的应用

先修改 TargetFramework 为 net8.0 使用 .NET 8 可以更好构建 AOT 应用

<PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

接着为了减少不断提示的平台警告,添加以下代码忽略 CA1416 警告

<PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <NoWarn>CA1416</NoWarn>
  </PropertyGroup>

接着再添加 PublishAot 属性,这样调用发布命令之后,就可以自动创建 AOT 应用的文件

<PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <NoWarn>CA1416</NoWarn>
    <PublishAot>true</PublishAot>
  </PropertyGroup>

此时运行起来将不会成功,将会提示大概如下的错误

Unhandled Exception: System.MissingMethodException: No parameterless constructor defined for type 'Vortice.DXGI.IDXGIFactory2'.
   at System.ActivatorImplementation.CreateInstance(Type, BindingFlags, Binder, Object[], Cultu
  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值