Опубликован: 17.08.2010 | Доступ: свободный | Студентов: 1000 / 59 | Оценка: 4.11 / 3.89 | Длительность: 29:38:00
Самостоятельная работа 19:

Модальные окна страниц свойств 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;
    }
  • Запустите приложение и убедитесь в результате - теперь на кнопке другая надпись
Александр Даниленко
Александр Даниленко
Стоит Windows 8 Pro, Visual Studio 2010 Express Edition .