我知道这个问题的术语可能都是错误的,但请您从我的外行人角度来看待,并尝试理解我(我没有计算机技术的背景,我是一个自学的爱好者。我最接近编程语言的正式教育是在学校机器人俱乐部)。
我想要的是能够使用托管DirectX 12作为我的应用程序的“背景”,带有游戏循环等所有内容。如果可能的话,还希望能够在实际的DirectX游戏周围拥有WPF控件,例如功能区、工具箱或菜单。我已经在互联网上寻找了很久,但发现的都是非常陈旧的Windows和DirectX 9.0的资料;我希望现在有一些新的东西。
我尝试了Windows窗体的方法,基本上是这样的:
没有任何异常被抛出,窗口根本没有被渲染。应用程序运行,但窗口没有显示出来。我原本认为这不会起作用,因为没有游戏循环,
接着我发现每帧(或者说每个tick)都会调用
于是我尝试了这个方法:
我想要的是能够使用托管DirectX 12作为我的应用程序的“背景”,带有游戏循环等所有内容。如果可能的话,还希望能够在实际的DirectX游戏周围拥有WPF控件,例如功能区、工具箱或菜单。我已经在互联网上寻找了很久,但发现的都是非常陈旧的Windows和DirectX 9.0的资料;我希望现在有一些新的东西。
我尝试了Windows窗体的方法,基本上是这样的:
using System;
using System.Windows;
using System.Windows.Interop;
using Microsoft.DirectX.Direct3D;
using DColor = System.Drawing.Color;
public partial class MainWindow : Window
{
Device device;
public MainWindow()
{
InitializeComponent();
initDevice();
}
private void initDevice()
{
try
{
PresentParameters parameters = new PresentParameters();
parameters.Windowed = true;
parameters.SwapEffect = SwapEffect.Discard;
IntPtr windowHandle = new WindowInteropHelper(this).Handle;
device = new Device(0, DeviceType.Hardware, windowHandle, CreateFlags.HardwareVertexProcessing, parameters);
}
catch(Exception e)
{
MessageBox.Show("initDevice threw an Exception\n" + e.Message, "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void render()
{
device.Clear(ClearFlags.Target, DColor.LightGreen, 0f, 1);
device.Present();
}
}
没有任何异常被抛出,窗口根本没有被渲染。应用程序运行,但窗口没有显示出来。我原本认为这不会起作用,因为没有游戏循环,
render
也没有从任何地方调用,但我没想到窗口甚至都没有显示出来。如果我注释掉调用initDevice()的那一行,WPF的空白窗口就会正常显示。接着我发现每帧(或者说每个tick)都会调用
CompositionTarget.Rendering
事件,所以必须使用该事件的处理程序作为游戏循环。于是我尝试了这个方法:
using System;
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Forms.Integration;
using Microsoft.DirectX.Direct3D;
using DColor = System.Drawing.Color;
using System.Windows.Forms;
public partial class MainWindow : Window
{
Device device = null;
MemoryStream stream;
PictureBox display;
WindowsFormsHost host;
public MainWindow()
{
InitializeComponent();
initDevice();
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
render();
}
private void initDevice()
{
try
{
PresentParameters parameters = new PresentParameters();
parameters.Windowed = true;
parameters.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, display, CreateFlags.HardwareVertexProcessing, parameters);
stream = new MemoryStream();
device.SetRenderTarget(0, new Surface(device, stream, Pool.Managed));
}
catch(Exception e)
{
System.Windows.MessageBox.Show("initDevice threw an Exception\n" + e.Message, "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void render()
{
device.Clear(ClearFlags.Target, DColor.LightGreen, 0f, 1);
device.Present();
display.Image = Image.FromStream(stream);
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
host = new WindowsFormsHost();
display = new PictureBox();
host.Child = display;
mainGrid.Children.Add(host);
}
}
尽管应用程序正在运行且未崩溃,但仍未显示任何窗口。
最终我尝试了相同的方法,但是没有处理CompositionTarget.Rendering
,而是使用一个DispatcherTimer,并在其中调用render的Tick
事件处理程序。结果相同:没有窗口。
有人能指导我走向正确的方向吗?