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

Модальные окна страниц свойств MFC

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

Получив средства отображения состояния отключенных вкладок (доступна или не доступна), добавим функцию, которая фактически отключает возможность выбора пользователем заблокированной вкладки. Эту задачу выполнит виртуальная функция OnNotify() базового класса CPropertySheet, которую мы переопределим в нашем классе-наследнике CFindSheet.

  • Выделите в панели Class View класс CFindSheet и перейдите в панель Properties
  • Установите в панели Properties режим Overrides и создайте в проекте переопределенную функцию OnNotify()

  • Наполните созданную функцию следующим кодом

    Переопределение виртуальной функции OnNotify()
    BOOL CFindSheet::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
    {
      NMHDR *pNmh = (NMHDR*)lParam;
      ASSERT(pNmh);
      if(pNmh->code == TCN_SELCHANGING)
        m_iLastActivePage = GetActiveIndex();
      else if(pNmh->code == TCN_SELCHANGE){
        int iCurrPage = GetActiveIndex();
        if(IsPageDisabled(iCurrPage))
          PostMessage(PSM_SETCURSEL, m_iLastActivePage);
      }
      
      return CPropertySheet::OnNotify(wParam, lParam, pResult);
    }

    Далее мы добавим функцию IsPageDisabled(), проверяющую, числится ли выбираемая пользователем вкладка как недоступная.

  • Выделите в панели Class View класс CFindSheet, вызовите мастер добавления функций, который заполните так

  • Нажмите кнопку Add, затем кнопку Finish

Мастер добавит заготовку в конец файла FindSheet.cpp, а в описание класса добавит прототип функции.

  • Наполните созданную функцию следующим кодом
    Проверка доступности вкладок
    // Определяет, числится ли выбираемая
    // пользователем вкладка в недоступных
    BOOL CFindSheet::IsPageDisabled(int iPage)
    {
      BOOL bFoundEntry = FALSE;
      int iSize = (int)m_arrDisabledPages.GetSize();
      
      int i = 0;
      while(i < iSize && !bFoundEntry)
        if(m_arrDisabledPages.GetAt(i) == (UINT)iPage)
          bFoundEntry = TRUE;
        else
          i++;
      
      return bFoundEntry;
    }

Пока ничего не было найдено, вкладка Result должна быть пользователю недоступной. Мы для этого создали соответствующий код. Теперь осталось проверить его работу.

  • Найдите функцию-член OnInitDialog() класса CFindSheet и добавьте в конец следующий код
    Сделать недоступной вкладку Result с индексом 1
    BOOL CFindSheet::OnInitDialog()
    {
    ..............................................
      pBtnOk->SetWindowText(_T("Close"));
      
      DisablePage(1, -1);
      
      return bResult;
    }
  • Постройте приложение и убедитесь, что в начальный момент вкладка Result недоступна

Подключение вкладок

Имея возможность отключать вкладки окна свойств нужно дать возможность включать их. Для этого необходимо добавить функцию EnablePage(), восстанавливающую доступ к вкладке, и функцию SetEnabledText(), удаляющую из ее заголовка маркер " - Disabled".

  • В панели Class View выделите класс CFindSheet, поскольку добавлять функцию-член мы будем именно в этот класс
  • Через контекстное меню по щелчку правой кнопкой мыши на классе CFindSheet вызовите мастер добавления функций, который заполните так

  • Нажмите кнопку Add, затем кнопку Finish. Мастер добавит заготовку в конец файла FindSheet.cpp, а в описание класса добавит прототип функции
  • Наполните созданную функцию следующим кодом
    Функция включения доступа к вкладке
    // Включение вкладки
    void CFindSheet::EnablePage(int iPage)
    {
      BOOL bFoundEntry = FALSE;
      int iSize = (int)m_arrDisabledPages.GetSize();
      
      int i = 0;
      while(i < iSize && !bFoundEntry)
        if(m_arrDisabledPages.GetAt(i) == (UINT)iPage)
          bFoundEntry = TRUE;
        else
          i++;
      
      if(bFoundEntry){
        m_arrDisabledPages.RemoveAt(i);
        SetEnabledText(iPage);
      }
    }
  • Снова в панели Class View выделите класс CFindSheet
  • Через контекстное меню по щелчку правой кнопкой мыши на классе CFindSheet вызовите мастер добавления функций, который заполните так

  • Нажмите кнопку Add, затем кнопку Finish

    Мастер добавит заготовку в конец файла FindSheet.cpp, а в описание класса добавит прототип функции.

  • Наполните созданную функцию следующим кодом
    Удаление маркера " - Disabled" из заголовка вкладки
    // Удаление маркера " - Disabled" из заголовка вкладки
    void CFindSheet::SetEnabledText(int iPage)
    {
      CTabCtrl *pTab = GetTabControl();
      ASSERT(pTab);
      TC_ITEM ti;
      char szText[100];
      ti.mask = TCIF_TEXT;
      ti.pszText = szText;
      ti.cchTextMax = 100;
      VERIFY(pTab->GetItem(iPage, &ti));
      // Функция strstr() осуществляет поиск в строке szText
      // первого вхождения подстроки DISABLED_TEXT
      char *pFound = strstr(szText, DISABLED_TEXT);
      if(pFound){
        *pFound = '\0'; // Устанавливаем метку конца заголовка
        VERIFY(pTab->SetItem(iPage, &ti));
      }
    }

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

Класс CFindSheet является родительским по отношению к классам вкладок CFindPage и CResultPage. Мы создадим обработчик кнопки Find первой вкладки, в котором получим указатель на объект родительского класса, а потом адресуемся к проверяемой функции EnablePage() родительского класса.

  • Откройте панель Resource View оболочки и вызовите на редактирование ресурс IDD_PROPPAGE_FIND
  • Выделите кнопку Find и через контекстное меню выполните пункт Add Event Handler... (то же самое можно сделать для создания обработчика двойным щелчком мыши на кнопке Find )

  • Наполните созданную функцию следующим кодом
    Обработчик кнопки Find
    void CFindPage::OnBnClickedButtonFind()
    {
      // TODO: Add your control notification handler code here
      CFindSheet *pParentSheet = (CFindSheet*)GetParent();
      
      ASSERT(pParentSheet->IsKindOf(RUNTIME_CLASS(CFindSheet)));
      
      pParentSheet->EnablePage(1);// Вторая вкладка
    }
  • В начало файла FindPage.cpp добавьте директиву #include, подключающую к этому файлу заголовочный файл с описанием класса CFindSheet, используемого в обработчике
    Подключение заголовочного файла FindSheet.h к файлу с обработчиком кнопки FindPage.cpp
    // FindPage.cpp : implementation file
    //
      
    #include "stdafx.h"
    #include "ModalDemo.h"
    #include "FindPage.h"
    #include ".\findpage.h"
      
    #include "FindSheet.h"
      
    // CFindPage dialog
      
    IMPLEMENT_DYNAMIC(CFindPage, CPropertyPage)
    CFindPage::CFindPage()
      : CPropertyPage(CFindPage::IDD)
    {
    }
      
    CFindPage::~CFindPage()
    {
    }
    ..................................................
  • Постройте приложение и убедитесь, что вкладка Result становится доступной после щелчка по кнопке Find
Александр Даниленко
Александр Даниленко
Стоит Windows 8 Pro, Visual Studio 2010 Express Edition .