procedure IniCOM;
var i, err: integer;
begin
FlagCOM:=False;
Form1.Label7.Caption:='COM?';
{инициализация COM — номер в строке stcom}
Form1.AfComPort1.Close; {закрываем старый COM, если был}
val(stcom[length(stcom)],i,err); {извлекаем номер порта}
if err=0 then Form1.AfComPort1.ComNumber:=i else exit;
{здесь требуется число, а не строка}
Form1.AfComPortl.BaudRate:=br9600; {скорость 9600}
try
Form1.AfComPortl.Open ;{пробуем открыть}
except
if not Form1.AfComPort1.Active then {если не открылся}
begin
st:=stcom+' does not be present or occupied.';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit {выход из процедуры — неудача}
end;
end;
ab[1]:=ord('A'); {будем посылать инициализацию модема}
ab[2]:=ord('Т');
ab[3]:=13; {CR}
ab[4]:=10; {LF}
for i:=1 to 4 do Form1.AfComPort1.WriteData(ab[i],1);
{ответ не сразу:}
Form1.Timer1.Enabled:=True;
tall:=0;
while tall<1 do application.ProcessMessages; {пауза в 1 с}
Form1.Timer1.Enabled:=False;
st:=Form1.AfComPort1.ReadString; {ответ модема 10 знаков}
if pos(1 OK',st)<>0 then {модем}
begin
st:=stcom+' занят модемом';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit;
end else {все нормально, COM открыт}
begin
Form1.Label7.Caption:=stcom+' 96001;
FlagCOM:=True;
end;
end;
Как видим, процедура создания порта много понятнее, чем в случае прямого обращения к API — все через привычную установку свойств компонента. FlagCOM играет у нас роль индикатора, доступен порт или нет. Если он остался при значении False, то процедуру следует повторить с другим значением в строке stcom (каковую мы задаем с помощью ComboBox, см. далее). При определении модема применен хитрый способ задания паузы — вместо обычного оператора Sleep, который тормозит программу, мы использовали таймер. Чтобы это сработало, надо в обработчике события OnTimer: все время увеличивать переменную tall. Полностью процедура по таймеру приводится далее, т. к. tall нам понадобится не только для этого.
Как только мы обратились к процедуре AfComPort1.open, у нас немедленно будет создан параллельный поток и весь прием пойдет через него. Поэтому, чтобы при определении модема принятые байты не обрабатывались, нужно не забыть добавить в процедуру приема выход по условию FiagCOM=Faise.
Для создания этой процедуры обычным способом — через инспектор объектов — создадим обработчик события AfComPort1DataRecived[17] (листинг 18.5).
procedure TForm1.AfComPort1DataRecived(Sender:TObject; Count:Integer);
{чтение очередного байта по сообщению wmCOMPORT}
var i: integer;
begin
if FlagCOM=False then exit; {если модем еще не опрошен}
if count<>0 then {если что-то принято}
begin
AfComPort1.ReadData(ab,count); {читаем буфер в массив}
хn:=xn+count; {число принятых байт}
tall:=0; {обнуляем время}
end;
end;
На самом деле условие count<>0 не требуется, оно введено просто ради порядка (иначе бы процедура просто не была бы вызвана). По выходу из процедуры в переменной хn будет накапливаться количество принятых байтов. Осталось только дописать остальные процедуры (листинг 18.6).