- •Основы программирования
- •Введение
- •Основы delphi
- •Общая технология программирования
- •Язык программирования
- •Объектно-ориентированное программирование
- •Визуальное программирование
- •Событийно управляемое программирование
- •Windows-приложение
- •Среда программирования
- •Первоначальные сведения о проекте приложения
- •Встроенный отладчик
- •Использование встроенных классов
- •Иерархия классов
- •Использование палитры компонентов и инспектора объектов
- •Использование графики
- •Основные инструменты
- •Основные характеристики шрифтов
- •Графические данные и палитра
- •Некоторые общие свойства компонентов
- •Сохранение проекта
- •Построение простейшего проекта
- •Понятие исключительной ситуации
- •Введение в object pascal
- •Структура приложения
- •Структура программы-проекта
- •Структура модуля
- •Пример 1
- •Описания программных элементов
- •Программные элементы и адреса памяти
- •Области видимости
- •Правила записи имен
- •Время жизни идентификаторов
- •Использование локальных переменных в примере 1
- •Использование глобальных переменных в примере 1
- •Простые типы
- •Целые типы
- •Целые типы
- •Некоторые операции с целым типом
- •Символьные типы
- •Логические типы
- •Тип перечень
- •Интервальный тип
- •Вещественный тип
- •Вещественные типы
- •Некоторые операции с вещественным типом
- •Тип дата-время
- •Выражения
- •Константы
- •Типизированные константы.
- •Переменные
- •Операции
- •Унарная операция not (отрицание)
- •Логические операции and, or, xor
- •Функции
- •Порядок вычисления выражений
- •Виды операторов
- •Простые операторы
- •Составной оператор
- •Операторы условного перехода
- •Оператор if
- •Пример 2
- •Оператор case
- •Пример 3
- •Использование enter в примере 3
- •Операторы цикла
- •Оператор цикла for
- •Пример 4
- •Оператор цикла while
- •Пример 5
- •Оператор цикла repeat
- •Пример 6
- •Использование процедур break и continue
- •Пример 7
- •Массивы
- •Статические массивы
- •Динамические массивы
- •Пример 8
- •Пример 9
- •Записи (объединения)
- •Оператор with
- •Пример 10
- •Совместимость и преобразование типов данных
- •Идентичность типов
- •Совместимость типов
- •Совместимость по присваиванию
- •Преобразование типов
- •Операторы обработки исключительных ситуаций
- •Пример 11
- •Множества
- •Операции над множествами
- •Пример 12
- •Вариантный тип данных
- •Процедуры и функции
- •Процедура
- •Функция
- •Рекурсия
- •Формальные и фактические параметры
- •Параметры-значения
- •Параметры-переменные
- •Параметры-константы
- •Параметры без типа
- •Массивы открытого типа
- •Парамеры по умолчанию
- •Процедура exit
- •Директивы подпрограммы
- •Соглашения по передаче данных
- •Директива forward
- •Директива external
- •Директива assembler
- •Перегруженные подпрограммы
- •Пример 13
- •Инкапсуляция
- •Класс как объектный тип
- •Наследование
- •Области видимости
- •Операции is и as
- •Виды методов
- •Методы virtual и полиморфизм
- •Методы dynamic
- •Методы message
- •Методы abstract
- •Методы override
- •Методы class
- •Пример 14
- •Динамическое создание компонентов
- •Использование класса со счетчиком объектов
- •Отслеживание разрушения объектов
- •События
- •Указатели на методы
- •Пример 15
- •Типы ссылки на класс
- •Свойства
- •Свойства simple
- •Свойства enumerated
- •Свойства set
- •Свойства object
- •Свойства array
- •Задание начальных значений свойствам
- •Пример 16
- •Файловые типы
- •Текстовые файлы
- •Типизированные файлы
- •Файлы без типа
- •Дополнительные процедуры и функции
- •Пример 17
- •Компонент tmainmenu
- •Указатели
- •Пример 18
- •Динамические структуры данных
- •Однонаправленные списки
- •Двунаправленные списки
- •Стеки, очереди
- •Бинарные деревья
- •Пример 19
- •Процедурный тип
- •Программные единицы dll
- •Пример 20
- •Технологии программирования
- •Потоки данных
- •Пример 21
- •Пример 22
- •Интерфейс drag and drop
- •Пример 23
- •Технология drag and dock
- •Пример 24
- •Использование функций windows api при работе с файлами
- •Пример 25
- •Использование отображаемых файлов
- •Пример 26
- •Программные потоки
- •Приоритеты потоков
- •Класс tthread
- •Пример 27
- •Использование блокировки в примере 27
- •Многопоточное приложение в примере 28
- •Проблемы синхронизации потоков
- •Список используемых в примерах компонентов
- •Список используемых компонентов и других классов
- •Библиографический список
- •Оглавление
Оператор with
Оператор With часто называется оператором присоединения. Для того чтобы не записывать каждый раз имя селектора, при обращении к полям записи используется этот оператор, например, With Data do begin
Year:= 1971; Month:=5;
Day:=28;
End;
Пример 10
Пусть требуется рассчитать зарплату (З), премию (П) и итоговую сумму (И) 2-м сотрудникам в соответствии с табл. 12.
Таблица 12
Данные к примеру 10.
Таб N |
ФИО |
Окл, Т.с |
Час |
Дни |
Дни граф |
З |
П |
И |
1 |
Иванов И.И. |
6000 |
176 |
22 |
24 |
|
|
|
2 |
Петров П.П. |
40 |
184 |
23 |
24 |
|
|
|
В
данном случае заданы два варианта
расчёта зарплаты: по окладу (Окл = 6000) и
по часовой тарифной ставке (Т.с = 40). В
первом случае зарплата (З) расчитывается
следующим образом:
Во
втором случае необходимо использовать
такие соотношения:
;
Указанные ограничения в формулах означают, что, если сотрудник отработал больше, чем по графику, то это сверхурочные, которые оплачиваются отдельно (в примере сверхурочные не учитываются). Используемая во втором случае цифра 8 означает, что задан восьмичасовой рабочий день.
Предусмотрена премия не более 150 % от зарплаты, которая выплачивается, если предприятие имеет прибыль. Форма с вариантом решения приводится на рис. 30.
Рис. 30 Форма с вариантом расчета примера 10.
Задача решается в 2 этапа: вначале - ввод информации (можно изменить исходные данные), затем - расчет.
Как и в предыдущих случаях, в данном примере использовались новые компоненты. Для указания, есть ли премия в данном месяце, необходим переключатель. При решении примера 10 использовался переключатель с независимой фиксацией TCheckBox. Этот стандартный элемент Windows позволяет выбрать или отменить определенную опцию. С помощью группы таких переключателей можно выбирать или отключать несколько опций одновременно. Состояние переключателя (вкл/выкл) содержится в свойстве Checked. Для обработки переключений используется событие OnClick. Кнопку можно перевести в третье состояние (“включённое серое”) c помощью свойства AllowGrayed. Это свойство используется, если переключатель содержит еще ряд вложенных переключателей. Третье состояние переключателя указывает, что вложенные опции не все включены или не все выключены. Узнать, включено ли свойство AllowGrayed, можно с помощью свойства State.
Для полноты представления проблемы рассмотрим ещё один вид переключателей – переключатель с зависимой фиксацией - TradioButton. Этот вид переключателей в примере 9 уже использовался, но в составе группы. Если выбрано несколько таких переключателей, то они автоматически объединяются в группу и позволяют из множества опций выбрать одну, в отличие от CheckBox. TradioButton также имеет свойство Checked и событие OnClick, свойство AllowGrayed отсутствует.
Событие OnClick обрабатывается по-разному у переключателей TCheckBox и TRadioButton. У TCheckBox событие обрабатывается независимо от того, включена или выключена опция Checked, у TRadioButton - только если Checked равно true в момент переключения.
Для представления табличных данных использовалась графическая таблица TDrawGrid, которая, в отличие от TStringGrid, может отображать не только текстовую информацию, но и графическую. TDrawGrid имеет значительно больше возможностей, чем TStringGrid. Например, размеры строк и столбцов можно изменять индивидуально. Можно изменять и цвет ячеек (индивидуально). Внешний вид графической сетки настраивается с помощью следующих свойств: ColCount, RowCount – количества столбцов и строк; DefaultColWidth, DefaultRowHeight – высота и ширина по умолчанию; Height, Width – ширина и высота таблицы; FixedColls, FixedRows – фиксированное количество столбцов и строк. Индивидуальные размеры строк и столбцов содержатся в свойствах ColWidth и RowHeight – эти свойства являются массивами. Отметим несколько опций свойства Options: GoRowSizing – разрешить или запретить изменение размеров строк, GoColSizing - разрешить или запретить изменение размеров столбцов, GoEditing – разрешить или не разрешить редактирование, GoAlwaysShowEditor - если эта опция отключена, то редактор загружается клавишей F2 или щелчком мыши, если эта опция включена, то редактор загружается автоматически. В отличие от TStringGrid, TDrawGrid не имеет свойства Cells (ячейки), поэтому ввод данных и запись данных после редактирования нужно организовывать самостоятельно. Для отображения данных необходимо воспользоваться событием OnDrawCell – перерисовка ячеек. При перерисовке ячеек область рисования (в пикселах) задается в виде свойства Rect (прямоугольник). Свойство Rect преобразует номера колонки и строки в прямоугольник, заданный в пикселах. Перерисовка ячейки зависит от свойства State (состояние), которое может иметь следующие значения: gdSelected – ячейка выбрана; gdFocused – на ячейке находится фокус gdFixed – зафиксированная ячейка (заголовок). Для рисования в DrawGrid имеется свойство TCanvas. Для задания прямоугольника существует метод CellRect, который в соответствии с аргументами: номером столбца и номером строки - задаёт координаты области рисования в пикселах. Событие OnSelectCell позволяет индивидуально запретить или разрешить передачу фокуса какой-либо ячейке внутри таблицы. Для организации ввода данных используется событие OnGetEditText. Для фиксирования изменений после ввода (после редактирования) используется событие OnSetEditText.
На форме рис. 30 выбраны такие значения для некоторых свойств DrawGrid: ColCount = 9, RowCount = 3, Options: goColSizing = true, goEditing = true, goAlwaysShowEditor = True, DefaultDrawing = False. Последнее свойство может отключать событие OnDrawCell, включая прорисовку по умолчанию.
В данном примере необходимо реализовать несколько обработчиков событий:
OnClick –запуск рисования ячеек;
OnDrawCell – перерисовка ячеек;
OnGetEditText – вызов редактора ввода данных в ячейки;
OnSetEditText – запись информации после ввода;
OnKeyPress – ограничение (фильтр) ввода;
OnSelectCell – ограничение доступа к некоторым ячейкам.
При выполнении приложения наступает момент, когда форма рисуется на экране. Ответственнен за этот процесс обработчик OnCreate, который вызывается автоматически. Можно дополнять код этого обработчика. В данном случае предусмотрим дополнительный код изменения ширины столбцов для DrawGrid.
С помощью Button1 предусмотрим обработчик, задающий начало расчета (OnClick).
Для Edit1 необходим OnKeyPress.
Для Edit1 необходим OnExit, чтобы контролировать ввод числа (не более 150) по условию задачи.
Для CheckBox1 организуем обработчик при потере фокуса этим элементом (OnExit) и передаче фокуса или Edit1 или DrawGrid1 (обход Edit1).
Для записи результатов ввода и итоговых результатов предусмотрим двумерный массив Field, который должен объявляться глобально. Размеры массива [0..2], [0..8] – 3 строки и 9 столбцов. Для выполнения всех расчетов воспользуемся типом данных запись. Ниже приводится программа.
unit prim10;
interface
uses Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs, Grids, Buttons, StdCtrls,
ExtCtrls;
type
TMainForm = class(TForm)
Panel1: TPanel;
Button1: TButton;
BitBtn1: TBitBtn;
DrawGrid1: TDrawGrid;
CheckBox1: TCheckBox;
Edit1: TEdit;
Label1: TLabel;
procedure DrawGrid1DrawCell
(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure DrawGrid1GetEditText(Sender: TObject;
ACol, ARow: Integer; var Value: String);
procedure DrawGrid1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure DrawGrid1SetEditText(Sender: TObject;
ACol, ARow: Integer;const Value: String);
procedure DrawGrid1SelectCell(Sender: TObject;
ACol, ARow: Integer;var CanSelect: Boolean);
procedure DrawGrid1KeyPress
(Sender: TObject; var Key: Char);
procedure CheckBox1Exit(Sender: TObject);
procedure Edit1KeyPress(Sender: TObject;
var Key: Char);
procedure Button1Click(Sender: TObject);
end;
var MainForm: TMainForm;
const Field: array [0..2, 0..8] of string =(('ТабN',
'Ф.И.О.','Окл,Т','Час','Дней','Дн.г.','Зарпл',
'Премия','Итого'), ('1','Иванов И.И.','6000',
'176','22','24','0','0','0'),('2','Петров П.П.',
'40','184','23','24','0','0','0'));
implementation
{$R *.DFM}
procedure TMainForm.DrawGrid1DrawCell(Sender: TObject;
ACol, ARow: Integer;Rect: TRect;
State: TGridDrawState);
var i,j:byte;
begin
with DrawGrid1 do
for j:=0 to RowCount-1 do begin
if j=0 then Canvas.Brush.Color:=clBtnFace
else Canvas.Brush.Color:=clWindow;
for i:=0 to ColCount-1 do begin
Rect:=CellRect(i,j);
with Canvas,Rect do TextRect(Rect,Left+(Right-
Left-TextWidth(Field[j,i])) div 2,Top+(Bottom-
Top-TextHeight(Field[j,i])) div 2,Field[j,i]);
end;
end;
end;
procedure TMainForm.DrawGrid1GetEditText(Sender:
TObject; ACol, ARow: Integer;var Value: String);
begin
Value:=Field[ARow,ACol];
end;
procedure TMainForm.DrawGrid1Click(Sender: TObject);
begin
with DrawGrid1 do begin
DrawGrid1DrawCell(Sender,0,0,CellRect(0,0),
[gdFixed]);
DrawGrid1DrawCell(Sender,0,1,CellRect(0,1),
[gdSelected,gdFocused]);
DrawGrid1DrawCell(Sender,0,2,CellRect(0,2),
[gdSelected,gdFocused]);
end;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var i:byte;
begin
with DrawGrid1 do
for i:=0 to ColCount-1 do
case i of
0,2: ColWidths[i]:=40;
1: ColWidths[i]:=90;
3..5:ColWidths[i]:=36;
else ColWidths[i]:=57;
end;
end;
procedure TMainForm.DrawGrid1SetEditText(Sender:
TObject; ACol, ARow: Integer;const Value: String);
begin
if (ARow = 1) and (ACol <> 3)
or (ARow = 2) and (ACol <> 4) then
Field[ARow,ACol]:=Value;
if (ARow = 1) and (ACol = 4) then
if Length(Value) > 0 then Field[ARow,3]:=
IntToStr(StrToInt(Value)*8);
if (ARow = 2) and (ACol = 3) then
if Length(Value) > 0 then Field[ARow,4]:=
IntToStr(round(StrToInt(Value)/8));
end;
procedure TMainForm.DrawGrid1SelectCell(Sender:
TObject; ACol, ARow: Integer;var CanSelect: Boolean);
begin
CanSelect:=true;
with DrawGrid1 do
if (ARow = 1) or (ARow = 2) then
if ACol in [0,5..8] then CanSelect:=false;
end;
procedure TMainForm.DrawGrid1KeyPress
(Sender: TObject; var Key: Char);
begin
with DrawGrid1 do
if Row > 0 then begin
if (Col = 2) and (not (key in
['0'..'9','.',#8])) then key:=#0;
if ((Col = 3) or (Col = 4)) and (not
(key in ['0'..'9',#8])) then key:=#0;
end;
end;
procedure TMainForm.CheckBox1Exit(Sender: TObject);
begin
if CheckBox1.Checked then Edit1.SetFocus
else DrawGrid1.SetFocus;
end;
procedure TMainForm.Edit1KeyPress
(Sender: TObject; var Key: Char);
begin
if not (key in ['0'..'9','.',#8]) then key:=#0;
end;
procedure TMainForm.Edit1Exit(Sender: TObject);
begin
if Length(Edit1.Text)=0 then Edit1.Text:='0.0';
if (StrToFloat(Edit1.Text)=0.0) or
(StrToFloat(Edit1.Text)>150.0) then
if Application.MessageBox('Введите % премии',
'Число <= 150',MB_OK)=IDOK then Edit1.SetFocus;
end;
procedure TMainForm.Button1Click(Sender: TObject);
type rec=record
tbn: word;
fio: string[20];
okl: Currency;
ch,dn,dng: word;
zp,pr,it: Currency;
end;
var z:array [1..2] of rec;
i:byte;
begin
for i:=1 to 2 do begin
with z[i] do begin
tbn:=StrToInt(Field[i,0]);
fio:=Field[i,1];
okl:=StrToFloat(Field[i,2]);
ch:= StrToInt(Field[i,3]);
dn:= StrToInt(Field[i,4]);
dng:=StrToInt(Field[i,5]);
if i = 1 then
if dng <> 0 then zp:=okl*dn/dng else zp:=0
else if ch>dng*8 then zp:=okl*dng*8
else zp:=okl*ch;
Field[i,6]:=FormatFloat('0.00',zp);
if CheckBox1.Checked then
pr:=StrToFloat(Edit1.Text)*zp/100
else pr:=0.0;
Field[i,7]:=FormatFloat('0.00',pr);
it:=zp+pr;
Field[i,8]:=FormatFloat('0.00',it);
with DrawGrid1 do DrawGrid1DrawCell(Sender,0,i,
CellRect(0,i),[gdSelected,gdFocused]);
end;
end;
BitBtn1.SetFocus;
end;
end.
Обработчик событий OnSetEditText содержит три оператора. Первый оператор не позволяет изменить количество часов для табельного номера 1 (оно связано с количеством отработанных дней) или количество дней для второго сотрудника (оно связано с количеством отработанных часов). Второй оператор изменяет количество часов, если количество дней изменено пользователем. Третий оператор служит тем же целям, что и второй, - изменяет количество дней для табельного номера 2.
Обработчик OnSelectCell запрещает при вводе выбор ячеек, находящихся в столбцах 0, 5, 6, 7, 8.
