- •Windows -приложение
- •Среда программирования
- •Встроенный отладчик
- •Использование графики
- •Графические данные и палитра
- •Сохранение проекта
- •Структура приложения
- •Структура модуля
- •Простые типы
- •Символьные типы
- •Логические типы
- •Тип перечень
- •Составной оператор
- •Оператор if
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла repeat
- •Пример приложения 6
- •Пример приложения 7
- •Статические массивы
- •Динамические массивы
- •Оператор with
- •Идентичность типов
- •Совместимость типов
- •Преобразование типов
- •Операторы обработки исключительных ситуаций
- •Рекурсия
- •Процедура exit
- •Директивы подпрограммы
- •Класс как объектный тип
- •Наследование
- •Операции is и as
- •Типы ссылки на класс
- •Типизированные файлы
- •Файлы без типа
- •Пример приложения 17
- •Компонент tmainmenii
- •Двунаправленные списки
- •Потоки данных
- •Пример приложения 22
- •Интерфейс drag and drop
- •Пример приложения 24
- •С файлами
- •Пример приложения 26
- •Программные потоки
- •Приоритеты потоков
- •Класс tthread
- •Проблемы синхронизации потоков
Оператор with
Оператор With часто называется оператором присоединения. Для того чтобы не записывать каждый раз имя селектора, при обращении к поля*1 записи используется этот оператор, например,
With Data do begin
78
Таблица 12
Табельный |
ФИО |
Окл., Т.е. |
Час |
Дни |
Дни граф. |
3 |
П |
И |
1 |
Иванов ИИ. |
6000 |
176 |
22 |
24 |
|
|
|
2 |
Петров П. П. |
40 |
184 |
23 |
24 |
|
|
|
В данном случае заданы два варианта расчета зарплаты: по окладу (Окл. = 6000) и по часовой тарифной ставке (Т.е. = 40). В первом случае зарплата расчитывается следующим образом: 3 =
Во втором случае необходимо использовать такие соотношения: 3 = Т.с.Час;Час<8-Дни.
Указанные ограничения в формулах означают, что, если сотрудник отработал больше, чем по графику, то это сверхурочные, которые оплачиваются отдельно (в примере сверхурочные не учитываются). Используемая во втором случае цифра 8 означает, что задан восьмичасовой рабочий день.
Предусмотрена премия не более 150 % от зарплаты, которая выплачивается, если предприятие имеет прибыль. Форма с вариантом решения приводится на рис. 30.
Рис-30
решается в 2 этапа: вначале - ввод информации (можно изменить исходные данные), затем - расчет.
Как и в предыдущих случаях, в данном примере использовались новые лоненты. Для указания, есть ли премия в данном месяце, необходим пе-
79
реключатель. При решении примера 10 использовался переключатель см зависимой фиксацией TCheckBox. Этот стандартный элемент Windows зволяет выбрать или отменить определенную опцию. С помощью групД таких переключателей можно выбирать или отключать несколько опций on. новременно. Состояние переключателя (вкл/выкл) содержится в свойств Checked. Для обработки переключений используется событие OnClick Кнопку можно перевести в третье состояние ("включенное серое") с иощ щью свойства AllowGrayed. Это свойство используется, если переключатеЯ содержит еще ряд вложенных переключателей. Третье состояние перекли чателя указывает, что вложенные опции не все включены или не все выкли чены. Узнать, включено ли свойство AllowGrayed, можно с помощью свойства State.
Для полноты представления проблемы рассмотрим еще один вид пере-ключателей - переключатель с зависимой фиксацией - TradioButton. Эта вид переключателей в примере 9 уже использовался, но в составе группа Если выбрано несколько таких переключателей, то они автоматически объе диняются в группу и позволяют из множества опций выбрать одну, в отЛ чие от CheckBox. TradioButton также имеет свойство Checked и событие OkClick, свойство AllowGrayed отсутствует.
Для представления табличных данных использовалась графическая таблица TDrawGrid, которая, в отличие от TStringGrid, может отображать не только текстовую информацию, но и графическую. TDrawGrid имеет значительно больше возможностей, чем TStringGrid. Например, размеры строк и столбцов можно изменять индивидуально. Можно изменять и цвет ячеек (индивидуально). Внешний вид графической сетки настраивается с помощью следующих свойств: ColCount, RowCount - число столбцов и строк; DefaultCoIWidth, DefauttRowHeight - высота и ширина по умолчанию; Height, Width - ширина и высота таблицы; FixedColls, FixedRows - фиксированное число столбцов и строк. Индивидуальные размеры строк и столбцов содержатся в свойствах ColWidth и RowHeight. Эти свойства являются массивами. Отметим несколько опций свойства Options: GoRowSizing -разрешить или запретить изменение размеров строк, GoColSizing - разрешить или запретить изменение размеров столбцов, GoEditing - разрешить или не разрешить редактирование, GoAIwaysShowEditor - если эта опция отключена, то редактор загружается клавишей F2 или щелчком мыши, если эта опция включена, то редактор загружается автоматически. В отличие от TStringGrid, TDrawGrid не имеет свойства Cells (ячейки), поэтому ввод данных и их запись после редактирования нужно организовывать самостоятельно. Для отображения данных необходимо воспользоваться событие*1 OnDrawCell - перерисовка ячеек. При перерисовке ячеек область рисований (в пикселах) задается в виде свойства Rect (прямоугольник). Свойство Rec* преобразует номера колонки и строки в прямоугольник, заданный в пиксе*
Перерисовка ячейки зависит от свойства 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.
-
С помощью Button 1 предусмотрим обработчик, задающий начало расчета (OnClick).
-
Для Edit1 необходим OnKeyPress.
-
Для Edit1 необходим OnExit, чтобы контролировать ввод числа (не более 150) по условию задачи.
-
Для CheckBoxl организуем обработчик при потере фокуса этим эле ментом (OnExit) и передаче фокуса или Edit1 или DrawGridl (обход Edit1).
Для записи результатов ввода и итоговых результатов предусмотрим Двумерный массив Field, который должен объявляться глобально. Размеры Массива [0...2], [0...8] - 3 строки и 9 столбцов. Для выполнения всех расчетов воспользуемся типом данных запись. Ниже приводится программа.
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, Buttons, StdCtrls, ExtCtrls;1 type TMainForm = class(TForm)
Panel1: TPanel;
Button1: TButton;
BitBtnl: TBitBtn;
DrawGridl: TDrawGrid;
CheckBoxl: TCheckBox;
Edit1: TEdit;
Label1: TLabel;
procedure DrawGridlDrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState); procedure DrawGridlGetEditText(Sender: TObject;
ACol, ARow: Integer; var Value: String); procedure DrawGridlClick(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure DrawGridlSetEditText(Sender: TObj ect;
ACol, ARow: Integer;const Value: String); procedure DrawGridlSelectCell(Sender: TObject; ACol, ARow: Integer;var CanSelect: Boolean); procedure DrawGridlKeyPress (Sender: TObject;
var Key: Char);
procedure CheckBoxlExit(Sender: TObject); procedure Edit1KeyPress(Sender: TObject;
var Key: Char)
procedure Button1Click(Sender: TObject); end;
0..8] of string =(('Ta6N' , 'Дней','Дн.г.','Зарпл', ','Иванов И.И.','6000', ','0'),('2','Петров П.П.’,
0 ' , ' 0 ', ' 0 ') ) ;
var MainForm: TMainForm; const Field: array [0..2, 'Ф.И.О.','Окл,Т','Час’,
Премия','Итого') , ('1 476','22','24', '0', '0’, ‘О' , 484' , '23', '24', implementation
{$R *.DFM)
procedure TMainForm.DrawGridlDrawCell(Sender: TObject;
ACol, ARow: Integer;Rect: TRect; State: TGridDrawState); var i,j:byte; begin
With DrawGridl 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-
82
Left-TextWidth(Field[j,i])) div 2,Top+(Bottom-Top-TextHeight(Field[j,i])) div 2,Field[j,i]); end;
end;
end;
procedure TMainForm.DrawGridlGetEditText(Sender:TObj ect; ACol, ARow: Integer;var Value: String);
begin
Value:=Field[ARow,ACol] ;
end;
procedure TMainForm.DrawGridlClick(Sender: TObject);
begin
with DrawGridl do begin
DrawGridlDrawCell(Sender,0,0,CellRect(0,0), [gdFixed]); DrawGridlDrawCell(Sender, 0,1,CellRect(0,1),
[gdSelected,gdFocused]) ; DrawGridlDrawCell(Sender,0,2,CellRect(0,2),
[gdSelected,gdFocused] ) ; end;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var i:byte; begin
with DrawGridl 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.DrawGridlSetEditText(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.DrawGridlSelectCell(Sender: TObject;
ACol, ARow: Integer;var CanSelect: Boolean); begin
CanSelect:=true;
83
with DrawGridl do
if (ARow - 1) or (ARow = 2) then
if ACol in [0,5..8] then CanSelect:=false; end; procedure TMainForm.DrawGridlKeyPress(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.CheckBoxlExit(Sender: TObject); begin
if CheckBoxl.Checked then Edit1.SetFocus
else DrawGridl.SetFocus; end; procedure TMainForm.Edit1KeyPress(Sender: TObject;
var Key: Char); begin
if not (key in ['0'..'91,'.',#8]) thenkey:=#0; end;
procedure TMainForm.Edit1Exit(Sender: TObject); begin
if Length(Edit1.Text)=O then Edit1.Text:=T0.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:=l to 2 do begin with z [i] do begin
tbn:=StrToInt(Field[i,0]); fio:=Field[i,l];
84
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 CheckBoxl.Checked then
pr:=StrToFloat(Edit1.Text)*zp/100 else pr:=0.0;
Field[i,7]:=FormatFloat('0.00',pr) ;
It:=zp-t-pr;
Field[i,8]:=FormatFloat('0.00',it); with DrawGridl do DrawGridlDrawCell(Sender,0,i,
CellRect(0,i), [gdSelected,gdFocused]); end; end;
BitBtnl.SetFocus; end; end.
Обработчик событий onSetEditText содержит три оператора. Первый оператор не позволяет изменить количество часов для табельного номера 1 (оно связано с количеством отработанных дней) или количество дней для второго сотрудника (оно связано с количеством отработанных часов). Второй оператор изменяет количество часов, если количество дней изменено пользователем. Третий оператор служит тем же целям, что и второй, - изменяет количество дней для табельного номера 2. Обработчик OnSelectCell запрещает при вводе выбор ячеек, находящихся в столбцах 0, 5, 6, 7, 8.
СОВМЕСТИМОСТЬ И ПРЕОБРАЗОВАНИЕ ТИПОВ ДАННЫХ
Когда в тех или иных операциях или операторах присутствуют данные Различных типов, то возникают вопросы о соответствии типов друг другу. Стандартно выделяют три группы вопросов:
•идентичность типов;
•совместимость типов;
•совместимость по присваиванию.
85