var Form1: TForm1; uins:array[1..1000,1..2,1..2,1..2] of string[30]; users:integer; implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject); begin randomize; end;
procedure TForm1.ICQClient1Error(Sender: TObject; ErrorType: TErrorType; ErrorMsg: string); begin slabel6.caption:=errormsg; end;
procedure TForm1.ICQClient1Login(Sender: TObject); var i,i2,i3,i4:integer; begin slabel5.Caption:='активен'; sedit1.Enabled:=false; sedit2.Enabled:=false; sbutton1.enabled:=false; for i:=1 to 1000 do for i2:=1 to 2 do for i3:=1 to 2 do for i4:=1 to 2 do uins[i,i2,i3,i4]:=''; end;
procedure TForm1.ICQClient1LogOff(Sender: TObject); begin slabel5.caption:='Неактивен'; end;
Function prov(s:string):boolean; var i:integer; begin for i:=1 to users do begin if uins[i,1,1,1]=s then begin prov:=true; break; end else prov:=false; end; end;
Function prov2(s:string):integer; var i:integer; begin for i:=1 to users do begin if uins[i,1,1,1]=s then begin prov2:=i; break; end else prov2:=0; end; end;
function provnick(s:string):boolean; var i:integer; begin for i:=1 to users do begin if uins[1,1,i,1]=s then begin provnick:=true; break; end else provnick:=false; end; end;
procedure TForm1.ICQClient1MessageRecv(Sender: TObject; Msg, UIN: string); var z,c1,c2,c3:byte; nick:string; begin if not(prov(uin)) then begin inc(users); uins[users,1,1,1]:=uin; uins[users,2,1,1]:='1'; end; begin case strtoint(uins[prov2(uin),2,1,1]) of 1:begin if uins[prov2(uin),1,1,2]<>'' then begin if (msg=uins[prov2(uin),1,1,2]) then begin icqclient1.sendmessage(strtoint(uin), 'Верно!Для входа в чат отправьте без кавычек "/go Ваш_Никнейм"'); uins[prov2(uin),2,1,1]:='2'; end else begin icqclient1.SendMessage(strtoint(uin),'Неверно! Попробуйте ещё раз'); uins[prov2(uin),1,1,2]:=''; end; end else begin c1:=random(100)+1; c2:=random(100)+1; c3:=c1+c2; icqclient1.SendMessage(strtoint(uin), 'Вопрос антиспама: сложите 2 числа и пришлите ответ: '+inttostr(c1)+'+'+inttostr(c2)); uins[prov2(uin),1,1,2]:=inttostr(c3); end; end; 2:begin if (copy(msg,1,3)='/go') or (copy(msg,1,3)='/GO') then begin delete(msg,1,4); if not(provnick(msg)) then begin uins[prov2(uin),1,2,1]:=msg; uins[prov2(uin),2,1,1]:='3'; slistbox1.Items.add(uins[prov2(uin),1,2,1]); end else begin icqclient1.sendmessage(strtoint(uin),'Такой никнейм уже существует, выберите другой!'); end; end; end; 3:begin smemo1.Lines.insert(0,msg); for z:=1 to users do begin if uins[z,2,1,1]='3' then begin // if (uins[z,1,1,1]<>uin) then (* !!! *) // begin icqclient1.sendmessage(strtoint(uins[z,1,1,1]),msg); sleep(500); // end; (* !!! *) end; end; end; end; end; end;
procedure TForm1.sButton1Click(Sender: TObject); begin users:=0; slabel6.caption:=''; icqclient1.UIN:=strtoint(sedit1.text); icqclient1.Password:=sedit2.text; icqclient1.login; end;
procedure TForm1.sEdit1KeyPress(Sender: TObject; var Key: Char); begin if not(key in ['0'..'9']) then key:=#0; end;
end.
Вот в таком виде программа работает. Но стоит раскомментировать указанные строки, или каким-то образом обратиться к элементу массива uins[prov2(uin),1,2,1]; (в этой ячейке хранятся никнеймы пользователей), вывести в Memo, например, то при получении первого сообщения программа вообще молчит, при получении второго вылетает Acsess Violation и отладчик показывает на строку
FOnMsg(Self, Msg, UIN);
в модуле IcqClient.pas. Что есть очень странно, ведь ответ на сообщение не добавленному пользователю в коде идёт намного раньше того места, где я что-то добавлял, ну или раскомментировал строки. Как я понял из ошибки (возможно, неправильно понял), программа при получении первого сообщения не выполняет обработчик OnMessageRecv до конца, и когда приходит второе сообщение, вылетает... Вот полный проект, на всякий случай.
--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."