Г.Тяпичев «Начальный курс быстрого программирования на СИ++». Глава 2.

 

Глава 2. От простого к сложному 1

Предисловие 2

Проект 1_ 2

Что должно делать данное приложение 3

Начинаем создавать проект 4

Работа с текстовыми файлами_ 11

Описание функций в файле decibell.cpp_ 15

Проект 2_ 26

Что делает приложение 26

Начинаем создавать проект 27

Работа с текстовыми файлами_ 34

Проект 3_ 43

Что должно делать это приложение 43

Начинаем создавать проект 45

Некоторые итоги_ 73

Проект 4_ 74

Что должно делать это приложение 74

Цели и задачи этого проекта_ 78

Создаем проект 78

Работа с текстовыми файлами_ 80

Как сделать окно About 90

Компиляция проекта 91

 

Глава 2. От простого к сложному

 

 

Предисловие

Эта глава содержит основной материал, который должен научить вас создавать проекты приложений для Windows. Следует очень внимательно читать и запоминать все пояснения, если появляются вопросы – обращайтесь к расположенным в конце книги четырем Приложениям (1, 2, 3 и 4). Каждое из Приложений содержит справочный материал по определенной теме.

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

Не спешите копировать только что сделанное приложение на дискету, чтобы бежать с этой дискетой к приятелю и  пробовать запустить приложение на компьютере приятеля. Прочитайте прежде внимательно главу 5, вернее раздел этой главы, который называется «Пакеты». Здесь вы узнаете о том, что нужно сделать перед компиляцией проекта программы, чтобы создать «автономно работающий» вариант приложения. 

 

Проект 1

В процессе работы над проектом очень простого Windows приложения обратим внимание на начало организации процесса создания программы.

Что должно делать данное приложение

Рассмотрим процесс создания проекта очень простого Windows приложения. Приложение предназначено для расчета величины отношения двух чисел в децибелах.

После запуска в работу уже готового приложения на экране появляется рабочее окно программы, представленное на рис. 2.1.

Рис. 2.1. Приложение для расчета отношения величин

Для выполнения расчета в верхнее окно редактирования следует ввести величину большего числа, а в нижнее окно – меньшего из этих двух чисел. Затем нужно нажать клавишу Выполнить расчет. Под сочетанием слов «нажать клавишу» я имею ввиду, что нужно установить курсор мышки на изображение клавиши и нажать левую кнопку мышки. Иногда в подобном случае будет употребляться выражение «щелкнуть левой кнопкой мышки на клавише». После этих действий на экране появляются результаты расчета.

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

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

 

Начинаем создавать проект

Перечислим все этапы создания нового проекта, которые следует твердо выучить и запомнить.

1.        Перед началом создания рабочего проекта приложения нужно создать для этого проекта отдельную директорию (папку). Это может быть заранее созданная директория, например, d:\moi_proekty\decibell\.

2.        Запускаем C++ Builder, выбираем FileèNewèApplication. На экране появляется готовая к заполнению форма и все прочие окна, необходимые для нового проекта. Появляется и название проекта – Proekt1.

3.        Поскольку нас не устраивает название проекта, следует проект сохранить в заранее созданную директорию и под назначенным заранее названием проекта. Для этого выбираем FileèSave Proekt As. Основные файлы проекта сохраняются поочередно. Первым C++ Builder сохраняет основной функциональный файл проекта и просит ввести имя этого файла. Вводим имя файла “decibell” и сохраняем файл под этим именем. Затем C++ Builder предлагает ввести имя файла проекта. Еще раз предупреждаю, что имена сохраняемого первым функционального файла и файла проекта должны различаться. Мною в таких случаях используется следующий прием: для имени проекта я беру имя функционального файла, но добавляю к этому имени цифру, обозначающую вариант программы. Вы можете выбирать любые удобные для вас имена. Итак, сохраняем файл проекта под именем “decibell1”.        

4.        Проект сохранен в определенной директории, приступаем к заполнению формы проекта. Когда вы будете разрабатывать собственную программу, следует предварительно на листе бумаги сделать эскиз формы с размещенными на ней компонентами. В процессе разработки программы количество и размещение компонентов могут значительно меняться, но предварительный эскиз нужен обязательно. В данном случае перед вами лежит книга с предложенным автором вариантом расположения компонентов, изображенном на рис. 2.2.

 

Рис. 2.2. Расположение компонентов на форме

На панели компонентов должна быть установлена страница библиотеки компонентов Standard.

Теперь можно, если это кому-то интересно, заглянуть в директорию d:\moi_proekty\decibell\ . Здесь вы увидите созданные программой файлы нашего нового проекта.

q      decibell1.bpr  главный файл проекта – текстовый файл, содержащий всю необходимую информацию для компилятора, используемую при трансляции и сборке программных модулей;

q      decibell1.cpp – главный программный файл – текстовый файл, содержащий список всех используемых программных модулей, а также стандартную для всех программ на языке С++ функцию WinMain(), обеспечивающую запуск приложения в работу. Этот файл создается и постоянно контролируется средой C++ Builder автоматически;

q      decibell1.res – файл ресурсов – в нем хранятся некоторые данные, например, выводимые на панель задач;

q      decibell.cpp – файл программного модуля – в нем будут находиться исходные коды всех функций на языке С++;

q      decibell.h – заголовочный файл – в нем содержатся интерфейсные части формы, выполняется объявление задействованных компонентов и функций класса формы;

q      decibell.dfm – файл описания форм – содержатся описания форм и расположенных на них компонентов, запоминаются начальные значения свойств, установленных в инспекторе объектов.      

Пока все эти файлы содержат только самый необходимый для проекта минимум информации. Начать разработку проекта следует с заполнения (разработки) формы.  В учебных целях действия по разработке формы проекта следует разбить на несколько этапов.

 

Этап 1

Для отображения на форме текстовых строк можно использовать компонент Label  (переводится как «метка»). Подводим курсор к символическому изображению самого первого (слева) компонента в библиотеке Standard и задерживаем на нем курсор. Сразу же рядом возникает небольшое выпадающее окошко подсказки с именем этого компонента. Переместив курсор на символ следующего компонента читаем его имя, затем, после установки курсора на «жирную» букву ‘A’ читаем название Label.  Это как раз то, что нам требуется. Щелкаем мышкой на символе компонента и переводим курсор в левый верхний угол формы, как раз в то место, откуда должна начинаться первая текстовая строка. Нажимаем левую клавишу мышки и немного перемещаем курсор вправо и вниз. При этом наблюдаем появления некоторого окна, размеры которого изменяются по мере перемещения курсора. Для нас размеры этого окна не имеют ни малейшего значения, поэтому оставляем окно минимальным и отпускаем клавишу мышки. На форме появляется название Label1, одновременно с ним в окне Object Inspector    появляется перечень всех свойств, принадлежащих этому компоненту. В данном случае для нас необходимы из всего этого перечня только три свойства – свойство Name, в котором содержится имя компонента, свойство Captionв этом свойстве хранится текст, который будет изображаться на форме,  а также свойство Font – для создания размера и цвета шрифта. Первым выбираем свойство Caption и в принадлежащем этому свойству окне редактирования стираем имеющееся там название “Label1” и вводим текст «Децибелы».  Затем выбираем свойство Font  и щелкаем, на появившейся в окне редактирования этого свойства справа, небольшой кнопке с тремя точками. После этого появляется окно выбора шрифта, в котором следует выбрать:

q      Шрифт – MS San Serif;

q      Начертание – обычный;

q      Размер – 14;

q      Цвет – синий.

На экране установился текст первой строки «Децибелы».

Точно таким же образом выбираем из библиотеки Standard компонент Label2 для второй строки, устанавливаем этот компонент на форму под первой строкой и в окне Object Inspector  задаем текст для второй строки в свойстве Caption «Введите большую величину». Затем в свойстве Font  выбираем обычный шрифт MS San Serif, размер – 10, цвет – черный.

Точно таким же образом устанавливаем на форму компонент Label3 для третьей строки и вводим текст «Введите меньшую величину».

Для создания следующих строк, изображенных на рис. 2.2, устанавливаем компоненты Label без  задания какого – либо текста. Это значит, что в свойстве Caption и свойстве Name каждого компонента останется одно и то же название. 

 При этом Caption для  строки 4 будет иметь текст Label4 и выглядеть на форме как Label4,  для  строки  5 – как Label5, для 6 – Label6 и так далее до Label10 для самой последней строки.  На рис. 2.3 показан вариант формы с установленными на ней всеми компонентами.

 

Рис. 2.3. Форма с установленными компонентами

Если щелкнуть мышкой на названии какого – то компонента, то этот компонент переходит в ранг «выбранного». Вокруг этого компонента образуется своеобразная рамка,  в окне Object Inspector  устанавливаются все свойства, доступные этому компоненту. В данном случае на рис. 2.3 выбран компонент Label5 и слева видны соответствующие этому компоненту свойства Caption, Name и другие.

Щелкнув мышкой поочередно на названиях меток Label4 … Label10 можно для каждого из этих компонентов задать параметры шрифтов. Тексты Caption мы будем назначать в процессе программирования.

Следует знать, что имена Label1Label10 так и останутся за соответствующими строками – метками. Эти имена находятся в свойствах Name каждого компонента. Конечно, эти имена можно изменять, но в данном случае делать это не следует. Новые имена компонентам даются тогда, когда возникает возможность запутаться в цифровых отличиях.

 

Этап 2

Теперь нужно установить на форму компоненты, позволяющие вводить в программу исходные данные. Таким компонентом является окно редактирования Edit, изображенный справа рядом с «жирной» буквой ‘A’. Устанавливаем курсор на символ этого компонента и убеждаемся по подсказке в том, что это действительно нужный для нас компонент. Переносим на форму сначала верхнее окно редактирования, затем нижнее. При этом в окне первого компонента имеется текст Edit1, а в окне второго – Edit2. Это названия компонентов, содержащиеся в свойствах Name и в свойствах Caption одновременно. Поскольку имена компонентов изменять не будем, то свойство Name оставим без изменения, а в окне редактирования свойств Caption  удалим это название, чтобы очистить само окошко.

Таким образом, на форме установлены два окна редактирования Edit1 и Edit2, предназначенных для ввода пользователем в работающую программу необходимых исходных данных.

 

Этап 3

Начало вычислительных действий в данном приложении задается кнопками Button.  Компоненты этих кнопок также располагаются в библиотеке Standard, символом этих кнопок является изображение миниатюрной кнопочки с буквами OK. Устанавливаем курсор на этот символ и убеждаемся, что подсказка выдает необходимое название Button. Затем переносим два этих компонента на форму в верхнюю часть формы, рядом с верхним окном редактирования. В свойстве Component первого окна пишем текст «Выполнить расчет», для второго окна пишем «Выход».

В нижнюю часть формы устанавливаем еще два компонента Button. На одном из них пишем текст «Да», на другом – текст «Нет».

При этом имена всех компонентов оставляем неизменными, т.е. Button1, Button2, Button3  и Button4.

 Все этапы заполнения формы компонентами закончены, форма приобрела вид, показанный на рис. 2.3. Переходим к процессу собственно программирования – работе по написанию программ – работе с текстовыми файлами.

 

Работа с текстовыми файлами

В то время, когда мы занимались размещением на рабочей форме различных компонентов, C++ Builder непрерывно работал в автоматическом режиме над основными текстовыми файлами проекта decibell.cpp,  decibell.h и другими. Перейти от работы с формой к работе с редактором текстов, в котором выводятся на экран текстовые файлы, можно нажатием на клавишу <F12>. Эта клавиша служит для переключения между формой и редактором текстов. Из любого другого окна редактор текстов можно вызвать совместным нажатием на клавиши <Ctrl>+<F12>, вызвать появление формы можно клавишами <Shift>+<F12>. Все эти операции можно выполнить также простым щелканьем мышкой, как это было описано в главе 1.

В листинге 2.1 приведен текст заголовочного файла decibell.h.

Листинг 2.1. Файл decibell.h

//----------------------------------------------------------------------

#ifndef decibellH

#define decibellH

//----------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

//----------------------------------------------------------------------

class TForm1 : public TForm

{

__published:    // IDE-managed Components

        TLabel *Label1;

        TButton *Button1;

        TButton *Button2;

        TLabel *Label2;

        TLabel *Label3;

        TEdit *Edit1;

        TEdit *Edit2;

        TLabel *Label4;

        TLabel *Label5;

        TLabel *Label6;

        TLabel *Label7;

        TLabel *Label8;

        TLabel *Label9;

        TButton *Button3;

        TButton *Button4;

        TLabel *Label10;

        void __fastcall Edit1Change(TObject *Sender);

        void __fastcall Edit2Change(TObject *Sender);

        void __fastcall Button2Click(TObject *Sender);

        void __fastcall Button1Click(TObject *Sender);

        void __fastcall Button3Click(TObject *Sender);

        void __fastcall Button4Click(TObject *Sender);

private:  // User declarations

public:         // User declarations

        __fastcall TForm1(TComponent* Owner);

};

//---------------------------------------------------------------------

extern PACKAGE TForm1 *Form1;

//---------------------------------------------------------------------

#endif

 

Рассмотрим подробно содержание этого файла. В дальнейшем таких рассмотрений делать не будем. Учтите и запоминайте. Расположенный ниже материал относится к основам языка С/C++.

Файл создается средой программирования автоматически, вмешательство в него должно быть только очень осмысленным.

Первые две строки совместно с последней строкой относятся к директивам препроцессора и описаны в Приложении 4. Фактически они задают начало и конец подключаемого заголовочного файла decibell.h.

Две наклонных черты «//» являются символом начала строки с пояснениями (комментариями). Пояснения могут также ограничиваться символами  /* и */.

Следующие четыре строки, начинающиеся с текста #include  равнозначны понятию             “подключение” и дают указание компилятору подключить к работе над программой указанные далее в угловых скобках специальные «подключаемые заголовочные файлы», которые содержат описания задействованных в данной программе функций и которые находятся в составе C++ Builder в директории INCLUDE.

Если подключаемый файл находится в директории разрабатываемого проекта, то он вместо угловых скобок заключается в двойные кавычки “…”.

Словами class Tform1 : public Tform  начинается “объявление” класса TForm1. Все, что далее находится между фигурными скобками, относится к этому классу. Первыми членами этого класса объявляются установленные нами ранее на форму компоненты типа Label и Button, затем объявляются функции, вызванные событиями этих компонентов.

Смысл понятия «объявление» заключается в том, что этим действием для объявляемого объекта выделяется необходимый участок памяти и организуется адресный указатель на этот участок.

Функции – члены класса TForm1 – в этом файле только объявляются, а вот описывать эти функции, т.е. наделять их соответствующими кодами будем делать уже в файле decibell.cpp. 

 

Описание функций в файле decibell.cpp

Выведем на экран рабочую форму Form1. Если установить курсор на верхнем окне редактирования Edit1 и выполнить двойной щелчок мышкой, то на экране возникнет редактор текста с находящемся в этом редакторе файлом decibell.cpp. При этом курсор будет находиться внутри функции, предназначенной для описания события, вызванного окном редактирования Edit1. Не будем ничего записывать в «тело» этой функции, напечатаем просто символы // .

Рассмотрим файл decibell.cpp несколько подробнее.

Начинается он с подключения файла <vcl.h>, который является главным файлом в описаниях всех задействованных в C++ Builder библиотек компонентов. Далее подключается файл  <math.h> - это файл с описаниями математических функций, и файл decibell.h – файл, который был нами рассмотрен чуть ранее. Строки, начинающиеся с выражения #pragma, являются специфическими для C++ Builder служебными строками и никаким изменениям или удаления подвергаться не должны.

Листинг 2.2. Файл decibell.cpp

//--------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include <math.h>

#include "decbell.h"

//--------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

//--------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)              // 1

        : TForm(Owner)

{

 Caption = "Отношение величин в дБ";

 Label4->Caption = "";

 Label5->Caption = "";

 Label6->Caption = "";

 Label7->Caption = "";

 Label8->Caption = "";

 Label9->Caption = "";

 Label10->Caption = "";

}

//-------------------------------------------------------------------

void __fastcall TForm1::Edit1Change(TObject *Sender)         // 2

{

  //       

}

//-------------------------------------------------------------------

 

Строки, начинающиеся с выражения void __fastcall являются функциями, каждая из которых выполняет определенные для неё действия, записанные в «теле» этой функции в виде программных кодов. Для удобства обращения, я пронумерую все функции, описанные в этом файле определенной цифрой в сочетании с символами начала комментариев, например, //2. Эти номера будут находиться справа от заголовка каждой из функций.  

После нашего первого входа в редактор текстов путем двойного щелчка в окне Edit1 в окне редактора текста в файле decibell.cpp будут находиться только две функции – функция под номером 1 и функция под номером 2. Никаких других функций в этот момент пока существовать не будет. Причем описания имеющихся функций будет состоять только из заголовка и расположенных ниже заголовка двух фигурных скобок. Как раз между этими двумя фигурными скобками (это место иногда называется «телом» функции) и должны находиться программные коды, которые должен написать сам программист.

В функцию 2 мы уже ввели коды в виде символа комментариев и больше к ней  возвращаться не будем. Рассмотрим функцию 1.

Эта функция имеет заголовок __fastcall TForm1::TForm1(TComponent* Owner) , который говорит о том, что функция служит для описания внешнего вида формы уже готового приложения (после компиляции). «Заготовка» формы с установленными на ней всеми компонентами изображена на рис. 2.3. Допускать, чтобы внешний вид готового приложения выглядел точно также нельзя, поэтому примем некоторые меры.

q      Сделаем для формы название. Для этого запишем команду

  Caption = "Отношение величин в дБ"; 

Эта команда в свойство формы Caption записывает нужный нам текст, который при запуске приложения выводится в верхней части окна этого приложения. 

q      Далее следует очистить форму от текстов в виде «Label4» и т.д. Для этого в свойства Caption каждой из меток типа Label запишем пустую строку, напрмер,

Label4->Caption = "";

На этом пока закончим и нажимаем <F12> для перехода в режим работы с формой. Двойной щелчок в окне редактирования Edit2 вызовет на экран текстовый редактор, при этом курсор будет установлен между двумя фигурными скобками, предлагая ввести в это место соответствующую команду. Мы так и сделаем, введем команду

Label4->Caption = "Нажмите клавишу <Выполнить расчет>";

Эта команда вводит в свойство Caption, принадлежащее компоненту Label4, соответствующий текст. По этой команде на запущенном в работу приложении, сразу после ввода данных во второе окно редактирования,  появится просьба нажать клавишу Выполнить расчет.

Итак, мы заполнили кодами описание третьей функции. Нажимаем клавишу <F12> и переходим в режим работы с формой.

Двойной щелчок на клавише Выход и курсор готов к написанию команд для функции 4, которая должна прекращать работу нашего приложения и выполнить выход в окно рабочего стола Windows.

Команда в данном случае очень простая – пишем  Close();       

Листинг 2.3. Продолжение 1 файла decibell.cpp

//-------------------------------------------------------------------

void __fastcall TForm1::Edit2Change(TObject *Sender)          // 3

{

 Label4->Caption = "Нажмите клавишу <Выполнить расчет>";

}

//--------------------------------------------------------------------

 

void __fastcall TForm1::Button2Click(TObject *Sender)          // 4

{

 Close();       

}

//--------------------------------------------------------------------

 

Постепенно мы подошли к самому важному этапу – этапу выполнения того самого расчета, ради которого делается проект этой программы.

Когда на форме имеется несколько окон редактирования, в которые при работе программы нужно вводить различные величины, возникают моменты, когда при замене одной величины  другой величиной окно редактирования на какое-то время оказывается пустым. C++ Builder этого не любит и выдает сообщение об ошибке. Чтобы предотвратить подобные сообщения, можно «узаконить» появление пустого пространства в окнах редактирования. Мною для этих целей используется оператор if else. Обязательно посмотрите описание этого оператора в Приложении 4 или в другой литературе.

Пронумерую строки описания этой функции индивидуальными номерами, как  //№1

Фраза Button1Click в заголовке функции обозначает, что функция выполняется при нажатии на кнопку Button1, т.е. клавишу «Выполнить расчет».

Строка №1 имеет следующий смысл (перевод): « если (if) в окне Edit1 ИЛИ в окне Edit2 нет текста, то выполняется строка №2». В середине строки №1 находятся две стоящие рядом вертикальные черточки ‘||’. Таким образом в С++ обозначается операция «логическое ИЛИ». Используется эта операция в данном случае для того, чтобы условие, определяемое оператором if выполнялось в зависимости от наличия текста в окне 1 ИЛИ от наличия текста в окне 2. Смотрите Приложение 4.

Строка №2 выдает на экран окно сообщения с текстом «Введите необходимые величины».

Расположенное в строке №3 слово else (иначе) обозначает, что если условия, описанные в строке №1 не выполнены (т.е. в окнах редактирования есть тексты), то начинают выполняться все программные строки начиная со строки №4, т.е. все строки, находящиеся между фигурными скобками, следующими за else.

Листинг 2.4. Продолжение 2 файла decibel.cpp

//--------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)           // 5

{

 if(Edit1->Text == "" || Edit2->Text == "")                    //№ 1

     ShowMessage("Введите необходимые величины");              //№ 2

 else                                                          //№ 3

    {

   float aa = StrToFloat(Edit1->Text);                         //№ 4

   float bb = StrToFloat(Edit2->Text);                         //№ 5

    float ras = aa / bb;                                       //№ 6

    float nap = 20 * log10(ras);                               //№ 7

    float pov = 10 * log10(ras);                               //№ 8

 Label5->Caption = "Результаты расчета";                       //№ 9

 Label6->Caption = "Отношение величин составляет       "+      //№ 10

         FloatToStrF(ras,ffGeneral,4,2)+ "  раз";              //№ 11

 Label7->Caption = "Отношение напряжений или токов    "+       //№ 12

         FloatToStrF(nap,ffGeneral,4,2)+ "  дБ";               //№ 13

 Label8->Caption = "Отношение величин мощностей        "+      //№ 14

         FloatToStrF(pov,ffGeneral,4,2)+ "  дБ";               //№ 15

 Label9->Caption = "Результаты расчета устраивают? (Да/Нет)";  //№ 16     

    }

}

//-------------------------------------------------------------------

 

В строке №4 объявлена переменная величина aa, тип этой переменной float, т.е. это может быть дробная величина (например, десятичная дробь). Численное значение этой величины получается переводом текста, записанного в окне редактирования Edit1 в численное значение типа float. Делается это функцией StrToFloat().

В строке №5 точно таким же образом объявлена переменная величина bb. 

Обязательно посмотрите в Приложении 4 или другой литературе о функциях перевода строк в числа и наоборот. Дело в том, что C++ Builder требует, чтобы все числа перед из записью на форму были переведены в строки символов  и наоборот, любое записанное на форме число, перед выполнением с этим числом математических действий, должно быть переведено из строки  в действительное число соответствующего типа (char, int, float, double и т.д.).

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

q      Для перевода строки в число типа int служит функция StrToInt(строка), функция StrToFloat(строка) переводит строку из цифр в число типа float и т.д.

q      Для перевода числа типа int в строку служит функция IntToStr(число), функция FloatToStr(число) переводит число типа float в строку и т.д. Во многих случаях число типа float имеет большое число знаков после запятой. Для ограничения этого числа служит специальная функция FloatToStrF(число,ffGeneral,4,2),  где  «число» - это заданное число, слово ffGeneral – специальный термин , число 4 задает общее число цифр в результате (может иметь любое значение), число 2 – задает число цифр после запятой (может быть любым).

В строке №6 объявляется число ras типа float и тут же показывается, что это число равно частному от деления числа aa на число bb.

В строке №7 объявляется число nap типа float и тут же показывается, что это число равно цифре 20 умноженной на десятичный логарифм числа ras. Точно также поступаем в строке №8 с числом float pov, которое равно числу 10 умноженному на десятичный логарифм числа ras. 

Строка №9 вам знакома. В строке №10 показано, как можно выполнить сложение двух строк в одну и записать эту строку в метку Label6.

Все остальные строки в теле этой функции аналогичны строке №10.

Прочитайте в Приложении 4 раздел “AnsiString”.

После выполнения всех математических действий программа спрашивает: "Результаты расчета устраивают? (Дает)". Чтобы ответить на этот вопрос нами установлены еще две кнопки Button – первая служит для ответа «Да», вторая – для «Нет».

Двойной щелчок мышкой на кнопке «Да» предложит нам ввести коды в функцию 6. Здесь можно запрограммировать запись в Label10  текста  "Результаты расчета устраивают".

Листинг 2.5. Продолжение 3 файла decibell.cpp

//-------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)         // 6

{

Label10->Caption = "Результаты расчета устраивают";

}

//------------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)        // 7

{

Label5->Caption = "";

Label6->Caption = "";

Label7->Caption = "";

Label8->Caption = "";

Label9->Caption = "";

Label10->Caption = "";

Edit1->Text = "";

Edit2->Text = "";

Label4->Caption = "";

}

//--------------------------------------------------------------------

 

Двойной щелчок на кнопке «Нет» предложит нам ввести коды в функцию 7. Думаю, что здесь нужно очистить текстовые поля меток от Label4 до Label10 и поля окон редактирования Edit1 и Edit2.

На этом программирование закончено. Для сохранения всех файлов выбираем File|èSave All.

Чтобы выявить возможные ошибки выбираем ProektèMake decibell1. Если ошибок в текстах исходных кодов программы нет, то выбираем ProektèBuild decibell1. В результате выполнения этой команды создается исполняемый файл decibell1.exe, который можно запустить в работу командой RunèRun.

Чтобы избежать одновременного исправления большого числа ошибок советую на промежуточных этапах программирования почаще выполнять компиляцию программы – выбирать Proekt|èMake <name>. 

Некоторые итоги

В процессе работы над этим проектом вы научились:

q      Находить по всплывающей подсказке  нужный компонент;

q      Устанавливать на форму компоненты Label, Edit, Button;

q      Назначать некоторые нужные свойства компонентов;

q      Выводить на поверхности формы нужные тексты;

q      Программировать некоторые математические операции;

q      Выполнять компиляцию программы.

В процессе работы над проектом вы узнали следующие моменты из основ языка С++:

q      Наличие подключаемых заголовочных файлов и способ их подключения;

q      Объявление класса формы в файле с расширением *.h;

q      Символы для отделения комментариев от текста кодов программы;

q      О работе оператора условий ifelse;

q      О существовании операции «логическое ИЛИ»;

q      Наличие различных типов у чисел и других переменных величин;

q      Перевод  чисел из строковой формы в действительную и наоборот;

q      Соединение текстовых строк друг с другом;

В заключении советую вам еще раз внимательно почитать соответствующие разделы Приложения 4 или учебника по C/C++. 

 

Проект 2

Что делает приложение

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

Рис. 2.4. Приложение для расчета размеров антенн

Приложение позволяет выполнить расчеты геометрических размеров одной из двух представленных антенн – антенны «тройной квадрат» и антенны «треугольник». Для выполнения расчета в окно редактирования соответствующей антенны следует ввести величину средней частоты рабочего диапазона а мегагерцах, затем нажать клавишу Выполнить расчет. Напоминаю еще раз, что под сочетанием слов «нажать клавишу» я имею ввиду, что нужно установить курсор мышки на изображение клавиши и нажать левую кнопку мышки. Иногда будет употребляться выражение «щелкнуть левой кнопкой мышки».

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

Начинаем создавать проект

В предыдущем примере я уже предупреждал о том, что перед началом создания рабочего проекта приложения нужно создать для этого проекта отдельную директорию (папку). Это может быть заранее созданная директория, например, d:\moi_proekty\antenn\.

Запускаем C++ Builder, выбираем FileèNewèApplication.  В заранее созданную директорию сохраняем  только что  созданные файлы проекта. Для этого выбираем FileèSave Proekt As. Основные файлы проекта сохраняются поочередно. Первым C++ Builder сохраняет основной функциональный файл проекта и просит ввести имя этого файла. Вводим имя файла “ant3q” и сохраняем файл под этим именем. Затем C++ Builder предлагает ввести имя файла проекта. Еще раз предупреждаю, что имена сохраняемого первым функционального файла и файла проекта должны различаться. Мною в таких случаях используется следующий прием: для имени проекта я беру имя функционального файла, но добавляю к этому имени цифру, обозначающую вариант программы. Вы можете выбирать любые удобные для вас имена.

Итак, сохраняем файл проекта под именем “ant3q1”.        

Проект сохранен в определенной директории, приступаем к заполнению формы проекта. Когда вы будете разрабатывать собственную программу, следует предварительно на листе бумаги сделать эскиз формы с размещенными на ней компонентами. В процессе разработки программы количество и размещение компонентов могут значительно меняться, но предварительный эскиз нужен обязательно. В данном случае перед вами лежит книга с предложенным автором вариантом расположения компонентов, изображенном на рис. 2.5.

Рис. 2.5. Расположение компонентов на форме

На панели компонентов должна быть установлена страница библиотеки компонентов Standard.

Чтобы закрепить материал предыдущего проекта, попытаюсь и на этот раз показать процесс заполнения формы также подробно, по этапам.

Этап 1

Для отображения на форме текстовых строк будем использовать компонент Label  (переводится как «метка»). Подводим курсор к символическому изображению самого первого (слева) компонента в этой библиотеке и задерживаем на нем курсор. Сразу же рядом возникает небольшое выпадающее окошко подсказки с именем этого компонента. Переместив курсор на символ следующего компонента читаем его имя, затем, после установки курсора на «жирную» букву ‘A’ читаем название Label.  Это как раз то, что нам требуется. Щелкаем мышкой на символе компонента и переводим курсор в левый верхний угол формы, как раз в то место, откуда должна начинаться первая текстовая строка. Нажимаем левую клавишу мышки и немного перемещаем курсор вправо и вниз. При этом наблюдаем появления некоторого окна, размеры которого изменяются по мере перемещения курсора. Для нас размеры этого окна не имеют ни малейшего значения, поэтому оставляем окно минимальным и отпускаем клавишу мышки. На форме появляется название Label1, одновременно с ним в окне Object Inspector    появляется перечень всех свойств, принадлежащих этому компоненту. В данном случае для нас необходимы из всего этого перечня только два свойства – свойство для создания текста и свойство для создания размера и цвета шрифта. Первым выбираем свойство Caption и принадлежащее этому свойству окне редактирования стираем имеющееся там название “Label1” и вводим текст «Антенна “тройной квадрат”».  Затем выбираем свойство Font  и щелкаем, на появившейся в окне редактирования этого свойства справа, небольшой кнопке с тремя точками. После этого появляется окно выбора шрифта, в котором следует выбрать:

q      Шрифт – MS San Serif;

q      Начертание – обычный;

q      Размер – 14;

q      Цвет – синий.

На экране установился текст первой строки.

Точно таким же образом задаем тексты для всех последующих срок. При этом шрифт в строке Label9 должен соответствовать шрифту в строке Label1, а шрифты в строках Label3 и Label11 желательно назначить красного цвета.

Следует знать, что имена Label1Label12 так и станутся за соответствующими строками – метками. Эти имена находятся в свойствах Name каждого компонента. Конечно, эти имена можно изменять, но в данном случае делать это не следует. Новые имена компонентам даются тогда, когда возникает возможность запутаться в цифровых отличиях.

Этап 2

На этом этапе нужно установить на форму компоненты, позволяющие вводить в программу исходные данные. Таким компонентом является Edit, изображенный справа рядом с «жирной» буквой ‘A’. Устанавливаем курсор на символ этого компонента и убеждаемся по подсказке в том, что это действительно нужный для нас компонент. Переносим на форму сначала верхний компонент, затем нижний. При этом в окне первого компонента имеется текст Edit1, а в окне второго – Edit2. Это названия компонентов, содержащиеся в свойствах Name и в свойствах Caption одновременно. Поскольку имена компонентов изменять не будем, то свойство Name оставим без изменения, а окне редактирования свойств Caption  удалим это название.

Таким образом, на форме установлены два окна редактирования Edit1 и Edit2, предназначенных для ввода пользователем в работающую программу необходимых исходных данных.

Этап 3

Начало вычислительных действий в данном приложении задается кнопками Button.  Компоненты этих кнопок также располагаются в библиотеке Standard, символом этих кнопок является изображение миниатюрной кнопочки с буквами OK. Устанавливаем курсор на этот символ и убеждаемся, что подсказка выдает необходимое название Button. Затем переносим три этих компонента на форму в соответствующие места, при этом имена компонентов оставляем неизменными, т.е. Button1, Button2, Button3, а свойствах Component пишем тексты «Выполнить расчет» и «Выход».

На форму установлены исполнительные компоненты – кнопки Button. 

Этап 4

Для придания приложению наглядности, следует разместить на форме рисунки с изображением схем антенн – объектов расчета. Разумеется, что рисунки схем уже выполнены в графическом редакторе и готовы к размещению на форме приложения. Сначала подготовим место для размещения двух рисунков. Чтобы каждый рисунок имел какое – то название, применим компонент GroupBox. (Напоминаю, что за справками по компонентам обращайтесь в Приложение 2 и Приложение 3.)

Этот компонент служит для создания (в данном случае) рамки с заголовком вокруг будущего рисунка. Вы уже научились по всплывающей подсказке находить нужные компоненты, поэтому самостоятельно устанавливайте два таких компонента. При этом нужно сначала задать рамкам компонентов наибольшие размеры, чтобы в дальнейшем их можно было легко уменьшить. Обратные действия выполнять сложнее. В свойствах Caption следует ввести тексты заголовков. В данном случае заголовком каждой из рамок является текст «Схема антенны». Компонент служит (в данном случае) чисто декоративным целям и не является обязательным, но вы должны его знать и уметь им пользоваться.

Собственно рисунок размещается на форму с использованием компонента Image и размещен в библиотеке Additional. Символ этого компонента представляет собой миниатюрную картинку, на которой изображено голубое небо и темно-синие горы. Установите курсор на этот символ и убедитесь по всплывающей подсказке о правильности сделанного выбора. Затем перенесите два компонента на форму и разместите из внутри установленных ранее рамок GroupBox. 

Для компонента Image выбираем свойство Picture. Щелкаем мышкой по кнопочке, расположенной в окне редактирования этого свойства, в результате чего всплывает окно Picture Editor. Окно изображено на рисунке рис. 2.6.

Рис. 2.6. Окно редактирования рисунка

В этом окне выбираем Load и  всплывает новое окно, окно Load Picture, предназначенное для нахождения пути к нужному рисунку (рис. 2.7). Это окно типовое для Windows и каких – то специальных пояснений не требует. Выбираете путь к нужному рисунку, нажимаете клавишу OK и этот нужный рисунок моментально устанавливается на форму.

Рис. 2.7. Окно выбора и просмотра рисунка

Теперь нужно под размеры рисунка подогнать размеры рамки и разработка формы на этом может считаться законченной.

Работа с текстовыми файлами

В процессе работы над установкой на форму необходимых компонентов, C++ Builder непрерывно работал в автоматическом режиме над основными текстовыми файлами проекта ant3q.cpp и ant3q.h. Текст файла ant3q.h очень похож на аналогичный файл из предыдущего проекта и каких – то иных особенностей не имеет. Поэтому приводить текст файла ant3q.h. нет смысла. В листинге 2.6 приведен текст  файла ant3q.cpp.

Так же, как и в предыдущем проекте, файл начинается с перечисления подключаемых заголовочных файлов. Первым стоит  файл <vcl.h>, который является главным файлом в описаниях всех задействованных в C++ Builder библиотек компонентов. Далее подключается файл  <stdlib.h> - это файл с описаниями математических функций, и файл ant3q.h – подключаемый файл собственно данного проекта. Строки, начинающиеся с выражения #pragma, являются специфическими для C++ Builder служебными строками и никаким изменениям или удаления подвергаться не должны.

Обратите внимание на то, что среди этих файлов нет файла <math.h>, примененного в прошлом проекте. Дело в том, что функции простых арифметических действий описаны также и в файле <stdlib.h>, который применен в этом проекте. Так что для простых арифметических действий вполне достаточно подключения файла <stdlib.h>.

В данном случае я также (для удобства обращения) пронумерую все функции.

Листинг 2.6.  Файл ant3q.cpp

//--------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include <stdlib.h>

#include "ant3q.h"

//---------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

//---------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)                 // 1

        : TForm(Owner)

{

 Caption = "Расчеты антенн";

}

//---------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)         // 2

{

 Close();       

}

//---------------------------------------------------------------------

 

Напоминаю еще раз, что строки, начинающиеся с выражения void __fastcall являются функциями, каждая из которых выполняет определенные для неё действия, записанные в «теле» этой функции в виде программных кодов. Для удобства обращения, я снова пронумерую все функции, описанные в этом файле определенной цифрой в сочетании с символами начала комментариев, например, //2. Эти номера будут находиться справа от заголовка каждой из функций.  

После нашего первого входа в редактор текстов путем двойного щелчка в окне Edit1 в окне редактора текста в файле ant3q.cpp будут находиться только две функции – функция под номером 1 и функция под номером 2. Никаких других функций в этот момент пока существовать не будет. Причем описания имеющихся функций будет состоять только из заголовка и расположенных ниже заголовка двух фигурных скобок. Как раз между этими двумя фигурными скобками (это место иногда называется «телом» функции) и должны находиться программные коды, которые должен написать сам программист.

Функция под номером 1 имеет заголовок __fastcall TForm1::TForm1(TComponent* Owner), который говорит о том, что функция служит для описания внешнего вида формы уже готового приложения (после компиляции). «Заготовка» формы с установленными на ней всеми компонентами изображена на рис. 2.5. Сделаем для формы название. Для этого запишем в тело функции №1 команду

  Caption = "Расчеты антенн"; 

Эта команда в свойство формы Caption записывает нужный нам текст, который при запуске приложения выводится в верхней части окна этого приложения. 

Итак, мы заполнили кодами описание первой функции. Нажимаем клавишу <F12> и переходим в режим работы с формой.

Двойной щелчок на клавише Выход и курсор готов к написанию команд для функции 2, которая должна прекращать работу нашего приложения и выполнить выход в окно рабочего стола Windows.

Команда в данном случае очень простая – пишем  Close();      

Выводим на экран форму программы.

Заполним тело функции 3, которая соответствует двойному щелчку левой кнопки мышки на верхней клавише Выполнить расчет. Пронумеруем основные строки программного текста этой функции, как №1 и т.д.

Листинг 2.7. Продолжение 1 файла ant3q.cpp

//---------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)         // 3

{

if(Edit1->Text == "")                                              //№1

ShowMessage("Введите среднюю частоту диапазона.");

else

  {

 float ld = 297.0 / StrToFloat(Edit1->Text);                       //№2

 float la = 306.30 / StrToFloat(Edit1->Text);                      //№3

 float lr = 314.0 / StrToFloat(Edit1->Text);                       //№4

 float ad = (300 * 9.5 / StrToFloat(Edit1->Text)) / 100;           //№5

 float ar = (300 * 13 / StrToFloat(Edit1->Text)) / 100;            //№6

 Label4->Caption = "Периметр директора =                           //№7

                   "+FloatToStrF(ld,ffGeneral,5,1)+" м";

 Label5->Caption = "Периметр излучателя =                          //№8

                   "+FloatToStrF(la,ffGeneral,5,1)+" м";

 Label6->Caption = "Периметр рефлектора =                          //№9

                   "+FloatToStrF(lr,ffGeneral,5,1)+" м";

 Label7->Caption = "Расстояние излучатель - директор = "+          //№10

                    FloatToStrF(ad,ffGeneral,5,1)+" м";

 Label8->Caption ="Расстояние излучатель - рефлектор = "+          //№11

                    FloatToStrF(ar,ffGeneral,5,1)+" м";

  }

}

//---------------------------------------------------------------------

 

Строка №1 и последующие за ней две строки представляют собой типовую условную функцию языка Си  ifelse. Смысл этой функции можно расшифровать следующим образом: «Если (if) соблюдено условие, заключенное в круглые скобки (Edit‑>Text == “ “), то выполняется команда, записанная в следующей строке. Если это условие не соблюдено, то выполняются все команды, заключенные в фигурные скобки, и расположенные после слова else».

В данном случае эта функция проверяет наличие записи в окне ввода и редактирования величины частоты. Если вы нажали клавишуу Выполнить расчет не введя нужную для расчета величину частоты, то программа выполнит вторую строчку и выдаст на экран предложение «Введите среднюю частоту диапазона».

Если до нажатия на клавишу Выполнить расчет величина частоту уже была введена, то программа начнет выполнять действия, описанные после слова else.  Первой после else находится строка №2. В этой строке записана команда

float ld = 297.0 / StrToFloat(Edit1->Text)

В этой строке назначается переменная величина ld, которая имеет тип float и которая равна частному от деления числа 297 на записанную вами в окне редактирования величину частоты, также приведенную к типу float функцией StrToFloat(Edit1->Text). Переменная ld характеризует размер антенной рамки, называемой «директор».

Строка №3 точно таким же образом назначает переменную величину la, которая характеризует размер элемента антенны «активная рамка».

Строка №4 назначает переменную величину lr, характеризующую элемент под названием «рефлектор».

Строка №5 назначает переменную величину ad, характеризующую расстояние между активной рамкой и директором.

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

Как вы уже заметили, при назначении переменной ей присваивается определенное значение, являющееся  результатом математического действия.

Строки №7 … 11 представляют собой тексты, которые заносятся в компоненты Label4 … Label8. Каждая из этих текстовых строк является сложным образованием и состоит из трех отдельных частей.

Первая часть каждой строки – это текстовая строка, например, «Периметр директора = » (для строки №7). Вторая составная часть – это записанная в виде текста величина вычисленной программой в самом начале функции 3 переменной, например, FloatToStrF(ld,ffGeneral,5,1).  Где FloatToStrF(ld) представляет собой функцию перевода численной величины переменной ld в вид текстовой строки, а добавления записей ffGeneral,5,1 ограничивает записываемое текстом число пятью значащими цифрами.

О преобразовании числа в вид текстовой строки и наоборот, следует почитать в Приложении 4 или каком – то учебнике по Си++.                      

Листинг 2.8. Продолжение 2 файла ant3q.cpp

//---------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)          // 4

{

if(Edit2->Text == "")

         ShowMessage("Введите среднюю частоту диапазона.");

else

  {

 float tr = 306.30 / StrToFloat(Edit2->Text);

 Label11->Caption = "Периметр излучателя =

                       "+FloatToStrF(tr,ffGeneral,5,1)+" м";

  }

}

//-----------------------------------------------------------------------

 

Функция 4 аналогична функции 3, поэтому подробно описывать эту функцию не стоит.

На этом программирование закончено. Для сохранения всех файлов выбираем FileèSave All.

Чтобы выявить возможные ошибки выбираем ProektèMake ant3q1. Если ошибок в текстах исходных кодов программы нет, то выбираем ProektèBuild ant3q1. В результате выполнения этой команды создается исполняемый файл ant3q1.exe, который можно запустить в работу командой RunèRun.

Чтобы избежать одновременного исправления большого числа ошибок советую на промежуточных этапах программирования почаще выполнять компиляцию программы – выбирать Proekt|èMake <name>. 

Некоторые итоги

В процессе работы над этим проектом вы научились:

q      Находить по всплывающей подсказке  нужный компонент;

q      Устанавливать на форму компоненты Label, Edit, Button;

q      Устанавливать на форму картинки;

q      Назначать некоторые нужные свойства компонентов;

q      Выводить на поверхности формы нужные тексты;

q      Программировать некоторые математические операции;

q      Выполнять компиляцию программы.

В процессе работы над проектом вы узнали следующие моменты из основ языка С++:

q      Наличие подключаемых заголовочных файлов и способ их подключения;

q      Объявление класса формы в файле с расширением *.h;

q      Символы для отделения комментариев от текста кодов программы;

q      О работе оператора условий ifelse;

q      Наличие различных типов у чисел и других переменных величин;

q      Перевод  чисел из строковой формы в действительную и наоборот;

q      Ограничение количества выводимых на экран цифр в десятичном числе;

q      Соединение текстовых строк друг с другом;

В заключении советую вам еще раз внимательно почитать соответствующие разделы Приложения 4 или учебника по C/C++. 

 

 

Проект 3

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

Что должно делать это приложение

В результате разработки данного проекта вы получите программу для расчета элементов орбит искусственных спутников Земли (ИСЗ). Вернее, это не собственно программа для расчета, а упрощенный до минимума один из вариантов демонстрационной версии подобной программы. Программа просто представляет собой учебное пособие, в котором задействовано большое число математических вычислений, показано программирование меню и работа с окном для многострочного текста. Если кто – то из читателей захочет познакомиться с действующей программой для расчета элементов орбит ИСЗ, то это можно сделать в Интернете на моей страничке, расположенной  по адресу:  http://r3xb.nm.ru/ .

Общий вид рабочего окна готового приложения ORBITA3 изображен на рис. 2.8.

Рис. 2.8. Рабочее окно программы ORBITA3

Предполагается следующий порядок работа с программой:

q      В главном меню программы выбираем название спутника, порядок движения которого необходимо проследить;

q      Выбираем название станции слежения за спутником, координаты места расположения которой будут задействованы в расчетах;

q      Выбираем время, начиная с которого будет организовано слежение за движением спутника;

q      После выбора всех перечисленных выше параметров и данных нажимаем на клавишу Выполнить расчет. Программа выполняет расчет времени появления спутника в зоне радиовидимости  станции слежения и времени выхода из этой зоны для определенного ранее количества орбит. Если на данном витке спутник не попадает в зону радиовидимости, то программа выдает сообщение «Спутник за горизонтом».

q      Одновременно с выдачей всех расчетных данных на экран, программа сохраняет все эти данные в специальном текстовом файле «text1.txt».

Начинаем создавать проект

Перед началом создания рабочего проекта приложения нужно создать для этого проекта отдельную директорию (папку). Это может быть заранее созданная директория, например, d:\moi_proekty\ORBITA\.

Запускаем C++ Builder, выбираем FileèNewèApplication. На экране появляется готовая к заполнению форма и все прочие окна, необходимые для нового проекта. Появляется и название проекта – Proekt1.

Далее сохраняем  проект в заранее созданную директорию и под назначенным заранее названием проекта. Для этого выбираем FileèSave Proekt As  и сохраняем поочередно все создаваемые файлы проекта в заданной директории (папке). Если вы забыли, как это делается, обратитесь снова к проектам 1 и 2.

 Итак, сохраняем файл проекта под именем “orbit31”,  приступаем к заполнению формы проекта. Когда вы будете разрабатывать собственную программу, не забудьте предварительно на листе бумаги сделать эскиз формы с размещенными на ней компонентами. В процессе разработки программы количество и размещение компонентов могут значительно меняться, но предварительный эскиз нужен обязательно. В данном случае перед вами лежит книга с предложенным автором вариантом расположения компонентов, изображенном на рис. 2.9.

Рис. 2.9. Расположение компонентов на форме

На панели компонентов должна быть установлена страница библиотеки компонентов Standard.

Если теперь заглянуть в директорию d:\moi_proekty\ORBITA\, то здесь вы увидите созданные программой файлы нашего нового проекта.

q      orbit31.bpr  главный файл проекта – текстовый файл, содержащий всю необходимую информацию для компилятора, используемую при трансляции и сборке программных модулей;

q      orbit31.cpp – главный программный файл – текстовый файл, содержащий список всех используемых программных модулей, а также стандартную для всех программ на языке С++ функцию WinMain(), обеспечивающую запуск приложения в работу. Этот файл создается и постоянно контролируется средой C++ Builder автоматически;

q      orbit31.res – файл ресурсов – в нем хранятся некоторые данные, например, выводимые на панель задач;

q      orbit3.cpp – файл программного модуля – в нем будут находиться исходные коды всех функций на языке С++;

q      orbit3.h – заголовочный файл – в нем содержатся интерфейсные части формы, выполняется объявление задействованных компонентов и функций класса формы;

q      orbit3.dfm – файл описания форм – содержатся описания форм и расположенных на них компонентов, запоминаются начальные значения свойств, установленных в инспекторе объектов.      

Пока все эти файлы содержат только самый необходимый для проекта минимум информации. Продолжаем разработку проекта  с заполнения (разработки) формы. 

Заполнение формы

В описаниях процесса создания предыдущих проектов 1 и 2 мною достаточно подробно был объяснен процесс установки на форму компонентов Label, Edit и Button. Поэтому установка этих компонентов должна быть выполнена вами без дополнительных объяснений с моей стороны.

Компонент Memo располагается в библиотеке  Standard.  Выбираем курсором этот компонент и устанавливаем его на форму. В перечне свойств этого компонента нужно найти свойство ScrollBars и установить его как ssVertical. Этим мы придаем текстовому окну Memo1 полосу прокрутки текста по вертикали. Далее выбираем свойство Font и устанавливаем:

q      шрифт – MS Sans Serif;

q      начертание – обычный;

q      размер – 12;

q      набор символов – Кириллический. 

О свойствах компонента Memo довольно много информации можете найти в главе 1.

Остановимся подробнее на процессе установки на форму главного меню.

Компонент Main Menu располагается в библиотеке Standard. Этот компонент является невизуальным и после того, как он будет установлен на форму, примет вид пиктограммы, изображенной на рис. 2.9 под номером 1.

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

Рис. 2.10. Создание первого пункта меню

В свойство Caption записываем название первого пункта меню – Спутник. Щелкаем мышкой на окне формирователя меню и видим, что название  первого пункта встало на свое место, а ниже этого пункта появился затемненный прямоугольник – это  приглашение для ввода наименования первого подпункта. См. рис. 2.11.

Рис. 2.11. Создание первого подпункта

Записываем в свойство Caption название первого спутника – RS – 10. Наблюдаем появление названия первого подпункта на рис. 2.12. Точно таким же образом вводим названия спутников RS-15 и RS-12/13 во второй и третий подпункт первого пункта главного меню.

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

Рис. 2.12. Формирование меню

Выбранный прямоугольник становится затемненным, это говорит о том, что в свойство Caption нужно вводить название второго пункта меню – Станция (см. рис. 2.13).

Рис. 2.13. Начало формирования второго пункта меню

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

Рис. 2.14. Формирование подпункта меню

Для второго подпункта название города можете придумать сами, это не принципиально. На этом формирование второго пункта меню можно закончить и переходите к формированию третьего пункта меню – Время. Этот пункт может иметь только один подпункт с указанием времени – По умолчанию.

 Далее подобным образом следует сформировать оставшийся пункт – Help. Никаких подпунктов подключать к нему не следует. Если вы в процессе формирования меню поняли и освоили все операции, то можно считать, что в дальнейших своих разработках вы сможете создать меню любой сложности. Советую вернуться еще раз к главе 1 и прочитать все, что относится к компоненту Main Menu. Не следует забывать, что в этом проекте создавался самый простой вариант меню.

Для того, чтобы подпункты меню начали работать, следует на каждом подпункте меню сделать двойной щелчок мышкой. После этого действия откроется окно редактора, в которой курсор будет находиться в «теле» соответствующей функции, являющейся ответом на выбор данного подменю. Например, вы выполнили двойной щелчок на пункте подменю RS-10, тогда в тело соответствующей функции нужно ввести запись: name = “RS-10”; . Этим самым при выборе подпункта меню RS-10 переменной величине name будет соответствовать строка RS-10.

Запомните, что при этом текст должен быть заключен в двойные кавычки и записанная строка должна оканчиваться точкой с запятой ‘;’.  Символ ‘;’ должен стоять в конце каждой функции, каждой законченной строки с операторами. Это одно из основных требований языка C/C++. 

Для второго пункта меню (Станция) записи в «тело» функции должны выполняться по форме: cl_st = “Калуга”; , т.е. все подпункты этой части меню должны давать название переменной cl_st (станция слежения).

Таким образом следует поступить со всеми подпунктами, которые входят в состав первого и второго пунктов главного меню.

Теперь форма была полностью заполнена необходимыми компонентами. Нужно переходить к работе с текстовыми файлами.

Работа с текстовыми файлами

По мере того, как вы устанавливали на форму необходимые компоненты, C++Builder заполнял в автоматическом режиме соответствующей информацией об установленных компонентах текстовые файлы. В предыдущих разделах мною были описаны назначения всех файлов проекта. Поэтому останавливаться на этом вопросе не буду. Если у кого то появятся вопросы по этому поводу, то следует еще раз просмотреть раздел Проект 1. Советую также просмотреть файл orbit3.h и познакомиться с тем, как C++Builder сделал в этом файле объявление всех компонентов, размещенных на форме.

Начнем работу с файлом orbit3.cpp. Именно в этом файле располагаются все функции, необходимые для работы программы. Ниже привожу листинги с текстом этого файла. Для удобства объяснения все главные функции будут пронумерованы как //1, а необходимые строки внутри этих функций будут пронумерованы как //№1.

Листинг 2.9.  Файл orbit3.cpp

//-------------------------------------------------------------------

 

#include <vcl.h>                                  //№1

#pragma hdrstop

#include <math.h>

#include <stdio.h>

#include "orbit3.h"

//----------------------------------------------------------------

 

#pragma package(smart_init)

#pragma resource "*.dfm"

#define RD 57.295779                              //№2

#define RM 6371.1

#define TC 0.0000308

#define UD 1.8E+07

 

TForm1 *Form1;                                     //№3

TMemo *Memo1;

TLabel *Label1;

 String name = "RS - 10 ";                         //№4

 String cl_st = "Людиново";                        //№5

 String sFile = "Text1.txt";                       //№6

 char letter;             // объявляется переменная

 int limit = 40;          //число доступных для расчета орбит

 int  md[2][12] = {0,31,60,91,121,152,182,213,244,274,305,335,

                   0,31,59,90,120,151,181,212,243,273,304,334};

int *mas;       //объявляется переменная

double  z02, zb2;                                  //№7

int  dy, mn, yr, ep;

double  hr, mi,  sc;

int  z1, s, z01, zb1, nf, az;

long n0, nd;

double z2, ut, dt;

double in, l0, pn, ps, pd;

double r0, f1, td;

double t1, t2, l1, l2;

int fn_yr,zi;

double  la,gm,ls,ea,dd,xx,yy,z0,g0,fn_rl;

 

          void sp_dat(void);                         //№8

          void ep1200(void);

          void ep1400(void);

          void ep1600(void);

          void mat1800(void);

          void mat1900(void);

          void mat2000(void);

          void mat2200(void);

          void mat2400(void);

          int fnyr(double);

          double fnrl(double);

//-------------------------------------------------------------------

 

В начале листинга, начиная со строки №1, записаны подключаемые файлы. Этот процесс вам уже  известен по предыдущим разделам. В строке №2 и ниже объявляются некоторые константы, нужные для расчетов, начиная со строки №3 объявляются компоненты – Form1, Memo 1 и Label 1. В строках №4 и №5 объявлены переменные – название спутника и станции слежения.  Записанные здесь названия будут использоваться программой «по умолчанию», т.е. в том случае, если пользователь не выбрал другие названия. О переменных величинах и об их объявлении много информации находится в Приложении  4. Изучите её.

В строке №6 вводится текстовая переменная величина, которая является именем файла, в котором будут сохраняться результаты расчета.

Интерес могут представить следующие две строки, находящиеся в листинге:

int  md[2][12] = {0,31,60,91,121,152,182,213,244,274,305,335,

                   0,31,59,90,120,151,181,212,243,273,304,334};

В этих двух строках представлен так называемый «двухмерный массив», который представляет собой две строки, в каждой из которых находятся по двенадцати числовых данных. Числовые данные в первой строке представляют собой числа, которые равны числу дней от начала года до начала месяца, порядковый номер которого равен порядковому номеру места, занимаемого этим числом в строке. Например, от начала года до первого месяца прошло 0 дней (первое число в строке),  от начала года до второго месяца прошёл 31 день (второе число в строке), от начала года до начала 12 месяца прошло 335 дней . При этом первая строка относится к високосному году, вторая – к  обычному.  Посмотрите, пожалуйста, материал по массивам в Приложении 4.

 Начиная со строки №7 происходит объявление большого числа переменных величин, которые будут задействованы в последующих расчетах.

Начиная со строки №8 записаны объявления функций, которые созданы разработчиком программы и предназначены для выполнения математических расчетов. Описание всех этих функций (каждой в отдельности) будет дано ниже. В Приложении 4 имеется целый раздел, посвященный  функциям. Вам обязательно нужно его изучить. По требованию С/C++ каждая функция должна быть предварительно объявлена. Таким образом компилятор, составляющий основу C++Builder, начиная работу с этим файлом встречает на своем пути сначала объявление функции, тут же резервирует для нее определенное количество памяти и устанавливает указатель на этот участок памяти. Впоследствии по этим указателям и участкам памяти, в которых хранится информация о функции, программа легко определяет пути поиска нужной функции. Точно такое же выделение памяти происходит и при первой встрече компилятора с объявлением переменных. 

В следующем листинге 2.10 первой стоит уже знакомая нам по прежним проектам функция __fastcall TForm1::TForm1(TComponent* Owner), которая служит для описания внешнего вида формы. Это функция 1. В первой строчке этой функции задается название программы, которое будет размещено на главном рабочем окне программы после её запуска. Следующие две строки является командами для выполнения функции  sp_dat() и функции  ep1200(). Таким вот простым образом и подается команда на выполнение функции – просто записывается название функции, заканчивающееся точкой с запятой. Иногда (в случае необходимости) в круглых скобках записываются необходимые аргументы. В нашем случае обе эти функции запускаются в работу без каких то специальных аргументов. Первая из этих функций считывает в память некоторые данные, размещенные ниже в этом файле, а вторая выполняет перевод календарного времени в эпохальное. Вам не следует задумываться над такими специфическими терминами, как «эпохальный», «календарный» и т.п., а следует больше обращать внимания на ход работы над файлом.

 

Листинг 2.10. Продолжение 1 файла orbit3.cpp

//--------------------------------------------------------------------

__fastcall Tform1::Tform1(Tcomponrnt* Owner)       //1

                  :Tform(Owner)

{

 Caption = "Расчет орбит ИСЗ";

       sp_dat();

     ep1200();

          z01 = z1;

          z02 = z2;

Label1->Caption = "";

Label2->Caption = "  Орбита       Время узла             Узел               Вход              Выход             Азим. ";

Label3->Caption = "                     чч мм сс                  град.               чч мм              чч мм             град.";

 

Memo1->Lines->Text = "";

}

//--------------------------------------------------------------------

Далее в этом листинге записано в двух строках условие равенства двух переменных, а затем описываются тексты, содержащиеся в в метках Label1, Label2 и Label3. При этом первая из меток никакого текста не содержит (пока).

Последняя строка очищает текстовое окно Memo1, подготавливая его для записи результатов последующих  расчетов.

В следующем листинге 2.11 размещаются функции, составленные разработчиком. Все они перед этим были объявлены в начале файла orbit3.cpp. Если в предыдущих проектах вы имели дело только с функциями, созданными C++Builder в автоматическом режиме, то в этом проекте имеются также функции, добавленные разработчиком.

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

Листинг 2.11. Продолжение 2 файла orbit3.cpp

//--------------------------------------------------------------------

// Функция для перевода календарного времени в эпохальное

void ep1200(void)

      {

      z1 = yr;

      fnyr(z1);

      z2 = md[fn_yr][mn-1] + dy + ((sc/60 + mi)/60 + hr)/24;

      return;

      }

// -----------------------------------------------------

// Функция для перевода времени Z во время EP

void ep1400(void)

      {

  int i,yy,yz;

       if(ep > z1) s = 1;

       if(ep < z1) s = -1;

       if(ep == z1) s = 0;

       if(s == 0) return;

      yz = (z1 +(s-1)/2);

      yy = (ep - (s + 1)/2);

   if(yz < yy) goto wyh1;

   for (i = yz; i >= yy; i-- )

      {

    fnyr(i);

        z2 =z2 - (366 - fn_yr)*s;

      }

      z1 = ep;

      return;

 wyh1:

     for(i = yz; i <= yy; i++)

     {

     fnyr(i);

     z2 = z2 - (366 - fn_yr)*s;

     }

     z1 = ep;

     return;

     }

// -------------------------------------------------------

// Функция для перевода времени Z в календарное время

void ep1600(void)

      {

  whod:

   int im;

   double nn;

     fnyr(z1);

     nn = ((z2 - 1)/(366 - fn_yr));

      ep = z1 + floor(nn);

      ep1400();

      yr = z1;

      fnyr(yr);

      for (im = 1; im <= 12; im++)

      {

      if(z2 >= md[fn_yr][im-1] + 1) mn = im;

      }

      dy = floor(z2 - md[fn_yr][mn-1]);

      if(dy > 31 || dy < 0) dy = 31;

      z2 = z2 - floor(z2);

      hr = floor(z2 * 24);

      z2 = z2 * 24 - hr;

      mi = floor(z2 * 60);

      z2 = z2 * 60 - mi;

      sc = floor(z2 * 60);

      return;

      }

// -------------------------------------------------------

// Функция для вычисления ARCSIN(X)

void mat1800(void)

      {

      if(xx == 1) {yy = 90; return;};

      if(xx == -1) {yy = - 90; return;};

      yy = RD * atan(xx/sqrt(fabs(1-xx * xx)));

    return;

      }

// -----------------------------------------------------

// Функция для вычисления ARCCOS(X)

void  mat1900(void)

      {

      if(xx == 0) {yy = 90; return;};

      yy = RD * atan(sqrt(fabs(1 - xx * xx))/xx);

      if(xx < 0) yy = yy +180;

      return;

      }

// ----------------------------------------------------

// Функция для вычисления ARCCTG(X)

void mat2000(void)

      {

      if(xx == 0) {yy = 90; return;};

      yy = RD * atan(1/xx);

      if (xx < 0) yy = yy +180;

      return;

      }

// ---------------------------------------------------

// Функция для вычисления T2, L2 и GM

void  mat2200(void)

      {

static int ss;

      xx = sin(ea/RD) * sin(in/RD);

      mat1800();

      t2 = yy;

      if(in > 90) { ss =1; goto wyh4;};

      ss = -1;

 wyh4:

      fnrl(ea);

      if(fn_rl > 180) ss = ss * (-1);

      if(t2 == 90 || t2 == -90) { l2 = 0;  goto wyh5;};

      xx = cos(ea/RD)/cos(t2/RD);

      mat1900();

      l2 = fnrl(la + ss * yy);

      l2 = fn_rl;

 wyh5:

      xx = cos(t1/RD) * cos(t2/RD) * cos((l1 - l2)/RD);

      xx = xx + sin(t1/RD) * sin(t2/RD);

      mat1900();

      gm = yy;

      return;

      }

// -----------------------------------------------------

// Функция для вычисления азимута (AZ)

void mat2400(void)

      {

      l2 = ls;

      if(l2 < l1/2) t2 = l2/1.8;

      if(l2 > l1/2 && l2 < l1) t2 = 90 - (l2 -l1/2)/2.1;

      if(l2 > l1 && l2 < 360) t2 = (l2-l1)/2;

      if(l1 != l2)   goto wyh6;

      if(t2 < t1) {az = 180;return;};

      az = 0; return;

 wyh6:

      if(fnrl(l1 - l2) != 180) goto wyh7;

      if(t2 < -t1) {az = 180; return;};

      az = 0; return;

 wyh7:

      if(t2 == 90) {az = 0; return;};

      if(t2 == -90) {az = 180;return;};

      xx = cos(t1/RD) * tan(t2/RD) - sin(t1/RD) * cos((l1 - l2)/RD);

      xx = xx/sin((l1 - l2)/RD);

      mat2000();

      az = floor(yy);

      if(l2 < l1/2 && az < 2) az = az + 180;

      if(l2 < l1/2)  az = az + 180;

      if(l2 > l1)    az = az + 180;

      if(az > 360)   az = az - 360;

      return;

      }

// -------------------------------------------------------

// Функция для определения високосного года

int fnyr(double x)

          {

    double result;

          result = fmod(x,4.0);

          if(result == 0) goto wyh1;

          fn_yr = 1;

          return(fn_yr);

 wyh1: fn_yr = 0; return(fn_yr);

          }

// ------------------------------------------------------

// Функция расчета дней при переходе от одного года к другому

double fnrl(double l)

          {

      double x;

//    if(l > 360) x = l -360;

//    x = l;

          x = (l - 360 * floor(l/360));

/* printf("^^^^^  fn_rl =  %d",x);              */

      fn_rl = x;

          return(fn_rl);

          }

// ------------------------------------------------------

// Функция, в которой содержатся данные для спутника

void sp_dat(void)

        {

   String name = "RS - 10 ";

    n0 = 38700;

    dy = 27;

    mn = 9;

    yr = 95;

    hr = 0;

    mi = 46;

    sc = 13;

    in = 83.0;

    l0 = 330.0;

    pn = 362.0498;

    ps = 104.98413;

    pd = -0.0000001;

    r0 = 1008.4;

    nf = 120;

        return;

        }

// ------------------------------------------------------

 

В следующем листинге 2.12 начинается самое интересное. Здесь описывается функция  // 2, в которой совершаются все операции, которые должны выполняться после нажатия на клавишу Выполнить расчет.  Основная рамка функции создается автоматически при двойном щелчке по клавише Выполнить расчет, а всю «начинку внутренностей» этой функции должен создавать и записывать сам разработчик программы.

В строке №1 объявляется переменная величина i, которая будет задействована в дальнейших расчетах. В следующей строке записывается текст в метку Label1. Это уже хорошо знакомая операция.

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

Листинг 2.12.  Продолжение 3 файла orbit3.cpp

//-------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)          // 2

{

int i;                                                        //№1

Label1->Caption = "Проход спутником "+name+

                 " зоны видимости станции "+cl_st;

    ep1200();          // выполняется функция перевода времени

    z01 = z1; z02 = z2;                                       //№2

     ps = ps/1440;

     pd = pd/1440;

     r0 = (r0 + RM)/RM;

     t1 = 53.85; l1 = 325.35;

     l1 = fnrl(l1);  l1 = fn_rl;

     dy = 1; mn = 3; yr = 99;

     hr = 00; mi = 00; sc = 00;

     ep1200();

     ep = z01;

     ep1400();

     zb1 = z1; zb2 = z2;

     nd = floor((zb2 - z02)/ps);

     dt = (ps + pd * nd)/nf;

     ut = (dt - TC) * UD;

static int cz;

int stop = 0;

 whod30:    dd = 0;                                           

//--------------------------------------------------------------------

 

Для удобства описания разобьем оставшуюся часть функции 2 еще на две части, первая из которых начинается со строки №3. В начале этой строки находится слово  whod40:, которое оканчивается символом ‘:’ – двоеточие. Такое сочетание слова с символом ‘:’ называется меткой  обычно представляет собой начало какого то куска программы, к которому иногда бывает нужно обратиться программным путем. Для перехода к метке в языке Си имеется специальная команда goto. Например, чтобы дальнейшая работа программы  продолжалась с метки  whod40: нужно в тексте исходных кодов написать команду  goto whod40;. Далее в листинге вам будут иногда встречаться такие команды.

В строке №3 нам встречается уже известный условный оператор if. В данном случае строку №3 можно перевести «на человеческий язык» следующим образом: «Если переменная величина letter равна символу ‘x’, то выполняется команда return, а это значит, что функция прекращает свою работу».

В этой строке вы встретились сразу с двумя понятиями из языка Си. Запомните их и почитайте по этому вопросу соответствующие материалы в Приложении 4.

Далее, в последующих строках, указанные выше операторы будут встречаться неоднократно.

Cо строки №4 начинается заполнение текстом компонента Memo. Вначале записывается пустая строка командой  Memo1->Lines->Add(" "); , затем, в следующей строке записывается дата, включающая в себя день, месяц и год. Обратите внимание на пустое пространство между первой кавычкой и словом «Дата в следующем предложении. Подобные «пустоты» нужны для того, чтобы слово «Дата расположилось в тексте посередине строки.

Листинг 2.13. Продолжение 4 файла orbit3.cpp

//--------------------------------------------------------------------

  

 whod40:  if(letter == 'x')  return;                           //№3

           stop++;

           if(stop == limit) letter = 'x';

           td =ps * nd + pd * nd * (nd -1)/2;

           z1 = z01;

           z2 = z02 + td;

      ep1600();

           if(dd == dy)  goto whod160;

           dd = dy;

Memo1->Lines->Add(" ");             // Задаем пустую строку     //№4

Memo1->Lines->Add("                  Дата:   "+IntToStr(dy)+" - "+IntToStr(mn)+" - "+IntToStr(yr) );

 whod160:   ls = fnrl(pn * td +l0);  ls = fn_rl;

    if(ls < 0) ls = 360 + ls;

String s1 = (IntToStr(n0+nd)+"         "+FloatToStr(hr)+":"+

        FloatToStr(mi)+":"+FloatToStr(sc)+"            "+FloatToStrF(ls,ffGeneral,3,1) );                              // №5

     ls = fnrl(pn * td + l0);  ls = fn_rl;

     zi = -1; z0 = nf -1; cz = 0; xx = 1/r0;

     mat1900();

     g0 = yy;

     mat2400();

     for(i = 0; i <= (nf-1); i++)

           {

           la = ls + pn * dt * i;

           ea = 360 * i/nf;

           mat2200();

           if(gm > g0) goto wyh250;

           if(cz == 0) { cz = 1;  zi = i;};

            goto wyh260;

 wyh250:   if(cz == 1) { cz = 0; z0 = i - 1;}

//-----------------------------------------------------------------------

 

В строке №5 формируется s1cтрока типа String,  в которой подготавливаются для записи в Memo1 основные расчетные данные. 

Листинг 2.14. Продолжение 5 файла orbit3.cpp

//-----------------------------------------------------------------------

 wyh260:

             }

          if(zi == -1)

           {

 Memo1->Lines->Add(IntToStr(n0+nd)+"                  Орбита за горизонтом ");

           nd = nd + 1;

         goto whod40;

         }

          z1 = z01;

           z2 = z02 + td + dt * zi;

           ep1600();

String s2 = "               "+(FloatToStr(hr)+":"+FloatToStr(mi));  // №6

           z1 = z01;

           z2 = z02 + td +dt * z0;

           ep1600();

String s3 = "           "+(FloatToStr(hr)+":"+FloatToStr(mi)+

                     "               "+IntToStr(az));              // №7

Memo1->Lines->Add(s1+s2+s3);                                       // №8

           nd = nd + 1;

           goto whod40;                                            // №9

 wyh360:

  return;

 }

//--------------------------------------------------------------------

 

В строках №6 и №7  формируются строки s2 и s3, которые после  этого в строке №8 складываются друг с другом и добавляются в Memo1. В строке №9 находится команда goto whod40;, которая возвращает действия функции 2 к строке №3, т.е. в начало функции 2. Создается замкнутый цикл, в котором как только функция 2 в своих действиях доходит до строки №9, она тут же возвращается к строке №3 и т.д.. Этот замкнутый цикл мог бы продолжаться до бесконечности, если бы  в строке №3 не было бы условия if(letter == 'x')  return; , т.е. если переменная величина letter равна символу ‘x’, то работа функции прекращается и бесконечный цикл прерывается.   Откуда же берется этот магический символ ‘x’?  Все очень просто. В самом начале программы, в листинге 2.9 чуть ниже строки №6 объявляется переменная int limit = 40; , далее в комментариях написано, что это число  доступных для расчета орбит.  Далее, в конце листинга 2.12 находится строка, в которой объявляется переменная int stop = 0; ,  которая  в начале листинга 2.13 увеличивается на одну единицу при начале каждого нового цикла. Получается так, что эта переменная величина является счетчиком циклов.   Как только число циклов станет равным цифре 40, переменная letter принимает значение ‘x’ и  бесконечный цикл прерывается. Конечно, можно было бы в условии прекращения цикла записать if(stop == 40); ,   но автор предпочел вариант с переменной letter.  

Итак, функция 2 закончила выполнение расчета и записала результаты этого расчета в окно многострочного редактора текста Memo1. Полоса прокрутки текста по горизонтали позволяет многократно просматривать текст от начала до конца и наоборот. Но обычно результаты расчета должны быть сохранены в текстовом файле, чтобы затем из можно было распечатать на принтере или хранить на дискете.

Выполняется процедура сохранения в файле текста, записанного в окне Memo1 очень просто. Достаточно написать команду: 

   Memo1->Lines->SaveToFile(sFile);, где sFile – строковая переменная, обозначающая имя файла, в котором должны будут сохранены результаты расчетов.

В данной программе эта команда записана в функцию 3, которая является результатом реакции на нажатие клавиши Выход и располагается в начале листинга 2.15. 

                                                                   

Листинг 2.15. Продолжение 6 файла orbit3.cpp

//--------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)      // 3

{

   Memo1->Lines->SaveToFile(sFile);

Close();

}

//--------------------------------------------------------------

void __fastcall TForm1::N2Click(TObject *Sender)       // 4

{

name = "RS - 10";

 

}

//------------------------------------------------------------------

void __fastcall TForm1::RS151Click(TObject *Sender)        // 5

{

name = "RS-15";

}

//---------------------------------------------------------------------

void __fastcall TForm1::RS12131Click(TObject *Sender)       // 6

{

 name = "RS-12/13";

}

//---------------------------------------------------------------------

void __fastcall TForm1::N7Click(TObject *Sender)            // 7

{

 cl_st = "Калуга";

}

//--------------------------------------------------------------------

void __fastcall TForm1::N4Click(TObject *Sender)       // 8

{

cl_st = "Людиново";

}

//--------------------------------------------------------------------

 

Далее в этом листинге располагаются функции 4 … 8, которые  являются откликами на выбор различных пунктов меню.

С созданием этого файла процесс программирования можно считать законченным. Теперь следует выбрать в главном меню C++Builder команду Filesè Save All. Все файлы проекта будут сохранены и подготовлены к отладке программы.

Далее выбираем в меню команду ProektèMake orbit31. В результате могут быть выявлены какие – то ошибки, которые следует исправлять и снова повторять ту же команду. Обычно я еще в процессе написания программных файлов частенько повторяю команду ProektèMake, чтобы почаще проверять подготавливаемый материал на наличие ошибок.

Если все ошибки исправлены, выполняем команду ProektèBuild orbit31. Таким путем создается исполняемый файл программы, который затем можно будет запускать в работу командой RunèRun.

Некоторые итоги

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

В процессе работы над этим проектом вы научились:

q      Создавать главное меню программы;

q      Работать с очень важным компонентом – окном для редактирования многострочных текстов;

q      Познакомились с процессом создания одного из видов бесконечного цикла и методом выхода из этого цикла;

q      Узнали о возможности создания пользователем своих собственных функций, о том, как нужно объявлять эти функции и где их располагать;

q       Сохранять в файле тексты, находящиеся в окне многострочного текстового редактора;

По ходу создания проекта приходилось встречаться с некоторыми новыми понятиями из основ языка С/С++. Советую еще раз освежить эти понятия по материалам, находящимся в главе 1 и Приложении 4.

 

Проект 4

При выполнении этого проекта вы познакомитесь с созданием полностью законченного не сложного автономного Windows приложения, которое можно будет запускать в работу на любом IBM PC компьютере.

Что должно делать это приложение

С детских лет мне нравилось заниматься изготовлением различных радиоприемников. Сначала (в первые послевоенные годы) это были детекторные приемники, потом делал приемники ламповые, транзисторные. Какое то время увлекался магнитофонами и сделал катушечный магнитофон своей конструкции, потом  из деталей самого древнего телевизора под названием «КВН» сделал современный (по тем временам) телевизор с широким экраном. Потом увлекся коротковолновой радиосвязью, этим занимаюсь и сейчас. Когда в 1986 году в журнале «Радио» появилось описание компьютера   «Радио-86РК», то главной моей целью стало изготовление такого аппарата. Через полтора года эта цель была достигнута и появилось новое увлечение – создание компьютерных программ. Начал осваивать язык программирования Ассемблер для «Радио-86РК». Вскоре были созданы программы для приема и передачи сигналов радиотелеграфа и радиотелетайпа посредством компьютера, связанного с любительской радиостанцией. Это было примерно в 1989 году, поэтому именно этот год я считаю началом своего занятия программированием.

Из этого небольшого «лирического отступления» вы должны понять, почему все предлагаемые мною в этой книге проекты связаны с радио. Так уж получилось, что все, что я делаю в любительском творчестве, тем или иным образом связано с радио. Вам, дорогой читатель, должно быть не так уж и важно, к какой теме относятся описанные в книге проекты, ваша главная цель – научиться создавать компьютерные программы, не так ли?

Предлагаемая в этом разделе программа, проект которой предстоит создать, также относится к миру радио. Практически в каждом радиотехническом устройстве имеется масса различных колебательных контуров, настроенных на различные радиочастоты. Поэтому радиолюбителю – человеку, который занимается изготовлением радиоконструкций, очень часто нужно знать параметры колебательных контуров, предназначенных для работе на той или иной частоте. Для определения таких параметров как раз и служит программа Induktiw, создание которой будет рассмотрено в этом проекте.  Познакомиться с работающим вариантом этой программы (более усложненным) и скачать его для собственных целей можно с моих сайтов в Интернете, которые располагается по адресу:  http://r3xb.nm.ru/ .

Как это выглядит в работе

На рис. 2.15 изображено главное рабочее окно программы Induktiw после ввода всех данных и нажатия на клавишу Выполнить расчет.

Рис. 2.15. Первое рабочее окно программы

На рисунке видно, что главное окно включает в себя шесть переключаемых рабочих окон, предназначенных для выполнения различных расчетов.

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

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

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

Рис. 2.16. Расчет числа витков цилиндрической катушки

Если у вас получается катушка с очень большим числом витков, то иногда такую катушку можно изготовить на цилиндрическом каркасе, между двумя щечками. Такой вариант катушки можно рассчитать в следующем рабочем окне, изображенном на рис. 2.17.

Рис. 2.17. Расчет катушки на цилиндрическом каркасе с щёчками

Иногда бывает удобно катушку индуктивности для выбранного колебательного контура выполнить на кольцевом каркасе, или каркасе в виде тора. Вариант расчета такой катушки представлен на рис. 2.18, где изображено следующее рабочее окно программы.

Рис. 2.18. Расчет катушки на кольцевом каркасе по заданной индуктивности

На рис. 2.19 изображено следующее рабочее окно программы. Исходные данные этого окна не связаны с предыдущими окнами. Здесь можно по имеющемуся количеству витков и по размерам тороидального каркаса определить индуктивность катушки.

Рис. 2.19. Расчет индуктивности тороидальной катушки

Следующее рабочее окно программы, изображенное на рис. 2.20, служит для расчета емкостей группы конденсаторов. Необходимость таких расчетов возникает очень часто для точной перестройки колебательного контура в пределах заданного диапазона частот. Вручную такие расчеты занимают массу времени.

Рис. 2.20. Расчет емкости группы конденсаторов

На рис. 2.21 показано рабочее окно программы с выведенным дополнительно информационным окном About. Изображение богини Афины является как бы символом продукции фирмы Borland, мне тоже нравится эта картинка.

Рис. 2.21. Рабочее окно программы с информацией About

Цели и задачи этого проекта

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

Создаем проект

Перед началом создания рабочего проекта приложения создаем для этого проекта отдельную директорию (папку), например, d:\moi_proekty\INDUKTIW\.

Запускаем C++ Builder, выбираем FileèNewèApplication. На экране появляется готовая к заполнению форма и все прочие окна, необходимые для нового проекта. Cохраняем автоматически созданный C++Builder проект в заранее созданную директорию  под названием INDUKTIW. Для этого выбираем FileèSave Proekt As. Если вы забыли о том, как нужно сохранять сгенерированный проект, то посмотрите в описании предыдущих проектов.

 Еще раз предупреждаю, что имена сохраняемого первым функционального файла и файла проекта должны различаться. Мною в таких случаях используется следующий прием: для имени проекта я беру имя функционального файла, но добавляю к этому имени цифру, обозначающую вариант программы. Вы можете выбирать любые удобные для вас имена.

 Проект сохранен в определенной директории, приступаем к заполнению формы проекта. Перед вами лежит эта книга, открытая на странице с рис. 2.22.

Рис. 2.22. Пример заполнения формы на странице 0

 Первым на форму устанавливаем компонент TabbedNotebook, который располагается в библиотеке компонентов Win 3.1 и представляет собой многооконную конструкцию. Растягиваем новое окно до необходимых размеров. Подобные компоненты имеются и в других страницах библиотек компонентов, но я решил выбрать более раннюю конструкцию, т.к. новые могут быть не во всех версиях C++Builder.

Обратите внимание на окно Object Inspector.  В этом окне выделено свойство Pageindex и чуть ниже находится свойство Pages. В Pageindex должен быть записан 0, что соответствует первой странице. Последующие страницы будут иметь в этом свойстве следующие цифры 1, 2 и т.д..  

Первым делом нужно установить названия и количество задействованных в этом компоненте страниц. Для этого как раз и предназначено свойство  Pages. Выбираем курсором это свойство и щелкаем на расположенном в этом свойстве квадратике. Появляется диалоговое окно Notebook Editor, изображенное на рис. 2.23.

Рис. 2.23. Окно для оформления заголовков

В этом окне выбираем команду Add и записываем название первого окна, которое будет изображено на закладке. Затем точно таким же образом вводим названия всех следующих окон. На этом организацию работы нескольких окон будем считать законченной. Переходим к оформлению каждого окно в отдельности.

Чтобы на экране находилась форма с первым окном, в свойстве  Pageindex должен находиться 0. Теперь нужно установить на первое окно формы все необходимые компоненты, показанные на рис. 2.22. Все эти процедуры вы уже неоднократно делали в предыдущих проектах, поэтому предоставляю возможность действовать самостоятельно. После заполнения первого окна, переходим к заполнению окна второго.

Чтобы на форме появилось второе окно, в свойство Pageindex нужно ввести цифру 1 и щелкнуть на форме в пределах первого окна. Таким образом на форме откроется второе окно (см. рис. 2.4), которое также, как и предыдущее, следует заполнить компонентами и рисунком.

Рис. 2.24. Второе окно на форме

Чтобы на форме появилось третье окно (см. рис. 2.25), в свойство Pageindex нужно ввести цифру 2 и повторить все операции из предыдущего пункта.

Рис. 2.25. Третье окно на форме

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

На рис. 2.26, рис. 2.27 и рис. 2.28 изображены находящиеся на форме последующие окна.

Рис. 2.26. Четвертое окно на форме

 

Рис. 2.27. Пятое окно на форме

 

Рис. 2.28. Шестое окно на форме.

Файлы с рисунками для размещения на различных окнах, постарайтесь сделать сами или возьмите их на моей страничке в Интернете.

Не забудьте ввести компоненты Button для кнопок Выход и About, хотя работу по оформлению информационного окна About оставим «на потом» .

Работа с текстовыми файлами

Работу с текстовыми файлами начнем с рассмотрения файла induktiw.h. Этот файл интересен тем, что в нем производится объявление компонентов и функций по мере их установления на форму, что позволяет проследить порядок установки этих компонентов, очередность установки.

Листинг 2.16 начинается, как обычно, с подключения заголовочных файлов, имеющих расширения .hpp. Обратите внимание на то, как много появилось новых подключаемых файлов, которые не встречались в предыдущих проектах.

Затем в файле происходит объявление класса  class TForm1 : public TForm{} в «теле которого» выполняется поочередное объявление всех компонентов, устанавливаемых на форму.

Начиная с предложения void __fastcall Edit2Change(TObject *Sender);, в котором объявляется функция, реагирующая на изменение записи в компоненте Edit2, следуют объявления всех остальных функций, задействованных в проекте.

Строчки, начинающиеся со слов private: и public: ,  предназначены для заполнения разработчиком.  Но нашего проекта это не касается.

Листинг 2.16. Файл induktiw.h  

//-------------------------------------------------------------------

#ifndef induktiwH

#define induktiwH

//-------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <ComCtrls.hpp>

#include <TabNotBk.hpp>

#include <ExtCtrls.hpp>

#include <Graphics.hpp>

//---------------------------------------------------------------------

class TForm1 : public TForm

{

__published:    // IDE-managed Components

        TTabbedNotebook *TabbedNotebook1;

        TLabel *Label1;

        TLabel *Label2;

        TEdit *Edit1;

        TLabel *Label3;

        TEdit *Edit2;

        TLabel *Label4;

        TButton *Button1;

        TButton *Button2;

        TLabel *Label5;

        TLabel *Label6;

        TLabel *Label7;

        TButton *Button3;

        TButton *Button4;

        TLabel *Label8;

        TLabel *Label9;

        TLabel *Label10;

        TLabel *Label11;

        TEdit *Edit3;

        TButton *Button5;

        TLabel *Label12;

        TEdit *Edit4;

        TLabel *Label13;

        TButton *Button6;

        TLabel *Label14;

        TEdit *Edit5;

        TLabel *Label15;

        TLabel *Label16;

        TLabel *Label17;

        TLabel *Label18;

        TLabel *Label19;

        TEdit *Edit6;

        TEdit *Edit7;

        TEdit *Edit8;

        TLabel *Label20;

        TButton *Button7;

        TLabel *Label21;

        TLabel *Label22;

        TLabel *Label23;

        TEdit *Edit9;

        TLabel *Label24;

        TLabel *Label25;

        TLabel *Label26;

        TLabel *Label27;

        TLabel *Label28;

        TLabel *Label29;

        TLabel *Label30;

        TLabel *Label31;

        TEdit *Edit10;

        TEdit *Edit11;

        TEdit *Edit12;

        TEdit *Edit13;

        TEdit *Edit14;

        TButton *Button8;

        TLabel *Label32;

        TLabel *Label33;

        TLabel *Label34;

        TLabel *Label35;

        TLabel *Label36;

        TLabel *Label37;

        TLabel *Label38;

        TLabel *Label39;

        TLabel *Label40;

        TLabel *Label41;

        TEdit *Edit15;

        TEdit *Edit16;

        TEdit *Edit17;

        TEdit *Edit18;

        TEdit *Edit19;

        TButton *Button9;

        TImage *Image1;

        TImage *Image2;

        TImage *Image3;

        TImage *Image4;

        TImage *Image5;

        TImage *Image6;

        TButton *Button10;

        TLabel *Label42;

        TLabel *Label43;

        TLabel *Label44;

        TLabel *Label45;

        TLabel *Label46;

        TLabel *Label47;

        TLabel *Label48;

        TLabel *Label49;

        TEdit *Edit20;

        TEdit *Edit21;

        TEdit *Edit22;

        TEdit *Edit23;

        TButton *Button11;

        TLabel *Label50;

        TEdit *Edit24;

        void __fastcall Edit2Change(TObject *Sender);

        void __fastcall Button2Click(TObject *Sender);

        void __fastcall Button1Click(TObject *Sender);

        void __fastcall Button3Click(TObject *Sender);

        void __fastcall Button4Click(TObject *Sender);

        void __fastcall Button5Click(TObject *Sender);

        void __fastcall Edit4Change(TObject *Sender);

        void __fastcall Button6Click(TObject *Sender);

        void __fastcall Edit5Change(TObject *Sender);

        void __fastcall Button7Click(TObject *Sender);

        void __fastcall Button8Click(TObject *Sender);

        void __fastcall Button9Click(TObject *Sender);

        void __fastcall Button10Click(TObject *Sender);

        void __fastcall Button11Click(TObject *Sender);

private:  // предназначено для заполнения разработчиком

public:         // предназначено для заполнения разработчиком

        __fastcall TForm1(TComponent* Owner);

};

//-----------------------------------------------------------------

extern PACKAGE TForm1 *Form1;

//-----------------------------------------------------------------

#endif

//-----------------------------------------------------------------

 

Теперь переходим к рассмотрению основного файла проекта – файла induktiw.cpp. Необычным в начале этого файла является то, что переменная L1 типа float объявляется в самом начале файла, сразу вслед за объявлением Form1. Такое объявление называется «глобальным», т.е. переменная L1 может быть задействована в любой из функций класса TForm1, объявленного в файле induktiw.h. Сделано такое объявление мною для того, чтобы с L1 можно было работать в различных окнах.

Как вы уже поняли, переменная величина может быть объявлена либо в теле какой – то функции, тогда она может применяться только в этой функции, либо в самом начале файла, тогда она может применяться со всеми функциями этого класса. Прочитайте, пожалуйста, об объявлении переменных и о их «видимости» в Приложении 4 или в каком – то учебнике по С++.

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

Листинг 2.17. Файл induktiw.cpp

//--------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include <math.h>

#include "induktiw.h"

#include "about.h"

//---------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

 

float L1;

//---------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)        // 1

        : TForm(Owner)

{

 Caption = "Расчеты контурных катушек";

 Label4->Caption = "";

 Label5->Caption = "Для справки нажимать клавишу <F1>";

 Label6->Caption = "";

 Label7->Caption = "";

 Label8->Caption = "";

 Label9->Caption = "";

 Label13->Caption = "";

 Label15->Caption = "";

 Label16->Caption = "";

 Label22->Caption = "";

 Label23->Caption = "";

 Label32->Caption = "";

 Label33->Caption = "";

 Label40->Caption = "";

 Label41->Caption = "";

 Label47->Caption = "";

 Label48->Caption = "";

 Label49->Caption = "";

 Label50->Caption = "";

 HelpContext = 1;

}

//--------------------------------------------------------------

void __fastcall TForm1::Edit2Change(TObject *Sender)     // 2

{

 Label4->Caption = "Нажмите клавишуыполнить расчет>";

}

//--------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)     // 3

{

 Close();

}

//--------------------------------------------------------------

 

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

Функция 2 вызывается при изменении записи в окне Edit2. В теле этой функции имеется всего одна строка – текст метки Label4.

Функция 3 является реакцией на нажатие клавиши Выход и имеет одну только запись, вызывающую окончание работы программы.

Листинг 2.18 начинается с функции 4, которая служит реакцией на нажатие клавиши Выполнить расчет, расположенной на первом рабочем окне программы.

Пронумеруем наиболее важные строки этой функции.

Запомните написание строки №1. В этой строке задается команда для вывода на экран информационного окна, в котором будет содержаться запись о необходимости ввода в окно редактирования необходимой величины.

В строке №2 вычисляется значение переменной величины LC, в строке №3 вычисляется переменная L. В последующих строках вводятся соответствующие тексты в метки Label.

Листинг 2.18. Продолжение 1 файла induktiw.cpp

//--------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)      // 4

{

 if(Edit1->Text == "")       

     ShowMessage("Введите недостающую величину - частоту");  //№ 1

 else

  {

    if(Edit24->Text == "")

      {

 

      float LC = pow((159 / StrToFloat(Edit1->Text)),2);     // № 2

       float L = LC / StrToFloat(Edit2->Text);               // № 3

       Label5 -> Caption = "Результаты расчета";

       Label6 -> Caption = "Величина индуктивности = "+

                FloatToStrF(L,ffGeneral,5,2)+"  мкГн";

       Label7 -> Caption = "Результаты расчета устраивают? (Дает)";

       Label9 ->Caption = "Вспомогательная величина LC ="+

                FloatToStrF(LC,ffGeneral,5,2);

       L1 = L;

       Edit24->Text = FloatToStr(L);

       }

       else

       {

       Label50->Caption = "Индуктивность катушки, мкГн";

       float LC = pow((159 / StrToFloat(Edit1->Text)),2);

       float C = LC / L1;

       float L = LC / C;

       Edit24->Text = FloatToStr(L);

       Label5 -> Caption = "Результаты расчета";

       Label6 -> Caption = "Величина емкости конденсатора = "+

                FloatToStrF(C,ffGeneral,5,2)+"  пф";

 

       Label9 ->Caption = "Вспомогательная величина LC ="+

                FloatToStrF(LC,ffGeneral,5,2);

        }

   }

}

//-------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)      // 5

{

 Label8 -> Caption = "Расчет выполнен";

 Edit3->Text = L1;

 Edit6->Text = L1;

 Edit10->Text = L1;

 }

//-------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)      // 6

{

 Label4->Caption = "";

 Label5->Caption = "";

 Label6->Caption = "";

 Label7->Caption = "";

 Label8->Caption = "";

 Label7->Caption = "Введите новую величину емкости ";

 Label9->Caption = "";

}

//--------------------------------------------------------------

void __fastcall TForm1::Button5Click(TObject *Sender)       // 7

{

 Close();

}

//--------------------------------------------------------------

 

Функция 5 срабатывает тогда, когда вы будете согласны результатами расчета и нажмете клавишу Да. Если результаты расчета вас не устраивают и вы нажали клавишу Нет, то срабатывает функция 6, которая убирает тексты многих меток и предлагает ввести новую величину емкости.

Функция 7 срабатывает при нажатии на клавишу Выход, которая находится на главной форме. Аналогично функция 3 срабатывает при нажатии клавиши Выход, которая находится на первом рабочем окне. Разумеется, такое дублирование является совершенно не обязательным. Это просто прихоть разработчика …

Листинг 2.19 начинается функцией 8, которая относится уже ко второму рабочему окну. Эта функция выводит запись с просьбой нажать на клавишу Выполнить расчет после ввода в окно редактирования величины емкости конденсатора.

Функция 9 является реакцией на нажатие клавиши Выполнить расчет во втором рабочем окне.

Первая строка этой функции ставит условие, что если нет текста в окнах редактирования Edit3  или Edit4 или Edit5, то на экране должно появиться информационное окно с просьбой ввести недостающие величины. Вспомните, ведь вы уже встречались с оператором  ‘| |’, который обозначает «или».

Если все условия выполнены, то функция выполняет вычисление переменных величин aa, bb и ww. Последняя из этих переменных представляет собой число витков и эта величина выводится на экран в соответствующей строке.

Функция 10 является реакцией на запись «Введите длину намотки».

Листинг 2.19. Продолжение 2 файла induktiw.cpp

//--------------------------------------------------------------

void __fastcall TForm1::Edit4Change(TObject *Sender)        // 8

{

 Label13->Caption = "Нажмите на клавишуыполнить расчет>";

}

//--------------------------------------------------------------

void __fastcall TForm1::Button6Click(TObject *Sender)       // 9

{

 if(Edit3->Text == "" || Edit4->Text == "" || Edit5->Text == "")

     ShowMessage("Введите недостающие величины");

 else

  {

 float aa = (9 * StrToFloat(Edit4->Text)+20*StrToFloat(Edit5->Text))

                          * StrToFloat(Edit3->Text);

 float bb = 0.02 * pow(StrToFloat(Edit4->Text),2);

 float ww = sqrt(aa / bb);

 Label15->Caption = "Результат расчета";

 Label16->Caption = "Число витков катушки = "+

         FloatToStrF(ww,ffGeneral,3,1)+" витков";

  }

}

//-------------------------------------------------------------

void __fastcall TForm1::Edit5Change(TObject *Sender)       // 10

{

 Label13->Caption = "Нажмите на клавишуыполнить расчет>";

}

//-------------------------------------------------------------

 

Листинг 2.20 уже относится к третьему рабочему окну. Функция 11 очень похожа на рассмотренную ранее функцию 9 и рассматривать её подробно, по моему мнению, не стоит.

Функция 12 относится к четвертому рабочему окну и по своему построению аналогична функциям 9 и 11, но в ней добавлены еще три переменные величины, которые не усложняют расчета и не вводят никаких новых понятий.

Функция 13 относится к пятому рабочему окну и ничего нового, по сравнению с функцией  12, в ней нет.

Листинг 2.20. Продолжение 3 файла induktiw.cpp

//--------------------------------------------------------------

void __fastcall TForm1::Button7Click(TObject *Sender)       // 11

{

 if(Edit6->Text == "" || Edit7->Text == "" || Edit8->Text == "")

     ShowMessage("Введите недостающие величины");

 else

  {

 float D = 0.1 * (StrToFloat(Edit7->Text)+ StrToFloat(Edit9->Text) * 0.5);

 float aa = StrToFloat(Edit9->Text) * StrToFloat(Edit8->Text) / D;

 float ab = 5*(StrToFloat(Edit7->Text)+2*StrToFloat(Edit8->Text)+

                          1.3*aa);

 float ab1 = StrToFloat(Edit6->Text) * ab;

 float bc = pow(D,2);

 float ww = sqrt(0.76 * ab1 / bc);

 Label22->Caption = "Результат расчета";

 Label23->Caption = "Число витков катушки = "+

         FloatToStrF(ww,ffGeneral,3,1)+" витков";

  }

}

//--------------------------------------------------------------

void __fastcall TForm1::Button8Click(TObject *Sender)       // 12

{

 if(Edit10->Text == "" || Edit11->Text == "" ||

    Edit12->Text == "" || Edit13->Text == "" || Edit14->Text == "" )

     ShowMessage("Введите недостающие величины");

 else

  {

 float b = (StrToFloat(Edit11->Text) - StrToFloat(Edit12->Text)) * 0.05;

 float S = b * StrToFloat(Edit13->Text) * 0.1;

 float l = M_PI * (b + StrToFloat(Edit12->Text) * 0.1);

 float aa = StrToFloat(Edit10->Text) * l;

 float bb = StrToFloat(Edit14->Text) * S * 0.043;

 float ww = sqrt(aa / bb);

 Label32->Caption = "Результат расчета";

 Label33->Caption = "Число витков катушки = "+

         FloatToStrF(ww,ffGeneral,4,1)+" витков";

  }

}

//----------------------------------------------------------------

void __fastcall TForm1::Button9Click(TObject *Sender)       // 13

{

 if(Edit15->Text == "" || Edit16->Text == "" ||

    Edit17->Text == "" || Edit18->Text == "" || Edit19->Text == "" )

     ShowMessage("Введите недостающие величины");

 else

  {

 float b = (StrToFloat(Edit16->Text) - StrToFloat(Edit17->Text)) * 0.05;

 float S = b * StrToFloat(Edit18->Text) * 0.1;

 float l = M_PI * (b + StrToFloat(Edit17->Text) * 0.1);

 float mw = StrToFloat(Edit19->Text) * pow(StrToFloat(Edit15->Text),2);

 float ll = 0.043 * mw * S / l;

 Label40->Caption = "Результат расчета";

 Label41->Caption = "Индуктивность катушки = "+

         FloatToStrF(ll,ffGeneral,4,1)+" мкГн";

  }

}

//--------------------------------------------------------------

 

Листинг 2.21. начинается с функции 14, которая относится к шестому рабочему окну и является реакцией на нажатие клавиши <Выполнить расчет>.

Первая строка функции представляет собой условие, что если не будет введен текст хотя бы в одно из четырех имеющихся окон редактирования Edit, то должно на экране выводиться информационное окно с просьбой ввести недостающие величины. Далее выполняется расчет значений переменных величин A, B, C и D, которые необходимы для последующего вычисления основных величин – переменных величин emC0min и emC0max.

Функция 15 является реакцией на нажатие клавиши About и выводит на экран информационное окно с картинкой и текстом информации о разработчике программы.

Листинг 2.21. Продолжение 4 файла induktiw.cpp

//--------------------------------------------------------------

void __fastcall TForm1::Button10Click(TObject *Sender)      // 14

{

 if(Edit20->Text == "" || Edit21->Text == "" ||

    Edit22->Text == "" || Edit23->Text == "" )

     ShowMessage("Введите недостающие величины");

 else

  {

 float A = (StrToFloat(Edit20->Text) + StrToFloat(Edit22->Text)) *

            StrToFloat(Edit23->Text);

 float B = (StrToFloat(Edit23->Text) + StrToFloat(Edit20->Text)) +

            StrToFloat(Edit22->Text);

 float C = (StrToFloat(Edit21->Text) + StrToFloat(Edit22->Text)) *

            StrToFloat(Edit23->Text);

 float D = (StrToFloat(Edit23->Text) + StrToFloat(Edit21->Text)) +

            StrToFloat(Edit22->Text);

 float emC0min = A / B;

 float emC0max = C / D;

 Label47->Caption = "Результат расчета";

 Label48->Caption = "Емкость С0min  =  "+

         FloatToStrF(emC0min,ffGeneral,4,1)+" пф";

 Label49->Caption = "Емкость С0max  =  "+

         FloatToStrF(emC0max,ffGeneral,4,1)+" пф";

  }

}

//----------------------------------------------------------------

void __fastcall TForm1::Button11Click(TObject *Sender)      // 15

{

AboutBox->ShowModal();

}

//----------------------------------------------------------------

 

Как сделать окно About

Для начала нужно на имеющуюся форму добавить еще одну форму, предназначенную специально для окна About. Для этого в главном меню C++Builder выбрать File è NEW è other. В появившемся диалоговом окне New Items выбираем страничку Form. Этот вариант показан на рис. 2.29/

Рис. 2.29. Окно New Items

Далее выбираем About box и нажимаем клавишу ОК.  На экране возникает форма - заготовка для окна About, изображенная на рис. 2.30.

Рис. 2.30. Форма для окна About

Чтобы включить выбранную форму в проект, необходимо активизировать на экране  главную форму программы и в главном меню выбрать пункты File èInclude Unit Hdr  После этого на экране появляется окно Include Unit, в котором присутствует название новой подключаемой формы – AboutBox.  Нажимаем клавишу ОК и процедура подключения выполнена.

Следующим этапом нужно написать программные коды для вывода новой формы на экран. На главной форме делаем двойной щелчок на клавише About. В появившемся окне редактора пишем AboutBox->ShowModal();

Теперь можно заняться оформлением новой формы AboutBox. В главном меню выбираем ViewèForms. В появившемся окне View Form выбираем AboutBox.  На экране появляется форма, изображенная на рис. 2.30, которую следует сделать более привлекательной. Возможные дальнейшие действия:

q      Выделяем самую верхнюю текстовую строку Product Name и в свойство Caption записываем: «Программа». Выбираем размер шрифта для этой записи.

q      Выделяем вторую текстовую строку Version и в свойство Caption записываем: «INDUKTIV  v1». Выбираем размер и цвет шрифта для этой записи.

q      Точно также поступаем со следующими строками. В результате можно получить информационное окно, похожее на то, которое изображено на рис. 2.31.

Рис. 2.31. Готовый вариант окна About

 Практически в форму этого окна можно вносить массу изменений:

q      Можно менять тексты и их количество;

q      Можно менять картинку или добавлять новые и т.д. …

Следует знать, что новая форма имеет свой заголовочный файл about.h и файл исполняемый about.cpp.  Приводить текст файла about.h не буду. Каждый сможет просмотреть его на своем компьютере. Листинг файла about.cpp, по моему мнению, привести следует.  Пронумеруем, как обычно, функции.

Листинг 2.22. Файл about.cpp

//---------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

 

#include "About.h"

//--------------------------------------------------------------------

#pragma resource "*.dfm"

TAboutBox *AboutBox;

//--------------------------------------------------------------------

__fastcall TAboutBox::TAboutBox(TComponent* AOwner)        // 1

     : TForm(AOwner)

{

  Capture: "О программе";

}

//-------------------------------------------------------------------

void __fastcall TAboutBox::OKButtonClick(TObject *Sender)    // 2

{

  Close();        

}

//--------------------------------------------------------------------

 

В функции 1 можно задать название информационного окна, а в функция 2 представляет собой оклик на нажатие клавиши ОК. После нажатия на эту клавишу окно закрывается.

Компиляция проекта

На этом этапе создание исходных кодов программы можно считать законченным. Непременно нужно сохранить всё наработанное, для чего в главном меню C++Builder выбираем FileèSave All.   Надеюсь, что вы не забыли мой совет и в процессе работы с редактором текста частенько выбирали команду ProjektèMake induktiw. Это нужно было делать для того, чтобы исправлять появившиеся случайные ошибки в начальной стадии.

На следующем этапе нужно создавать исполняемый файл программы. Если бы мы не ставили своей задачей создать такой проект, который мог бы работать на любом компьютере под управлением Windows, то нужно было бы просто выбрать в главном меню пункты ProjectèBuild decibel и задача была бы решена. Но создание программы, которая должна работать «автономно», заставляет обратиться к специальным опциям проекта. Для этого выполняем:

q      Выбираем в главном меню ProjectèOptions и на экране появляется окно с массой страниц, заполненных различными опциями, т.е. определенными условиями, необходимыми для создания проекта с теми или иными параметрами. Окно ProjectèOptionsèLincer изображено на рис. 2.32.

Рис. 2.32. Окно Project Options

q      Затем переходим на страницу Packages (см. рис. 2.33) и выключаем на этой странице индикатор Built with runtime packages.

Рис. 2.33. Страница Packages

q      После этого переходим на страницу Compiler (см. рис. 2.34) и нажимаем клавишу Release, обеспечивающую создание файла без отладочной документации.

Рис. 2.34. Страница Compiler

q      Заключительная команда ProjectèBuild заставляет компилятор создать исполняемый файл induktiw.exe.

Работа над созданием проекта окончена. Чтобы приложение для Windows, отвечающее всем требованиям любого коммерческого приложения нужно выполнить еще ряд задач.

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

q      Далее нужно создать справочник, в котором пользователь мог бы найти любую справку по вашему приложению. Чем полнее справка, тем больше благодарности от пользователя вашего приложения. Несколько вариантов создания такого справочника описано в главе 4.

q      Заключительным этапом является создание инсталляционной программы, которая бы устанавливала в автоматическом режиме ваше приложение на компьютер. Несколько вариантов создания такой программы описано в главе 5.