Меню главного окна приложения описывается, как обычно, в файле ресурсов.rс. Значения идентификаторов пунктов меню (имена идентификаторов могут быть любыми) определены в файле.h. Для пункта выхода из приложения использован стандартный идентификатор СМ_ЕХIТ (со значением 24310), описанный в файле window.rh. С таким же успехом можно было использовать другое обозначение (например, CM_QUIT) или присвоить идентификатору СМ_ЕХIТ произвольное значение.
Для того, чтобы меню появилось в окне приложения, достаточно вызвать функцию AssignMenu(), принадлежащую классу TFrameWindow, с указанием в качестве параметра имени меню из файла ресурсов; этот вызов удобнее всего выполнить в
конструкторе класса MyWindow. Как и в случае API Windows, обработку сообщений от "корневых" пунктов меню (в нашем случае это пункты "Файл" и "Графики") Windows берет на себя: при выборе этих пунктов Windows отображает на экране соответствующие всплывающие меню (рис. 27.3). Нам же надо обрабатывать сообщения от пунктов всплывающих меню (их часто называют командами
|
|
меню), для чего необходимо включить в таблицу откликов сообщения EV_COMMAND - по одному на каждую команду меню (обратите внимание на отсутствие в обозначении сообщения EV_COMMAND префикса WM).
В отличие от макросов типа EV_WM_TIMER или EV_WM_GETMINMAXINFO, которые при расширении задают имена функций отклика, макрос EV_COMMAND требует указания двух параметров -идентификатора соответствующего пункта меню и имени прикладной функции отклика, предназначенной для обработки сообщения от этого пункта:
EV_COMMAND(CM_ABOUT,CmAbout), EV_COMMAND(CM_SIN,CmSin),...
Обычно функциям отклика назначают имена, схожие с идентификаторами (например, CmAbout для пункта меню с идентификатором CM_ABOUT), однако это не обязательно. Разумеется, для всех включенных в программу функций отклика необходимо объявить их прототипы (в составе класса MyWindow) и определить содержание самих функций. Исключение составляет команда "Выход". Если для этого пункта меню использовать стандартный идентификатор СМ_ЕХIТ, то всю обработку команды пользователя на завершение программы берет на себя Windows. Таким образом, для пункта меню с идентификатором CM_EXIT не надо иметь ни функции отклика, ни даже макроса EV_COMMAND в составе таблицы откликов (разумеется, лишь в том случае, если выбором этого пункта меню мы хотим именно завершить программу).
Содержательная часть примера 27-2 относительно проста. В классе MyWindow объявляются два массива чисел с плавающей точкой типа double для записи в них таблиц значений тригонометрических функций sin(x) и cos(x), которые затем будут выведены на экран в виде точечных графиков. Булевы переменные sinIs и cosIs служат в качестве флагов, индицирующих наличие в этих массивах достоверных данных. В функциях отклика CmSin() и CmCos() вычисляются таблицы синуса и косинуса, устанавливаются флаги достоверности данных и вызовом функции Invalidate() инициируется посылка в приложение сообщения WM_PAINT. В функции Paint() отклика на это сообщение на экран выводится сначала ось X (на расстоянии 150 пикселов от верхнего края окна), а затем графики тригонометрических функций с предварительной проверкой для каждой функции состояния флага достоверности. Для наглядности каждому графику назначается свой цвет.
|
|
Команда меню "О программе" служит, как обычно, для вывода на экран окна (в нашем примере -стандартного окна сообщения) с информацией о данном программном продукте. Для улучшения внешнего вида окна сообщения (рис. 27.4) в замещенную нами функцию InitMainWindow() включен вызов функции EnableBWCC() класса TApplication, которая загружает библиотеку BWCC (Borland Windows Custom Controls).
В рассматриваемом примере не предусмотрено какого-либо "управления" графиками - после первого выполнения команд "Синус" или "Косинус" они остаются как в памяти, так и на экране. В этом случае не было необходимости вычислять их заново при каждом выполнении функции Paint(); заполнить массивы
250 Глава 27
sine[] и cosine[] можно было на этапе инициализации, например, в конструкторе MyWindow. В следующем примере, где предусмотрен вывод любой комбинации графиков по желанию, их вычисление в функции Paint() становится более оправданным.