我一直在 2009 年 3 月的 DirectX SDK 中试验 Direct3D 应用程序的 DXUT 函数。它们似乎具有许多有用的功能,包括自动检测 DirecX10 或 DirectX9 以及绕过 Direct3D 通常需要的许多繁琐窗口管理任务的窗口管理功能。但是,我在使用 DXUTSetWindow 时遇到问题使 Direct3D 绘制到已创建窗口的函数。在本例中,CFrameWndEx
的 View 子窗口是应用程序的主窗口。
如果我将 bHandleMessages
参数设置为 true,所有内容都会调整大小和重置,而无需我进行任何干预。但是当我尝试关闭程序时应用程序崩溃(并立即退出,所以我什至无法中断查看导致崩溃的原因)并出现一堆内存泄漏。如果我将 bHandleMessages
设置为 false,则调整大小都不起作用,但我不会崩溃,也不会在退出时发生任何内存泄漏。
它看起来像 DXUTMainLoop正在寻找一个 WM_QUIT
消息来退出,然后清除所有 Direct3D 对象,子窗口永远不会接收到该对象。我尝试了以下但没有成功:
- 重写
CFrameWndEx
的OnClose
函数并手动向 child 发送WM_QUIT
消息。 - 将
DXUTMainLoop
调用放在工作线程上。 - 重写
CFrameWndEx::DefWindowProc
并使用 DXUTStaticWndProc函数(如果使用DXUTSetWindow
,DXUT 文档说要使用,但忽略在任何示例中显示)。 - 将窗口设置为使用
CFrameWndEx
的句柄并为子窗口创建单独的交换链。似乎 DXUT 将DXUTSetWindow
中使用的句柄涂黑,无论是否在 OnD3D9FrameRender 中对其进行了任何操作。回调。
更新:覆盖子窗口的 DefWindowPro
c 并从子窗口的 DefWindowProc
调用 DXUTStaticWndProc
后,我能够获得应用程序运行、调整大小、处理设备丢失和退出而不会崩溃、内存泄漏。这是通过将 bHandleMessages
设置为 false 来完成的。但是,这会导致一个新问题:
Direct3D 绘图表面比子窗口的区域小几个像素,在绘图表面周围留下视频噪声边界。当 bHandleMessages
为真时,这不会发生,即使它在相同的 DXUTStaticWndProc
函数中对相同的 HWND
进行操作。
更新 2:看起来像素问题现在已经解决了。使用这个问题的第一次更新的方案,我发现我只需要在子窗口的覆盖 DefWindowProc
中调用 CWnd::DefWindowProc
只有 DXUTStaticWndProc
没有返回 0。所以下面的代码似乎可以解决它:
LRESULT ChildView::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam){
LRESULT lr = DXUTStaticWndProc(this->GetSafeHwnd(), message, wParam, lParam);
if(lr != 0) {
return CWnd::DefWindowProcW(message, wParam, lParam);
}
return lr;
}
我的另一个问题仍然存在,是否值得使用 DXUT 库?它会在多大程度上限制我使用 DirectX 可以做什么?我是否应该返回到手动管理所有 Direct3D 对象、设备设置/重置和渲染?
最佳答案
在我看来,DXUT 库是垃圾。我会从中窃取您需要的任何代码并将其直接插入到您的应用程序中并自由地应用重构。整个 DXUT 哲学似乎是“尽管是 2009 年,但人们认为对象很难,所以我们将设置 1988 年的回归机器,并使用全局函数对所有 C 风格进行编码”。太糟糕了。
关于c++ - 在 MFC Direct3D 应用程序中使用 DXUTSetWindow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1066651/