Разработка полноценных Windows-приложений
Проектирование и разработка приложений
Этапы разработки
- Создать ресурс диалогового окна.
- Организовать ввод и редактирование начальных данных.
- Построить СЛАУ и решить ее.
- Организовать вывод результатов.
Создадим с помощью мастера MFC приложение "Regr" на основе диалогового окна. Для этого установим Application type в значение Dialog based. Снимем флажок Use Unicode libraries.
1. Создание ресурса диалогового окна
Создадим диалоговое окно с тремя текстовыми полями для ввода данных в таблицу и указания степени аппроксимации, четырьмя кнопками(Add, Delete, Start Approximation, Exit), списковым представлением для отображения таблицы точек и текстовым полем RichEdit для вывода строки результата. Шаблон диалога приведен на рисунке: рис. 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); //Удаляем строку из списка
}
