Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Как заработать в Интернет" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
← Декабрь 2005 → | ||||||
1
|
2
|
3
|
4
|
|||
---|---|---|---|---|---|---|
5
|
6
|
7
|
8
|
9
|
10
|
|
12
|
13
|
14
|
15
|
16
|
17
|
18
|
19
|
20
|
21
|
22
|
23
|
24
|
25
|
26
|
27
|
28
|
29
|
30
|
31
|
Автор
Статистика
736 подписчиков
0 за неделю
0 за неделю
Программирование с нуля для инженера - выпуск 10
Информационный Канал Subscribe.Ru |
Программирование с нуля для инженера - разбор задания из выпуска 5б (выпуск 10)
Содержание
Вступление
Этот выпуск получился объёмнее, чем обычно. Советую вам читать
его в два захода - по две части за каждый заход.
В этом выпуске будет рассмотрено задание с квадратным уравнением,
предложенное вам в выпуске 5б. К предыдущему выпуску я выложил на сайте исполняемый файл программы
для решения квадратных уравнений. В той программе была допущена ошибка в знаке условия, из-за
этого программа в случае отрицательного значения коэффициента A выдавала сообщение, что уравнение
не является квадратным. Я исправил эту ошибку, но некоторые подписчики успели скачать программу
до этого. Хочу извиниться за свою невнимательность. В дальнейшем постараюсь так не ошибаться.
Исходный код
Привожу исходный код модуля главной формы программы. Полный код программы
находится в архиве примеров в папке Example1.
Unit Main; Interface Uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; Type TMainForm = Class(TForm) InputDataBox: TGroupBox; EquationViewBox: TGroupBox; EquationLB: TLabel; AX_PowerLB: TLabel; CoeffChoozeLB: TLabel; CoeffChoozeCB: TComboBox; CoeffInputLB: TLabel; CoeffInputET: TEdit; OutputDataBox: TGroupBox; SolveEquationBtn: TButton; ExitBtn: TButton; SaveToFileBtn: TButton; ExportToHTMLBtn: TButton; PrintBtn: TButton; EqRootsLB: TLabel; EqRootsOutputLB: TLabel; EqSolutionLB: TLabel; EqSolutionMemo: TMemo; Procedure FormClose(Sender: TObject; Var Action: TCloseAction); Procedure FormCreate(Sender: TObject); Procedure CoeffChoozeCBClick(Sender: TObject); Procedure ExitBtnClick(Sender: TObject); Procedure CoeffInputETKeyPress(Sender: TObject; Var Key: Char); Procedure SolveEquationBtnClick(Sender: TObject); Procedure CoeffInputETExit(Sender: TObject); Procedure ReadCoeff; Procedure ShowEquationView; // Объявление переменных - коэффициентов уравнения, // дискриминанта, корней, и индикатора состояния решения Private CoeffA: Double; CoeffB: Double; CoeffC: Double; Discriminant: Double; Root1: Double; Root2: Double; EqSolved: Boolean; End; Var MainForm: TMainForm; Implementation {$R *.DFM} // Обработчик нажатия на кнопку "Выход" Procedure TMainForm.ExitBtnClick(Sender: TObject); Begin // закрытие формы - выход из программы Close(); End; // Обработчик закрытия формы Procedure TMainForm.FormClose(Sender: TObject; Var Action: TCloseAction); Begin Action := caFree; End; // Обработчик создания формы (выполняется при запуске приложения) Procedure TMainForm.FormCreate(Sender: TObject); Begin // задаём начальные значения коэффициентов уравнения CoeffA := 1; CoeffB := -5; CoeffC := 6; // изначально уравнение не решено EqSolved := False; // выводим первый коэффициент - A CoeffChoozeCB.ItemIndex := 0; CoeffChoozeCBClick(Application); End; // Процедура чтения выбранного коэффициента из поля ввода // В зависимости от выбранного элемента раскрывающегося списка // читается определённый коэффициент. Первый элемент списка - // коэффициент A, второй - B, третий - C. Procedure TMainForm.ReadCoeff; Begin // если выбран 1 элемент раскрывающегося списка (коэф. A), // читаем коэффициент A If CoeffChoozeCB.ItemIndex = 0 Then CoeffA := StrToFloat(CoeffInputET.Text) Else // второму элементу соответствует B If CoeffChoozeCB.ItemIndex = 1 Then CoeffB := StrToFloat(CoeffInputET.Text) Else // третьему элементу соответствует C If CoeffChoozeCB.ItemIndex = 2 Then CoeffC := StrToFloat(CoeffInputET.Text); End; // Обработчик щелчка по раскрывающемуся списку. // Процедура выводит коэффициент в поле ввода. // В зависимости от выбранного элемента раскрывающегося списка // выводится определённый коэффициент. Procedure TMainForm.CoeffChoozeCBClick(Sender: TObject); Begin If CoeffChoozeCB.ItemIndex = 0 Then CoeffInputET.Text := FloatToStr(CoeffA) Else If CoeffChoozeCB.ItemIndex = 1 Then CoeffInputET.Text := FloatToStr(CoeffB) Else If CoeffChoozeCB.ItemIndex = 2 Then CoeffInputET.Text := FloatToStr(CoeffC); End; // Обработчик нажатия клавиши в поле ввода коэффициентов Procedure TMainForm.CoeffInputETKeyPress(Sender: TObject; Var Key: Char); Begin // Отдельно рассматриваем случай, когда нажимается клавиша ENTER. // Константа VK_RETURN является числовым кодом клавиши ENTER и // объявлена в модуле Windows. В процедуру передаётся параметр Key // типа Char, содержащий символ, который пользователь попытался ввести. // Перед проверкой нужно преобразовать константу к типу Char. If Key = Chr(VK_RETURN) Then // пользователь нажал ENTER Begin // читаем текущий выбранный коэффициент ReadCoeff(); // затем переходим к следующему коэффициенту в списке, // то есть выбираем другой элемент списка. If CoeffChoozeCB.ItemIndex = 0 Then // если был выбран 1-ый коэф. CoeffChoozeCB.ItemIndex := 1 // выбираем второй Else If CoeffChoozeCB.ItemIndex = 1 Then // если был выбран 2-ой коэф. CoeffChoozeCB.ItemIndex := 2 // выбираем третий Else If CoeffChoozeCB.ItemIndex = 2 Then // если был выбран 3-ий коэф. CoeffChoozeCB.ItemIndex := 0; // выбираем первый CoeffChoozeCBClick(Application); // выводим выбранный коэф. End Else // если пользователь нажал не ENTER, тогда... // если нажатая клавиша не принадлежит заданному множеству, // то изменяем её на нулевой символ, обозначающий в // данном случае отсутствие символа If Not (Key In ['-', '0'..'9', #8, DecimalSeparator]) Then Key := #0; End; // Обработчик потери фокуса полем ввода Procedure TMainForm.CoeffInputETExit(Sender: TObject); Begin // читаем текущий выбранный коэффициент ReadCoeff(); End; // Процедура вывода вида решаемого уравнения Procedure TMainForm.ShowEquationView; Begin EqSolutionMemo.Lines.Add('Коэффициенты уравнения:'); // вывод коэффициентов уравнения - каждый коэффициент // на отдельной строке EqSolutionMemo.Lines.Add(' A = ' + FloatToStr(CoeffA)); EqSolutionMemo.Lines.Add(' B = ' + FloatToStr(CoeffB)); EqSolutionMemo.Lines.Add(' C = ' + FloatToStr(CoeffC) + #13#10); End; Procedure TMainForm.SolveEquationBtnClick(Sender: TObject); Begin // уравнение не является квадратным If CoeffA = 0 Then Begin EqRootsOutputLB.Caption := '(уравнение не является квадратным)'; EqSolutionMemo.Text := 'Ошибка! Уравнение не является квадратным!'; EqSolved := False; // уравнение не решено Exit; End; EqSolutionMemo.Clear(); // очищаем поле для вывода информации ShowEquationView(); // выводим коэффициенты уравнения Discriminant := Sqr(CoeffB) - 4 * CoeffA * CoeffC; If Discriminant > 0 Then Begin Root1 := (-CoeffB + Sqrt(Discriminant)) / (2 * CoeffA); Root2 := (-CoeffB - Sqrt(Discriminant)) / (2 * CoeffA); EqSolved := True; // уравнение решено, результат получен // вывод корней в заголовок метки и в текстовое поле EqRootsOutputLB.Caption := 'X1 = ' + FloatToStr(Root1) + '; X2 = ' + FloatToStr(Root2); EqSolutionMemo.Lines.Add('Дискриминант положительный (D = ' + FloatToStr(Discriminant) + ')'); EqSolutionMemo.Lines.Add('Уравнение имеет два корня: '); EqSolutionMemo.Lines.Add(' X1 = ' + FloatToStr(Root1)); EqSolutionMemo.Lines.Add(' X2 = ' + FloatToStr(Root2)); End Else If Discriminant = 0 Then Begin Root1 := -CoeffB / (2 * CoeffA); Root2 := Root1; EqSolved := True; // уравнение решено, результат получен // вывод корней в заголовок метки и в текстовое поле EqRootsOutputLB.Caption := 'X1 = X2 = ' + FloatToStr(Root1); EqSolutionMemo.Lines.Add('Дискриминант равен нулю (D = 0)'); EqSolutionMemo.Lines.Add('Уравнение имеет один корень двойной кратности: '); EqSolutionMemo.Lines.Add(' X = ' + FloatToStr(Root1)); End Else Begin EqSolved := False; // уравнение не решено EqRootsOutputLB.Caption := '(уравнение не имеет решения)'; EqSolutionMemo.Lines.Add('Дискриминант отрицательный (D = ' + FloatToStr(Discriminant) + ')'#13#10 + 'Уравнение не имеет действительных корней.'); End; End; End.
Свойства, методы, события компонентов
Рассмотрим по порядку все объекты интерфейса программы. Чтобы лучше понять
эту часть выпуска, желательно сверять всё написанное в ней с проектом программы в среде Delphi.
Здесь описаны те свойства, которые я настроил, чтобы получить требуемый вид интерфейса программы,
те события компонентов, обработчики которых были использованы для создания функциональности программы, а
также методы компонентов.
Форма - объект MainForm
- Стиль границы - свойство BorderStyle. В первую очередь нужно настроить стиль границы. В нашем случае форма должна быть фиксированного размера (пользователь не имеет возможности изменить её размер), поэтому устанавливаем значение bsSingle.
- Иконки на полосе перетаскивания - свойство BorderIcons. По умолчанию у форм отображается иконка разворачивания на весь экран, и форму можно развернуть даже в том случае, когда Borderstyle="bsSingle." Чтобы убрать эту иконку, нужно установить свойство BorderIcons.biMaximize в True
- Заголовок формы - свойство Caption. У формы задаём заголовок "QuadricEquation 1.0".
- Позиция формы при запуске - свойство Position. Лучше всего отображать форму по центру экрана. Для этого устанавливаем значение свойства в poScreenCenter.
- Компонент, которому передаётся фокус при создании формы - свойство
ActiveControl. Выбирается из списка компонентов формы, которым можно передать фокус.
Фокус может передаваться не всем компонентам (к таким относятся, например, метки).
Выбираем поле для ввода коэффициентов - компонент CoeffInputET.
- При запуске программы можно не задавать начальные значения
коэффициентов и не выводить ничего в поле ввода, но лучше это сделать. При создании
любой формы выполняется её обработчик OnCreate. Для главной формы её создание равносильно
запуску программы. Чтобы создать обработчик OnCreate, нужно выбрать в инспекторе объектов
объект MainForm, затем на вкладке Events дважды щёлкнуть в строке события
OnCreate. Автоматически будет создана пустая заготовка обработчика. В обработчике
задаём начальные значения коэффициентов, предполагаем, что уравнение не решено, а
также выбираем первый коэффициент в списке и выводим его.
Этот момент особенно важен. Если вручную не задать индекс выбираемого элемента списка, то никакой элемент выбран не будет. Попробуйте закомментировать строку CoeffChoozeCB.ItemIndex := 0. Ошибка не произойдёт, но выглядеть будет не очень красиво. Если мы выбрали элемент списка, то следует вывести коэффициент, соответствующий нашему выбору. Для вывода определённого коэффициента в зависимости от выбранного элемента списка у нас используется обработчик CoeffChoozeCBClick, о котором будет написано чуть позже. Не будем писать код вывода коэффициента заново, а просто вызовем этот обработчик. Этому вызову соответствует строка CoeffChoozeCBClick(Application);.
В обработчик любого события передаётся как минимум один параметр. Это параметр Sender типа TObject. Этот параметр указывает, какой объект инициировал событие, обрабатываемое данным обработчиком. Можно написать обработчик события так, чтобы он выполнял какие-то действия в зависимости от объекта-инициатора события. В нашем случае обработчик CoeffChoozeCBClick выполяет действия независимо от параметра Sender. Поэтому не имеет значения, какой объект будет инициатором события. Передадим в обработчик CoeffChoozeCBClick объект Application - приложение. Этот объект является глобальной переменной, автоматически создаваемой при подключенном к проекту модуле Forms. Если вы посмотрите код головного модуля проекта, то увидите, что весь он состоит из вызовов методов этого объекта.
Групповые элементы - объекты EquationViewBox, InputDataBox, OutputDataBox
Групповые элементы, или, иначе, компоненты TGroupBox, используются для логической
группировки элементов интерфейса. Для краткости групповой элемент можно называть группой.
Чтобы выделить заголовки групп жирным шрифтом, нужно установить свойство
Font.Style.fsBold в True. Bold в переводе с английского в данном случае означает
"жирный". Префикс fs в названии свойства расшифровывается как font style. В инспекторе
объектов свойство Font.Style выглядит так, будто у него есть 4 вложенных свойства - fsBold,
fsItalic, fsUnderline, fsStrikeOut. На самом деле это свойство является множеством, которое
может содержать до четырёх элементов, перечисленных выше. Множество - стандартный
структурированный тип данных языка Delphi. Позднее мы рассмотрим множества более подробно.
После установки свойства группы Font.Style.fsBold в True компоненты, помещаемые внутрь группы,
будут автоматически наследовать это свойство шрифта. У каждого компонента, установленного внутрь
группы, приходится менять значение свойства обратно в False.
Далее рассмотрим по порядку содержимое групп.
Группа EquationViewBox - вид уравнения.
Группа содержит две метки - EquationLB. и AX_PowerLB. Заголовок первой метки - вид уравнения без степени X при коэффициенте A. Заголовок метки отображается по горизонтальной прямой, поэтому для степени X приходится устанавливать на форму ещё одну метку - AX_PowerLB. У метки EquationLB размер шрифта (свойство Font.Size) равен 12, у AX_PowerLB он равен 8. У обеих меток задан цвет шрифта: Font.Color = clHighlight. clHighlight - системный цвет фона выделенного текста, по умолчанию тёмно-синий.
Группа содержит две метки - EquationLB. и AX_PowerLB. Заголовок первой метки - вид уравнения без степени X при коэффициенте A. Заголовок метки отображается по горизонтальной прямой, поэтому для степени X приходится устанавливать на форму ещё одну метку - AX_PowerLB. У метки EquationLB размер шрифта (свойство Font.Size) равен 12, у AX_PowerLB он равен 8. У обеих меток задан цвет шрифта: Font.Color = clHighlight. clHighlight - системный цвет фона выделенного текста, по умолчанию тёмно-синий.
Группа InputDataBox - исходные данные.
Эта группа нас интересует больше всего, поскольку компоненты, расположенные в ней, используются для ввода данных. В данной реализации задачи наиболее сложная часть кода - ввод данных.
Метки CoeffChoozeLB и CoeffInputLB используются только для вывода статического текста на экран и имеют стандартный набор свойств, которые им задаёт среда при помещении на форму. Рассмотрим остальные два компонента.
Эта группа нас интересует больше всего, поскольку компоненты, расположенные в ней, используются для ввода данных. В данной реализации задачи наиболее сложная часть кода - ввод данных.
Метки CoeffChoozeLB и CoeffInputLB используются только для вывода статического текста на экран и имеют стандартный набор свойств, которые им задаёт среда при помещении на форму. Рассмотрим остальные два компонента.
Выпадающий список CoeffChoozeCB.
Из этого списка выбирается коэффициент для ввода.
Из этого списка выбирается коэффициент для ввода.
- Свойство Items - элементы списка. Основное свойство списка.
Элементы списка редактируются в редакторе списка строк (String List editor). Для его открытия
нужно нажать кнопку с троеточием в правой части строки таблицы инспектора объектов.
Открыв редактор, вы увидите 3 строки - на каждый элемент списка по строке. Добавление и
удаление элементов из списка производится легко. После приведения списка к нужному
виду нужно нажать клавишу "OK". Список элементов компонента изменится, редактор закроется.
- Свойство Style - стиль списка. Компонент TComboBox
- "смесь" компонентов TEdit (однострочное текстовое поле) и TListBox
(список элементов). В зависимости от стиля компонента в текстовое поле списка либо можно,
либо нельзя вводить текст. По умолчанию у компонентов TComboBox установлен стиль csDropDown.
В этом режиме строка текстового поля списка выбирается из списка строк либо вводится пользователем
вручную. Нас это не устраивает, поскольку набор коэффициентов фиксированный. Пользователь
должен выбирать коэффициент, возможность ввода отсутствует. Стиль csDropDownList
как раз устанавливает такой режим, в котором возможен только выбор строки из списка. Нужно
учесть, что в этом режиме возможна ситуация, когда не выбран ни один элемент. При запуске
программы выбирается первый элемент списка (его индекс равен нулю).
- Свойство Text - строка текстового поля списка.
Эта строка не зависит от стиля компонента и всегда равна тому, что содержится в
текстовом поле выпадающего списка.
- Событие OnClick - происходит при выборе элемента списка.
Элемент списка может быть выбран с помощью клавиатуры или мыши. Сюда включается и выбор
с помощью колёсика мышки. Обработчик этого события должен перейти к тому коэффициенту,
который выбран из списка, то есть должен вывести этот коэффициент в поле ввода
коэффициентов - CoeffInputET. Событие происходит после того, как пользователь
выбрал элемент списка. Чтобы вывести на экран коэффициент, нам достаточно знать, какой индекс
имеет выбранный элемент списка. Для этого нужно обратиться к свойству ItemIndex.
Элементы списка нумеруются с нуля. Коэффициенту A соответствует индекс 0, коэффициенту B - 1,
коэффициенту C - 2.
Поле ввода коэффициентов CoeffInputET
Это поле используется для ввода всех коэффициентов уравнения.
Это поле используется для ввода всех коэффициентов уравнения.
- Событие OnKeyPress - происходит при нажатии клавиатурной клавиши
в текстовом поле. В обработчик этого события кроме параметра Sender передаётся ещё
один параметр - нажатая клавиша Key. Я использовал этот обработчик, чтобы ограничить
допустимое множество вводимых клавиш, а также для возможности перехода к следующему
коэффициенту по нажатию клавиши Enter.
- Событие OnExit - происходит при потере компонентом фокуса.
Это событие происходит, когда фокус ввода перемещается от данного компонента к любому другому.
В этот момент читается текущий выбранный коэффициент.
Группа OutputDataBox - решение уравнения
Группа содержит 4 компонента - EqRootsLB, EqRootsOutputLB, EqSolutionLB, EqSolutionMemo. Метки EqRootsLB и EqSolutionLB нужны только для вывода статического текста на экран.
Группа содержит 4 компонента - EqRootsLB, EqRootsOutputLB, EqSolutionLB, EqSolutionMemo. Метки EqRootsLB и EqSolutionLB нужны только для вывода статического текста на экран.
Метка EqRootsOutputLB
Используется для вывода корней или информации о том, что они отсутствуют.
Используется для вывода корней или информации о том, что они отсутствуют.
- Свойство AutoSize - автоматический подгон длины метки под текст
её заголовка. Устанавливается в False. При выводе корней не производится их округление до какого-либо знака.
Если текст метки окажется слишком длинным, он вылезет за пределы формы. Чтобы этого
не произошло, нужно запретить подгон длины и задать такую высоту метки, чтобы в ней
уместились две строки текста для вывода корней.
- Свойство WordWrap - перенос по словам. Устанавливается в True.
В сочетании со значением свойства AutoSize и большой высотой метки появляется возможность
вывода многострочного текста в метку.
- Также у метки установлен жирный шрифт.
Многострочное текстовое поле EqSolutionMemo
- Свойство Lines - текст поля. Редактируется в редакторе списка строк.
- Свойство ScrollBars - наличие полос прокрутки. По умолчанию
полосы прокрутки у TMemo отсутствуют, свойство равно ssNone. Даже если текст будет
содержать много строк, полосы прокрутки не появятся. Нам нужна только вертикальная полоса
прокрутки. Свойство ScrollBars зададим равным ssVertical. Горизонтальная полоса не
нужна потому, что по умолчанию у TMemo установлен перенос по словам - WordWrap = True.
- Свойство ReadOnly - запрет редактирования текста поля. Поле EqSolutionMemo служит только для вывода текста, поэтому нужно запретить ввод символов в него. ReadOnly = True.
Осталось отметить последний компонент - кнопку SolveEquationBtn. При нажатии на
эту кнопку происходит решение уравнения. Кнопка выделена жирным шрифтом.
При нажатии происходит событие OnClick, и выполняется его обработчик.
Логика работы программы
Частично логика работы уже описана в предыдущей части выпуска. Так
получилось, потому что логика работы определяется событиями, которые позволяет обрабатывать среда Delphi.
Если бы события были другими, происходили бы в других случаях, или если бы какие-то из них
отсутствовали, пришлось бы писать программу по-другому, учитывая эти моменты. В нашей программе
пока пять полезных обработчиков (не включаю сюда MainForm.FormClose). О том, какие задачи
возлагаются на эти обработчики, написано выше. Рассмотрим содержание обработчиков. Не буду
останавливаться на тех обработчиках, которые уже были подробно описаны выше.
Ваша задача - написать программу, которая реализует переход по элементам списка TComboBox в двух направлениях, зацикливая его с обеих сторон. Имеется в виду возможность перехода от первого элемента к последнему при обратном направлении и возможность перехода от последнего элемента к первому при прямом направлении. Для управления переходами используйте любые компоненты. Чтобы узнать количество элементов в списке, нужно обратиться к свойству Items.Count. Присылайте свои решения. В качестве примера смотрите программу из папки Example2 архива примеров. Не смотрите её исходный код! Откомпилируйте программу и посмотрите, как она работает в готовом виде.
- TMainForm.FormCreate - обработчик создания формы.
О нём было написано выше. - TMainForm.CoeffChoozeCBClick - обработчик выбора элемента
выпадающего списка.
В зависимости от индекса выбранного элемента списка нужно вывести в поле CoeffInputET соответствующий коэффициент. Для реализации выбора записываем три условных оператора If. Сначала проверяем, не равен ли индекс нулю. Если равен, выводим коэффициент A, хранящийся в переменной CoeffA. Иначе проверяем, не равен ли индекс единице. Если да, выводим коэффициент B. Иначе - проверка, не равен ли индекс двум. Если равен, выводим коэффициент C. Для реализации выбора коэффициента можно было использовать оператор Case. Рекомендую вам для тренировки переписать этот код с использованием оператора Case. - TMainForm.CoeffInputETExit - обработчик потери фокуса полем ввода
коэффициентов.
Этот обработчик уже был описан. Его код состоит из вызова метода ReadCoeff. Чтобы убедиться, что этот обработчик читает коэффициенты в нужные моменты, добавьте в него строку ShowMessage('Чтение коэффициента');.
Метод ReadCoeff не является обработчиком события, я добавил его вручную. Заметьте, он объявлен в том же месте, где и все обработчики событий, по тем же правилам. Полное имя метода - TMainForm.ReadCoeff. Это означает, что он принадлежит классу TMainForm. Можно было объявить метод в интерфейсе модуля, а можно было вообще не объявлять его, а сразу писать код в разделе реализации модуля. А ещё посмотрите, где я объявил переменные. В том же классе TMainForm, в разделе Private. Также можно было объявить их либо в интерфейсе модуля, либо в его реализации. В нашей маленькой программе с одним окном разница в объявлениях незаметна. Но в действительности она велика. Когда мы дойдём до классов (это будет нескоро, но, надеюсь, будет), обязательно рассмотрим различие в объявлениях переменных и методов в разных разделах модуля. Пока просто запомните, что выбранные в этой программе варианты объявления переменных и методов более правильные и подходят для общего случая.
Наконец-то рассмотрим метод ReadCoeff. Он используется для чтения текущего выбранного коэффициента. Метод очень похож на CoeffChoozeCBClick. Отличие в том, что коэффициенты читаются из поля ввода, а не выводятся в него. - TMainForm.CoeffInputETKeyPress - обработчик нажатия на клавишу внутри
поля ввода коэффициентов.
В обработчике основной является проверка, нажата ли клавиша Enter или какая-либо другая клавиша. Если нажата клавиша Enter, необходимо выполнить набор действий. Сначала читаем текущий выбранный коэффициент, при помощи метода ReadCoeff. Затем переходим к следующему элементу списка. Для этого используются три условия, каждое из которых изменяет индекс выделенного элемента списка. Реализован циклический переход по списку. При вводе третьего коэффициента происходит переход к первому. Далее нужно вывести коэффициент, соответствующий выбранному вновь элементу. Для этого используется обработчик CoeffChoozeCBClick.
Если нажата не клавиша Enter, наша задача - запретить ввод посторонних символов. Проще разрешить ввод определённых символов. В коде для этого используется проверка:If Not (Key In ['-', '0'..'9', Chr(VK_BACK), DecimalSeparator]) Then Key := #0; Дословно проверку можно перевести так: ЕСЛИ клавиша НЕ принадлежит множеству допустимых символов ['-', '0'..'9', Chr(VK_BACK), DecimalSeparator], ТОГДА изменяем код клавиши на ноль. Здесь появляется множество, содержащее допустимые для ввода символы. Как видно, оно состоит из элементов типа Char. Допускается вводить цифры, знак минус, разделитель целой и дробной части числа. А также допускается стирать символы из поля. При нажатии клавиши BackSpace (стереть) в обработчик также передаётся определённый код клавиши. Эта клавиша имеет код 8 и символическое имя VK_BACK. Только константа VK_BACK имеет числовой тип, поэтому её нужно преобразовать в символ с помощью функции Chr. Ниже представлена таблица кодов и символических имён некоторых клавиш. Таблица используется при написании подобных обработчиков. DecimalSeparator - переменная, объявленная в модуле SysUtils. Она содержит символ, являющийся в данный момент системным разделителем целой и дробной части числа.
Для проверки принадлежности символа множеству используется оператор In. Позже мы рассмотрим его подробнее.
В случае успешной проверки (а это означает, что клавиша не принадлежит множеству допустимых символов) код клавиши заменяется на ноль. Ноль в данном случае является зарезервированным значением кода, означающим отсутствие символа. Изменяя код клавиши на ноль, мы отменяем её ввод в текстовое поле. - TMainForm.SolveEquationBtnClick - обработчик нажатия на кнопку с
заголовком "Решить уравнение".
Основной обработчик, ради которого создавался весь остальной код.
Сначала нужно проверить - не равен ли коэффициент A нулю? Если равен, тогда уравнение не является квадратным. Нужно вывести информацию об этом и прекратить выполнение метода. Последнее действие осуществляется процедурой Exit, которая заканчивает выполнение текущей подпрограммы. Если Exit вызвать непосредственно в коде головного модуля проекта, завершится выполнение программы. Существует также процедура Abort, которая прерывает выполнение подпрограммы. В чём разница - покажу позже на примере.
Смотрим код дальше. Производим очистку текстового поля EqSolutionMemo вызовом метода Clear. Вызываем метод ShowEquationView. Метод выводит информацию о коэффициентах уравнения в поле EqSolutionMemo, где подробно описывается решение. Можно было не выносить этот код в отдельный метод. Я сделал так, чтобы показать, что программу нужно делить на подпрограммы. Подпрограммы, желательно, должны выполнять логически законченные действия.
Дальнейший код не слишком интересен, особенно для тех, что решал это задание. Один момент - у компонента TMemo есть свойство Lines, содержащее массив из строк текста поля. У этого свойства есть метод Add, добавляющий строку в текстовое поле. При вызове метода ему передаётся строка - та, которую нужно добавить.
Ваша задача - написать программу, которая реализует переход по элементам списка TComboBox в двух направлениях, зацикливая его с обеих сторон. Имеется в виду возможность перехода от первого элемента к последнему при обратном направлении и возможность перехода от последнего элемента к первому при прямом направлении. Для управления переходами используйте любые компоненты. Чтобы узнать количество элементов в списке, нужно обратиться к свойству Items.Count. Присылайте свои решения. В качестве примера смотрите программу из папки Example2 архива примеров. Не смотрите её исходный код! Откомпилируйте программу и посмотрите, как она работает в готовом виде.
Таблица кодов клавиш
Ниже приведены коды и символические имена клавиш, которые являются
командными и не могут быть представлены в виде символов на экране (кроме Tab). Эта таблица
пригодится вам для создания обработчиков OnKeyDown, OnKeyPress, OnKeyUp.
Клавиша | Десятичный код | Шестнадцатеричный код | Символическое имя |
F1 | 112 | $70 | VK_F1 |
F2 | 113 | $71 | VK_F2 |
F3 | 114 | $72 | VK_F3 |
F4 | 115 | $73 | VK_F4 |
F5 | 116 | $74 | VK_F5 |
F6 | 117 | $75 | VK_F6 |
F7 | 118 | $76 | VK_F7 |
F8 | 119 | $77 | VK_F8 |
F9 | 120 | $78 | VK_F9 |
F10 | 121 | $79 | VK_F10 |
F11 | 122 | $7A | VK_F11 |
F12 | 123 | $7B | VK_F12 |
BackSpace | 8 | $08 | VK_BACK |
Tab | 9 | $09 | VK_TAB |
Enter | 13 | $0D | VK_RETURN |
Shift | 16 | $10 | VK_SHIFT |
Ctrl | 17 | $11 | VK_CONTROL |
Alt | 18 | $12 | VK_MENU |
CapsLock | 20 | $14 | VK_CAPITAL |
Esc | 27 | $1B | VK_ESCAPE |
Insert | 45 | $2D | VK_INSERT |
PageUp | 33 | $21 | VK_PRIOR |
PageDown | 34 | $22 | VK_NEXT |
End | 35 | $23 | VK_END |
Home | 36 | $24 | VK_HOME |
Delete | 46 | $2E | VK_DELETE |
PrintScreen | 44 | $2C | VK_SNAPSHOT |
ScrollLock | 145 | $91 | VK_SCROLL |
Pause | 19 | $13 | VK_PAUSE |
NumLock | 144 | $90 | VK_NUMLOCK |
Заключение
Ссылка на
примеры.
В заключение хочу извиниться за большую задержку с выходом выпуска. Три-четыре месяца рассылка
будет выходить нерегулярно. В течение этого времени выпуски, скорее всего, будут выходить реже
раза в две недели.
Subscribe.Ru
Поддержка подписчиков Другие рассылки этой тематики Другие рассылки этого автора |
Подписан адрес:
Код этой рассылки: comp.soft.others.prog2eng Архив рассылки |
Отписаться
Вспомнить пароль |
В избранное | ||