Для прямого доступа к поверхности необходимо предварительно вызвать функцию Lock() интерфейса DirectDrawSurface. Lock() получает экземпляр структуры DDSURFACEDESC и возвращает указатель на левый верхний пиксель поверхности, шаг поверхности, ее размеры и даже формат пикселей (структура DDSURFACEDESC содержит экземпляр DDPIXELFORMAT, поэтому вызов GetPixelFormat() интерфейса DirectDrawSurface оказывается необязательным). Прототип функции Lock() выглядит так:
| HRESULT Lock(LPRECT rect, LPDDSURFACEDESC desc, DWORD flags, HANDLE event); |
Второй аргумент функции Lock() - структура DDSURFACEDESC, которая используется для возвращения указателя на память поверхности (поле lpSurface) и шага поверхности (поле lPitch). Функция Lock() (как и другие функции DirectDraw) требует правильно присвоить значение полю dwSize структуры DDSURFACEDESC.
Третий аргумент используется для настройки параметров Lock(). В него могут входить следующие флаги:
На момент выхода DirectX 5 флаг DDLOCK_EVENT не поддерживался. Возможно, в будущих версиях DirectDraw он будет использоваться совместно с последним аргументом Lock() для реализации альтернативного метода блокировки поверхностей.
Флаги DDLOCK_READONLY и DDLOCK_WRITEONLY следует использовать в том случае, когда доступ к памяти поверхности осуществляется исключительно для чтения или записи. В большинстве ситуаций эти флаги ни на что не действуют, однако в видеорежимах «Mode X» DirectDraw использует их для оптимизации доступа к поверхности.
Флаг DDLOCK_SURFACEMEMORYPTR необязателен, потому что он задает поведение Lock(), которое и так является стандартным. Lock() возвращает указатель на память поверхности как с этим флагом, так и без него, поэтому мы не станем использовать его в своих программах (флаг DDLOCK_SURFACEMEMORYPTR на самом деле определен равным 0, так что я нисколько не преувеличиваю, говоря, что он ни на что не влияет).
Флаг DDLOCK_WAIT показывает, что функция Lock() должна дождаться завершения блокировки в том случае, если в данный момент поверхность используется для другой цели — например, участвует в операции блиттинга или переключения поверхностей. Если этот флаг задан, Lock() работает в цикле до тех пор, пока поверхность не освободится для блокировки или пока не произойдет ошибка. При отсутствии флага DDLOCK_WAIT функция Lock() для занятой поверхности возвратит код DDERR_SURFACEBUSY, и блокировка не состоится. Для упрощения кода мы будем использовать этот флаг.