Опубликован: 10.03.2009 | Доступ: свободный | Студентов: 2297 / 279 | Оценка: 4.31 / 4.07 | Длительность: 09:23:00
Лекция 5:

Разработка полноценных Windows-приложений

Проектирование и разработка приложений

Этапы разработки

  1. Создать ресурс диалогового окна.
  2. Организовать ввод и редактирование начальных данных.
  3. Построить СЛАУ и решить ее.
  4. Организовать вывод результатов.

Создадим с помощью мастера MFC приложение "Regr" на основе диалогового окна. Для этого установим Application type в значение Dialog based. Снимем флажок Use Unicode libraries.

1. Создание ресурса диалогового окна

Создадим диалоговое окно с тремя текстовыми полями для ввода данных в таблицу и указания степени аппроксимации, четырьмя кнопками(Add, Delete, Start Approximation, Exit), списковым представлением для отображения таблицы точек и текстовым полем RichEdit для вывода строки результата. Шаблон диалога приведен на рисунке: рис. 5.9

Создание диалогового окна

Рис. 5.9. Создание диалогового окна

Для всех элементов управления типа поле ввода, установим свойство Right Align Text в значение true. Для элемента управления типа поле ввода, расположенного напротив надписи Approximation degree: установим свойство Number в значение true. Для элемента управления типа поле ввода с форматированием, установим свойство Auto HScroll в значение true, свойство Align Text в значение center, свойство Horizontal Scroll в значение true, свойство Read Only в значение true. Для элемента управления типа списковое представление, установим свойство Border в значение false (убираем рамку для того, чтобы проще было получить размеры клиентской области элемента управления), свойство Single Selection в значение true, свойство View в значение Report (будем выводить таблицу).

2. Ввод и редактирование начальных данных

Начальные данные представляют собой точки плоскости. Как и в примере "Интерполяционный полином", введем класс, инкапсулирующий вещественную точку на плоскости. Добавим в файл RegrDlg.h, содержащий прототип класса основного диалога, следующий код:

class SDPoint
{
public:
  double x;
  double y;
  SDPoint():x(0),y(0){}  //Конструктор по умолчанию
  SDPoint(double a, double b):x(a),y(b){}  //Конструктор с параметрами
};

после строки

#pragma once

Теперь, создадим в классе диалога массив объектов класса SDPoint, который будет хранить начальные данные. Прототип класса CRegrDlg:

// CRegrDlg dialog
class CRegrDlg : public CDialog
{
// Construction
public:
  CRegrDlg(CWnd* pParent = NULL);  // standard constructor
// Dialog Data
  enum { IDD = IDD_REGR_DIALOG };
protected:
  virtual void DoDataExchange(CDataExchange* pDX);  // DDX/DDV support
// Implementation
protected:
  HICON m_hIcon;
  // Generated message map functions
  virtual BOOL OnInitDialog();
  afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
  afx_msg void OnPaint();
  afx_msg HCURSOR OnQueryDragIcon();
  DECLARE_MESSAGE_MAP()
//Обработчики событий добавлены с помощью мастера
public:
  afx_msg void OnBnClickedButtonAdd();
  afx_msg void OnBnClickedButtonDel();
  afx_msg void OnBnClickedButtonStart();
public:
  matrix<double> mRightPart;  //Вектор - правая часть системы
  matrix<double> mNodeMatrix;  //Матрица системы
  CArray<SDPoint,SDPoint&> mInitArr;  //Массив точек
//Следующие переменные добавлены с помощью утилиты ClassView и связаны с элементами управления
  double mX;  //Координата X точки связана с первым текстовым полем
  double mY;  //Координата Y связана со вторым текстовым полем
  int mNum;  //Степень аппроксимации связана с третьим текстовым полем
  CListCtrl mListCtrl;  //Переменная для управления списковым представлением
};

Жирным шрифтом выделена переменная, которую необходимо добавить в данном пункте. CArray - это шаблонный класс, инкапсулирующий динамические массивы в MFC. В качестве первого аргумента шаблону передается тип хранимых в массиве объектов (в данном случае SDPoint ), вторым аргументом передается тип объектов, использующихся для получения доступа к данным массива, обычно это ссылка на тип, указанный в первом аргументе (в данном случае SDPoint ). Для ввода данных в диалоге была создана кнопка Add и два текстовых поля. Добавим в диалоговый класс связанные с текстовыми полями переменные mX, mY, mNum и mListCtrl с помощью мастера. Прежде чем обрабатывать нажатие на кнопку Add, настроим списковое представление. Добавим следующие строки в функцию OnInitDialog():

BOOL CRegrDlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  // Add "About..." menu item to system menu.
  // IDM_ABOUTBOX must be in the system command range.
  ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  ASSERT(IDM_ABOUTBOX < 0xF000);

  CMenu* pSysMenu = GetSystemMenu(FALSE);
  if (pSysMenu != NULL)
  {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
    pSysMenu->AppendMenu(MF_SEPARATOR);
    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
  }
  //Настраиваем Элемент управления "списковое представление"
  CRect cr;  
  mListCtrl.GetWindowRect(&cr); //Получение размеров окна элемента управления
  mListCtrl.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_EX_ONECLICKACTIVATE);  
   //Задаем необходимые стили
  mListCtrl.InsertColumn(0,_T("X"),LVCFMT_LEFT,(cr.right-cr.left)/2);  //Добавляем колонку
  mListCtrl.InsertColumn(1,_T("Y"),LVCFMT_RIGHT,(cr.right-cr.left)/2);  //Добавляем еще одну
  //Настраиваем самую левую колонку
  LVCOLUMN lvm;  //Структура для хранения информации о колонке
  lvm.mask = LVCF_FMT;  //Инициализация полей структуры
  lvm.fmt = LVCFMT_RIGHT;
  mListCtrl.SetColumn(0,&lvm);  //Задание необходимого стиля колонки
  SetIcon(m_hIcon, TRUE);      // Set big icon
  SetIcon(m_hIcon, FALSE);    // Set small icon
  return TRUE;  // return TRUE  unless you set the focus to a control
}

Жирным шрифтом выделен добавленный код. А теперь добавим обработчик кнопки Add и Delete. Обработчик нажатия на кнопку Add:

void CRegrDlg::OnBnClickedButtonAdd()
{
  CString str;        
  UpdateData(true);      //Обмен данными
  for(int i = 0; i < mInitArr.GetSize(); i++)    //Перебираем все точки в массиве
    if(mInitArr[i].x == mX && mInitArr[i].y == mY) return;  //Если существует такая же, то выходим
  mInitArr.Add(SDPoint(mX,mY));    //Проверка сделана, повторов нет, добавляем точку в массив
  str.Format("%f",mX);    //Форматирум строку для вывода в таблицу
  mListCtrl.InsertItem((int)mInitArr.GetSize()-1,str);    //Добавляем строку в таблицу
  str.Format("%f",mY);    //Повторяем для следующей колонки
  mListCtrl.SetItemText((int)mInitArr.GetSize()-1,1,str);
}

Обработчик нажатия на кнопку Delete:

void CRegrDlg::OnBnClickedButtonDel()
{
  int n = mListCtrl.GetSelectionMark();  //Получаем номер выделенной строки списка
  if(n < 0) return;      //Если ничего не выделено,то выходим
  mInitArr.RemoveAt(n);    //Удаляем точку из массива
  mListCtrl.DeleteItem(n);  //Удаляем строку из списка
}