|
|

楼主 |
发表于 2006-11-29 21:06:00
|
显示全部楼层
Re:求助:D3D全屏模式和桌面相互切换的问题
谢谢高手指点。
经过多次研究和实验,这个问题我已经搞定。下面是我的一个比较好的解决方法(比D3DFramework的方法好),在此公开一下:
Namespace TouringSon.GameFramework
. . . . . .
Module Console
. . . . . .
Friend Graphics_Device As Direct3D.Device
Friend Graphics_DeviceEnable As Boolean
Friend Graphics_DeviceState As Direct3D.PresentParameters
. . . . . .
''' <summary>
''' 测试图形设备是否可用。
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function mGraphics_IsDeviceEnable() As Boolean
If Graphics_Device Is Nothing Then Graphics_DeviceEnable=False:Return False
Try
Graphics_Device.TestCooperativeLevel()
Catch ex As Direct3D.DeviceLostException '设备刚刚丢失,无法进行任何操作:不可用。
Graphics_DeviceEnable=False
Return False
Catch ex As Direct3D.DeviceNotResetException '设备处于丢失状态丢失,但已经可以进行恢复处理:尝试一次恢复操作(操作结果未知,视为不可用)。
Graphics_DeviceEnable=False
Graphics_Device.Reset(Graphics_DeviceState)
Return False
End Try
Graphics_DeviceEnable=True
Return True
End Function
''' <summary>
''' 更新绘图区内容。
''' </summary>
''' <remarks></remarks>
Public Sub mGraphicsUpdateScreen()
检查数据。
If Graphics_Device Is Nothing Then Exit Sub
If Graphics_DeviceEnable = False Then Exit Sub
'刷新。
Graphics_Device.Present(Graphics_DeviceState.DeviceWindowHandle)
End Sub
发现关键问题有两个:
1第二个"Catch“:Graphics_Device.Reset()以后并不能立刻使用,所以我称为”尝试一次恢复“。是否可用要检查下一次TestCoorperativeLevel()的结果。也就是再调用一次我写的mGraphics_IsDeviceEnable()函数。
这样,使用mGraphics_IsDeviceEnable()在返回设备是否可用的同时就可以恢复设备。可以不断调用并检查返回值直到返回True。用VB6可以模仿写出类似的代码。
2刷新时的Present():要使用Present(OverrideWindowHandle As IntPtr)重载方法。传递窗口句柄,这个句柄一般和设备丢失之前的窗口相同,我的方法是在PresentParameters.DeviceWindowHandle中保存一个窗体句柄(VB6是D3DPresent_Parameters.hDeviceWindow)。
以前经常使用不带参数的Present(),所以设备恢复后不知往哪里画图,出现设备恢复正常,但窗口复原并没有图像的现象。
这里只恢复了设备,图形资源的恢复可利用Device的事件处理,但是很麻烦,我更喜欢把资源声明为D3DPool.Managed。
这是我摸索的经验,至于为何Reset()以后不能立刻使用还不清楚,希望有深入理解Windows窗体内部原理的高手继续讨论。 |
|