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

Использование элементов управления MFC

Управление доступностью и видимостью инструментов приложения

Закрепим за флажками возможность блокировать или скрывать закрепленные за ними инструменты. Для этого воспользуемся методами базового класса CWnd. Будем иметь в виду, что любой элемент управления на этапе проектирования приложения является ресурсом, а после компиляции представляет собой обычное окно Windows, созданное на базе MFC -класса CWnd. Это позволяет управлять элементами управления программно через методы базового класса CWnd, в частности

  • GetDlgItem() - возвращает указатель на дочернее окно, коим является элемент управления. Данному методу передается идентификатор дочернего окна.
  • EnableWindow() - включает или отключает возможность взаимодействовать с окном. Передается ненулевой или нулевой аргумент.
  • ShowWindow() - позволяет отобразить или скрыть окно. Передается ненулевой или нулевой аргумент.
  • Создайте для каждого флажка обработчики событий BN_CLICKED и наполните их кодом, как показано в листингах ниже
    Обработчик флажка "Разрешить сообщения" файла ControlsDlg.cpp
    // Доступность блока сообщений
    void CControlsDlg::OnBnClickedEnableMsg()
    {
      // Получить текущие значения от экрана
      UpdateData(TRUE);
        
      if(m_bEnableMsg == TRUE){ // Флажок "Разрешить сообщение" установлен
        // Включить все элементы управления,
        // имеющие отношение к отображению сообщений
        GetDlgItem(IDC_STATIC_MSG)->EnableWindow(TRUE);  // надпись "Ввести сообщение"
        GetDlgItem(IDC_MSG)->EnableWindow(TRUE);    // поле ввода
        GetDlgItem(IDC_SHOW_MSG)->EnableWindow(TRUE);  // кнопка "Отобразить сообщение"
        GetDlgItem(IDC_DEFAULT_MSG)->EnableWindow(TRUE);// кнопка "Сообщение по умолчанию"
        GetDlgItem(IDC_CLEAR_MSG)->EnableWindow(TRUE);  // кнопка "Очистить сообщение"
      }
      else{
        // Выключить все элементы управления,
        // имеющие отношение к отображению сообщений
        CWnd *pWnd;  // Указатель на оконный базовый класс MFC
            // Переменная-указатель локальный внутри блока кода else
      
        pWnd = GetDlgItem(IDC_STATIC_MSG);
        pWnd->EnableWindow(FALSE);  // надпись "Ввести сообщение"
      
        pWnd = GetDlgItem(IDC_MSG);
        pWnd->EnableWindow(FALSE);  // поле ввода
        
        pWnd = GetDlgItem(IDC_SHOW_MSG);
        pWnd->EnableWindow(FALSE);  // кнопка "Отобразить сообщение"
      
        pWnd = GetDlgItem(IDC_DEFAULT_MSG);
        pWnd->EnableWindow(FALSE);  // кнопка "Сообщение по умолчанию"
      
        pWnd = GetDlgItem(IDC_CLEAR_MSG);
        pWnd->EnableWindow(FALSE);  // кнопка "Очистить сообщение"
      }
    }
    Обработчик флажка "Разрешить выполнение" файла ControlsDlg.cpp
    // Доступность блока выполнения
    void CControlsDlg::OnBnClickedEnableProgram()
    {
      // Получить текущие значения от экрана
      UpdateData(TRUE);
      CWnd *pWnd;  // Указатель на оконный базовый класс MFC
          // Переменная-указатель локальный внутри функции
      
      if(m_bEnableProgram == TRUE){ // Флажок "Разрешить выполнение" установлен
        // Включить все элементы управления,
        // имеющие отношение к отображению выполнений
        pWnd = GetDlgItem(IDC_STATIC_PROGRAM);
        pWnd->EnableWindow(TRUE);  // надпись "Запустить программу"
      
        pWnd = GetDlgItem(IDC_COMBO_RUN);
        pWnd->EnableWindow(TRUE);  // раскрывающийся список
      
        pWnd = GetDlgItem(IDC_RUN);
        pWnd->EnableWindow(TRUE);  // кнопка "Выполнить"
      }
      else{
        // Выключить все элементы управления,
        // имеющие отношение к отображению выполнений
        GetDlgItem(IDC_STATIC_PROGRAM)->EnableWindow(0);// надпись "Запустить программу"
        GetDlgItem(IDC_COMBO_RUN)->EnableWindow(0);  // раскрывающийся список
        GetDlgItem(IDC_RUN)->EnableWindow(0);    // кнопка "Выполнить"
      }
    }
    Обработчик флажка "Отображать сообщения" файла ControlsDlg.cpp
    // Отобразить - скрыть блок сообщений
    void CControlsDlg::OnBnClickedShowsMsg()
    {
      // Получить текущие значения от экрана
      UpdateData(TRUE);  
      
      if(m_bShowsMsg == TRUE){ // Флажок "Отображать сообщения" установлен
        // Нарисовать все элементы управления,
        // имеющие отношение к отображению сообщений
        GetDlgItem(IDC_STATIC_MSG)->ShowWindow(TRUE);  // надпись "Ввести сообщение"
        GetDlgItem(IDC_MSG)->ShowWindow(TRUE);    // поле ввода
        GetDlgItem(IDC_SHOW_MSG)->ShowWindow(TRUE);  // кнопка "Отобразить сообщение"
        GetDlgItem(IDC_DEFAULT_MSG)->ShowWindow(TRUE);  // кнопка "Сообщение по умолчанию"
        GetDlgItem(IDC_CLEAR_MSG)->ShowWindow(TRUE);  // кнопка "Очистить сообщение"
      }
      else{
        // Скрыть все элементы управления,
        // имеющие отношение к отображению сообщений
        GetDlgItem(IDC_STATIC_MSG)->ShowWindow(FALSE);  // надпись "Ввести сообщение"
        GetDlgItem(IDC_MSG)->ShowWindow(FALSE);    // поле ввода
        GetDlgItem(IDC_SHOW_MSG)->ShowWindow(FALSE);  // кнопка "Отобразить сообщение"
        GetDlgItem(IDC_DEFAULT_MSG)->ShowWindow(FALSE);  // кнопка "Сообщение по умолчанию"
        GetDlgItem(IDC_CLEAR_MSG)->ShowWindow(FALSE);  // кнопка "Очистить сообщение"
      }
    }
    Обработчик флажка "Отображать выполнение" файла ControlsDlg.cpp
    // Отобразить - скрыть блок выполнения
    void CControlsDlg::OnBnClickedShowsProgram()
    {
      // Получить текущие значения от экрана
      UpdateData(TRUE);
        
      if(m_bShowsProgram == TRUE){ // Флажок "Отображать выполнение" установлен
        // Нарисовать все элементы управления,
        // имеющие отношение к отображению выполнений
        GetDlgItem(IDC_STATIC_PROGRAM)->ShowWindow(TRUE);  // надпись "Запустить программу"
        GetDlgItem(IDC_COMBO_RUN)->ShowWindow(TRUE);    // раскрывающийся список
        GetDlgItem(IDC_RUN)->ShowWindow(TRUE);      // кнопка "Выполнить"
      }
      else{
        // Скрыть все элементы управления,
        // имеющие отношение к отображению выполнений
        GetDlgItem(IDC_STATIC_PROGRAM)->ShowWindow(FALSE);  // надпись "Запустить программу"
        GetDlgItem(IDC_COMBO_RUN)->ShowWindow(FALSE);    // раскрывающийся список
        GetDlgItem(IDC_RUN)->ShowWindow(FALSE);      // кнопка "Выполнить"
      }
    }
  • Постройте приложение и убедитесь, что флажки работают как и было задумано
Управление раскрывающимся списком

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

  • Выделите на форме элемент управления Combo Box, который имеет идентификатор IDC_COMBO_RUN
  • В контекстном меню вызовите мастер добавления переменной и настройте его как показано на рисунке

Мастер добавит в описание класса CControlsDlg файла ControlsDlg.h код

Изменения в объявлении класса CControlsDlg файла ControlsDlg.h, 
добавленные мастером при создании переменной для управления списком
// CControlsDlg dialog
class CControlsDlg : public CDialog
{
  ...............
  afx_msg void OnBnClickedExit();
  afx_msg void OnBnClickedShowMsg();
  afx_msg void OnBnClickedClearMsg();
  afx_msg void OnBnClickedDefaultMsg();
  afx_msg void OnBnClickedEnableMsg();
  afx_msg void OnBnClickedEnableProgram();
  afx_msg void OnBnClickedShowsMsg();
  afx_msg void OnBnClickedShowsProgram();
  // Переменная для управления раскрывающимся списком
  CComboBox m_lstCombo;
};

В файл ControlsDlg.cpp мастер добавит код для обеспечения механизма обмена данными между программой и экраном

Изменения в файле ControlsDlg.cpp, добавленные мастером для обмена данными кода и списка
void CControlsDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialog::DoDataExchange(pDX);
  DDX_Text(pDX, IDC_MSG, m_strMessage);
  DDX_CBString(pDX, IDC_COMBO_RUN, m_strRun);
  DDX_Check(pDX, IDC_ENABLE_MSG, m_bEnableMsg);
  DDX_Check(pDX, IDC_ENABLE_PROGRAM, m_bEnableProgram);
  DDX_Check(pDX, IDC_SHOWS_MSG, m_bShowsMsg);
  DDX_Check(pDX, IDC_SHOWS_PROGRAM, m_bShowsProgram);
  DDX_Control(pDX, IDC_COMBO_RUN, m_lstCombo);
}

Мы хотим, чтобы при запуске приложения список устанавливался в первую позицию (нумерация элементов списка начинается с нуля), поэтому

  • Добавьте код в функцию инициализации
    Код установки начальной позиции раскрывающегося списка
    BOOL CControlsDlg::OnInitDialog()
    {
      .............
      // TODO: Add extra initialization here
      
      // Установить список в начало
      m_lstCombo.SetCurSel(0);
      UpdateData(TRUE);  // скачать из списка в переменную m_strRun
      
      // Поместить заданное по умолчанию значение
      // в поле редактирования Edit Control
      m_strMessage = "Привет студентам!!!";
        
      // Установить все флажки
      m_bEnableMsg = TRUE;
      m_bEnableProgram = TRUE;
      m_bShowsMsg = TRUE;
      m_bShowsProgram = TRUE;
      
      // FALSE - передать значения из переменных в элементы управления
      // TRUE - передать значения из элементов управления в переменные
      UpdateData(FALSE);
      
      return TRUE;  // return TRUE  unless you set the focus to a control
    }
  • Постройте проект и убедитесь, что код работает
Запуск внешних приложений

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

Для запуска внешних приложений существуют функции

  • WinExec()
  • ShellExecute()
  • CreateProcess()
  • execlp()
  • spawnlp()

Ознакомимся только с функцией WinExec(). Эта функция может работать в любых версиях Windows и выполнять любые файлы. Функция работает асинхронно, т.е. после запуска внешнего приложения не ждет его закрытия. Функции, которые ждут завершения запущенного ими процесса, работают синхронно.

Заголовок функции WinExec()
UINT WinExec(
  LPCSTR lpCmdLine,
  UINT uCmdShow
);

Параметр lpCmdLine является указателем на строковую константу, содержащую имя выполняемого файла и, если необходимо, параметры командной строки. Если имя файла указано без пути, то Windows будет искать файл в следующей последовательности:

  1. Каталог, из которого загружено вызывающее приложение
  2. Текущий каталог
  3. Системный каталог Windows, возвращаемый API -функцией GetSystemDirectory()
  4. Каталог Windows, возвращаемый API -функцией GetWindowsDirectory()
  5. Список каталогов из переменной окружения PATH

Параметр uCmdShow определяет форму представления окна запускаемого приложения и может иметь значения

Значение uCmdShow Описание
SW_HIDE Окно делается невидимым и фокус передается другому окну
SW_MAXIMIZE Развертывает окно
SW_MINIMIZE Свертывает окно, активизируя следующее в Z -последовательности окно верхнего уровня в списке системы
SW_RESTORE Активизирует и отображает окно с первоначальными параметрами
SW_SHOW Активизирует и отображает окно с текущими параметрами
SW_SHOWDEFAULT Устанавливает состояние окна в соответствии с флагом SW_ в структуре STARTUPINFO
SW_SHOWMAXIMIZED Активизирует и отображает окно в развернутом виде
SW_SHOWMINIMIZED Активизирует и отображает окно в виде пиктограммы в панели задач
SW_SHOWMINNOACTIVE Отображает окно в свернутом виде, оставляя активным предыдущее окно
SW_SHOWNA Отображает окно в его текущей позиции и текущими размерами, не передавая фокус. Активным остается то окно, которое было активным до этого
SW_SHOWNOACTIVATE Отображает окно в его последней позиции и с последними размерами. Активным остается то окно, которое было активным до этого
SW_SHOWNORMAL Активизирует и отображает окно, восстанавливая его до первоначальных размеров и в первоначальной позиции

Функция WinExec() возвращает беззнаковое целое, свидетельствующее об успехе или ошибке. Если возвращаемое значение меньше или равно 31, то это указывает на ошибку.

Именованная константа Значение Описание
0 0 Системе не хватает памяти, выполняемый файл испорчен или произошло ошибочное перераспределение памяти
ERROR_BAD_FORMAT 11 Плохой исполняемый файл. Или это не приложение Windows, или ошибка в .exe файле
ERROR_FILE_NOT_FOUND 2 Файл не найден
ERROR_PATH_NOT_FOUND 3 Путь не найден
  • Обработайте кнопку "Выполнить" следующим кодом
    Обработчик нажатия на кнопку "Выполнить"
    void CControlsDlg::OnBnClickedRun()
    {
      // Передать текущие значения элементов управления в переменные
      UpdateData(TRUE);
      // Объявить локальную переменную для хранения названия программы
      CString strName;
      // Копировать текущее поле списка в локальную переменную
      strName = m_strRun;
      // Перевести название программы в верхний регистр
      strName.MakeUpper();
      int error = WinExec(strName, SW_RESTORE);
      switch(error){
        case 0:
          MessageBox( "Не хватает памяти или ресурсов!",
                "Ошибка!", MB_OK | MB_ICONINFORMATION );
          break;
    
        case ERROR_BAD_FORMAT:
          MessageBox( "Ошибочный файл!",
                "Ошибка!", MB_OK | MB_ICONINFORMATION );
          break;
    
        case ERROR_FILE_NOT_FOUND:
          MessageBox( "Файл не найден!",
                "Ошибка!", MB_OK | MB_ICONINFORMATION );
          break;
    
        case ERROR_PATH_NOT_FOUND:
          MessageBox( "Путь не найден!",
                "Ошибка!", MB_OK | MB_ICONINFORMATION );
      }
    }
  • Постройте приложение и убедитесь в его работоспособности

Александр Даниленко
Александр Даниленко
Стоит Windows 8 Pro, Visual Studio 2010 Express Edition .