Locking SurfacesNot surprisingly, the function we'll use to do this is IDirectDrawSurface7::Lock(). Let's take a look at it. HRESULT Lock( LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent ); Remember to check the function call for success or failure, or it could lead to problems. If the lock fails, then the pointer to the surface won't be correct, and who knows what part of memory you'd be messing with then? The parameters for this function are: LPRECT lpDestRect: This is a RECT that represents the area on the surface we want to lock. If you want to lock the entire surface, simply pass NULL. LPDDSURFACEDESC2 lpDDSurfaceDesc: This is a pointer to a DDSURFACEDESC2 structure, which is the big baddie we covered last time. All you need to do is initialize the structure, then pass the pointer. If Lock() succeeds, it fills in some of the members of the structure for you to use. DWORD dwFlags: What kind of DirectX function would this be if it didn't have a list of flags do go along with it? Here are the most useful ones, which you can combine in the usual way:
Since we'll be using the lock to manipulate pixels, you'll always want to use DDLOCK_SURFACEMEMORYPTR. And even though we haven't gotten to using the blitter yet, it's usually a good idea to include DDLOCK_WAIT as well. HANDLE hEvent: This parameter is not used and should be set to NULL. Once we lock the surface, we need to take a look at the DDSURFACEDESC2 structure to get some information about the surface. We went over all of the members of this structure last time, but there are only two that we need to concern ourselves with at this point. Since both are very important, I'll list those two here again. LONG lPitch: The lPitch member represents the number of bytes in each display line. You'd think this would be obvious. For example, in 640x480x16, there are 640 pixels in each line, and each one requires 2 bytes for color information, so the pitch (also called the "stride") should be 1280 bytes, right? Well, on some video cards, it will be greater than 1280. The extra memory on each line doesn't hold any graphical data, but sometimes it's there because the video card can't create a perfectly linear memory mode for the display mode. This will happen on a very small percentage of video cards, but you need to take it into account. LPVOID lpSurface: This is a pointer to the memory represented by the surface. No matter what display mode you're using, DirectDraw creates a linear addressing mode you can use to manipulate the pixels of the surface. The lpSurface pointer is pretty easy to understand, but are you following me on this whole pitch thing? It's an important value to remember, because you'll have to use it to calculate the offset to a particular pixel. We'll get back to it in just a minute. There's one thing I want to get out of the way first. When you're done plotting pixels, you need to unlock the surface that you locked. The prototype for IDirectDrawSurface7::Unlock() is this: HRESULT Unlock(LPRECT lpRect); The parameter is the same RECT you passed to Lock(). All right, let's plot some pixels. |
|||||||||