Step 6: Shut Down

At some point during execution, your application must shut down. Shutting down a DirectX application not only means that you should destroy the application window, but you also deallocate any DirectX objects your application uses and invalidate the pointers to them. The Triangle calls an application-defined function to handle this cleanup, called Cleanup3DEnvironment, when it receives a WM_DESTROY message:

HRESULT Cleanup3DEnvironment()
{
    // Cleanup any objects created for the scene
    App_DeleteDeviceObjects( g_pd3dDevice, g_pvViewport );
 
    // Release the DDraw and D3D objects used by the app
    if( g_pvViewport )     g_pvViewport->Release();
    if( g_pD3D )           g_pD3D->Release();
    if( g_pddsBackBuffer ) g_pddsBackBuffer->Release();
    if( g_pddsPrimary )    g_pddsPrimary->Release();
    if( g_pDD4 )           g_pDD4->Release();
 
    // Do a safe check for releasing the D3DDEVICE. RefCount should be zero.
    if( g_pd3dDevice )
        if( 0 < g_pd3dDevice->Release() )
            return E_FAIL;
 
    // Do a safe check for releasing DDRAW. RefCount should be zero.
    if( g_pDD1 )
        if( 0 < g_pDD1->Release() )
            return E_FAIL;
 
    g_pvViewport     = NULL;
    g_pd3dDevice     = NULL;
    g_pD3D           = NULL;
    g_pddsBackBuffer = NULL;
    g_pddsPrimary    = NULL;
    g_pDD4           = NULL;
    g_pDD1           = NULL;
 
    return S_OK;
} 
 

The preceding function deallocates the DirectX objects it uses by calling the IUnknown::Release methods for each object. Because the tutorial follows COM rules, the reference counts for most objects should become zero and are automatically removed from memory.

In addition to shut down, there are times during normal execution—such as when the user changes the desktop resolution or color depth—when you might need to destroy and re-create the DirectX objects in use. As a result, it's handy to keep your application's cleanup code in one place, which can be called when the need arises.