- •Овсянник в.Н. Лабораторные работы по курсу «Объектно-ориентированное программирование»
- •13. Разработка приложения с архитектурой «документ-вид». Часть 2 120
- •14. Разработка приложения с архитектурой «документ-вид». Часть 3 135
- •1.Разработка типового консольного приложения
- •1.1.Методические указания
- •1. Запуск и настройка ис mvs-2008.
- •2.Поиск данных в массиве
- •3.Обработка текстового файла
- •4.Задача «куча камней»
- •5.Реализация алгоритма полного перебора
- •6. Исследование погрешностей вычислений
- •7.Поиск экстремумов с ограничениями или «Брачное агенство»
- •Постановка задачи
- •Задание
- •Листинг файла mAgency.Cpp (с главной функцией)
- •Листинг файла Lib.H
- •Листинг файла Lib.Cpp
- •8.Приложение с окном вида
- •9.Разработка графического редактора
- •Задание.
- •9.1.Проектирование программы
- •9.2.Разработка интерфейса
- •Установка флагов
- •Создание меню и панели инструментов
- •Обработка сообщений о нажатии кнопки мыши
- •9.3.Рисование
- •9.4.Растягивание фигур
- •9.5.Обновление изображения
- •9.6.Сохранение метафайла на диске и его загрузка
- •10.Приложение, основанное на модальном диалоговом окне
- •Методические указания Модальные и немодальные диалоговые окна
- •Ресурсы и элементы управления
- •Сценарий создания приложения
- •Разбор приложения
- •Усовершенствование приложения
- •11.Приложение с контекстным меню и строкой состояния
- •11.1.Методические указания к первой части работы
- •11.2.Сценарий выполнения первой части работы
- •11.3.Методические указания ко второй части работы Строка состояния
- •Определение секций в строке состояния
- •Строка сообщений
- •Индикатор состояния
- •Управление строкой состояния
- •11.4.Сценарий выполнения второй части работы
- •12.Разработка приложения с архитектурой «документ-вид». Часть 1
- •12.1.Сценарий создания приложения
- •13.Разработка приложения с архитектурой «документ-вид». Часть 2
- •13.1.Методические указания Класс коллекций cObList
- •13.2.Сценарий выполнения работы
- •14.Разработка приложения с архитектурой «документ-вид». Часть 3
- •14.1.Методические указания
- •15.Класс вектор
- •15.1.Пример класса tVector
- •15.2.Класс tVector с перегруженными операциями
- •16.Приложение с таблицей
- •16.1.Вариант 1 Сценарий выполнения работы
- •16.2.Вариант 2 Сценарий выполнения работы
Управление строкой состояния
Стандартной строке состояния присваивается идентификатор дочернего окна AFX_IDW_STATUS_BAR. Именно его каркас приложений ищет для вывода подсказки по элементам меню. Обработчики сообщений обновления пользовательского интерфейса используют три идентификатора строковых ресурсов для индикаторов состояния клавиатуры в базовом классе окна-рамки: ID_INDICATOR_CAPS, ID_INDICATOR_NUM и ID_INDICATOR_SCRL. Чтобы самому управлять строкой состояния, нужно применить другой идентификатор дочернего окна и другие константы для индикаторов.
Примечание. Изменять идентификатор дочернего окна строки состояния имеет смысл только в том случае, если Вы хотите предотвратить вывод каркасом приложений подсказок в секцию 0.
Идентификатор для окна строки состояния назначается вызовом CStatusBar::Create() в функции-члене OnCreate() производного класса окна-рамки. Эта функция содержится в файле MainFrm.cpp, генерируемом мастером. Третий параметр функции Create() – идентификатор окна – по умолчанию равен AFX_IDW_STATUS_BAR.
Чтобы назначить свой идентификатор, замените вызов
m_wndStatusBar.Create(this);
на
m_wndStatusBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM,
ID_MY_STATUS_BAR);
Конечно, нужно определить и константу ID_MY_STATUS_BAR в файле resource.h, используя редактор символов. (Предполагается, что пока Вы не изменяете программный код, а просто наматываете информацию на свой ус.)
Но Вы кое-что забыли. Стандартное меню View, формируемое каркасом приложений, позволяет включать и отключать показ строки состояния. Эта логика реализуется кодом, использующим идентификатор окна AFX_IDW_STATUS_BAR, который тоже придется изменить. В своем производном классе окна-рамки напишите элементы таблицы сообщений и обработчики для команды ID_VIEW_STATUS_BAR и сообщений, связанных с обновлением пользовательского интерфейса. ID_VIEW_STATUS_BAR – это идентификатор элемента меню Status Bar. Как Вы будете лицезреть ниже, обработчики в производном классе переопределяют стандартные обработчики из базового класса.
11.4.Сценарий выполнения второй части работы
Сейчас мы заменим, для тренажа, стандартную строку состояния новой со следующими текстовыми секциями:
Индекс секции |
Идентификатор строки |
Тип |
Описание |
0 |
ID_SEPARATOR (0) |
Строка сообщений |
х-координата курсора |
1 |
ID_SEPARATOR (0) |
Строка сообщений |
у-координата курсора |
2 |
ID_INDICATOR_LEFT |
Индикатор состояния |
Состояние ЛКМ |
3 |
ID_INDICATOR_RIGHT |
Индикатор состояния |
Состояние ПКМ |
Новая строка состояния показана на рис. 3. Обратите внимание: при увеличении размеров окна-рамки крайняя левая секция растягивается за пределы своей обычной длины в 1/4 ширины экрана.
|
Рис. 3. Новая строка состояния программы
Шаг 11. Отредактируйте в редакторе ресурсов ресурс строковой таблицы. Чтобы запустить редактор строковых ресурсов, дважды щелкните папку String Table на странице ResourceView. Затем дважды щелкните пустой элемент в конце списка, чтобы перейти в режим редактирования ресурса, задайте идентификатор ID равным ID_INDICATOR_RIGHT и Caption==Right. Значение Value оставьте неизменным (рис. 4).
|
Рис. 4. Добавление новой строки ресурса
Аналогичным образом добавьте ID==ID_INDICATOR_LEFT и Caption==Left.
Шаг 12. Выберите из меню Edit команду Resource Symbols. В появившемся окне с помощью кнопаря New добавьте новый идентификатор ID_MY_STATUS_BAR и оставьте для него значение, предлагаемое по умолчанию.
Шаг 13. Добавьте в класс CMainFrame обработчики команд, содержащихся в меню View. Добавьте заготовки следующих обработчиков командных сообщений:
Идентификатор объекта |
Сообщение |
Член-функция |
ID_VIEW_STATUS_BAR |
COMMAND |
OnViewStatusBar |
ID_VIEW_STATUS_BAR |
UPDATE_COMMAND_UI |
OnUpdateViewStatusBar |
Кроме того, объявите m_wndTollBar открытой, а не защищенной переменной (файл MainFrm.h).
Шаг 14. Отредактируйте файл MainFrm.cpp. Замените старое содержимое массива indicators новым:
|
Далее отредактируйте функцию-член OnCreate(). Замените оператор
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
следующим
|
В модифицированном вызове функции Create() вместо AFX_IDW_STATUS_BAR (объект строки состояния, формируемый каркасом приложений и используемый по умолчанию) используется наш идентификатор строки состояния ID_MY_STATUS_BAR.
Теперь добавьте, вручную, следующие элементы таблицы сообщений для класса CMainFrame, так как ИС (такая тупая, как любит говорить Задорнов, американская ИС!) это сделать не в состоянии по причине отсутствия способности к распознаванию идентификаторов из строковой таблицы в качестве идентификаторов объектов:
ON_UPDATE_COMMAND_UI(ID_INDICATOR_LEFT, OnUpdateLeft)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_RIGHT, OnUpdateRight)
В результате таблица сообщений (файл MainFrm.cpp) должна приобрести такое обличье:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_WM_SETFOCUS()
ON_COMMAND(ID_VIEW_STATUS_BAR, &CMainFrame::OnViewStatusBar)
ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, &CMainFrame::OnUpdateViewStatusBar)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_LEFT, OnUpdateLeft)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_RIGHT, OnUpdateRight)
END_MESSAGE_MAP()
Затем вставьте функции-члены класса CMainFrame, отвечающие за обновление индикаторов состояния кнопочек мыши:
|
Заметьте: левой и правой кнопкам мыши, как и клавишам на клавиатуре, соответствуют коды виртуальных клавиш, поэтому при определении состояния кнопок можно обойтись без обработки сообщений от мыши.
Не забудьте также добавить прототипы этих функций в заголовочный файл MainFrm.h (то бишь тело класса CMainFrm) в следующем виде и месте (добавленные строки выделены курсивом):
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnViewStatusBar();
afx_msg void OnUpdateViewStatusBar(CCmdUI *pCmdUI);
afx_msg void OnUpdateLeft(CCmdUI* pCmdUI); // добавлено
afx_msg void OnUpdateRight(CCmdUI* pCmdUI); // добавлено
И, в конце концов, отредактируйте следующие функции для меню View, заготовки которых были сгенерированы в файле MainFrm.cpp:
|
Эти функции обеспечивают надлежащую связь команды Status Bar меню View с новой строкой состояния.
Соберите приложение и запустите на выполнение. Убедитесь в том, что нашу строку состояния можно показывать и прятать с помощью команды Status Bar меню View. Также проверьте, что при нажатии ЛКМ или ПКМ в строке состояния появляется, как черт из коробочки, текст Left или Right. Проверили, не появляется? Попробуйте сильно увеличить ширину окна, чтобы появилось место для отображения состояния ЛКМ и ПКМ. Теперь получается?
Для того чтобы уменьшить ширину строки статуса, которая отводится для первых двух панелей, добавьте в функцию CMainFrame::OnCreate() (после вызова функции Create для строки состояния) следующие операторы:
m_wndStatusBar.SetPaneInfo(0, 0, 0, 50);
m_wndStatusBar.SetPaneInfo(1, 0, SBPS_STRETCH, 50);
Узнайте назначение параметров SetPaneInfo() из MSDN. Проверьте, что теперь строка состояния ведет себя подобающим образом.
Шаг 14. Добавьте вывод координат мыши в строку состояния. Для этого присовокупите сначала к классу вида обработчик сообщения WM_MOUSEMOVE и наполните его таким кодом:
|
Соберите и тестируйте приложение. Не получается? В чем проблема? Попробуйте сами устранить ошибки. Если не получится – станьте на голову и прочтите ценные указания.
|
Боевое задание для совершения подвига. В нынешнем виде программа открывает для просмотра файлы только с расширениями .bmp, .jpg, .gif и .png, хотя система поддерживает большее число форматов. Вам предоставляется возможность расширить функциональность программы, научив ее открывать и файлы других графических форматов. Найдите в MSDN описание функции CImage::GetExporterFilterString() и … Вы сможете решить эту проблему. Убедитесь в том, что программа корректно сохраняет открытый файл любого формата. Для этого, очевидно, Вам понадобится отредактировать текст функции CChildView::OnSaveimage(). Вообще говоря, было бы уместно передать перечень типов файлов, возвращаемых функцией CImage::GetExporterFilterString(), в функцию CChildView::OnSaveimage().
