IDirect3DDevice7::BeginScene和IDirect3DDevice7::EndScene方法在绘制开始或完成时会向系统发出信号。只能在调用这些方法之间调用绘制方法。即使绘制方法失败了,也应当在再次调用BeginScene 之前调用EndScene。
(3)更新显示
一旦场景被绘制到绘制目标表面上,就可以在屏幕上显示结果了。窗口化的应用程序通常通过将绘制目标表面的内容按位块传送到主表面的方法来执行这一任务。使用页面翻转的全屏应用程序则简单地翻转位于翻转链中的表面。Triangle例子程序使用前一种方法,因为它在窗口中运行使用下列代码:
HRESULT ShowFrame()
{
if( NULL == g_pddsPrimary )
return E_FAIL;
// 现在处于窗口化模式,因此执行一次从后台缓冲区到主表面上的当前位置之
// 间的位块传送
return g_pddsPrimary->Blt( &g_rcScreenRect, g_pddsBackBuffer,
&g_rcViewportRect, DDBLT_WAIT, NULL );
}
上面的应用程序定义的函数简单地将绘制目标表面位块传送到位于桌面上的窗口中。例子程序在g_rcScreenRect全局变量中跟踪位块传送的目标矩形,该矩形在用户移动窗口时更新。
6. 关闭
在执行期间的某些点处,应用程序必须关闭。关闭一个DirectX应用程序不仅意味着应当销毁应用程序的窗口,也必须释放应用程序使用的任何DirectX对象并使指向它们的指针无效。当收到WM_DESTROY消息时,Triangle调用一个应用程序定义的函数来处理这样的清理,其名称是Cleanup3DEnvironment,如下所示:
HRESULT Cleanup3DEnvironment()
{
// 清除任何为这种场景创建的对象
App_DeleteDeviceObjects( g_pd3dDevice );
// 释放由应用程序使用的DDraw和D3D对象
if( g_pD3D ) g_pD3D->Release();
if( g_pddsBackBuffer ) g_pddsBackBuffer->Release();
if( g_pddsPrimary ) g_pddsPrimary->Release();
// 为释放D3DDEVICE进行一次安全检查。RefCount应当是零
if( g_pd3dDevice )
if( 0 < g_pd3dDevice->Release() )
return E_FAIL;
//为释放DDRAW进行一次安全检查。RefCount应当是零
if( g_pDD )
if( 0 < g_pDD->Release() )
return E_FAIL;
g_pd3dDevice = NULL;
g_pD3D = NULL;
g_pddsBackBuffer = NULL;
g_pddsPrimary = NULL;
g_pDD = NULL;
return S_OK;
}
上面的函数通过为每一个对象调用IUnknown::Release方法释放了它所使用的DirectX对象。因为这个例子程序遵循了COM规则,所以大多数对象的引用计数应当变为零并自动从内存中卸载。
除了关闭之外,在正常执行期间会多次调用清除代码。例如,在用户改变了桌面分辨率或颜色深度时,在需要销毁并重新创建正在使用的DirectX对象时都需要这样做。所以将应用程序的清除代码放在一个非常便利的位置,在需要执行清除任务时就可以调用清除代码