Учебник по Visual C++ .Net


Диалог для исследования решений


Форма диалога для управления параметрами краевой задачи

Таблица 11.1. Идентификаторы элементов управления

Элемент

Идентификатор

Диалог

IDD_PARAM

Окно редактирования Source

IDC_SOURCE

Окно редактирования Start группы Source

IDC_SOURCE1

Окно редактирования End группы Source

IDC_SOURCE2

Окно редактирования Value

IDC_PROP

Окно редактирования Start группы Properties

IDCLPROP1

Окно редактирования End группы Properties

IDC_PROP2

Окно редактирования Nodes

IDC.NODES

Окно редактирования Distance

IDCJHST

Окно редактирования Decrement

IDC_DECR

Окно редактирования g группы Left Boundary

IDC_LEFTG

Окно редактирования d группы Left Boundary

IDCJ.EFTD

Окно редактирования g группы Right Boundary

IDC_RIGHTG

Окно редактирования d группы Right Boundary

IDC_RIGHTD

Кнопка Add группы Source

IDC_ADDSOURCE

Кнопка Add группы Properties

IDC_ADDPROP

Кнопка Apply

IDC_APPLY

Кнопка Close

IDCANCEL

Вручную введите изменения в файл с объявлением класса, так чтобы он стал: ftpragma once

class CParamDlg : public CDialog {

//===== Будем общаться с окном

friend class CChildView;

DECLARE_DYNAMIC(CParamDlg)

public:

//===== Будем помнить его адрес

CChildView *m_pView;

//===== В конструкторе запросим его адрес

CParamDlg(CChildView* р) ;

virtual ~CParamDlg () ;

// Dialog Data

enum { IDD = IDD_PARAM );

protected:

virtual void DoDataExchange(CDataExchange* pDX) ;

DECLARE_MESSAGE_MAP() );

Для всех четырех кнопок на форме диалога создайте обработчики уведомлений, или, используя терминологию Microsoft, Control Event типа BN_CLICKED. Вы помните, что это делается с помощью небольшой кнопки Control Event, которая расположена на панели инструментов окна Properties. В это окно надо входить в тот момент, когда фокус находится на соответствующей кнопке. Во всяком случае, именно так это работает в бета-версии Studio.Net.

Для обмена данными с шестью окнами редактирования (IDC_SOL)RCE, IDC_SOURCE1, IDC_SOURCE2, IDC_PROP, IDC_PROP1, IDC_PROP2) создайте с помощью мастера Add Member Variable Wizard шесть переменных:


//==== Интенсивность источника поля

double m_Source;

// Индекс ячейки сетки, где расположено начало источника

int m_Src!dl;

// Индекс ячейки сетки, где расположен конец источника

int m_Srdd2;

//==== Значение физического свойства ячейки сетки

double m_Prop;

// Индексы начала и конца области со свойством

m_Prop int m_PropIdl;

int m_PropId2;

В результате этих действий в классе CParamDlg кроме указанных переменных должны появиться шесть вызовов функции обмена данными DDX_Text, которые мастер размещает внутри функции CParamDlg::DoDataExchange. Вручную добавьте в DoDataExchange еще семь вызовов функции DDX_Text для обмена данными с переменными, которые расположены не в диалоговом, а в оконном классе (cchildview). После этого функция должна приобрести вид:

void CParamDlg::DoDataExchange(CDataExchange* pDX) {

DDX_Text (pDX, IDC_PROP2, m_Prop!d2);

DDXJText(pDX, IDC_PROP1, m_Prop!dl);

DDX_Text(pDX, IDC_PROP, m_Prop);

DDX_Text(pDX, IDC_SOURCE2, m_Srdd2);

DDX_Text(pDX, IDC_SOURCE1, ra_SrcIdl);

DDX_Text(pDX, IDC_SOURCE, m_Source);

//===== Обмен с переменными оконного класса

DDX_Text(pDX, IDC_NODES,m_pView->m__n);

DDX_Text(pDX, IDC_DIST, m_pView->m_L);

DDX_Text(pDX, IDC_DECR, m_pView->m_k);

DDX_Text(pDX, IDC_LEFTG, m_pView->m_g0);

DDX_Text(pDX, IDC_LEFTD, ra_pView->m_d0);

DDX_Text(pDX, IDC_RIGHTG, mj?View->m_gn);

DDX_Text(pDX, IDC_RIGHTD, m_pView->m_dn);

CDialog::DoDataExchange(pDX);

}

При нажатии на одну из кнопок Add в соответствующем контейнере параметров системы (m_f или m_r) должны произойти замены значений по индексам, определяемым диапазоном (m_Srddl, m_Srdd2) ИЛИ (m_Prop!dl, m_Prop!d2). В первом случае вы вводите новые источники поля, а во втором — изменяете свойства среды. В уже существующие заготовки функций обработки нажатия на кнопки введите такие коды:

void CParamDlg::OnClickedApply(void) {

//====== Считываем данные из окон

UpdateDataO ;

//====== Заново решаем систему и выводим график

m_jpView->Solve () ; }



void CParamDlg::OnClickedAddsource(void)

{

UpdateData();

//====== Изменяем контейнер m_f (источников поля)

for (int i=m_Src!dl; i <= m_Srdd2; i + + ) {

if (0 <= i && i < m_pView~>m_n)

m_pView->m_f[i] = -m_Source; )

m_pView->Solve0; }

void CParamDlg::OnClickedAddprop(void) { UpdateDataO ;

//====== Изменяем контейнер m_r (свойств среды)

for (int i=m_Prop!dl; i <= m_PropId2; i++) {

if (0 <= i &i i < m_pView->m_n && m_Prop > 0.)

m_pView->ra_r[i] = m_Prop; }

m_pView->Solve(); }

void CParamDlg::OnClickedCancel(void)

{

//====== Закрываем немодальный диалог

m_pView->m_pDlg = 0;

DestroyWindow(); }

Измените коды конструктора класса так, чтобы запоминался обратный указатель на объект оконного класса. Заодно сверьте начало файла ParamDlg.h с тем фрагментом, что приведен ниже:

#include "stdafx.h"

#include "Heat.h"

#include"ParamDlg.h"

IMPLEMENT_DYNAMIC(CParamDlg, CDialog)

CParamDlg::CParamDlg(CChildView* p)

: CDialog(CParamDlg::IDD, p)

{

m_pView = p;

//===== Начальное значение свойств среды

//===== не должно равняться нулю

m_Prop =1.0;

m_Prop!dl = 0;

m_Prop!d2 = 0;

m_Source =0.0;

m_Src!dl = 0;

m_Srdd2 = 0;

}

CParamDlg::~CParamDlg()

{

}

Инициализация диалога, как вы помните, должна производиться в обработчике сообщения WM_INITDIALOG. Здесь я опять попадаю в ловушку. В рамках Visual C++ Studio.Net вы не найдете WM_INITDIALOG в списке доступных сообщений, но вместо этого найдете функцию OnlnitDialog в списке виртуальных функций (overrides). Введите в класс CParamDlg эту функцию. В ней мы просто отодвинем окно диалога, чтобы оно при появлении на экране не заслоняло график. Другие установки должны происходить автоматически:

BOOL CParamDlg::OnInitDialog(void) {

CDialog:rOnlnitDialog();

CRect r;

//===== С помощью контекста устройства

//===== узнаем размеры всего экрана CClientDC dc(this);

int w = dc.GetDeviceCaps(HORZRES);



int h = dc.GetDeviceCaps(VERTRES);

//===== Узнаем размеры окна диалога GetWindowRect(&r);

//===== Смещаем его вправо и вниз

r.OffsetRect(w-r.right-10,h-r.bottom-30);

MoveWindow(Sr);

return TRUE;

}

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

#include "ChildView.h"

в список директив файла ParamDlg.cpp, а также директиву

#include "ParamDlg.h"

в список директив файла ChildView.cpp. После этого исправления вы увидите еще одно сообщение об ошибке, которое напомнит вам о том, что еще не реализована работа с диалогом в немодальном режиме. Для этого надо немного потрудиться. Введите в класс CChildView реакцию на событие выбора пользователем команды меню ID_EDIT_PARAMETERS. Напомним, что это делается с помощью кнопки Events окна Properties. В обработчике мы открываем диалог в немодальном режиме:

void CChildView::OnEditParameters(void) {

//===== Если диалог не открыт,

if (!m_pDlg)

{

//== Динамически создаем объект диалогового класса

m_pDlg = new CParamDlg(this);

//== и после этого создаем окно диалога

m_pDlg->Create(IDD_PARAM);

}

}

В окне свойств для формы диалога установим в True свойство visible. В классе cParamDlg следует переопределить виртуальную функцию PostNcDestroy, в теле которой необходимо освободить память, занимаемую объектом диалогового класса:

void CParamDlg::PostNcDestroy(void)

{

delete this;

}

После этого диалог должен работать. Задайте точечный источник поля в узле 100, и вы увидите график решения, которое имеет вид, показанный на рис. 11.5.

Диалог для исследования решений


Диалог для исследования решений


Рис. 11.5. Управление параметрами краевой задачи из диалога

Диалог для исследования решений


Диалог для исследования решений


Рис. 11.6 Распределение поля в неоднородной среде при наличии осточнтков


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