Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Итак, наконец-то мы добрались до темы создания окон свойств, которые в MFC реализуются с помощью, как вы уже догадались, класса CPropertySheet.
Как известно, практически во всех более-менее серъезных программах есть диалоговые окна настройки параметров, или опций, приложения. Такие окна получили название окон свойств . Чтобы увидеть одно из таких окон, достаточно выбрать Tools|Options в Visual C++ IDE.
Задача создания окон свойств стоит практически перед каждым разработчиком, именно поэтому в MFC решение этой проблемы в некоторой степени автоматизировано с помощью класса CPropertySheet. В результате его применения вы получаете готовое диалоговое окно с набором закладок и некоторым количеством стандартных кнопок – OK, Cancel, и т.д. Закладки здесь – это объекты типа CPropertyPage. Этот класс, кажется, уже фигурировал в одном из выпусков. Никогда не путайте CPropertySheet и CPropertyPage: помните, что первый (CPropertySheet) СОДЕРЖИТ вторые (CPropertyPage) так же, как книга содержит страницы.
Так, с этим разобрались, идем дальше. Как пользоваться классом CPropertySheet? Очень несложно, вы в этом сами сейчас убедитесь.
Для каждой закладки нужно создать диалоговый ресурс (не обязательно со стилем child), куда вы помещаете все содержимое соответствующей страницы (также, как и при работе с CTabCtrl). Например, IDD_PROPPAGE1 и IDD_PROPPAGE2ROPPAGE2. Можно сразу заполнить поле Caption в диалогах, чтобы потом заголовки закладок сформировались автоматически.
В проект добавляется класс-наследник от CPropertySheet, пускай он называется CMyPropSheet.
Для того, чтобы можно было работать с контролами на закладках, добавляется отдельный класс для каждой страницы-закладки (наследованный от CPropertyPage). Например, для двух закладок это будут классы CPropPage1 и CPropPage2 (эти классы добавьте дабл-кликнув на поверхности соответствующего диалога и выбрав "Create a new class", затем в поле "Base class" выберите CPropertyPage в качестве класса-родителя). В эти классы нужно поместить члены, связанные с контролами, расположенными на странице. Например, если у нас на первой странице (IDD_PROPPAGE1) есть Edit Box, добавляем в класс CPropPage1 переменную m_strEdit класса CString, доступ – public. Пусть на второй странице у нас Check Box, значит в класс CPropPage2 записываем член m_isChecked типа BOOL, и т.д. Использование типа доступа public к этим полям в данном случае оправданно, т.к. избавляет в дальнейшем от многих хлопот. И не забывайте, эти члены класса должны быть связаны с соответствующими контролами на закладке.
Теперь в файл mypropsheet.h (где объявлен класс CMyPropSheet) пишем:
#include "proppage1.h" // делаем классы страниц видимыми
#include "proppage2.h"
…
class CMyPropSheet: public CPropertySheet {
…
protected:
CPropPage1 page1; // первая страница
CPropPage2 page2; // вторая страница
…
}
Чтобы добавить страницы к окну свойств, необходимо в каждый из конструкторов CMyPropSheet вставить по две следующие строчки:
AddPage(&page1);
AddPage(&page2);
Таким образом, мы сделали страницы-закладки частью нашего окна свойств. Настал момент теперь решить, где вы собираетесь хранить настройки вашего приложения. Я это обычно делаю в классе главного окна, по причине легкости доступа, но ничто не мешает вам хранить их там, где удобнее, причем не обязательно все вместе. Неплохой вариант – хранить их в классе приложения, даже с некоторой точки зрения он более логичный.
Но предположим, вы решили хранить их в классе главного окна, а чтобы они не перемешивались с другими полями класса, объединить их в структуру:
…
class CMainFrame: public CFrameWnd {
…
public:
struct Options {
CString str;
BOOL val;
} options;
…
}
В конструкторе CMainFrame поля структуры options установите в начальные значения. Их можно задать жестко, но обычно сохраненные ранее значения загружаются из файла или реестра , иначе вы быстро доведете пользователя вашей программы до белого каления, заставляя его менять параметры после каждого запуска.
Теперь вставьте обработчик события, возникновение которого должно приводить к выводу на экран вашего окна свойств (например, выбор пункта меню "Сервис|Параметры…"). В обработчике вы устанавливаете параметры, после чего выводите окно свойств. Если пользователь нажал "OK", то после закрытия окна свойств нужно обновить структуру options:
#include "mypropsheet.h"
…
void CMainFrame::OnToolsOptions() {
CMyPropSheet ps("Параметры приложения", this, 0);
ps.page1.m_strEdit = options.str; // настраиваем закладки
ps.page2.m_isChecked = options.val; // соответственно текущим параметрам
if (ps.DoModal() == IDOK) // если пользователь нажал OK
{
options.str = ps.page1.m_strEdit; // сохраняем параметры
options.val = ps.page2.m_isChecked;
}
}
Вот и все, что касается элементарного использования класса CPropertySheet для создания окна свойств. Как видите, работать с ним довольно просто. В одном из следующих выпусков я расскажу вам о задействовании кнопки "Применить" ("Apply"), о нетривиальном использовании этого класса для создания мастеров (wizards), а также о расширенном классе CPropertySheetEx.
Q. Возникла вот такая задачка. Имеется некоторое разбиение SDI на несколько view при помощи сплиттеров (A). Как его изменить не убивая окна (на B или C)?
+--+----+ +--+----+ +--+----+
| | | | | | + + +
+--+----+ +--+ | + +----+
| | | | | + + +
A +-------+ B +--+----+ C +--+----+
A. Для создания окна сплиттера в MFC служит класс CSplitterWnd. Этот класс предоставляет функции для создания вида (CreateView) и удаления вида DeleteView) в заданной панели, но не предоставляет функции, которая позволила бы перенести вид из одной панели в другую. Чтобы проделать это вручную, нужно понимать, каким образом связаны объект класса CSplitterWnd и объекты дочерних видов CView.
CSplitterWnd может иметь не более 16 панелей по горизонтали и столько же по вертикали. Таким образом, он может сожержать не более 256 панелей. Каждой панели соответствует уникальный идентификатор, который и назначается тому виду, который в этой панели находится. Отображение координат панели на её идентификатор выполняет функция int CSplitterWnd::IdFromRowCol(int row, int col);
На самом деле после целой серии ASSERT'ов она просто возвращает значение
AFX_IDW_PANE_FIRST + row * 16 + col
где AFX_IDW_PANE_FIRST — константа, объявленная в MFC.
Это подсказывает простой способ перемещения вида из одной панели в другую: нужно всего лишь подменить его идентификатор, после чего вызвать CSplitterWnd::RecalcLayout для обновления содержимого сплиттера. Если изначально вид не являлся дочерним окном сплиттера и требуется поместить его в одну из панелей, то необходимо также поменять ему родителя с помощью функции CWnd::SetParent. Таким образом функция, вставляющая вид в заданную панель, может выглядеть примерно так:
Читать дальшеИнтервал:
Закладка: