Студия web-дизайна Хостмэйк
Наши работыКонтактыО компанииОтзывыГлоссарийСтатьи

Глава 15. Наборы свойств

Статьи Программирование на С/С++

Наборы свойств

Набор свойств представляет собой особый вид диалогового окна, применяемый для
модификации свойств как самого приложения, так и каких-то внешних объектов.
Набор свойств содержит три основные части:



  •  Блок диалога, внутри которого размещаются все остальные элементы
    набора свойств.
  •  Одна или несколько страниц свойств. Одновременно на экране может
    быть видна только одна из. них, находящаяся как бы поверх других.
  •  Вкладки, расположенные вверху каждой страницы. Пользователь, выбирая
    одну из вкладок, делает видимой соответствующую ей страницу свойств.


.........................................................1

Рис. 15.1. Окно Options
оболочки Visual C++ 6.0


В качестве примера набора свойств можно привести блок диалога просмотра и
изменения параметров оболочки Visual C++ 6.0 (рис. 15.1).


Использовать набор свойств весьма удобно в тех случаях, когда имеются группы
некоторых параметров, которые можно изменять. Он позволяет собрать большое
количество информации в небольшие группы, выводимые на экран поочередно, что
значительно облегчает и упрощает работу.


Наборы свойств могут применяться не только для отображения свойств объектов,
но и для группирования сходных по назначению или по используемым параметрам
действий. Например, приложение MS Word 97 таким образом группирует действия для
поиска, замены и перехода (рис. 15.2).



..............................................................2

Рис. 15.2. Окно "Найти и заменить" приложения MS Word 97



Создание набора свойств


Библиотека MFC предоставляет специальные классы для создания набора свойств и
обеспечения работы с ним: CPropertySheet
и СPropertySheetEx позволяют создать
набор свойств, a CPropertyPage и face="Courier New" size=2>CPropertyPageEx предназначены для создания
включаемых в набор страниц свойств. Несколько особняком стоит класс face="Courier New" size=2>CTabCtrl, используемый для создания вкладок и
работы с ними. Дело 'В том, что в общем случае нет необходимости напрямую
работать с вкладками в наборе свойств, достаточно лишь задать текст, который
нужно поместить на них, а все остальное сделает библиотека. Однако возможность
доступа к объектам данного класса все же имеется, и его функции применяются в
основном для создания вкладок, отличающихся от создаваемых по умолчанию.


 Примечание 


Классы size=2>CPropertySheetEx и size=2>CPropertyPageEx доступны только в Visual C++ 6.0.


Проще всего создать набор свойств, воспользовавшись средством добавления в
проект различных программных компонентов. Для этого выберите команду face="Courier New" size=2>InsertComponent, а затем вставьте в проект
набор свойств с требуемыми характеристиками (рис. 15.3).



.................................................................3

Рис. 15.3. Окно выбора добавляемых в проект программных компонентов


При этом требуется проделать следующее:



  •  определить, будет ли добавляемый компонент набором свойств или
    мастером;
  •  указать, поддерживается ли возможность предварительного просмотра
    произведенных изменений (по сути это добавление рисованного объекта и ничего
    больше);
  •  определить, будет ли набор свойств модальным или нет;
  •  задать класс из набора существующих в проекте классов, который будет
    иметь функцию создания набора свойств и возможность доступа к его элементам;
  •  задать количество страниц;
  •  заменить имена создаваемых классов (по желанию).

Если впоследствии понадобится добавить новые страницы свойств, то следует
воспользоваться механизмом, изложенным ниже.



Создание объекта "набор свойств"


Следующим шагом будет создание объекта класса size=2>СPropertySheet в тексте программы. Обычно такой объект создается в
обработчике команды, осуществляющей вывод на экран набора свойств.



CPropertySheet
propsheet;


CPropertySheet
propsheet("Параметры", pParentWnd);


ИЛИ



CPropertySheet
propsheet("Параметры ", GetParent());


Конструктор класса имеет несколько реализаций:



size=2>CPropertySheet::CPropertySheet()


size=2> CPropertySheet::CPropertySheet (


UINT nIDCaption,


CWnd* pParentWnci =
NULL,


UINT iSelectPage =
0) 


size=2>CPropertySheet::CPropertySheet (


LPCTSTR pszCaption,


CWnd* pParentWnd =
NULL,


UINT iSelectPage =0)


Параметр nIDCaptbn — идентификатор
заголовка для набора свойств; pParentWnd— указатель на родительское окно. Если
его значение равно NULL, то родительским окном является главное окно
приложения. Параметр iSelectPage— индекс страницы, выводимой первой при
отображении набора свойств на экран. По умолчанию выводится первая страница
набора свойств. Параметр pszCaption — указатель на строку, содержащую
заголовок для набора свойств (не может быть равным NULL).


Если не нужно добавлять в набор свойств дополнительные элементы управления
(например, окно предварительного просмотра) или выводить на экран немодальный
набор свойств, то создавать класс, производный от класса face="Courier New" size=2>CpropertySheet, вообще не требуется.


Примечание 


Немодальный набор свойств по умолчанию не содержит
кнопок, и в большинстве случаев в него потребуется добавить элементы управления
для того, чтобы его можно было в дальнейшем по крайней мере закрыть.



Настройка окна набора свойств


По умолчанию набор свойств выделяет окно для размещения страниц свойств с
вкладками, для модальных наборов свойств в этом окне также размещаются кнопки
OK, Cancel (Отмена) и face="Courier New" size=2>Apply (Применить). Допускается добавлять и
другие необходимые для работы элементы управления, например, дополнительное окно
просмотра, в котором будут выводиться изображения, находящиеся в выбираемых
пользователем файлах. Дополнительные элементы управления можно вводить в
обработчике OnCreate, однако лучше это
делать в функции OnlnitDialog, т. к. на
момент вызова этой функции уже созданы окна страниц свойств, доступ к которым
также может понадобиться.


Вставка дополнительных элементов управления в набор свойств обычно требует
увеличения размеров его диалогового окна. Для этого после вызова функции
базового класса OnCreate или face="Courier New" size=2>OnlnitDialog необходимо вызвать функцию face="Courier New" size=2>CWnd::GetWindowRect для получения значений
размеров текущего окна набора свойств, задать требуемые размеры и вызвать
функцию CWnd::MoveWindow или face="Courier New" size=2>CWnd::SetWindowPos для изменения размеров окна,
в котором выводится набор свойств.



Добавление страниц


Наиболее удобный способ обеспечения доступа к страницам свойств внутри набора
свойств является встраивание объектов класса size=2>CPropertyPage в класс, производный от size=2>СPropertySheet. Такой подход отличается от разработки модальных
наборов свойств, когда объект-владелец набора свойств создает объекты face="Courier New" size=2>CPropertyPage, а затем передает их набору
свойств, вызывая функцию size=2>CProperty'Sheet::AddPage.


На этом этапе следует сделать еще одно важное замечание: если нужно создать
несколько объектов класса CPropertySheet,
например, массив наборов свойств, то следует воспользоваться не конструктором
СPropertySheet, а функцией face="Courier New" size=2>Construct.



void
CPropertySheet::Construct ( 


UINT nIDCaption, 


CWnd* pParentWnd =
NULL, 


UINT iSelectPage =0)


ИЛИ



void
CPropertySheet::Construct ( 


LPCTSTR
pszCaption, 


CWnd* pParentWnd =
NULL, 


UINT iSelectPage =0)


Параметры здесь те же, что и у конструктора
класса CPropertySheet Данную функцию можно вызывать, если ни один из
конструкторов с параметрами класса CPropertySheet еще не вызывался. В случае
создания массива объектов CPropertySheet вызов функции Construct обязателен
для каждого элемента массива.


Ниже приведен пример, иллюстрирующий применение этой функции:



int i;


CPropertySheet
propsheetarray[3];


// Для одиночного набора
свойств не требуется


// вызывать функцию
Construct


CPropertySheet
oneSheet;


UINT sheetsID[3] =
(IDS_SHEET_1, IDS_SHEET_2, IDS_SHEET_3};


for (i = 0; i < 3;
i++)


{


// Функция Construct
вызывается для каждого


/./ создаваемого набора
свойств


size=2>propsheetarray[i].Construct(sheetsID[i]}; 


}


Следующим важным шагом на пути создания набора свойств будет выполнение
следующих операций для каждой добавляемой в набор свойств страницы:



  •  создание одного объекта каждого класса, производного от класса
    CPropertyPage, который ранее был создан с помощью Class Wizard;
  •  вызов функции С Property Sheet: :AddPage для каждой страницы,
    добавляемой в набор свойств.

Обычно функция, в которой создается объект size=2>CPropertySheet, на этом же шаге также создает и объекты класса
CPropertyPage. Однако если создается
производный от CPropertySheet класс, то
можно встроить объекты класса size=2>CPropertyPage в объект класса size=2>CPropertySheet и вызвать из конструктора производного от face="Courier New" size=2>CPropertySheet класса функцию face="Courier New" size=2>CPropertySheet::AddPage для каждой страницы
свойств. Функция AddPage добавляет
страницу свойств в набор свойств, однако не создает окно для этой страницы.
Следовательно, для добавления страницы можно не ждать создания окна набора
свойств, а вызвать функцию AddPage
непосредственно из конструктора.



// Первый способ


CPropertySheet
propsheet;


CFirstPage pagel; // Класс,
производный от CPropertyPage


CSecondPage page2; // Класс,
производный от CPropertyPage


size=2>propsheet.AddPage(&pagel);


size=2>propsheet.AddPage(&page2);



// Второй способ


class CPropSheet : public
CPropertySheet


{


public:


CPropSheet(CWnd* pParentWnd =
NULL);


public:


CFirstPage m_Pagel; // Класс,
производный от CPropertyPage


 CSecondPage m_Page2; //
Класс, производный от CPropertyPage


...


};


CPropSheet::CPropSheet(CWnd*
pWndParent)


:
CPropertySheet(IDS_PROPSHT_CAPTION, pWndParent)


{


AddPage(&m_Pagel);


size=2>AddPage(&m_Page2); 


}


Для вывода на экран набора свойств необходимо вызвать одну из функций: face="Courier New" size=2>CPropertySheet::DoModal или face="Courier New" size=2>CPropertySheet::Create.



Создание модального окна свойств


Создание набора свойств в виде модального блока диалога осуществляется
вызовом функции DoModai.



virtual int
CPropertySheet::DoModal ()


Выводит на экран модальный набор свойств.
Функция возвращает значения IDОК или IDCANCEL, а в случае неуспешного
завершения — 0. Следует иметь в виду, что если набор свойств создан как
мастер, то возвращаются другие значения - ID_WIZFINISH или IDCANCEL.


После завершения работы функции окна и все страницы, связанные с набором
свойств, удаляются. Сами объекты остаются существовать. Как правило, данные от
объектов CPropertyPage считываются после
того, как функция DoModal вернула
значение IDOK.



Создание немодального окна набора свойств


Обычно создаваемая страница свойств является модальной. Так же. как и
модальный диалог, пользователь должен закрыть окно модального набора свойств
прежде, чем он сможет работать с другими объектами данного приложения (окнами,
меню и т. п.). Однако существуют случаи, когда необходимо создать немодальный
набор свойств, который позволяет, не закрыв его, перейти к работе с другими
объектами приложения. Немодальный набор свойств формируется вызовом функции face="Courier New" size=2> CPropertySheet::Create.



BOOL
CPropertySheet::Create


CWnd* pParentWnd =
NULL, 


DWORD dwStyle = (DWORD)
-1, 


DWORD dwExStyle =0)


Параметр pParentWnd указывает на
родительское окно (если равен NULL, то родительским окном является главное
окно приложения); dwStyle задает стили окна (по умолчанию- комбинация стилей
WS_SYSMENU, WS_POPUP, WS_ CAPTION, DS_MODALFRAME, DS_CONTEXT_HELP и
WS_VISIBLE); a dwExStyie-расширенные стили окна (по умолчанию — стиль
WS_EX_DLGMODALFRAME).


Функцию СProperty Sheet::Create можно
вызывать как из конструктора, так и после того, как объект набора свойств уже
создан. Функция возвращает управление непосредственно после создания набора
свойств. Для уничтожения набора свойств следует использовать функцию face="Courier New" size=2> CWnd::.DestroyWindow.


При создании немодального набора свойств придется выполнить несколько
дополнительных операций. Одной из них является обеспечение обмена данными между
набором свойств и внешними объектами в то время, когда окно набора свойств
открыто. Эта задача целиком совпадает с аналогичной задачей для обычных
немодальных блоков диалога. В данном случае такой обмен проще реализовать,
создав производный от CPropertySheet
класс
. Одним из методов обеспечения обмена является определение указателя
из набора свойств на внешний объект. Далее следует определить функцию в
производном от CPropertySheet классе,
которая будет отслеживать изменения данных набора свойств всякий раз, когда
фокус ввода передается от одного внешнего объекта к другому. Такая функция
вызывается, естественно, не объектом набора свойств, а самим приложением и
осуществляет сброс текущих данных каждой страницы для отображения свойств
текущего внешнего объекта, для чего она должна иметь доступ к объектам face="Courier New" size=2>CPropertyPage, определенным в классе face="Courier New" size=2>CPropertySheet.


Примечание 


Если вы, как и я, воспользовались услугами face="Courier New" size=2>Galery Components, то всю эту работу за вас
проделает мастер, и полученные в последних разделах сведения понадобятся только
в случае, когда вы захотите расширить возможности созданного набора
свойств. 



Обмен данными


Кроме вывода на экран набора свойств, следует обеспечить также обмен данными
между страницами свойств и объектом-владельцем набора свойств. Как и при работе
со всеми блоками диалога, процесс обмена между набором свойств и приложением
играет очень важную роль (что, впрочем, неудивительно, ведь набор свойств и
служит для того, чтобы задавать значения или параметры, необходимые для работы
приложения).


Обмен данными с набором свойств реально является обменом данными с его
отдельными страницами. Процедура обмена при этом ничем не отличается от обмена в
обычном блоке диалога в силу того, что объект класса size=2>CPropertyPage является просто специализированным объектом класса
CDialog. При этом используются средства
обмена данными диалога (Dialog Data Exchange,
DDX),
которые позволяют осуществлять обмен между элементами управления
блока диалога и переменными объекта-владельца блока диалога.


Важное различие в обмене данными между обычным блоком диалога и набором
свойств заключается в том, что набор свойств имеет в своем составе несколько
страниц, для каждой из которых необходимо обеспечить обмен данными.



Операция Apply


Следует остановиться еще на одной важной детали — обработке нажатия кнопки
Apply (Применить). Набор свойств имеет
одну важную способность, отсутствующую у обычных блоков диалога, а именно —
позволяет пользователям изменять задаваемые на странице свойств параметры во
внешнем объекте до того, как окно с набором свойств будет закрыто. Это
осушествляется с помощью кнопки Apply,
нажатие которой приводит к изменению у объекта всех параметров всех страниц (а
не только текущей активной страницы) в наборе свойств. По умолчанию эта кнопка
недоступна. Необходимо самостоятельно написать код программы, делающий ее
доступной для использования в требуемый момент работы с набором свойств. Следует
также написать код, реализующий выполнение необходимых действий при нажатии этой
кнопки.


Если не требуется предоставлять пользователю описанную возможность, то в
общем случае нет необходимости удалять саму кнопку. Ее можно просто оставить
недоступной для того, чтобы сохранить общность с другими приложениями Windows.
Чтобы объявить об изменении параметров в странице свойств и сделать кнопку face="Courier New" size=2>Apply доступной, следует вызвать функцию face="Courier New" size=2>CPropertyPage::SetModified со значением ее
единственного параметра, равным TRUE.
Если какая-либо из страниц свойств содержит изменения, которые еще не применены
к объекту, то, даже если текущая страница таких свойств не содержит, кнопка
Apply все равно будет доступна. Это
значит, что достаточно вызвать функцию size=2>SetModified хотя бы для одной из страниц. Функцию face="Courier New" size=2>SetModified следует вызывать всякий раз, когда
пользователь внес какие-либо изменения в параметры. Одним из способов
обнаружения этого действия является обработка уведомляющих сообщений от
элементов управления страницы свойств, таких, например, как face="Courier New" size=2>EN_CHANGE или size=2>BN_CLICKED.


При нажатии кнопки Apply набор свойств
должен сообщить своему владельцу или какому-то другому внешнему объекту
приложения о том, что необходимо модифицировать текущие параметры в наборе
свойств. Одновременно кнопка становится недоступной, для чего нужно вызвать
функцию SetModified со значением
параметра, равным FALSE. Причем сделать
это необходимо для каждой из страниц свойств, для которых функция SetModified
вызывалась ранее со значением параметра, равным size=2>TRUE, иначе будет считаться, что операция по обновлению не была
совершена. Обратите внимание, что только size=2>Windows хранит информацию о состоянии страницы. Так что при
небольшом количестве страниц свойств можно смело вызвать функцию face="Courier New" size=2>SetModified со значением параметра, равным
FALSE, для всех страниц набора свойств,
чтобы гарантировать результат.


Обработчик команды Apply описывается
следующим кодом:



BEGIN_MESSAGE_MAP(CPropSheet,
CPropertySheet)


size=2>//{{AFX_MSG_MAP(CPropPSheet)


ON_COMMAND(ID_APPLY_NOW,
OnApplyNow)


//}}AFX_MSG_MAP 


size=2>END_MESSAGE_MAP() 


void
CPropSheet::OnApplyNow()


{


Default!);


...


size=2>m_Pagel.SetModifled(FALSE); 


size=2>m_Page2.SetModifled(FALSE);


}


Запретить отображение кнопки Apply
очень просто:



void
[11]CMainFrame::OnProperties()


 {


// Создаем объект
класса


CMyPropertySheet
propSheet;


// Удаляем кнопку
Apply


propSheet.m_psh.dwFlags |=
PSH_NOAPPLYNOW;


// Выводим набор свойств на
экран


propSheet.DoModal();


}


Далее мы приводим очень краткий обзор классов size=2>CPropertySheet и СProperty
Page, используемых для создания набора
свойств, а также новых — CPropertySheetEx
и CPropertyPageEx, реализующих некоторые
дополнительные возможности.



Операции над набором свойств


Несомненный интерес представляют функции, которые предназначены для
выполнения операций над набором свойств.


Для добавления страниц в набор свойств служит функция, о которой уже не раз
упоминалось выше:



void
CPropertySheet::AddPage (CPropertyPage* pPage)


Параметр рРаде — указатель на добавляемую
страницу (не может быть равным NULL). Функция добавляет страницу в набор
свойств, располагая ее вкладку справа от последней из уже имеющихся. Страницы
в наборе свойств будут располагаться в том же порядке, в каком" они
добавлялись в него. Функция добавляет объект класса CPropertyPage в список
страниц свойств класса CPropertySheet, но не создает окно для его размещения.
Библиотека откладывает создание окна для страницы до того момента, пока
пользователь не выберет его.


Если функция вызывается после вывода набора свойств на экран, то в строку
вкладок будет добавлена вкладка новой страницы.


Чтобы удалить страницу из набора свойств, следует воспользоваться одним из
вариантов следующей функции:



void
CPropertySheet::RemovePage (CPropertyPage* pPage)


ИЛИ



void
CPropertySheet::RemovePage (int nPage)


Параметр рРаде в первой версии — указатель
на удаляемую страницу (не может быть равен NULL), а во второй — индекс
страницы, которая должна быть удалена (должен лежать в пределах от 0 до
значения, на единицу меньшего числа страниц в наборе свойств).


Функция удаляет страницу из набора свойств
и уничтожает ассоциированное с ней окно. Сам объект CPropertyPage не удаляется
до того момента, пока владелец окна CPropertySheet не закроет его.


В ходе работы с набором свойств может появиться необходимость определить
какие-либо из его атрибутов или изменить их. Для этого в классе face="Courier New" size=2>CPropertySheet реализованы следующие функции:
GetActiveIndex, GetPage, GetPagelndex,
GetPageCount, GetActive Page, SetActivePage,
SetTitle.


Следует отдельно отметить функцию, позволяющую получить доступ к вкладкам
набора свойств:



CTabCtrl*
CPropertySheet::GetTabControl ()


Возвращает указатель на объект класса
СТаЬСМ.


Вкладки входят в набор свойств неявно и в
общем случае нет необходимости работать с ними отдельно, достаточно лишь при
создании страницы свойств задать текст, который должен будет появиться на
вкладке страницы — все остальное за вас сделает библиотека. Но может
возникнуть ситуация, когда понадобится произвести некоторые дополнительные
действия с вкладками набора свойств, например, поместить на вкладки битовые
изображения. Тогда можно воспользоваться данной функцией, чтобы затем с
помощью функций класса СТаЬСМ выполнить необходимые операции.


Для завершения работы набора свойств служит функция:



void
CPropertySheet::EndDialog (int nEndID)


Параметр nEndID задает значение, которое
возвращает как результат своей работы функция DoModal.


Функция EndDialog вызывается
библиотекой, когда окно набора свойств закрывается нажатием кнопок face="Courier New" size=2>OK, size=2>Cancel или иным способом — нажатием клавиши < face="Courier New" size=2>Esc> или нажатием кнопки закрытия окна в
правой части заголовка, а также в случае, если будет нажата кнопка face="Courier New" size=2>Close (Закрыть). Самим эту функцию можно
вызывать в том случае, когда происходит событие, требующее закрытия набора
свойств.



Изменение параметров отображения


В заключение описания класса size=2>CPropertySheet приведем пример изменения стилей и параметров
отображения набора свойств. На рис. 15.4 представлен набор свойств с
установленными по умолчанию параметрами вывода.


Для изменения некоторых флагов (параметров вывода) следует изменить
конструктор класса, базирующегося на классе size=2>CPropertySheet. Если набор свойств был добавлен в качестве
программного компонента, то такой класс будет создан в обязательном порядке. В
противном случае аналогичные действия следует провести сразу же после создания
объекта в набор свойств, перед вызовом функции
CPropertySheet::DoModal
или size=2>CPropertySheet::Create.



................................................................4

Рис. 15.4. Набор свойств со значениями параметров вывода, заданными по
умолчанию


Вот как можно, например, удалить кнопку size=2>Apply из окна набора свойств:



size=2>CMyPropertySheet::CMyPropertySheet(CWnd* pWndParent)


:
PropertySheet(IDS_PROPSHT_CAPTION, pWndParent)


 {


// Удаляем кнопку
Apply


m_psh.dwFlags ]=
PSH_NQAPPLYNOW;


}


Как видите, для настройки набора свойств используется компонент класса face="Courier New" size=2>m_psh:



PROPSHEETHEADER
CPropertySheet:;m_psh


В структуре PROPSHEETHEADER хранятся
основные параметры набора свойств. Ее можно использовать для изменения этих
параметров уже после создания набора, но до того, как он будет выведен на
экран вызовом функции DoModal
.


typedef struct
_PROPSHEETHEADER { 


DWORD dwSize;


DWORD dwFlags; 


HWND hwndParent; 


HINSTANCE hlnstance;


 union 


{


HICON hIcon;


LPCTSTR pszIcon;


};


LPCTSTR
pszCaption; 


UINT nPages 


union {


UINT nStartPage


LPCTSTR pStartPage;


};


union {


LPCPROPSHEETPAGE ppsp;


HPROPSHEETPAGE FAR
*phpage; 


};


PFNPROPSHEETCALLBACK
pfnCallback; 


#if (_WIN32_IE >=
0x0400)


 union {


HBITMAP hbmWatermark;


LPCTSTR pszbmWatermark;
};


HPALETTE
hplWatermark; 


union {


HBITMAP hbmHeader;


LPCSTR
pszbmHeader; 


};


#endif 


} PROPSHEETHEADER


Поле dwSize— размер структуры в байтах;
dwFlags— массив флагов, указывающих, какие переменные данной структуры должны
быть использованы, а какие проигнорированы. Может быть комбинацией следующих
значений:


PSH_DEFAULT



 Использовать значения по умолчанию
для всех переменных структуры


PSH_HASHELP 



Выводить кнопку Help (Справка). Эта кнопка
будет доступна только в том случае, если флаг PSP_HASHELP также установлен и в
структуре PROPSHEETPAGE для текущей страницы свойств. Если флаг PSP_HASHELP
установлен для какой-либо из страниц в наборе свойств, то кнопка Help появится
автоматически независимо от того, установлен или нет флаг PSH_HASHELP. Однако
флаг PSH_HASHELP полезен тогда, когда ни одна из страниц не имеет его
установленным, но потом могут быть добавлены страницы свойств, содержащие
кнопку Help


PSH_HEADER 



Сообщает, что для заголовка используется
специальный битовый массив, который задается в поле pszbmHeader, если
установлен флаг PSH_USEHBMHEADER, или в поле hbmHeader, если этот флаг не
установлен. Флаг PSH_HEADER игнорируется, если одновременно не установлен флаг
PSH_ WIZARD97


PSH_MODELESS



 Сообщает функции ::PropertySheet, что
набор свойств необходимо создать как немодальный блок диалога (по умолчанию
создается модальный). Если установлен этот флаг, то функция ::PropertySheet
немедленно после создания диалога возвращает дескриптор набора свойств. (При
использовании класса CPropertySheet манипуляции флагом осуществляются
функциями класса.)


PSH_NOAPPLYNOW 



Удаляет кнопку Apply


PSH_PROPSHEETPAGE 



Сообщает о необходимости использовать поле
ppsp структуры и игнорировать phpage


PSH_PROPTITLE 



Добавляет слева строку "Properties for" (в
русской версии Windows — "Свойства:") к строке, заданной в поле
pszCaption


PSH_STRETCHWATERMARK



 Растягивает битовый массив, чтобы
заполнить фон набора свойств вместо перекрытия "водяных знаков" и битового
массива заголовка. Этот флаг игнорируется, если не установлены флаги
PSH_WIZARD97 и PSH_WATERMARK или флаг PSH_HEADER


PSH_USECALLBACK 



Сообщает о необходимости вызывать функцию,
заданную в поле pfnCallback, при инициализации набора свойств, определяемого
данной структурой


PSH_USEHBMHEADER



Сообщает, что для задания битового массива
заголовка используется поле hbmHeader. Если флаг не установлен, то информация
находится в поле pszbmHeader. Этот флаг игнорируется, если не установлены
флаги PSH_WIZARD97 и PSH_HEADER


size=2>PSH_USEHBMWATERMARK 



Сообщает, что для задания битового массива
фона используется поле hbmWatemnark. Если флаг не установлен, то информация
находится в поле pszbmWatermark. Этот флаг игнорируется, если не установлены
флаги PSH_WIZARD97 и PSH_WATERMARK


PSH_USEHICON 



Сообщает о необходимости использовать
пиктограмму, заданную дескриптором в поле hIcon, в заголовке набора
свойств


size=2>PSH_USEHPLWATERMARK 



Для рисования битовых массивов фона и/или
заголовка используется палитра, заданная в поле hplWateimark. Этот флаг
игнорируется, если не установлены флаги PSH_WIZARD97 и PSH_WATERMARK, или флаг
PSH_HEADER


PSH_USEICONID 



Сообщает о необходимости использовать
значок, заданный именем в поле pszlcon, в заголовке набора свойств


PSH_USEPAGELANG 



Устанавливает, что язык для набора свойств
берется из ресурсов первой страницы


PSH_USEPSTARTPAGE 



Сообщает о необходимости использования поля
pStartPage и игнорирования поля nStartPage для определения начальной страницы
набора свойст
в


PSH_WATERMARK 



Сообщает, что для фона используется битовый
массив, который в зависимости от значения флага PSH_USEHBMWATERMARK берется
либо из поля pszbmWatermark, либо из поля hbmWatermark. Этот флаг
игнорируется, если не установлен флаг PSH_ WIZARD97


PSH_WIZARD 



Создается мастер PSH_WIZARD97 Создается
набор свойств мастера с возможностью вывода в фоне и/или в заголовке битовых
массивов


size=2>PSH_WIZARDCONTEXTHELP 



В набор свойств мастера добавлено системное
меню. Этот флаг игнорируется, если не установлен флаг PSH_WIZARD или >,
PSH_WIZARD9
7


size=2>PSH_WIZARDHASFINISH 



В окне мастера отображается кнопка Finish
(Готово). Этот флаг игнорируется, если не установлен флаг PSH_WIZARD или PSH_
WIZARD97


PSH_RTLREADING



 Задает вывод заголовка набора свойств
для чтения справа налево (для арабского языка или иврита)


 Примечание 


Все флаги, которые требуют наличия установленного флага
PSH_ WIZARD97, не поддерживаются в классе CPropertySheet. Для работы с этим
стилем в библиотеке реализован новый класс — CPropertySheetEx.



Поле hwndParent— дескриптор родительского
окна; hlnstance— дескриптор объекта, чья пиктограмма или заголовок должны быть
загружены (если заданы pszlcon или pszCaption, то данный параметр должен быть
заполнен); hlcon— дескриптор значка, помещаемого в заголовке набора свойств
(если dwFlags не содержит значения PSH_USEHICON, то данный параметр
игнорируется). Поле pszlcon предназначено для задания значка, который должен
быть загружен и помещен в заголовке набора свойств, может содержать
идентификатор значка или указатель на строку, задающую ее имя (если в dwFlags
не задано значение PSH_USEHICONID, то данный параметр будет проигнорирован).
Поле pszCaption задает заголовок набора свЬйств, может содержать идентификатор
строкового ресурса или указатель на строку, содержащую заголовок. Если в
dwFlags задано значение PSH_PROPTITLE, то к заголовку будет добавлена слева
строка


"Properties for" (в русской версии Windows—
"Свойства:"). Поле nPages— число элементов в массиве phpage. Поле nStartPage
задает индекс, а поле pStertPage — имя страницы, которая появится на экране
первой при создании набора свойств (параметр должен содержать идентификатор
строкового ресурса или указатель на строку, содержащую имя). Поле ppsp—
указатель на массив структур PROPSHEETPAGE, определяющих страницы набора
свойств. Если в dwFlags не задано значение PSH_PROPSHEETPAGE, то данный
параметр будет проигнорирован. Поле phpage — указатель на массив, содержащий
дескрипторы страниц набора свойств. Каждый дескриптор должен быть создан
предшествующим вызовом функции ::CreatePropertySheetPage (если в dwFlags не
задано значение PSH_PROPSHEETPAGE, то данный параметр будет проигнорирован).
Поле pfnCallback— указатель на функцию приложения, которая вызывается при
инициализации набора свойств (если в dwFlags не задано значение PSH_
USECALLBACK, то данный параметр будет проигнорирован); hbmWatermark и
pszbmWatermark — дескриптор или указатель на текстовую строку ресурса битового
массива, используемого для фона набора свойств (что именно, задается флагом
PSH_USEHBMWATERMARK); hplWatermark — дескриптор палитры, используемой для
вывода битовых массивов (если в dwFlags не задано значение PSH_USEHBMHEADER,
то данный параметр будет проигнорирован); hbmHeader и pszbmHeader— дескриптор
или указатель на текстовую строку ресурса битового массива, используемого для
заголовка набора свойств (что именно, задается флагом
PSH_USEHBMHEADER).


Для изменения способа отображения вкладок следует использовать функцию face="Courier New" size=2>OnlnitDialog.



BOOL
CMyPropertySheet::OnlnitDialog()


{


BOOL bResult =
CPropertySheet::OnlnitDialog();


size=2> CWnd::ModifyStyle(GetTabControl()->m_hWnd,


TCS_MULTILINE,
TCS_SINGLELINE, 0); 


return bResult; 


}


Как видите, в данном случае не обойтись без создания своего собственного
класса. Однако есть более правильный способ (введенный в последней версии
библиотеки MFC), при котором изменение стиля вывода вкладок осуществляется кодом
библиотеки.



void
CPropertySheet::EnableStackedTabs(BOOL bStacked)


Позволяет изменить стиль вывода вкладок
набора свойств. Если параметр bStacked равен FALSE, то вкладки располагаются в
несколько рядов, а если TRUE, то в одну строку с возможностью их
прокрутки.


Эту функцию следует вызывать при создании набора свойств, но до вывода его на
экран.


BOOL
CMyPropertySheet::OnlnitDialog()



{


// Устанавливаем стиль вывода
вкладок в одну линию


size=2>EnableStackedTabs(TRUE);


BOOL bResult =
CPropertySheet::OnInitDialog(); 


return bResult; 


}


Результат использования функции size=2>EnableStackedTabs приведен на рис. 15.5.



..............................................................5

Рис. 15.5. Набор свойств после изменения некоторых значений параметров
вывода


В последней версии библиотеки MFC добавлен новый класс набора свойств face="Courier New" size=2>CPropertySheetEx, который предоставляет
поддержку для расширенной структуры size=2>PROPSHEETHEADER, введенной в Windows 98 и Windows NT Эта структура
была описана раньше, и вы, конечно же, обратили внимание на дополнительные поля
и соответствующие флаги для поддержки битового массива для отображения фона.


Вторым классом, используемым для создания включаемых в набор свойств страниц,
является класс СPropertyPage.



Настройка страниц набора свойств


Выше мы говорили, что объекты класса size=2>CPropertyPage представляют собой отдельные страницы, входящие в
набор свойств. Прежде всего должен быть создан сам объект face="Courier New" size=2>CPropertySheet, а затем необходимо создать
объекты класса С PropertyPage для каждой
вставляемой в набор свойств страницы и добавить созданные страницы в набор
свойств функцией СPropertySheet::AddPage
Теперь можно вывести набор свойств на экран с помощью функций face="Courier New" size=2>LPropertySheet::DoModal - для модального или
CPropertySheet::Create - для немодального
набора свойств.


Как и в случае класса CPropertySheet,
для знакомства с возможными параметрами страницы свойств сначала рассмотрим
переменную, в которой хранятся основные параметры страницы:



PROPSHEETPAGE
CPropertyPage::m_psp


Эту структуру можно использовать для изменения параметров страницы уже после
ее создания, но до того, как она выведена на экран



Создание страницы свойств


Класс CPropertyPage имеет три версии
конструктора:



size=2>CPropertyPage::CPropertyPage (),


CPropertyPage::CPropertyPage
(


UINT nIDTemplate,


UINT nIDCaption =
0) 


И



size=2>CPropertyPage::CPropertyPage (


LPCTSTR
IpszTemplateName,


UINT nIDCaption = 0)


Параметр nIDTemplate — идентификатор
шаблона создаваемой страницы; nIDCaption — идентификатор строки, которая будет
помещена на вкладку данной страницы (если параметр задан равным 0, то имя
будет взято из шаблона диалога для данной страницы); IpszTemplateName—
указатель на строку, содержащую имя шаблона диалога для данной страницы (не
может быть равным NULL).


В случае, если создается массив страниц свойств, вместо конструктора
используется функция Construct.



Изменение состояния


Выше уже описывалась обработка нажатия кнопки size=2>Apply (Применить) в наборе свойств. Для этого предназначена
следующая пара функций:



void
CPropertyPage::SetModifled (BOOL bChanged = TRUE)


Делает доступной или недоступной кнопку
Apply набора свойств в зависимости от того, должны ли быть применимы
параметры, задаваемые в странице свойств, к внешнему объекту. Параметр
bChanged может иметь значение TRUE, если с момента последнего применения
измененных параметров страницы свойств пользователь внес новые изменения, и
FALSE, если значения, заданные в странице свойств, уже применены к внешнему
объекту или они должны быть проигнорированы
.


Кнопка Apply станет доступной, если вызвана функция size=2>SetModified со значением параметра, равным face="Courier New" size=2>TRUE. При значении size=2>FALSE кнопка станет недоступна только в том случае, если все
другие страницы набора свойств не содержат измененных и не модифицированных у
объекта параметров.



Переопределяемые функции


Если страница выбрана пользователем и становится активной (получает фокус
ввода), то библиотека вызывает функцию size=2>OnSetActive:



virtual BOOL
CPropertyPage::OnSetActive ()


Реализация по умолчанию создает окно для
страницы, если оно еще не было создано, и делает его активным.


Данную функцию нужно переопределить, если требуется выполнить какие-либо
операции во время активизации страницы. Если данная функция переопределяется, то
сначала нужно вызвать из нее реализацию функции по умолчанию, а затем выполнять
требуемые действия.


Если текущая страница набора свойств становится неактивной, библиотека
вызывает функцию:



virtual BOOL
CPropertyPage::OnKillActive ()


Реализация по умолчанию копирует данные из
элементов управления страницы в соответствующие переменные набора свойств,
осуществляя их проверку. Если при этом происходит ошибка, то страница не
теряет фокус ввода. Функцию нужно переопределить, если необходимо осуществлять
дополнительную проверку данных.


После успешного завершения функции OnKillActive библиотека вызывает функцию:



virtual void
CPropertyPage::OnOK ()


Вызывается при нажатии кнопок OK, Apply и
Close сразу после вызова функции OnKillActive. Данную функцию нужно
переопределить, если необходимо выполнить какие-либо действия над текущей
страницей перед тем, как будет удален весь набор свойств. Реализация по
умолчанию помечает данную страницу как не имеющую изменений, это означает, что
данные были успешно обновлены функцией OnKillActive.


При нажатии кнопок ОК или face="Courier New" size=2>Apply вызывается функция:



virtual BOOL
CPropertyPage::ОnАрр1у ()


Принимаются все изменения для всех страниц
набора свойств, набор свойств теряет фокус ввода, и функция возвращает
значение TRUE. Чтобы данная функция могла быть вызвана, необходимо прежде
вызвать функцию SetModified со значением параметра, равным TRUE, которая
делает доступной кнопку Apply, если пользователь произвел изменения параметров
в странице свойств. Реализация по умолчанию вызывает функцию ОпОК.


Переопределив данную функцию, можно дать
возможность приложению выполнить требуемые действия при нажатии пользователем
кнопки Apply. Переопределенная функция должна возвращать значение TRUE (если
изменения принимаются) или FALSE (если они не принимаются).


Перегрузка данной функции для каждой
страницы свойств, наверное, вряд ли имеет смысл, гораздо проще обработать
команду в функции класса, производного от CPropertySheet, где можно произвести
изменения сразу всех страниц. Тем более, что функция OnApply вызывается
зачастую даже в том случае, если собственно на странице никаких изменений
произведено не было. Во всяком случае вызов OnApply при активной второй
странице приводит к ее вызову и для первой страницы, и для второй.


При нажатии кнопки Cancel библиотека
вызывает следующую группу функций:



virtual void
CPropertyPage::OnCancel ()


Реализация по умолчанию отменяет все
произведенные изменения. Функцию можно переопределить, если при этом
необходимо дополнительно совершать какие-либо действия.


Как я уже неоднократно упоминал, в библиотеку MFC добавлены несколько новых
классов, в число которых входит и size=2>CPropertyPageEx, расширяющий возможности работы со страницами
свойств.


Этот новый класс библиотеки MFC предоставляет поддержку для расширенной
структуры PROPSHEETPAGE, введенной в
Windows 98 и Windows NT и содержащей дополнительные флаги и компоненты для
работы с широкой областью заголовка, приспособленной для размещения как самого
заголовка, так и подзаголовка.



Мастера


Мастер (Wizard) представляет собой
набор свойств с последовательным набором страниц, которые пользователь может
переключать (перемещение при этом идет на одну страницу вперед или назад).
Мастера широко применяются в программах, например, для установки нового
оборудования или создания факсимильного сообщения. Набор свойств в режиме
мастера не имеет вкладок в верхней части страниц, и на экран в текущий момент
времени выводится только одна страница свойств. В отличие от обычного набора
свойств, мастер не имеет кнопок ОК и
Apply (Применить), а содержит кнопки
Back (Назад), size=2>Next (Далее) (рис. 15.6) или size=2>Finish (Готово), Cancel
(Отмена) и Help (Справка).



...................................................6

Рис. 15.6. Типичное окно мастера



Создание мастеров


Для создания мастера нужно следовать шагам создания обычного набора свойств,
но прежде, чем вызывать функцию size=2>CPropertySheet::DoModal, следует вызвать функцию face="Courier New" size=2>SetWizardMode:



void
CPropertySheet::SetWizardMode ()


Переводит создаваемый набор свойств в режим
мастера. В этом случае при завершении работы пользователя с мастером функция
CPropertySheet::DoModal вернет значение ID_WIZFINISH — если пользователь
закрыл мастер, нажав кнопку Finish, или IDCANCEL — если была нажата кнопка
Cancel. Функция устанавливает флаг PSF_WIZARD.


Чтобы сделать доступными требуемые кнопки мастера, нужно вызвать функцию:



void
CPropertySheet::SetWizardButtons (DWORD dwFlags)


Параметр dwFlags может содержать комбинацию
следующих значений, задающих кнопки, которые должны .быть доступны:


size=2>PSWIZB_BACK                    
Кнопка Back


size=2>PSWIZB_NEXT                    
Кнопка Next


size=2>PSWIZB_FINISH                                    
Кнопка Finish


size=2>PSWIZB_DISABLEDFINISH          
Кнопка Finish недоступна


Данную функцию можно вызвать только после
того, как было открыто диалоговое окно мастера. Ее невозможно вызвать раньше
функции CPropertySheet::DoModal. Обычно ее вызывают из функции
CPropertyPage::OnSetActive.


Чтобы сделать доступной кнопку Finish
или скрыть кнопки Back и face="Courier New" size=2>Next в тот момент, когда пользователь, работая
с мастером, достигнет последней страницы, нужно вызвать функцию face="Courier New" size=2>SetFinishText.



void
CPropertySheet::SetFinishText (LPCTSTR IpszText)


Помещает на кнопке Finish текст, заданный
параметром IpszText, и скрывает кнопки Back и Next, когда пользователь
завершает действия на последней странице мастера
.



Переопределяемые функции


Класс CPropertyPage содержит следующие
переопределяемые функции, используемые при создании мастера:



virtual LRESULT
CPropertyPage::OnWizardBack() 


Вызывается, если нажата кнопка Back.


virtual LRESULT
CPropertyPage::OnWizardNext()


Вызывается, если нажата кнопка Next. Обе
функции возвращают 0, если должен быть осуществлен переход соответственно на
одну страницу назад или вперед, или —1, что означает невозможность перехода к
другой странице.


Если необходим переход более чем на одну страницу, то возвращается
соответствующий идентификатор диалогового окна. Другим способом перехода к
нужной странице является возможность задания в качестве текущей той, которая
находится перед или после нужной, при помощи функции size=2>CPropertySheetr::SetActivePage.



virtual BOOL
CPropertyPage::OnWizardFinish ()


Вызывается библиотекой, когда пользователь
нажал кнопку Finish. Если функция возвращает значение TRUE, то набор свойств
не уничтожается. Данную функцию можно переопределить, если необходимо
выполнить какие-либо действия при нажатии пользователем кнопки Finish. При
этом функция должна вернуть значение TRUE для того, чтобы набор свойств не был
уничтожен.


Вот, собственно, и все, что я хотел рассказать о наборах свойств и мастерах.
С примерами использования и работы с наборами свойств мы познакомимся в
следующей главе, где предметом изучения станут элементы управления.


По материаллам сайта: www.realcoding.net

16.02.2006

Телефон

+7 8636 237-836

Поиск

VSESMI.ru — новости в СМИ.
Один из больших по объему информации проектов, работающих под управлением HostCMS.

Tur-Hotel.ru — отзывы об отелях
На сайте представлено описание отелей, рейтинг отелей с отзывами туристов.