Стоит Windows 8 Pro, Visual Studio 2010 Express Edition . |
Модальные окна страниц свойств MFC
Модификация стандартного окна свойств
Выполним работу по настройке страниц свойств в соответствии с нашими пожеланиями.
Удаление стандартных кнопок
При отображении модального окна свойств автоматически создаются несколько кнопок. Но иногда в приложении эти стандартные кнопки не нужны.
Предположим, что необходимо удалить кнопки Cancel (Отмена) и Apply (Применить). Обычно изменения параметров, внесенные в диалоговое окно, вступают в силу либо при нажатии кнопки Применить, либо после закрытия окна, если только при этом не была нажата кнопка Cancel (Отмена). В нашем случае окно свойств никаких параметров изменять не будет, поэтому эти две кнопки можно убрать. Но как их убрать, если для окна свойств в нашем приложении отсутствует ресурс диалогового окна свойств и все кнопки созданы с помощью MFC. Выход в том, чтобы скрыть ненужные кнопки.
Стандартные кнопки, создаваемые MFC, всегда имеют идентификаторы, показанные в таблице
Идентификаторы стандартных кнопок | |
---|---|
Кнопка | Идентификатор |
OK | IDOK |
Cancel | IDCANCEL |
Help | IDHELP |
Apply | ID_APPLY_NOW |
- В панели Class View выделите верхний узел дерева классов проекта и через контекстное меню выполните команду Add Class...
- Появится окно настройки Add Class, которое разметьте так
-
После щелчка по кнопке Open появится окно мастера добавления класса, которое заполните так
После щелчка по кнопке Finish создастся класс, производный от MFC -класса CPropertySheet и с именем CFindSheet. Этот класс расширяет возможности стандартного базового класса CPropertySheet и мы можем в этом расширении внести свои дополнения. Код нового класса мы будем использовать в файле ModalDemoView.cpp, поэтому подключим с помощью директивы #include описание класса к этому файлу.
-
Вынесите подключение заголовочного файла FindSheet.h в начало файла ModalDemoView.cpp после подключений заголовков файлов страниц свойств
Подключение класса CFindSheet к файлу ModalDemoView.cpp // ModalDemoView.cpp : implementation of the CModalDemoView class // #include "stdafx.h" #include "ModalDemo.h" #include "ModalDemoDoc.h" #include "ModalDemoView.h" #include ".\modaldemoview.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #include "FindPage.h" #include "ResultPage.h" #include "FindSheet.h" // CModalDemoView IMPLEMENT_DYNCREATE(CModalDemoView, CView) ..............................................
-
Измените обработчик пункта меню Find Book так, чтобы вместо экземпляра стандартного класса CPropertySheet создавался экземпляр созданного нами класса-расширения CFindSheet
Изменение обработчика пункта меню void CModalDemoView::OnBooksFindbook() { // CPropertySheet sheet(IDS_FIND); CFindSheet sheet(IDS_FIND); CFindPage pageFind; CResultPage pageResult; sheet.AddPage(&pageFind); sheet.AddPage(&pageResult); sheet.DoModal(); }
Теперь скроем ненужные кнопки IDCANCEL и ID_APPLY_NOW в окне свойств, переопределив функцию OnInitDialog() в классе CFindSheet.
- Откройте панель Class View, найдите и выделите класс CFindSheet
- Сразу после выделения откройте панель Properties, установите режим Overrides и найдите функцию OnInitDialog() для выделенного класса
-
Создайте переопределенную функцию, которую заполните следующим кодом
Переопределенная функция OnInitDialog() BOOL CFindSheet::OnInitDialog() { BOOL bResult = CPropertySheet::OnInitDialog(); // TODO: Add your specialized code here int ids[] = { IDCANCEL, ID_APPLY_NOW }; int len = sizeof(ids) / sizeof(ids[0]); for(int i = 0; i < len; i++){ CWnd *pWnd = GetDlgItem(ids[i]); ASSERT(pWnd); if(pWnd) pWnd->ShowWindow(FALSE); } return bResult; }
- Постройте проект и убедитесь, что двух кнопок больше нет, мы их скрыли перед появлением окна свойств на экране
Перемещение стандартных кнопок
Оставшаяся нескрытой кнопка OK расположена на том же самом месте, где она находилась и ранее до сокрытия двух других кнопок. Переместим оставшуюся кнопку в другое место. Для этого воспользуемся функцией-членом класса CWnd::MoveWindow(), предварительно рассчитав координаты нового положения кнопки.
-
Дополните переопределенную функцию CFindSheet::OnInitDialog() следующим кодом
Дополнение функции кодом перемещения кнопки BOOL CFindSheet::OnInitDialog() { BOOL bResult = CPropertySheet::OnInitDialog(); // TODO: Add your specialized code here int ids[] = { IDCANCEL, ID_APPLY_NOW }; int len = sizeof(ids) / sizeof(ids[0]); for(int i = 0; i < len; i++){ CWnd *pWnd = GetDlgItem(ids[i]); ASSERT(pWnd); if(pWnd) pWnd->ShowWindow(FALSE); } CWnd *pBtnOk = GetDlgItem(IDOK); ASSERT(pBtnOk); CRect rectSheet; GetWindowRect(rectSheet); // Размер окна свойств CRect rectBtnOk; pBtnOk->GetWindowRect(rectBtnOk); // Размер окна кнопки // Выяснить расстояние между нижней частью кнопки // и нижней частью окна свойств int iBorder = rectSheet.bottom - rectBtnOk.bottom; // Изменить размеры окна свойств rectSheet.right += rectBtnOk.Width() + iBorder; rectSheet.bottom = rectBtnOk.top; MoveWindow(rectSheet); // Найти первую страницу CPropertyPage *pPage = GetPage(0); ASSERT(pPage); CRect rectPage; pPage->GetWindowRect(rectPage); // Размер страницы свойств // Сохранить ширину и высоту кнопки OK int cxOk = rectBtnOk.Width(); int cyOk = rectBtnOk.Height(); // Переместить кнопку OK rectBtnOk.top = rectPage.top; rectBtnOk.bottom = rectPage.top + cyOk; rectBtnOk.left = rectSheet.right - (cxOk + iBorder); rectBtnOk.right = rectBtnOk.left + cxOk; ScreenToClient(rectBtnOk); pBtnOk->MoveWindow(rectBtnOk); return bResult; }
- Постройте приложение и убедитесь, что кнопка переместилась на нужное место, а окно свойств изменило размеры
Результат должен выглядеть так
Изменение надписей стандартных кнопок
Надпись на кнопке должна описывать действия, осуществляемые при щелчке на ней. Увидев в диалоговом окне Find Book кнопку OK, пользователь вряд ли сможет догадаться, что случится, если он щелкнет по ней. Приведет ли щелчок на кнопке OK к закрытию диалогового окна или началу поиска - из названия не ясно. Заменим надпись на кнопке более содержательной.
Еще раз вспомним, что диалоговый ресурс, который можно править в редакторе диалоговых окон, у нас имеется только для страниц свойств. Мы же в данный момент учимся изменять структуру диалогового окна свойств, которое стандартно сгенерировано MFC -библиотекой и не имеет ресурса в приложении, который мы могли бы визуально отредактировать. Поэтому мы вынуждены добиваться необходимых визуальных результатов программно.
-
Добавьте в конец все той же функции OnInitDialog() класса CFindSheet следующий код
Дополнение функции кодом изменения надписи на кнопке OK BOOL CFindSheet::OnInitDialog() { ........................................... ScreenToClient(rectBtnOk); pBtnOk->MoveWindow(rectBtnOk); pBtnOk->SetWindowText(_T("Close")); return bResult; }
- Запустите приложение и убедитесь в результате - теперь на кнопке другая надпись