Работа с Visual Studio.Net

         

Класс окна для отображения графика

Откройте файл ChildView.cpp, который содержит коды реализации методов класса CChildView. Его имя содержит ложный намек на происхождение от CView. На самом деле он происходит от класса CWnd и инкапсулирует функциональность окна, оккупирующего клиентскую область окна рамки, которое управляется классом CMainFrame. Простое окно, как вы помните, для перерисовки своего содержимого, вместо метода OnDraw использует метод OnPaint. Найдите этот метод в классе CChildView и убедитесь, что в нем контекст устройства создается, а не приходит в качестве параметра от каркаса приложения, как это было в приложениях, поддерживающих архитектуру документ — представление. Вставьте внутрь этого метода вызов конструктора класса CGraph с последующим сообщением Draw:

void

CChildView::OnPaint() {

CPaintDC dc(this);

CGraph(m_Points, "Field Distribution", "x[m]","Field").Draw(&dc); }

Класс CGraph разработаем позже. Он будет создавать двухмерный график функции — решения краевой задачи, автоматически масштабируемый и подстраивающийся под текущий размер окна CChildView. Перейдите к файлу с определением оконного класса (ChildFrame.h) и введите следующие коррективы:

# pragma once

#include "Graph.h"

Class CChildView : public CWnd

{

// Вспомогательные классы будут пользоваться данными

friend class CParamDlg;

friend class CGraph;

private:

//===== Контейнер координат точек графика

vector<CDPoint> m_Points;

//===== Вектор источников и свойств среды (см. f и р)

vector<double> m_f, m_r;

//===== Размерность задачи (см. N)

int m_n;

//===== Параметры

double m_k, // Коэффициент k

m_L, // Протяженность расчетной области

m_g0, // Коэффициенты, задающие ГУ слева

m_d0,

m_gn, // Коэффициенты, задающие ГУ справа m_dn ;

CParamDlg *m_pDlg; // Немодальный диалог параметров

public:

CChildView();

virtual -CChildViewO;

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

//===== Изменение размерности задачи

void Resize();

//===== Решение системы методом прогонки

void Solve();

protected:

afx_msg void OnPaint();

DECLARE_MESSAGE_MAP() };

Точки графика будем хранить в контейнере объектов класса CDPoint, который мы неоднократно использовали, так как исследователи реальных систем работают с вещественными координатами. Переход к экранным координатам будет произведен в классе CGraph. Инициализацию данных проведите в конструкторе оконного класса:

CChildView: :CChildView()

{

m_n = 200;

m_k = -0.0005;

m_L = 200.;

//====== Слева ГУ первого рода Uo=100

m_g0 = 0.;

m_d0 =100.;

m_gn = 0.;

m_dn = 0.;

Resize () ;

m_pDlg = 0;

}

В деструктор вставьте коды освобождения памяти, занимаемой контейнерами:

CChildView::~CChildView()

{

m_Points.clear();

m_f.clear();

m_r.clear();

}

При работе с диалогом по управлению параметрами пользователь будет иметь возможность изменять количество узлов разбиения расчетной области, поэтому мы должны изменять размерность используемых контейнеров:

void CChildView::Resize ()

{

//===== Число узлов равно N+1 (с учетом 0-го узла)

int n = m n + 1;

m_Points.resize(n, CDPoint(0.,0.));

m_f.resize(n, 0.);

m_r.resize(n, 1.); }

Функция Solve решает систему уравнений методом прогонки:

void CChildView::Solve()

{

Resize () ;

int n = m_n + 1;

//======= Коэффициенты разностных уравнений

vector<double> a(n), b(n), c(n);

//======= Коэффициенты прогонки

vector<double> d(n), e(n);

double h = m L / m_n, // Размер шага вдоль оси х

hh = h * h;

// Квадрат шага

//======= Коэффициенты с 0-м индексом не используются

а[0] = 0.;

b[0] = 0.;

с[0] = 0.;

//=== Вычисляем координаты х и коэффициенты уравнений

m_Points[0].х = 0.;

for (int i=1; i < m_n; i++)

{

m_Points[i],x = i * h;

//======= Смотри формулы (4)

a[i] = m_r[i-l]/hh;

c[i] = m_r[i]/hh;

b[i] = - a[i] - c[i] + m_k;

}

m_Points[m_n].x = m_L;

//======== -Прямой ходпрогонки

d[0] = m_gO; //ГУ слева e[0] * m_d0; double den;

for (i=1; i < m_n; 1++)

{

//======= Общий знаменатель

den = a[i) * d[i-l] + b[i] ; d[i] = -c[i] / den;

e[i] = <m_f[i] - a[i] * e[i-l]) / den;

}

//======= Готовимся к обратному ходу

den = 1. - m_gn * d[m_n-l];

//======= Случай некорректно поставленной задачи

if (den==0.)

{

MessageBox ("ГУ заданы некорректно", "Ошибка-",МВ_ОК) ;

return;

}

//====== Два последних узла используют ГУ справа

//======= Смотри формулы (13)

m_Points[m_n-l].у = (e[m_n-l] + m_dn * d[m_n-l])/den;

m_Points[m_n].y = (m_dn + m_gn* e[m_n-l])/den;

//======= Обратный ход прогонки

for (i = m_n-2; i >= 0; i--)

m_Points[i].y = d[i) * m_Points[i+1].у + e[i]; Invalidate();

}

С помощью инструментов Studio.Net введите в класс CChildView реакцию на сообщение о создании окна WM_CREATE и вставьте в нее единственную строку, которая вызывает функцию Solve. Она формирует и решает систему разностных уравнений, определенную данными по умолчанию. Позже мы создадим диалог по изменению этих данных:

int CChildView::OnCreate(LPCREATESTRUCT IpCreateStruct)

{

if (CWnd::OnCreate(IpCreateStruct) == -1)

return -1;

//======= Решаем систему, определенную по умолчанию

Solved;

return 0;

}

Содержание раздела