подробно.
За функций LoadAvi() объявляется функция DrawScene(). Мы воспользуется ею для вывода кадров видеоролика. Помимо извлечения и восстановления кадров видеопотока DrawScene() осуществляет блиттинг и переключение страниц, необходимые для отображения кадра.
Функция RestoreSurfaces() отвечает за восстановление поверхностей, хранящихся в видеопамяти, в случае их потери. Как вы вскоре убедитесь, в нашей программе эта функция выглядит примитивно.
Функции CreateAviSurface() и UpdateAviSurface() отвечают за создание и обновление поверхности AVI. Размеры поверхности AVI определяются размерами кадров AVI-файла, выбранного пользователем, поэтому при каждом открытии нового AVI-файла создается новая поверхность AVI. Функция UpdateAviSurface() готовит поверхность AVI к отображению, копируя выходные данные функции ICDecompress() в память поверхности.
Последней объявлена функция InstallPalette(), которая устанавливает палитру AVI перед началом воспроизведения ролика. Однако перед этим она должна извлечь данные палитры из потока AVI.
Оставшаяся часть класса содержит лишь переменные. Мы познакомимся с ними во время рассмотрения программы.
Мы будем рассматривать функции примерно в порядке их выполнения. Начнем с функции OnCreate(), которая выглядит так:
int AviPlayWin::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (DirectDrawWin::OnCreate(lpCreateStruct) == -1) return -1;
AVIFileInit();
ShowDialog();
return 0;
}
Сначала мы вызываем версию OnCreate() базового класса (а она инициализирует DirectDraw). Если вызов этой функции закончится неудачей, продолжать бессмысленно, и мы возвращаем код неудачного завершения –1.
Затем мы вызываем функцию AVIFileInit(), которая инициализирует Video For Windows. После этого можно спокойно пользоваться функциями VFW.
Наконец, функция ShowDialog() выводит диалоговое окно для выбора AVI-файла и ожидает ввод от пользователя. Однако перед тем, как обсуждать ShowDialog(), необходимо рассмотреть функцию SelectInitialDisplayMode(), которая вызывается при использовании функции OnCreate() класса DirectDrawWin.
Как упоминалось выше, функция SelectInitialDisplayMode() решает три задачи. Она выглядит так:
int AviPlayWin::SelectInitialDisplayMode() {
GetSystemPalette();
int i, nummodes=GetNumDisplayModes();
DWORD w,h,d;
for (i=0;i<nummodes;i++) {
DisplayModeDescription desc;
GetDisplayModeDimensions(i, w, h, d);
if (d==8) {
desc.w=w;
desc.h=h;
desc.d=d;
desc.desc.Format('%dx%d', w, h);
displaymode.Add(desc);
}
}
int curdepth=GetDisplayDepth();
if (curdepth!=8) ddraw2->SetDisplayMode(640, 480, curdepth, 0, 0);
for (i=0;i<nummodes;i++) {
GetDisplayModeDimensions(i, w, h, d);
if (w==640 && h==480 && d==8) return i;
}
return 1;
}
Перед тем как выполнять свою основную задачу (выбор исходного видеорежима), функция SelectInitialDisplayMode() вызывает функцию GetSystemPalette(). В свою очередь GetSystemPalette() создает палитру DirectDraw на базе текущей палитры Windows. Эта палитра обеспечивает правильный вывод диалогового окна независимо от того, какая палитра была установлена для воспроизведения ролика. Вспомните — GDI ничего не знает о DirectDraw и поэтому всегда пытается вывести диалоговое окно с использованием системной палитры, несмотря на то что она могла быть переопределена DirectDraw.
Затем функция SelectInitialDisplayMode() перебирает список доступных видеорежимов и сохраняет описания 8-битных режимов в массиве displaymodes. Позднее этот массив передается диалоговому окну для вывода списка доступных видеорежимов.
Наконец, функция ищет 8-битный режим с разрешением 640x480. Этот режим выбран лишь потому, что он поддерживается абсолютным большинством видеокарт (если не всеми). После вывода диалогового окна пользователь сможет выбрать любой другой 8-битный режим.
Давайте рассмотрим функцию для вывода диалогового окна. Функция ShowDialog() приведена в листинге 8.2.
Листинг 8.2. Функция ShowDialog()
void AviPlayWin::ShowDialog() {
const CRect& displayrect=GetDisplayRect();
if (displayrect.Width()<640 || displayrect.Height()>480) ddraw2->SetDisplayMode(640, 480, 8, 0, 0);
ClearSurface(backsurf, 0);
ClearSurface(primsurf, 0);
primsurf->SetPalette(syspal);
ddraw2->FlipToGDISurface();
ShowCursor(TRUE);
if (avidialog==0) {
avidialog=new AviDialog();
avidialog->SetArray(&displaymode);
}
if (avistream) AVIStreamRelease(avistream), avistream=0;
if (avidialog->DoModal()==IDCANCEL) {
PostMessage(WM_CLOSE);
return;
}
ShowCursor(FALSE);
fullfilename=avidialog->fullfilename;
filename=avidialog->filename;
pathname=avidialog->pathname;
int index=avidialog->GetIndex();
DWORD w,h,d;
w=displaymode[index].w;
h=displaymode[index].h;
d=displaymode[index].d;
ActivateDisplayMode(GetDisplayModeIndex(w, h, d));
LoadAvi();
CreateAviSurface();
InstallPalette();
curframe=startframe;
}
Функция ShowDialog() начинается с проверки текущего разрешения. Если в данный момент установлен видеорежим с разрешением