【发布时间】:2017-09-16 22:49:43
【问题描述】:
鉴于 Windows 窗体 中的旧桌面应用程序,在 .NET Framework 3.5 上运行的托管代码(C# 和 VB 项目的混合) (由于超出此问题范围的原因,无法迁移到较新的 .NET), 如何逐步将代码从 GDI+ 转换为 Direct2D?或者可能是 Direct3D?
另一个限制是生成的应用程序可以在 Windows 7 上运行,但如果这是使其运行的唯一方法,我们将迁移到 Windows 8 或 Windows 10。
(推动力是 GDI+ 在与 Graphics.FillPath 和小的纹理缩放因子一起使用时处理纹理中的错误;但我们最终还是希望转向 Direct2D 或 Direct3D。)
如果我们以 .NET Framework 4.0+ 和 Windows 8+ 为目标,我们想做的事情将很简单,如下所述:
Direct2D and GDI Interoperability Overview
不幸的是,尝试使这些指令适应我们旧的目标规范遇到了一系列障碍。
第一步是使用一些托管包装器来访问 Direct2D。
(不确定是否 Direct2D 1.0 或 1.1 是 Microsoft 和其他地方的包装器/代码示例/教程的目标。)
我知道的选项:
A. Microsoft DirectX 9.0 for Managed Code (MDX)(最后更新 2006 年):
我看到 cmets 对这个长期不受支持的软件包感到沮丧,并建议改用 SlimDX 或 SharpDX [或迁移到受支持但与我们指定的旧平台不兼容的更新的 Microsoft 技术]。似乎不是一个好的长期方向。所以我还没有尝试过。
B. Win2D - 不支持 Windows 7,也不支持 .NET Framework 3.5。
C. SharpDX(开源,积极维护):
试过用这个。不幸的是,直到 v.3.0.0 才添加 Direct2D,它需要 .NET Framework 4.0+。所以这不是一个选择,直到我们准备好对我们的应用程序进行更重大的改革。
D. SlimDX(开源,2012 年最后更新):
成功安装并呈现到独立 Direct2D 窗口。
坚持调整此以呈现到“GDI 上下文”,如上面链接的“互操作性概述”中所述。
来自“互操作性”链接的 C++ 代码:
// Create a DC render target.
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(
DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_IGNORE),
0,
0,
D2D1_RENDER_TARGET_USAGE_NONE,
D2D1_FEATURE_LEVEL_DEFAULT
);
hr = m_pD2DFactory->CreateDCRenderTarget(&props, &m_pDCRT);
尝试编写VB代码:
Dim factory As New Direct2D.Factory
' --- THIS WORKS using SlimDX, SlimDX.Direct2D ---
' (But it is not what I need; taken from SlimDX sample code)
' Stand-alone D2D window (NOT to GDI)
' "IntPtr handle" is "The window handle to associate with the device.".
Dim windowProperties As New WindowRenderTargetProperties(handle, New Size(600, 600))
Dim target As New WindowRenderTarget(factory, windowProperties)
' --- Hand-Translation of C++ code from "interoperability" link ---
Dim targetProperties As New RenderTargetProperties
targetProperties.Type = RenderTargetType.Default
targetProperties.PixelFormat = New PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Ignore)
' *** How invoke "ID2D1Factory::CreateDCRenderTarget"? ***
' (There aren't many methods on SlimDX.Direct2D.Factory "factory" above,
' so if it is possible at all, SlimDX must do this some other way.)
' TODO
如何前进
第一个问题:上面链接中描述的 D2D/GDI 互操作性是否可用于指定的目标平台(.NET 3.5、Windows 7)?
如果不是,那么我正在尝试的事情是不可能的。虽然如果 Windows 7 是问题所在,那么“Windows 10 上的 .NET 3.5”的解决方案将是值得了解的。
第二个问题假设互操作性是可能的,那么我面临SlimDX的限制吗?或者我忽略了什么?我不想在这个解决方案中添加 C++ 项目,但是如果可以预编译自定义 C++ dll,然后使用 [除了 SlimDX dll],那将是一个(几乎)可以容忍的解决方案。
手动编写托管包装器而不是 C++ 代码来访问所需的 [但我在 SlimDX 中找不到] 来初始化 D2D/GDI 互操作性?如何从上面那个链接转换 C++ 代码?
更新
在 SlimDX 中找到所需的调用。详情见我的回答。
【问题讨论】:
-
您无需包含整个 SlimDX 项目即可使用它。下载他们的 SDK 并添加对 .dll 文件的引用(它们以预编译的形式出现)。您可以在 Developer SDK 下的 their website 上找到它。
-
@VisualVincent - 是的,这就是我正在做的。我现在已经添加了相关的 VB 代码,所以你可以看到我卡在哪里了。
-
(我提到添加一些 DLL 是因为我需要的功能似乎不在 SlimDX 中。)
-
哦,我刚刚明白你的意思:你不想写你自己的包装器。 - 如果事实证明不存在适合您需求的包装器,为什么为您需要的功能编写自己的包装器会如此糟糕?我一直混合使用 VB.NET 和 C++,因为它使(本机)代码更易于使用,并且也不太可能失败,因为您可以使包装器比原始函数简单得多。
标签: vb.net winforms windows-7 gdi+ direct2d