Step 5: Rendering to the Surfaces
After the primary surface and a back buffer have been created, the DDEX1 example renders some text on the primary surface and back buffer surface by using standard Windows GDI functions, as shown in the following example:
if (lpDDSPrimary->GetDC(&hdc) == DD_OK)
{
SetBkColor(hdc, RGB(0, 0, 255));
SetTextColor(hdc, RGB(255, 255, 0));
TextOut(hdc, 0, 0, szFrontMsg, lstrlen(szFrontMsg));
lpDDSPrimary->ReleaseDC(hdc);
}
if (lpDDSBack->GetDC(&hdc) == DD_OK)
{
SetBkColor(hdc, RGB(0, 0, 255));
SetTextColor(hdc, RGB(255, 255, 0));
TextOut(hdc, 0, 0, szBackMsg, lstrlen(szBackMsg));
lpDDSBack->ReleaseDC(hdc);
}
The example uses the IDirectDrawSurface3::GetDC method to retrieve the handle of the device context, and it internally locks the surface. If you are not going to use Windows functions that require a handle of a device context, you could use the IDirectDrawSurface3::Lock and IDirectDrawSurface3::Unlock methods to lock and unlock the back buffer.
Locking the surface memory (whether the whole surface or part of a surface) ensures that your application and the system blitter cannot obtain access to the surface memory at the same time. This prevents errors from occurring while your application is writing to surface memory. In addition, your application cannot page flip until the surface memory is unlocked.
After the surface is locked, the example uses standard Windows GDI functions: SetBkColor to set the background color, SetTextColor to select the color of the text to be placed on the background, and TextOut to print the text and background color on the surfaces.
After the text has been written to the buffer, the example uses the IDirectDrawSurface3::ReleaseDC method to unlock the surface and release the handle. Whenever your application finishes writing to the back buffer, you must call either IDirectDrawSurface3::ReleaseDC or IDirectDrawSurface3::Unlock, depending on your application. Your application cannot flip the surface until the surface is unlocked.
Typically, you write to a back buffer, which you then flip to the primary surface to be displayed. In the case of DDEX1, there is a significant delay before the first flip, so DDEX1 writes to the primary buffer in the initialization function to prevent a delay before displaying the surface. As you will see in a subsequent step of this tutorial, the DDEX1 example writes only to the back buffer during WM_TIMER. An initialization function or title page may be the only place where you might want to write to the primary surface.
Note After the surface is unlocked by using IDirectDrawSurface3::Unlock, the pointer to the surface memory is invalid. You must use IDirectDrawSurface3::Lock again to obtain a valid pointer to the surface memory.