В классе главного окна размещаются все элементы управления, а также описаны функции работы регулятора и объекта. Элементы m_StaticY1 и m_StaticY2 показывают текущие положения двух выходных параметров. Элемент m_editFamp нужен для задания амплитуды шума возмущения. Элемент m_spinFamp нужен для изменения элемента m_editFamp т.е. это две кнопки “Больше-меньше”. Все остальные элементы (Z1,Z2,U1,U2) создаются по такому же принципу.
При создании любого элемента управления очень важно не перепутать его идентификатор. Значение идентификатора – это число, которое определено в макросах в начале программы (например, #define IDC_BUTTON_START 10001006). Эти числа понадобятся для обработки нажатий на кнопки – т.е. после создания кнопки с помощью макросов указываем функцию, которая будет запускаться при нажатии на кнопку (например ON_COMMAND(IDC_BUTTON_START,OnStart)).
Продолжаем добавлять текст в файл main.cpp.
class CMainWnd:public CFrameWnd
{
public:
CAlarmStatic m_StaticY1;
CAlarmStatic m_StaticY2;
CGraphDlg*pGraphDlg01;
CGraphDlg*pGraphDlg02;
CEdit m_editFamp;
CSpinButtonCtrl m_spinFamp;
CEdit m_editZ1;
CSpinButtonCtrl m_spinZ1;
CEdit m_editZ2;
CSpinButtonCtrl m_spinZ2;
CEdit m_editU1;
CSpinButtonCtrl m_spinU1;
CEdit m_editU2;
CSpinButtonCtrl m_spinU2;
CMainWnd();//Функция инициализации окна
void OnPaint();//Перерисовка окна
void OnTimer(UINT nIDEvent);
void OnStart();//Функция кнопки Start
bool bstart; //Флаг того, что регулятор запущен
double m_Y1; //Текущее значение выхода Y1
double m_Y2; //Текущее значение выхода Y2
double m_U1; //Текущее значение управл. Возд U1
double m_U2; //Текущее значение управл. возд. U2
//Матрицы используемые в расчете.
//Следующие матрицы загружаются из файла
CMatrix Ar;
CMatrix Br;
CMatrix Cr;
CMatrix Ad;
CMatrix Bd;
CMatrix Cd;
CMatrix C;
//Эти матрицы рассчитываются в программе
CMatrix x;
CMatrix xr;
CMatrix y;
CMatrix u;
CMatrix e;
CMatrix f;
CMatrix z;
BOOL bShowGraphY;//Флаг того, что окно графика Y показано
BOOL bShowGraphU;//Флаг того, что окно графика U показано
BOOL bAutomatic; //Флаг того, что регулятор работает
BOOL bSygnal; //Флаг того, что включена сигнализация
CButton m_buttonStart;//Кнопка Старта
CButton m_buttonSygnalisation;//Кнопка сигнализация
CButton m_buttonAutomatic;//кнопка смены режима
CButton m_buttonShowY;//Кнопка показа графиков Y
CButton m_buttonShowU;//Кнопка показа графиков U
CButton m_buttonShowLog;//Кнопка показа LOG-файла
void OnMenuSygnalisation();//Функция кнопки сигнализации
void OnMenuAutomatic();//Функция кнопки смены режима
void OnMenuShowGraphY();//Функция кнопки показа графика Y
void OnMenuShowGraphU();//Функция кнопки показа графика U
void OnMenuLog();//Функция кнопки показа LOG файла
void LoadMatrix(char*filename);// Функция загрузки матриц
void OnDestroy();//Функция закрытия окна
void CheckSygnalisation();//Функция сигнализации
BOOL bY1max;//флаг того, что y1 вышел за максимальное допустимое знач
BOOL bY1min;//флаг того, что y1 вышел за минимальное допустимое знач
BOOL bY2max;//флаг того, что y2 вышел за максимальное допустимое знач
BOOL bY2min;//флаг того, что y2 вышел за минимальное допустимое знач
protected:
DECLARE_MESSAGE_MAP();
};
//{{AFX
BEGIN_MESSAGE_MAP(CMainWnd,CFrameWnd)
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_DESTROY()
ON_COMMAND(IDC_SETTINGS_SYGNALISATION,OnMenuSygnalisation)
ON_COMMAND(IDC_SETTINGS_AUTOMATIC,OnMenuAutomatic)
ON_COMMAND(IDC_SETTINGS_SHOWGRAPHY,OnMenuShowGraphY)
ON_COMMAND(IDC_SETTINGS_SHOWGRAPHU,OnMenuShowGraphU)
ON_COMMAND(IDC_BUTTON_START,OnStart)
ON_COMMAND(IDC_VIEW_LOG,OnMenuLog)
END_MESSAGE_MAP()
//}}AFX
void CMainWnd::OnMenuLog()
{
CDialogText dlg;
dlg.DoModal();
}
void CMainWnd::CheckSygnalisation()
{
char str[200];
_strtime(str);
if(y.pData[0]>pGraphDlg01->y_max1)
{
if(!bY1max)
{
fprintf(fileLog,"Y1 превысил доп знач %s\n",str);
m_StaticY1.color=RGB(255,0,0);
}
bY1max=TRUE;
}
else
{
if(bY1max)
{
fprintf(fileLog,"Y1 вернулся в нужный диапазон %s\n",str);
m_StaticY1.color=RGB(200,200,200);
}
bY1max=FALSE;
}
if(y.pData[0]<pGraphDlg01->y_min1)
{
if(!bY1min)
{
fprintf(fileLog,"Y1 ниже доп знач %s\n",str);
m_StaticY1.color=RGB(255,0,0);
}
bY1min=TRUE;
}
else
{
if(bY1min)
{
fprintf(fileLog,"Y1 вернулся в нужный диапазон %s\n",str);
m_StaticY1.color=RGB(200,200,200);
}
bY1min=FALSE;
}
//проверка у2
if(y.pData[1]>pGraphDlg01->y_max2)
{
if(!bY2max)
{
fprintf(fileLog,"Y2 превысил доп знач %s\n",str);
m_StaticY2.color=RGB(255,0,0);
}
bY2max=TRUE;
}
else
{
if(bY2max)
{
fprintf(fileLog,"Y2 вернулся в нужный диапазон %s\n",str);
m_StaticY2.color=RGB(200,200,200);
}
bY2max=FALSE;
}
if(y.pData[1]<pGraphDlg01->y_min2)
{
if(!bY2min)
{
fprintf(fileLog,"Y2 ниже доп знач %s\n",str);
m_StaticY2.color=RGB(255,0,0);
}
bY2min=TRUE;
}
else
{
if(bY2min)
{
fprintf(fileLog,"Y2 вернулся в нужный диапазон %s\n",str);
m_StaticY2.color=RGB(200,200,200);
}
bY2min=FALSE;
}
}
void CMainWnd::OnDestroy()
{
char str[200];
_strtime(str);
fprintf(fileLog,"System end at %s\n/*********************/\n",str);
fclose(fileLog);
CFrameWnd::OnDestroy();
}
void CMainWnd::OnMenuShowGraphU()
{
bShowGraphU=!bShowGraphU;
if(bShowGraphU)
{
pGraphDlg02->ShowWindow(SW_SHOW);
}
else
{
pGraphDlg02->ShowWindow(SW_HIDE);
}
}
void CMainWnd::OnMenuShowGraphY()
{
bShowGraphY=!bShowGraphY;
if(bShowGraphY)
{
pGraphDlg01->ShowWindow(SW_SHOW);
}
else
{
pGraphDlg01->ShowWindow(SW_HIDE);
}
}
void CMainWnd::OnMenuAutomatic()
{
bAutomatic=!bAutomatic;
if(bAutomatic)
m_buttonAutomatic.SetWindowText("REG: Auto");
else m_buttonAutomatic.SetWindowText("REG: Man");
}
void CMainWnd::OnMenuSygnalisation()
{
bSygnal=!bSygnal;
if(bSygnal)
m_buttonSygnalisation.SetWindowText("Sygnal on");
else m_buttonSygnalisation.SetWindowText("Sygnal off");
}
void CMainWnd::LoadMatrix(char*filename)
{
FILE *file=fopen(filename,"r");
char tmp[200];
fscanf(file,"%s",tmp);
Ad.LoadMatrix(file);
fscanf(file,"%s",tmp);
Bd.LoadMatrix(file);
fscanf(file,"%s",tmp);
Cd.LoadMatrix(file);
fscanf(file,"%s",tmp);
Ar.LoadMatrix(file);
fscanf(file,"%s",tmp);
Br.LoadMatrix(file);
fscanf(file,"%s",tmp);
Cr.LoadMatrix(file);
fscanf(file,"%s",tmp);
C.LoadMatrix(file);
fclose(file);
f=_matrix(2,1,0.0);
z=_matrix(2,1,0.0);
x=_matrix(12,1,0.0);
xr=_matrix(16,1,0.0);
u=_matrix(2,1,0.0);
}
void CMainWnd::OnTimer(UINT nIDEvent)
{
if(nIDEvent==ID_TIMER_CALC)
{
z.pData[0]=GetValue(&m_editZ1) - Z1_NOM;
z.pData[1]=GetValue(&m_editZ2) - Z2_NOM;
//Рассчитываем шум
int r=0;
int amp=(int)GetValue(&m_editFamp);
if(amp>0)r=rand()%((int)amp*2*100)-(int)amp*100;
f.pData[0]=(double)r/100.0;
if(amp>0)r=rand()%((int)amp*2*100)-(int)amp*100;
f.pData[1]=(double)r/100.0;
y=C*x;
if(bSygnal)CheckSygnalisation();
if(bAutomatic)
{
//Автоматический режим
e=y-z;
u=Cr*xr;
xr=Ar*xr+Br*e;
SetValue(&m_editU1,u.pData[0] + U1_NOM);
SetValue(&m_editU2,u.pData[1] + U2_NOM);
}
else
{
//Ручной режим
u.pData[0]=GetValue(&m_editU1);
u.pData[1]=GetValue(&m_editU2);
}
x=Ad*x+Bd*(u+f);
y=C*x;
pGraphDlg01->graph01.AddValue(y.pData[0] + Z1_NOM);
pGraphDlg01->graph02.AddValue(y.pData[1] + Z2_NOM);
pGraphDlg01->Invalidate();
pGraphDlg02->graph01.AddValue(u.pData[0] + U1_NOM);
pGraphDlg02->graph02.AddValue(u.pData[1] + U2_NOM);
pGraphDlg02->Invalidate();
char strval[200];
char str[200];
_gcvt(y.pData[0]+Z1_NOM,3,strval);
sprintf(str,"%s ^C",strval);
m_StaticY1.strMessage=str;
m_StaticY1.Invalidate();
_gcvt(y.pData[1]+Z2_NOM,3,strval);
sprintf(str,"%s МВт",strval);
m_StaticY2.strMessage=str;
m_StaticY2.Invalidate();
}
CFrameWnd::OnTimer(nIDEvent);
}
void CMainWnd::OnStart()
{
if (bstart)
{
//Нажата пауза
KillTimer(ID_TIMER_CALC);
m_buttonStart.SetWindowText("Start");
bstart=false;
}
else
{
//Нажат start
SetTimer(ID_TIMER_CALC,50,NULL);
m_buttonStart.SetWindowText("Pause");
pGraphDlg01->ShowWindow(SW_SHOW);
pGraphDlg02->ShowWindow(SW_SHOW);
bstart=true;
}
}
//Функция рисования на окне
void CMainWnd::OnPaint()
{
//Сначала выводим на окно картинку
CPaintDC dc(this);
CBitmap bmp,*p_bmp;
bmp.LoadBitmap(IDB_BITMAP1);
CDC mem_dc;
mem_dc.CreateCompatibleDC(&dc);
p_bmp=mem_dc.SelectObject(&bmp);
dc.BitBlt(10,10,642,670,&mem_dc,0,0,SRCCOPY);
mem_dc.SelectObject(p_bmp);
//Далее подписываем элементы на окне
dc.TextOut(650,10,"f возмущение(шум)");
dc.TextOut(10,80,"Z1 температура (T)");
dc.TextOut(630,230,"Z2 мощность (N)");
}
//Ф-ция инициализации окна
CMainWnd::CMainWnd()
{
fileLog=fopen(LOG_FILENAME,LOG_FILETYPE);
bY1max=FALSE;
bY1min=FALSE;
bY2max=FALSE;
bY2min=FALSE;
bstart=false;
//Создание окна
Create(NULL,"Kursovoy");
char str[200];
_strtime(str);
//Создание кнопок на окне
m_buttonStart.Create("Start",//Имя кнопки
WS_VISIBLE|WS_CHILD|WS_BORDER,//Стиль
CRect(200,10,//Верхний левый угол кнопки на окне
300,40),//Нижний правый угол
this,//Указатель на окно
IDC_BUTTON_START);//Идентификатор кнопки
m_buttonSygnalisation.Create("Sygnal on",
WS_VISIBLE|WS_CHILD|WS_BORDER,
CRect(700,70,
800,90),
this,
IDC_SETTINGS_SYGNALISATION);
m_buttonAutomatic.Create("REG: Auto",
WS_VISIBLE|WS_CHILD|WS_BORDER,
CRect(700,90,
800,110),
this,
IDC_SETTINGS_AUTOMATIC);
m_buttonShowY.Create("Show graph Y",
WS_VISIBLE|WS_CHILD|WS_BORDER,
CRect(700,110,
800,130),
this,
IDC_SETTINGS_SHOWGRAPHY);
m_buttonShowU.Create("Show graph U",
WS_VISIBLE|WS_CHILD|WS_BORDER,
CRect(700,130,
800,150),
this,
IDC_SETTINGS_SHOWGRAPHU);
m_buttonShowLog.Create("Show Log",
WS_VISIBLE|WS_CHILD|WS_BORDER,
CRect(700,150,
800,170),
this,
IDC_VIEW_LOG);
m_StaticY1.Create("Y1",
WS_VISIBLE|WS_CHILD|WS_BORDER,
CRect(0,10,
100,40),
this);
m_StaticY2.Create("",
WS_VISIBLE|WS_CHILD|WS_BORDER,
CRect(630,300,
730,330),
this);
fprintf(fileLog,"\n/*******************/\nSystem started at %s\n",str);
m_editFamp.Create(WS_VISIBLE|WS_CHILD|WS_BORDER|ES_RIGHT,
CRect(700,30,
780,60),
this,
IDC_EDIT_FAMP);
m_spinFamp.Create(WS_VISIBLE|WS_CHILD|UDS_SETBUDDYINT,
CRect(780,30,
800,60),
this,
IDC_SPIN_FAMP);
m_spinFamp.SetBuddy(&m_editFamp);
m_spinFamp.SetRange(0,900);
m_spinFamp.SetPos(50);
m_editZ1.Create(WS_VISIBLE|WS_CHILD|WS_BORDER|ES_RIGHT,
CRect(10,100,
80,130),
this,
IDC_EDIT_FAMP);
m_spinZ1.Create(WS_VISIBLE|WS_CHILD|UDS_SETBUDDYINT,
CRect(80,100,
100,130),
this,
IDC_SPIN_Z1);
m_spinZ1.SetBuddy(&m_editZ1);
m_spinZ1.SetRange(0,900);
m_spinZ1.SetPos(Z1_NOM);
m_editZ2.Create(WS_VISIBLE|WS_CHILD|WS_BORDER|ES_RIGHT,
CRect(630,250,
700,280),
this,
IDC_EDIT_FAMP);
m_spinZ2.Create(WS_VISIBLE|WS_CHILD|UDS_SETBUDDYINT,
CRect(700,250,
720,280),
this,
IDC_SPIN_Z2);
m_spinZ2.SetBuddy(&m_editZ2);
m_spinZ2.SetRange(0,900);
m_spinZ2.SetPos(Z2_NOM);
m_editU1.Create(WS_VISIBLE|WS_CHILD|WS_BORDER|ES_RIGHT,
CRect(130,400,
200,430),
this,
IDC_EDIT_FAMP);
m_spinU1.Create(WS_VISIBLE|WS_CHILD|UDS_SETBUDDYINT,
CRect(200,400,
220,430),
this,
IDC_SPIN_U1);
m_spinU1.SetBuddy(&m_editU1);
m_spinU1.SetRange(0,900);
m_spinU1.SetPos(0);
m_editU2.Create(WS_VISIBLE|WS_CHILD|WS_BORDER|ES_RIGHT,
CRect(510,380,
580,410),
this,
IDC_EDIT_FAMP);
m_spinU2.Create(WS_VISIBLE|WS_CHILD|UDS_SETBUDDYINT,
CRect(580,380,
600,410),
this,
IDC_SPIN_U2);
m_spinU2.SetBuddy(&m_editU2);
m_spinU2.SetRange(0,900);
m_spinU2.SetPos(0);
pGraphDlg01=new CGraphDlg();
pGraphDlg01->Create(IDD_DIALOG_GRAPH,this);
pGraphDlg01->ShowWindow(SW_SHOW);
pGraphDlg01->SetWindowText("Выход");
pGraphDlg01->strX="t";
pGraphDlg01->strY="Y(t)";
pGraphDlg02=new CGraphDlg();
pGraphDlg02->Create(IDD_DIALOG_GRAPH,this);
pGraphDlg02->ShowWindow(SW_SHOW);
pGraphDlg02->SetWindowText("Управляющее воздействие");
pGraphDlg02->ym=-1.0;
pGraphDlg02->strX="t";
pGraphDlg02->strY="u(t)";
pGraphDlg02->y_max1=Y1_MAX;
pGraphDlg02->y_min1=Y1_MIN;
pGraphDlg02->y_max2=Y2_MAX;
pGraphDlg02->y_min2=Y2_MIN;
m_Y1=0;
m_Y2=0;
m_U1=0;
m_U2=0;
LoadMatrix("matrix.txt");
bShowGraphY=TRUE;
bShowGraphU=TRUE;
bShowGraphY=TRUE;
bSygnal=TRUE;
bAutomatic=TRUE;
}
//Класс приложения
class CMainApp:public CWinApp
{
public:
CMainApp()
{
}
virtual BOOL InitInstance();
};
BOOL CMainApp::InitInstance()
{
m_pMainWnd=new CMainWnd;
ASSERT(m_pMainWnd);
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();
return true;
}
CMainApp theApp;
Отчет о лабораторной работе должен содержать документ Текст программы, включающий титульный лист, содержание и распечатанные тексты каждого модуля.