При разработке программ в среде программирования Visual C как правило используется библиотека Microsoft Foundation Classes (MFC), позволяющая упростить взаимодействие с системными библиотеками Windows за счет использования объектно - ориентированного подхода.
В тексте программы мы воспользуемся классом CFrameWnd из библиотеки MFC, от которого будут наследоваться все создаваемые окна. Класс главного окна имеет имя CMainWnd. Для окон графика и таблицы используется класс CDialog. Класс приложения имеет имя CWinApp. Файл resource.h создастся автоматически и добавится в проект при трансляции.
Запись программы в файл main.cpp начнем с подключения основных библиотек
#include <afxwin.h>
#include <afxext.h>
#include <afxcmn.h>
#include <time.h>
#include "resource.h"
#include "s_matrix.h"
Далее описываем идентификаторы элементов управления – это любые числовые значения, нужные для обработки этих элементов. Причем эти значения берутся произвольно, главное – чтобы они не совпадали, иначе программа будет зависать.
#define IDC_SETTINGS_SYGNALISATION 10001001
#define IDC_SETTINGS_AUTOMATIC 10001002
#define IDC_SETTINGS_SHOWGRAPHY 10001003
#define IDC_SETTINGS_SHOWGRAPHU 10001004
#define IDC_VIEW_LOG 10001005
#define IDC_BUTTON_START 10001006
#define IDC_EDIT_Z1 1000001
#define IDC_EDIT_Z2 1000002
#define IDC_SPIN_Z1 1000003
#define IDC_SPIN_Z2 1000004
#define IDC_EDIT_FAMP 1000005
#define IDC_SPIN_FAMP 1000006
#define IDC_EDIT_U1 1000007
#define IDC_SPIN_U1 1000008
#define IDC_EDIT_U2 1000009
#define IDC_SPIN_U2 1000010
#define ID_TIMER_CALC 101
#define LOG_FILENAME "system.log"
#define LOG_FILETYPE "a+"
//отклонения от номинального значения
#define Y1_MAX 40
#define Y1_MIN -40
#define Y2_MAX 60
#define Y2_MIN -60
//номинальное открытие клапанов
#define U1_NOM 60
#define U2_NOM 60
//заданные значения переменных
#define Z1_NOM 200
#define Z2_NOM 300
FILE *fileLog; // Объявляем переменную для обращения к LOG-файлу
Объявляем функции для работы с полем ввода. Функция GetValue возвращает значения в численном виде из поля ввода. Функция SetValue записывает численное значение в поле ввода.
int GetValue(CEdit*pEdit)
{
char str[200];
pEdit->GetWindowText(str,pEdit->GetWindowTextLength()+1);
return atoi(str);
}
void SetValue(CEdit*pEdit,int value)
{
char str[200];
sprintf(str,"%d",value);
pEdit->SetWindowText(str);
}
Объявляем класс графика. В этом классе самой важной для нас функцией является функция AddValue, которая смещает график по оси времени – имея массив точек, мы смещаем его элементы на один вниз. Функция SetSize устанавливает максимальный размер массива. Функция InitNullData инициализирует все элементы массива нулевыми значениями. Переменная data – динамический массив, т.е. это массив, который может во время выполнения программы изменить свой размер. Переменная m_size – размер массива.
class CGraph
{
public:
CGraph();
void SetSize(UINT num);
void InitNullData();
void AddValue(double val);
double *data;
UINT m_size;
};
CGraph::CGraph()
{
m_size=0;
}
void CGraph::SetSize(UINT num)
{
m_size=num;
data=new double[m_size];
}
void CGraph::InitNullData()
{
for(UINT i=0;i<m_size;i++)
{
data[i]=0;
}
}
void CGraph::AddValue(double val)
{
for(UINT i=0;i<m_size-1;i++)
{
data[i]=data[i+1];
}
data[m_size-1]=val;
}
Объявим класс окна для вывода на экран графиков класса CGraph. В данном случае так как система, рассматриваемая в примере, имеет два входа и два выхода, то соответственно в одном окне будут выводиться сразу два графика. Для каждого дополнительного выхода (например, третьего) нужно добавить график graph03 и предельные значения y_max3 и y_min3 и в функции OnPaint вставить еще одни цикл рисования графика graph03.
class CGraphDlg:public CDialog
{
public:
CGraphDlg(CWnd*pWnd=NULL);
void OnPaint();
CGraph graph01;
CGraph graph02;
double ym;//Масштабный коэффициент по оси y
double y_max1;//значения для сигнализации
double y_min1;//
double y_max2;//значения для сигнализации
double y_min2;//
CString strY;//Подпись к оси Y
CString strX;//Подпись к оси X
protected:
DECLARE_MESSAGE_MAP();
};
//{{AFX
BEGIN_MESSAGE_MAP(CGraphDlg,CDialog)
ON_WM_PAINT()
END_MESSAGE_MAP()
//}}AFX
//Функция рисования графика на окне
void CGraphDlg::OnPaint()
{
CPaintDC dc(this);
CPen pen_dot1(PS_DOT,1,RGB(0,0,255));
CPen pen_dot2(PS_DOT,1,RGB(255,0,0));
CPen pen_solid(PS_SOLID,1,RGB(0,0,0));
dc.SelectObject(&pen_solid);
CPen pen_g(PS_SOLID,1,RGB(0,0,255));
CPen pen_g2(PS_SOLID,1,RGB(255,0,0));
double yn;
yn=200;
int x01=50,x02=400;
dc.MoveTo(x01,(int)yn);
dc.LineTo(x02,(int)yn);
dc.TextOut(x02,(int)yn+20,strX);
dc.MoveTo(x01,(int)yn);
dc.LineTo(x01,20);
dc.TextOut(x01-30,20,strY);
dc.SelectObject(&pen_dot1);
dc.MoveTo(x01,(int)(ym*y_max1)+(int)yn);
dc.LineTo(x02,(int)(ym*y_max1)+(int)yn);
dc.MoveTo(x01,(int)(ym*y_min1)+(int)yn);
dc.LineTo(x02,(int)(ym*y_min1)+(int)yn);
dc.SelectObject(&pen_dot2);
dc.MoveTo(x01,(int)(ym*y_max2)+(int)yn);
dc.LineTo(x02,(int)(ym*y_max2)+(int)yn);
dc.MoveTo(x01,(int)(ym*y_min2)+(int)yn);
dc.LineTo(x02,(int)(ym*y_min2)+(int)yn);
dc.SelectObject(&pen_g);
char str[200];
sprintf(str,"%0.1f",y_max1);
dc.TextOut(x01-40,(int)(ym*y_max1)+(int)yn,str);
sprintf(str,"%0.1f",y_max2);
dc.TextOut(x01-40,(int)(ym*y_max2)+(int)yn,str);
//Цикл рисования первого графика
dc.MoveTo(x01,int(graph01.data[0]*ym+(int)yn));
for(UINT i=0;i<graph01.m_size;i++)
{
double x=(double)x01+(x02-x01)*(double)(i)/(double)graph01.m_size;
dc.LineTo((int)x,int(graph01.data[i]*ym+yn));
}
dc.SelectObject(&pen_g2);
//Цикл рисования Второго графика
dc.MoveTo(x01,int(graph02.data[0]*ym+yn));
for(i=0;i<graph02.m_size;i++)
{
double x=(double)x01+(x02-x01)*(double)(i)/(double)graph02.m_size;
dc.LineTo((int)x,int(graph02.data[i]*ym+yn));
}
}
CGraphDlg::CGraphDlg(CWnd*pWnd)
:CDialog(IDD_DIALOG_GRAPH,pWnd)
{
ym=-0.2;
graph01.SetSize(500);
graph01.InitNullData();
graph02.SetSize(500);
graph02.InitNullData();
strY="Y";
strX="X";
y_max1=Y1_MAX;//700;
y_min1=Y1_MIN;//-10;
y_max2=Y2_MAX;//400;
y_min2=Y2_MIN;//100;
}
// функция _getline возвращает следующую строку из текста –
//нужна для чтения из LOG-файла
int _getline(char*buffer,char*str,int &position)
{
int len=strlen(buffer);
for(int i=position;buffer[i]!='\n';i++)
{
str[i-position]=buffer[i];
if(buffer[i]=='\0')
{
str[i-position]='\0';
position=i+1;
return 1;
}
}
str[i-position]='\0';
position=i+1;
return 0;
}
// Класс нужен для вывода содержимого LOG-файла на экран
class CDialogText:public CDialog
{
public:
CDialogText(CWnd*pWnd=NULL);
CListBox m_list;
void DoDataExchange(CDataExchange*pDX);
};
CDialogText::CDialogText(CWnd*pWnd)
:CDialog(IDD_DIALOG_TEXT,pWnd)
{
}
void CDialogText::DoDataExchange(CDataExchange*pDX)
{
DDX_Control(pDX,IDC_LIST1,m_list);
FILE*file;
file=fopen(LOG_FILENAME,"r");
if(file!=NULL)
{
char str_line[200];
char *buffer;
int len;
fseek(file,0,SEEK_END);
len=ftell(file);
fseek(file,0,SEEK_SET);
buffer=new char[len];
int j=fread(buffer,sizeof(char),len,file);
buffer[j]='\0';
int p=0;
for(;;)
{
if(_getline(buffer,str_line,p)!=0)break;
m_list.AddString(str_line);
}
}
else
{
AfxMessageBox("No file");
}
fclose(file);
}
Класс CAlarmStatic предназначен для вывода численного значения на экран, а также изменения фонового цвета в случае аварийной ситуации.
class CAlarmStatic:public CStatic
{
public:
CAlarmStatic();
void OnPaint();
CString strMessage;
COLORREF color;
protected:
DECLARE_MESSAGE_MAP();
};
//{{AFX
BEGIN_MESSAGE_MAP(CAlarmStatic,CStatic)
ON_WM_PAINT()
END_MESSAGE_MAP()
//}}AFX
void CAlarmStatic::OnPaint()
{
CPaintDC dc(this);
CBrush brush;
brush.CreateSolidBrush(color);
CRect rect;
GetClientRect(&rect);
dc.FillRect(rect,&brush);
dc.TextOut(10,10,strMessage);
}
CAlarmStatic::CAlarmStatic()
{
strMessage="";
color=RGB(200,200,200);
}
Отчет о лабораторной работе должен содержать документ Описание программы разрабатываемый в расчете на то, что читать его должен программист, владеющий текстом программы и призванный исправлять и модифицировать программу. Текст подраздела должен состоять изследующих пунктов:
· общие сведения (наименование программы и программное обеспечение, необходимое для функционирования программы, языки программирования, на которых написана программа)
· функциональное назначение (назначение программы, сведения об ограничениях на применение)
· описание логической структуры (алгоритм программы - блок-схема, математическое описание, словесное описание, используемые математические методы, структура программы с описанием функций составных частей (процедур, задач, модулей), и связей между ними);
· используемые технические средства (типы компьютеров и устройств, необходимых для работы программы);
· вызов и загрузка (способ вызова программы, сведения о ресурсах);
· входные и выходные данные (характер и организация входных и выходных данных).