Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
записка.лянг.100.docx
Скачиваний:
2
Добавлен:
27.04.2019
Размер:
423.82 Кб
Скачать

2.3 Создание меню

Для создания меню необходимо произвести следующую последовательность действий:

  1. Откроем редактор меню. (Вкладка ResourseVeiw->Menu->IDR_MAINFRAME)

рис. 2.3.1. Создание пунктов меню, вкладка Ресурсы

Добавим в строку меню кнопки «Входные данные», «Траектории», «Старт/Стоп».

  1. Для каждой из них выключим параметр Pop-up.

рис. 2.3.2. Изменение параметров пункта меню

2.4 Создание диалога для входных значений

  1. Для создания нового диалога перейдем на вкладку ResourseVeiw->Dialog(правый клик мышью)->Insert…->Dialog->New.

рис. 2.4.1. Создание нового диалога, вкладка Ресурсы

  1. Аналогичным образом добавим к ресурсам изображение нашего варианта задания, предварительно скопировав изображение в папку /res

рис. 2.4.2. Добавление нового изображения в Ресурсы

  1. Придадим нашему новому диалогу следующий вид.

рис. 2.4.3. Окно редактора диалога

  1. При помощи MFC ClassWizard(пункт меню View) свяжем поля нашего диалога с соответствующими переменными

рис. 2.4.4. Окно MFC ClassWizard, вкладка Member Variables,

связь элементов управления и переменных

Расшифровка переменных:

M_com – значение масштаба;

M_ab – длина звена AB и A’C, в % от длины звена AB ;

M_aa – длина звена AA’, в % от длины звена AB;

M_bc – длина звена BC, в % от длины звена AB;

M_mk – длина звена MK, в % от длины звена AB;

M_dab – длина звена AB, в мм;

M_gs – скорость движения звена AB, в град/с;

M_kp – количество положений механизма для отрисовки;

M_bx – координата X стойки A, относительно левого края экрана;

M_by – координата Y стойки A, относительно верхнего края экрана;

2.5 Описание использованных в прогрмамме функций

С помощью MFC ClassWizard создаем функции нажатий на кнопки окна диалога, пункты меню и событие инициализации диалога.

рис. 2.5.1. Окно MFC ClassWizard, создание функций по событию

  1. Нажатие на кнопку «Стандартные данные» описано в файле vxod_dialog.cpp и имеет вид:

void vxod_dialog::OnDefaultd()

{

m_ab=1;

m_aa=0.198;

m_bc=1.105;

m_mk=0.211;

m_com="1:1";

m_dab=100;

m_gs=5;

m_kp=0;

m_bx=50;

m_by=500;

UpdateData(0);

}

Данная функция заполняет поля ввода стандартными данными при желании пользователя.

  1. Нажатие на кнопку «Сохранить данные» описано в файле vxod_dialog.cpp и имеет вид:

void vxod_dialog::OnSaved()

{

UpdateData(1);

FILE *file=fopen("saved.txt","w");

fprintf(file,"%f\n",m_ab);

fprintf(file,"%f\n",m_aa);

fprintf(file,"%f\n",m_bc);

fprintf(file,"%f\n",m_mk);

if(m_com=="1:1") fputs("1\n",file);

if(m_com=="1:4") fputs("4\n",file);

if(m_com=="1:5") fputs("5\n",file);

if(m_com=="1:20") fputs("20\n",file);

if(m_com=="1:25") fputs("25\n",file);

fprintf(file,"%f\n",m_dab);

fprintf(file,"%i\n",m_gs);

fprintf(file,"%f\n",m_kp);

fprintf(file,"%f\n",m_bx);

fprintf(file,"%f",m_by);

fclose(file);

}

Данная функция сохраняет введенные данные в отдельный файл «saved.txt» при желании пользователя.

  1. Нажатие на кнопку «Загрузить данные» описано в файле vxod_dialog.cpp и имеет вид:

void vxod_dialog::OnLoadd()

{

FILE *file=fopen("saved.txt","rw");

char s[15];

fgets(s,15,file);

m_ab=atof(s);

fgets(s,15,file);

m_aa=atof(s);

fgets(s,15,file);

m_bc=atof(s);

fgets(s,15,file);

m_mk=atof(s);

fgets(s,15,file);

if(atoi(s)==1)m_com="1:1";

if(atoi(s)==4)m_com="1:4";

if(atoi(s)==5)m_com="1:5";

if(atoi(s)==20)m_com="1:20";

if(atoi(s)==25)m_com="1:25";

fgets(s,15,file);

m_dab=atof(s);

fgets(s,15,file);

m_gs=atof(s);

fgets(s,15,file);

m_kp=atof(s);

fgets(s,15,file);

m_bx=atof(s);

fgets(s,15,file);

m_by=atof(s);

fclose(file);

UpdateData(0);

}

Данная функция загружает данные в поля ввода из отдельного файла «saved.txt» при желании пользователя.

  1. Функция при инициализации диалога описана в файле vxod_dialog.cpp и имеет вид:

BOOL vxod_dialog::OnInitDialog()

{

CDialog::OnInitDialog();

FILE *file=fopen("in.txt","rw");

char s[15];

fgets(s,15,file);

m_ab=atof(s);

fgets(s,15,file);

m_aa=atof(s);

fgets(s,15,file);

m_bc=atof(s);

fgets(s,15,file);

m_mk=atof(s);

fgets(s,15,file);

if(atoi(s)==1)m_com="1:1";

if(atoi(s)==4)m_com="1:4";

if(atoi(s)==5)m_com="1:5";

if(atoi(s)==20)m_com="1:20";

if(atoi(s)==25)m_com="1:25";

fgets(s,15,file);

m_dab=atof(s);

fgets(s,15,file);

m_gs=atof(s);

fgets(s,15,file);

m_kp=atof(s);

fgets(s,15,file);

m_bx=atof(s);

fgets(s,15,file);

m_by=atof(s);

fclose(file);

UpdateData(0);

return TRUE; // return TRUE unless you set the focus to a control

// EXCEPTION: OCX Property Pages should return FALSE

}

Данная функция подгружает введенные в прошлый раз данные из файла «in.txt», таким образом программа помнит последние изменения.

  1. Нажатие на кнопку «ОК» описано в файле vxod_dialog.cpp и имеет вид:

void vxod_dialog::OnOK()

{

UpdateData(1);

FILE *file=fopen("in.txt","w");

fprintf(file,"%f\n",m_ab);

fprintf(file,"%f\n",m_aa);

fprintf(file,"%f\n",m_bc);

fprintf(file,"%f\n",m_mk);

if(m_com=="1:1") fputs("1\n",file);

if(m_com=="1:4") fputs("4\n",file);

if(m_com=="1:5") fputs("5\n",file);

if(m_com=="1:20") fputs("20\n",file);

if(m_com=="1:25") fputs("25\n",file);

fprintf(file,"%f\n",m_dab);

fprintf(file,"%i\n",m_gs);

fprintf(file,"%f\n",m_kp);

fprintf(file,"%f\n",m_bx);

fprintf(file,"%f",m_by);

fclose(file);

CDialog::OnOK();

}

  1. В хедер-файле ZasyadkoView.h объявим необходимые для расчёта и отрисовки механизма функции и переменные:

// Attributes

public:

CZasyadkoDoc* GetDocument();

void Draw();

void Clear();

void Raschet();

// Operations

public:

float bx,by,ax,ay,a1x,a1y,cx,cy,mx,my,kx,ky,kl,a, b, ab, aa1, a1c, km, dab, kp, ox,oy;

int gs, nTimer, n, nn;

bool flag, flag2,flag3,flag4;

Расшифровка:

void Draw() – функция содержащая операции для отрисвки механизма после каждого тика счетчика;

void Clear() – функция для очистки экрана после каждого тика счетчика;

void Raschet() – функция для расчета координат точек механизма;

bx, by, ax, ay, a1x, a1y, cx, cy, mx, my, kx, ky– координаты точек механизма;

ox, oy – центр координат;

kp – количество положений механизма;

kl – масштабный коэффициент;

a, b – углы наклона звеньев AB и A’C;

ab, aa1, a1c, km, dab – длины звеньев;

gs – время одного тика счетчика;

n, nn, flag, flag2, flag3, falg4 – вспомогательные счетчики и условия.

  1. Нажатие на пункт меню «Входные данные» описано в файле zasyadkoView.cpp и имеет вид:

void CZasyadkoView::OnVxod()

{

vxod_dialog dlg;

if(dlg.DoModal()==IDOK)

{

if(dlg.m_com =="1:1"){kl=1;}

if(dlg.m_com =="1:4"){kl=4;}

if(dlg.m_com =="1:5"){kl=5;}

if(dlg.m_com =="1:10"){kl=10;}

if(dlg.m_com =="1:20"){kl=20;}

if(dlg.m_com =="1:25"){kl=25;}

ox=dlg.m_bx;

oy=dlg.m_by;

bx=0;

by=0;

cy=by;

cx=bx+dlg.m_bc*dlg.m_dab*10/kl;

ab=dlg.m_ab*dlg.m_dab*10/kl;

a1c=dlg.m_ab*dlg.m_dab*10/kl;

aa1=dlg.m_dab*10*dlg.m_aa/kl*1.06;

km=dlg.m_dab*10*dlg.m_mk/kl;

kx=(bx+cx)/2;

dab=dlg.m_dab;

flag=1;

flag2=1;

flag3=0;

flag4=1;

a=65;

gs=dlg.m_gs;

kp=dlg.m_kp;

if(kp!=0){ n=0; nn=0;}

CClientDC dc(this);

CPen Pen1; Pen1.CreatePen(PS_DOT, 10, RGB(255,255,255));

dc.SelectObject(Pen1);

dc.Rectangle(0,0,2000,2000);

int s=250;

s=s/gs;

nTimer=SetTimer(1,s,NULL);

ASSERT(nTimer != 0);

}

}

Данная функция по окончанию ввода данных в вызванном диалоговом окне присваивает переменным значения, учитывая размеры звеньев, масштаб и сдвиг по координатам. Очищает экран. Запускает счетчик. И мы видим на экране результат – наш механизм.

рис. 2.5.2. Окно программы, отрисовка механизма

  1. Функция описывающая срабатывание счетчика описана в файле zasyadkoView.cpp и имеет вид:

void CZasyadkoView::OnTimer(UINT nIDEvent)

{

if(kp!=0){

Raschet();

nn=nn+1;

if(kp>2 && nn>=(186/kp)) { Draw(); nn=0;}

if(n>=186) nTimer=KillTimer(1);

n=n+1;

}

if(kp==0){

Clear();

Raschet();

Draw();

CView::OnTimer(1);

}

}

Данная функция в зависимости от введенного параметра «Количество положений механизма» выполняет различные действия:

  • если введено 0, значит механизм движется непрерывно. А последовательность действий на каждый тик счетчика выглядит так:

  • очистка экрана

  • перерасчет значений

  • отрисовка

  • если параметр больше 0 то на экране мы увидим статическое изображение нескольких наложенных друг на друга положений нашего механизма.

  1. Нажатие на пункт меню «Старт/Стоп» описано в файле zasyadkoView.cpp и имеет вид:

void CZasyadkoView::OnStop()

{

if(flag4==1)

{

nTimer=KillTimer(1);

flag4=0;

}

else

{

int s=250;

s=s/gs;

nTimer=SetTimer(1,s,NULL);

ASSERT(nTimer != 0);

flag4=1;

}

}

Данная функция имеет двойное значение, если механизм двигался во время нажатия, то он остановится(будет уничтожен счетчик, отвечающий за пересчет и отрисовку следующих положений), если же механизм остановлен, то он снова заработает(мы создадим в этом случае счетчик заново).

  1. Нажатие на пункт меню «Траектории» описано в файле zasyadkoView.cpp и имеет вид:

void CZasyadkoView::OnTRAEKTOR()

{

if(flag3==0)flag3=1;

else

{

flag3=0;

CClientDC dc(this);

CPen Pen1; Pen1.CreatePen(PS_DOT, 10, RGB(255,255,255));

dc.SelectObject(Pen1);

dc.Rectangle(0,0,2000,2000);

}

}

Данная функция включает отрисовку траекторий на движущемся механизме, и при повторном нажатии отключает их отрисовку.

рис. 2.5.3. Окно программы, отрисовка механизма, траектории

  1. Функция Raschet() описана в файле zasyadkoView.cpp и имеет вид:

void CZasyadkoView::Raschet()

{

ax=bx+cos(a*3.14/180)*ab;

ay=by+sin(a*3.14/180)*ab;

double z, z1, z2;

z=sqrt((cy-ay)*(cy-ay)+(cx-ax)*(cx-ax));

if(a>=70 && flag2==1)flag2=0;

else

if(flag2==0 && a>=70)flag2=1;

z1=(z*z+a1c*a1c-aa1*aa1)/(2*z*a1c);

z2=((cx-ax)*(cx-ax)+z*z-(by-ay)*(by-ay)) / (2*z*(cx-ax));

z1=fabs(z1);

z2=fabs(z2);

if(z1<1.000)z1=acos(z1);

else z1=acos(1);

if(z2<1.000)z2=acos(z2);

else z2=acos(1);

if(flag2==1)

b=(z1+z2)*180/3.14;

else

b=(z2-z1)*180/3.14;

a1x=cx-cos(b*3.14/180)*a1c;

a1y=cy+sin(b*3.14/180)*a1c;

mx=(ax+a1x)/2;

my=(a1y+ay)/2;

ky=+my+sqrt( km*km - (mx-kx)*(mx-kx) );

if(flag==1)a+=0.15;

else a-=0.15;

if(a>=70)flag=0;

if(a<=61 && a1x<=kx)flag=1;

if(a<=65 && a1x>=kx)flag=1;

}

Данная функция реализует рассчет координат узлов механизма. Для удобства рассчетов в качестве входного звена взято звено AB и угол между этим звеном и положительным направлением оси X. На каждый тик счетчика вызывается функция рассчета, увеличивается(уменьшается) угол на шаг 0.15 градуса. Крайние положения механизма были получены исходя из конструктивных особенностей данного механизма, а именно максимальной амплитуды хода штока.

  1. Функция Draw() описана в файле zasyadkoView.cpp и имеет вид:

void CZasyadkoView::Draw()

{

CClientDC dc(this);

SetMapMode(dc,MM_LOMETRIC);

SetViewportOrgEx(dc, ox, oy, NULL);

//Траектории

if(flag3==1)

{

int x,y;

x=bx+cos(65*3.14/180)*ab;

y=by+sin(65*3.14/180)*ab;

CPen newpen3(PS_SOLID,20,RGB(100,255,100));

dc.SelectObject(newpen3);

dc.MoveTo(x-(209-340)/kl*(dab/100),y+(200)/kl*(dab/100));

dc.LineTo(x-(209-340)/kl*(dab/100),y+(50)/kl*(dab/100));

CPen newpen4(PS_SOLID,20,RGB(255,150,150));

dc.SelectObject(newpen4);

kl=kl/2.6;

dc.Arc(x-(209-197)/kl*(dab/100), y+(157-162)/kl*(dab/100),

x-(209-320)/kl*(dab/100), y+(157-210)/kl*(dab/100),

x-(209-272)/kl*(dab/100), y+(157-150)/kl*(dab/100),

x-(209-213)/kl*(dab/100), y+(157-200)/kl*(dab/100));

CPen newpen5(PS_SOLID,20,RGB(150,150,255));

dc.SelectObject(newpen5);

dc.Arc(x-(209-37)/kl*(dab/100), y+(157-100)/kl*(dab/100),

x-(209-1037)/kl*(dab/100), y+(157-1100)/kl*(dab/100),

x-(209-37)/kl*(dab/100), y+(157+390)/kl*(dab/100),

x-(209-37)/kl*(dab/100), y+(157-75)/kl*(dab/100));

CPen newpen6(PS_SOLID,20,RGB(100,100,100));

dc.SelectObject(newpen6);

dc.Arc(x-(209+479)/kl*(dab/100), y+(157-120)/kl*(dab/100),

x-(209-521)/kl*(dab/100), y+(157-1120)/kl*(dab/100),

x-(209-266)/kl*(dab/100), y+(157-120)/kl*(dab/100),

x-(209-191)/kl*(dab/100), y+(157-120)/kl*(dab/100));

kl=kl*2.6;

}

//Звенья

CPen newpen1;

newpen1.CreatePen(PS_SOLID,1,RGB(0,0,0));

dc.SelectObject(newpen1);

dc.MoveTo(bx, by);

dc.LineTo(ax, ay);

dc.MoveTo(cx, cy);

dc.LineTo(a1x, a1y);

dc.MoveTo(a1x, a1y);

dc.LineTo(ax, ay);

dc.MoveTo(ax-(a1x-ax), (ay-(a1y-ay)));

dc.LineTo(a1x, a1y);

dc.MoveTo(mx, my);

dc.LineTo(kx, ky);

dc.MoveTo(kx,ky);

dc.LineTo(kx,ky-ab);

CBrush brush;

brush.CreateHatchBrush(HS_BDIAGONAL,RGB(0,0,0));

dc.SelectObject(brush);

CPen newpen2;

newpen2.CreatePen(PS_SOLID,1,RGB(255,255,255));

//Стойки

dc.MoveTo(bx,by);

dc.LineTo(bx-30,by-30);

dc.MoveTo(bx,by);

dc.LineTo(bx+30,by-30);

dc.SelectObject(newpen2);

dc.Rectangle(bx-30, by-30, bx+30, by-60);

dc.SelectObject(newpen1);

dc.MoveTo(bx-30,by-30);

dc.LineTo(bx+30,by-30);

dc.MoveTo(cx,cy);

dc.LineTo(cx-30,cy-30);

dc.MoveTo(cx,cy);

dc.LineTo(cx+30,cy-30);

dc.SelectObject(newpen2);

dc.Rectangle(cx-30, cy-30, cx+30, cy-60);

dc.SelectObject(newpen1);

dc.MoveTo(cx-30,cy-30);

dc.LineTo(cx+30,cy-30);

dc.MoveTo(kx-ab/60,by+ab/5*2);

dc.LineTo(kx-ab/60,by+ab/5);

dc.SelectObject(newpen2);

dc.Rectangle(kx-ab/60-30, by+ab/5*2, kx-ab/60, by+ab/5);

dc.SelectObject(newpen1);

dc.MoveTo(kx+ab/60-1, by+ab/5*2);

dc.LineTo(kx+ab/60-1, by+ab/5);

dc.SelectObject(newpen2);

dc.Rectangle(kx+ab/60+30, by+ab/5*2, kx+ab/60+1, by+ab/5);

dc.SelectObject(newpen1);

//Шарниры

CPen newpen6;

newpen6.CreatePen(PS_SOLID,1,RGB(100,100,255));

dc.SelectObject(newpen6);

dc.Ellipse(bx-10/kl*dab/100,by-10/kl*dab/100,bx+10/kl*dab/100,by+10/kl*dab/100);

dc.Ellipse(cx-10/kl*dab/100,cy-10/kl*dab/100,cx+10/kl*dab/100,cy+10/kl*dab/100);

dc.Ellipse(a1x-10/kl*dab/100,a1y-10/kl*dab/100,a1x+10/kl*dab/100,a1y+10/kl*dab/100);

dc.Ellipse(ax-10/kl*dab/100,ay-10/kl*dab/100,ax+10/kl*dab/100,ay+10/kl*dab/100);

dc.Ellipse(mx-10/kl*dab/100,my-10/kl*dab/100,mx+10/kl*dab/100,my+10/kl*dab/100);

dc.Ellipse(kx-10/kl*dab/100,ky-10/kl*dab/100,kx+10/kl*dab/100,ky+10/kl*dab/100);

//Буквы

dc.SetTextColor(RGB(255,100,100));

dc.SetBkMode(TRANSPARENT);

dc.TextOut(bx+10,by+4,"B");

dc.TextOut(cx+10,cy+4,"C");

dc.TextOut(kx+10,ky-10,"K");

dc.TextOut(ax-15,ay-10,"A");

dc.TextOut(a1x+10,a1y-10,"A'");

dc.TextOut(mx,my+10,"M'");

}

Данная функция осуществляет построение на экране данного механизма, на основании рассчитанных данных. Используем для рисования режим MM_LOMETRIC, это означает что для измерения длины линий используются единицы измерения мм, а не пиксели.

  1. Функция Clear() описана в файле zasyadkoView.cpp и имеет вид:

void CZasyadkoView::Clear()

{

CClientDC dc(this);

SetMapMode(dc,MM_LOMETRIC);

SetViewportOrgEx(dc, ox, oy, NULL);

CPen newpen1;

newpen1.CreatePen(PS_SOLID,1,RGB(255,255,255));

dc.SelectObject(newpen1);

dc.MoveTo(bx, by);

dc.LineTo(ax, ay);

dc.MoveTo(cx, cy);

dc.LineTo(a1x, a1y);

dc.MoveTo(a1x, a1y);

dc.LineTo(ax, ay);

dc.MoveTo(ax-(a1x-ax), ay-(a1y-ay));

dc.LineTo(a1x, a1y);

dc.MoveTo(mx, my);

dc.LineTo(kx, ky);

dc.MoveTo(kx,ky);

dc.LineTo(kx,ky-ab);

CPen newpen6;

newpen6.CreatePen(PS_SOLID,1,RGB(255,255,255));

dc.SelectObject(newpen6);

dc.Ellipse(bx-10/kl*dab/100,by-10/kl*dab/100,bx+10/kl*dab/100,by+10/kl*dab/100);

dc.Ellipse(cx-10/kl*dab/100,cy-10/kl*dab/100,cx+10/kl*dab/100,cy+10/kl*dab/100);

dc.Ellipse(a1x-10/kl*dab/100,a1y-10/kl*dab/100,a1x+10/kl*dab/100,a1y+10/kl*dab/100);

dc.Ellipse(ax-10/kl*dab/100,ay-10/kl*dab/100,ax+10/kl*dab/100,ay+10/kl*dab/100);

dc.Ellipse(mx-10/kl*dab/100,my-10/kl*dab/100,mx+10/kl*dab/100,my+10/kl*dab/100);

dc.Ellipse(kx-10/kl*dab/100,ky-10/kl*dab/100,kx+10/kl*dab/100,ky+10/kl*dab/100);

dc.SetTextColor(RGB(255,255,255));

dc.SetBkMode(TRANSPARENT);

dc.TextOut(bx+10,by+4,"B");

dc.TextOut(cx+10,cy+4,"C");

dc.TextOut(kx+10,ky-10,"K");

dc.TextOut(ax-15,ay-10,"A");

dc.TextOut(a1x+10,a1y-10,"A'");

dc.TextOut(mx,my+10,"M'");

dc.Rectangle(cx*1.4,0,cx*1.5,25);

}

Данная функция осуществляет очистку области отображения механизма по тику счетчика.