我一直在2009年3月DirectX SDK中为Direct3D应用程序测试DXUT功能。它们似乎具有许多有用的功能,包括自动检测DirecX10或DirectX9以及窗口管理功能,这些功能绕过了Direct3D通常要求的许多繁琐的窗口管理任务。但是,当我使用DXUTSetWindow函数让Direct3D绘制到已经创建的窗口时,我遇到了问题。在这种情况下,CFrameWndEx的查看子窗口是应用程序的主窗口。

如果将bHandleMessages参数设置为true,则一切都会调整大小并重置,而无需我进行任何干预。但是,当我尝试关闭程序时,应用程序崩溃了(并立即退出,因此我什至无法中断导致崩溃的原因),并且发生了一系列内存泄漏。如果将bHandleMessages设置为false,则无法进行任何大小调整,但是退出时不会崩溃,也不会导致内存泄漏。

看来DXUTMainLoop正在寻找WM_QUIT消息以退出,然后清除所有Direct3D对象,子窗口从未接收到该对象。我已经尝试了以下方法,但均未成功:


覆盖CFrameWndExOnClose功能,并手动向该子级发送WM_QUIT消息。
DXUTMainLoop调用放在辅助线程上。
覆盖CFrameWndEx::DefWindowProc并使用DXUTStaticWndProc函数(DXUT文档在使用DXUTSetWindow时会使用该函数,但在任何示例中均未显示)。
将窗口设置为使用CFrameWndEx的句柄,并为子窗口创建单独的交换链。似乎DXUT会使DXUTSetWindow中使用的句柄变黑,而不管OnD3D9FrameRender回调中是否对其进行了任何处理。


更新:覆盖子窗口的DefWindowPro c并从子窗口的DXUTStaticWndProc调用DefWindowProc之后,我能够使应用程序运行,调整大小,处理设备丢失并退出而不会崩溃,内存泄漏。这是通过将bHandleMessages设置为false来完成的。但是,这会导致一个新问题:

Direct3D绘图表面比子窗口的区域小几个像素,从而在绘图表面周围留下了视频噪声的边界。即使bHandleMessages为true,也不会发生这种情况,即使它在同一HWND函数中的同一DXUTStaticWndProc上运行也是如此。

更新2:看起来像素问题现在已经解决。使用从第一次更新到该问题的方案,我发现仅在CWnd::DefWindowProc不返回0的情况下,才需要在子窗口的覆盖的DefWindowProc中调用DXUTStaticWndProc。因此,以下代码似乎可以解决该问题:

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语言的所有代码进行编码”。简直太糟糕了。

09-10 04:57
查看更多