Версия MechWarrior 2, о которой я говорю, проектировалась для чипов 3Dfx. Для видеоустройств, построенных на таких чипах, вывод диалоговых окон в DirectDraw невозможен, потому что 3Dfx являются вторичными видеоустройствами, и GDI ничего не знает об их существовании. Поэтому команда разработчиков Activision не могла выбрать первый вариант и отображать диалоговые окна в DirectDraw.
Третья стратегия (создание нестандартных интерфейсов на базе DirectDraw) оказывается самой трудоемкой. Разработка нестандартных управляющих элементов давно превратилась в отдельную отрасль программной индустрии, и мало кто из разработчиков позволяет себе тратить время на создание кнопок, ползунков и списков, когда с приложением и без того хватает хлопот. С другой стороны, этот вариант позволяет создать интерфейс, спроектированный специально для вашего приложения. Теоретически этот интерфейс может быть столь же привлекательным и впечатляющим, как и само приложение.
В программе BmpView используется первый вариант. Перед выводом диалогового окна на рис. 5.7 мы отображаем поверхность GDI и восстанавливаем системную палитру.
Определение класса
В программе BmpView, как и в других программах этой книги, класс окна приложения является производным от класса DirectDrawWin. К сожалению, по нашему соглашению об именах имя производного класса образуется из имени приложения и суффикса Win. Следовательно, класс окна приложения BmpView называется BmpViewWin, что выглядит несколько неуклюже. Объявление класса BmpViewWinприведено в листинге 5.5.
Листинг 5.5. Класс BmpViewWin
class BmpViewWin : public DirectDrawWin {
public:
BmpViewWin();
protected:
//{{AFX_MSG(BmpViewWin)
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int SelectInitialDisplayMode();
BOOL CreateCustomSurfaces() {
return TRUE;
}
void DrawScene();
void RestoreSurfaces();
void GetSystemPalette();
void ShowDialog();
BOOL LoadBmp();
void PageUp();
void PageDown();
void Home();
void End();
void Left(int inc=4);
void Right(int inc=4);
void Up(int inc=4);
void Down(int inc=4);
private:
BmpDialog* bmpdialog;
LPDIRECTDRAWPALETTE syspal;
CString fullfilename;
CString filename;
CString pathname;
CRect displayrect;
LPDIRECTDRAWSURFACE bmpsurf;
CRect bmprect;
int x,y;
int xscroll, yscroll;
int xlimit, ylimit;
BOOL update_screen;
DisplayModeArray palettemode, nonpalettemode;
};
Единственной открытой ( public) функцией класса является конструктор, используемый для инициализации переменных. Далее мы объявляем четыре обработчика сообщений:
• OnKeyDown()
• OnRButtonDown()
• OnCreate()
• OnDestroy()
Функция OnKeyDonw()обрабатывает нажатия нескольких клавиш, среди которых клавиши со стрелками, Home, End, Page Up, Page Down, Enter, пробел и Escape.
Функции OnCreate()и OnDestroy()предназначены соответственно для инициализации и освобождения структур данных приложения. В частности, функция OnCreate()создает диалоговое окно для выбора BMP-файла, а функция OnDestroy()уничтожает его.
Далее следуют объявления нескольких закрытых переменных. Функция SelectInitialDisplayMode()похожа на версию, созданную DirectDraw AppWizard и использованную в прошлых программах, но в нее внесены некоторые изменения. Кроме выбора исходного видеорежима, эта функция сохраняет текущую палитру Windows с помощью функции GetSystemPalette()(которая объявляется несколькими строками ниже функции SelectInitialDisplayMode()).
Функция CreateCustomSurfaces()объявляется и определяется в объявлении класса. В отличие от других программ, рассмотренных нами, BmpView не отображает никаких вспомогательных поверхностей, поэтому эта функция не делает ничего. Однако из-за того, что функция DirectDrawWin::CreateCustomSurfaces()является чисто виртуальной, нам приходится объявить и определить ее минимальную реализацию.
Функция DrawScene()отвечает за графический вывод и переключение страниц. Поскольку нашей программе незачем постоянно обновлять экран, функция DrawScene()делает это лишь в ответ на пользовательский ввод. Этим она отличается от других программ, в которых экран обновлялся непрерывно. Функция RestoreSurfaces()восстанавливает поверхности в случае их потери.
Читать дальше