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 IDirectDrawSurface::GetDC method to retrieve the handle to the device context, and it internally locks the surface. If you are not going to use Windows functions that require a handle to a device context, you could use the IDirectDrawSurface::Lock and IDirectDrawSurface::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 the standard SetBkColor Windows GDI function 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 IDirectDrawSurface::ReleaseDC method to unlock the surface and release the handle. Whenever your application finishes writing to the back buffer, you must call either IDirectDrawSurface::ReleaseDC or IDirectDrawSurface::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 IDirectDrawSurface::Unlock, the pointer to the surface memory is invalid. You must use IDirectDrawSurface::Lock again to obtain a valid pointer to the surface memory.