Функции для работы с поверхностями
Наше приложение Bounce является очень простым, поэтому функция CreateCustom Surfaces() делает не так уж много. Реальное приложение может создавать десятки и даже сотни поверхностей. Класс
DirectDrawWin содержит несколько служебных функций, которые могут пригодиться при работе с поверхностями, поэтому мы ненадолго отвлечемся от приложения Bounce и рассмотрим эти функции:
LPDIRECTDRAWSURFACE CreateSurface(LPCTSTR filename, BOOL installpalette=FALSE); LPDIRECTDRAWSURFACE CreateSurface(DWORD w, DWORD h ); BOOL LoadSurface(LPDIRECTDRAWSURFACE surf, LPCTSTR filename); BOOL ClearSurface(LPDIRECTDRAWSURFACE surf, DWORD clr, RECT* rect=0); BOOL ClearSurface( LPDIRECTDRAWSURFACE surf, DWORD r, DWORD g, DWORD b, RECT* rect=0 ); BOOL GetSurfaceDimensions( LPDIRECTDRAWSURFACE surf, DWORD& w, DWORD& h );
|
Первая функция нам уже знакома. Функция
CreateSurface(), получая имя BMP-файла, создает новую поверхность на основании его содержимого. Кроме того, эта функция может извлекать палитру из 8-битных файлов и назначать ее поверхности. Реализация этой функции подробно рассматривается в
главе 5.
Вторая функция -
CreateSurface() - создает поверхность заданных размеров. Эта функция полезна в тех случаях, когда вам нужна новая поверхность, содержимое которой не связано с BMP-файлом. Данная версия
CreateSurface() реализована так:
LPDIRECTDRAWSURFACE DirectDrawWin::CreateSurface( DWORD w, DWORD h ) { DWORD bytes=w*h*(displaydepth/8); DDSURFACEDESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.dwSize = sizeof(desc); desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; desc.dwWidth = w; desc.dwHeight = h; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; LPDIRECTDRAWSURFACE surf; HRESULT r=ddraw2->CreateSurface( &desc, &surf, 0 ); if (r==DD_OK) { TRACE("CreateSurface(%d,%d) created in video memory \n", w, h); return surf; } desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; r=ddraw2->CreateSurface( &desc, &surf, 0 ); if (r==DD_OK) { TRACE("CreateSurface(%d,%d) allocated in system memory \n", w, h); return surf; } TRACE("CreateSurface(%d,%d) failed\n", w, h); return 0; }
|
Функция
ClearSurface() получает три аргумента: указатель на заполняемую поверхность; величину, присваиваемую каждому пикселю; и необязательную структуру
RECT, которая определяет заполняемую область поверхности.
После проверки указателя мы подготавливаем экземпляр структуры
DDBLTFX. Полю
dwFillColor присваивается величина, используемая для заполнения, а сама операция осуществляется функцией
Blt() интерфейса
DirectDrawSurface. Флаг
DDBLT_COLORFILL сообщает
Blt() о том, что вместо блиттинга выполняется цветовое заполнение.
Получившаяся функция удобна, но ей не хватает универсальности. Дело в том, что величина, применяемая для заполнения поверхности, может иметь различный смысл. Например, для палитровых поверхностей она представляет собой индекс в палитре. Без предварительной проверки палитры невозможно предсказать, какой цвет будет использоваться для заполнения. Аналогичные проблемы возникают и для беспалитровых поверхностей, поскольку конкретное значение пикселя зависит от глубины и формата пикселей. Форматы пикселей особенно часто различаются в режимах High Color, поэтому заполнение поверхности конкретным цветом превращается в нетривиальную задачу.
Вторая версия
ClearSurface() получает в качестве аргументов RGB-составляющие и рассчитывает по ним конкретную величину, присваиваемую пикселям поверхности. В таком варианте функция становится более универсальной, но и работает медленнее; быстродействие особенно сильно снижается для палитровых поверхностей, потому что нужный цвет приходится искать в палитре. Код этой функции будет рассмотрен в
главе 5. Нам остается рассмотреть лишь функцию
GetSurfaceDimensions(), которая получает указатель на поверхность и возвращает ее ширину и высоту. Код этой функции выглядит так:
BOOL DirectDrawWin::GetSurfaceDimensions( LPDIRECTDRAWSURFACE surf, DWORD& w, DWORD& h ) { if (surf==0) return FALSE; DDSURFACEDESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.dwSize=sizeof(desc); desc.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; if (surf->GetSurfaceDesc( &desc )!=DD_OK) return FALSE; w=desc.dwWidth; h=desc.dwHeight; return TRUE; }
|
После проверки указателя мы подготавливаем экземпляр структуры
DDSURFACEDESC. Нас интересуют ширина и высота поверхности, поэтому в поле
dwFlags заносятся флаги
DDSD_WIDTH и
DDSD_HEIGHT.
Затем мы вызываем функцию
GetSurfaceDesc() интерфейса
DirectDrawSurface и передаем ей указатель на структуру с описанием поверхности. Функция
GetSurfaceDesc() сохраняет размеры поверхности в полях
dwWidth и
dwHeight. Они присваиваются переданным по ссылке переменным
w и
h типа
DWORD, после чего функция завершается.
Все рассмотренные функции встречаются в демонстрационных программах этой книги, однако вы вовсе не обязаны пользоваться ими. Впрочем, независимо от этого вам будет полезно познакомиться с их реализацией.
Содержание Назад Вперед