チャットプログラムを作っています。
LAN内で特定のサーバに依存しない複数 対 複数とのやり取りをするため、clientsocketを以下の手順でコンポーネント配列にしてみました。
----------------------------------------------------------
var sck : array[0..99] of TClientSocket;
rocedure TForm1.FormCreate(Sender: TObject);
var i : integer;
begin
serversocket1.port := 23451;//ポート番号は変更できるようにしています。
serversocket1.open;
for i:=0 to cc do
begin
sck[cc] := TClientSocket.Create(self);
end;
//略
end;
----------------------------------------------------------
このようにした時、sck[n]のOnReadイベントをやOnConnectイベントを実行させる為にはどのようにしたら良いですか?
また、これでは、使わないソケット、あるいは、ソケットが足りなくなるという問題が残ります。動的に(OnConnectイベントでソケットを1つ生成してオープンさせるといった風な)ソケットを追加する方法はありますか?
長くなってしまいましたが、ご教授お願いします。
プログラムの7行目間違いです。
ccではなくて、99です。
おねがいします。
プログラムの9行目間違いです。
ccではなくて、iです。
おねがいします。
動的にコンポーネントをつくり、イベントハンドラを割り当て、インスタンスを
管理する例を TLabel について示します。参考にしてください。
public
LabelList:TList;
procedure LblClick(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
i,index:integer;
Lbl:TLabel;
begin
LabelList := TList.Create;
for i := 1 to 3 do
begin
Lbl := TLabel.Create(self);
index := LabelList.Add(Lbl);
Lbl.Parent := self;
Lbl.Left := 150*index + 10;
Lbl.Top := 10;
Lbl.Color := clYellow;
Lbl.Caption := 'Label '+IntToStr(index);
Lbl.Tag := index;
Lbl.OnClick := LblClick;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
LabelList.Free;
end;
procedure TForm1.LblClick(Sender: TObject);
var
index:integer;
begin
index := TComponent(Sender).Tag;
TLabel(LabelList[index]).Caption := 'You Clicked Me!';
end;
ありがとうございます。
これは、フォーム生成時に無条件に3つのコンポーネントを生成していますね。
チャットをする場合、相手の数だけソケットを用意する必要があり、未知の数のソケットが必要になります。しかも、無駄にソケットがあるのは好ましくありません。
何か、イベントが起こる毎にコンポーネントを1つずつ追加するようなことは出来ないでしょうか。
これだと、相手が何人であろうが、ソケットは相手の数+1で済みます。
ご教授おねがいします。
いくつでもコンストラクタで生成していけばいいんでは?
OnCreate イベントハンドラのコードはその一例にすぎません
Button1Click でラベルのインスタンスをつくり、そのラベルのクリックで
削除できるようにしました。参考にしてください。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
LabelList:TList;
CountHistory:integer;
procedure LblClick(Sender: TObject);
procedure WMApp(var Msg:TMessage);message WM_APP;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
LabelList := TList.Create;
CountHistory := 0;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
LabelList.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Lbl:TLabel;
begin
Lbl := TLabel.Create(self);
LabelList.Add(Lbl);
Lbl.Parent := self;
Lbl.Left := 150*(CountHistory mod 4) + 10;
Lbl.Top := 50*(CountHistory div 4)+ 10;
Lbl.Color := clYellow;
Lbl.Caption := 'Label '+IntToStr(CountHistory);
Lbl.Tag := CountHistory;
Lbl.OnClick := LblClick;
Inc(CountHistory);
end;
procedure TForm1.LblClick(Sender: TObject);
var
Lbl:TLabel;
index:integer;
begin
Lbl := TLabel(Sender);
Lbl.Color := clLime;
Lbl.Caption := 'This is '+IntToStr(Lbl.Tag);
if MessageDlg('このラベルを削除しますか?',mtInformation,
[mbYes,mbNo],0) = mrYes then
begin
index := LabelList.IndexOf(pointer(Lbl));
PostMessage(Handle,WM_APP,index,0);
end;
end;
procedure TForm1.WMApp(var Msg:TMessage);
begin
if Msg.WParam >= 0 then
begin
TLabel(LabelList[Msg.WParam]).Free;
LabelList.Delete(Msg.WParam);
end;
end;
end.
このように出来るのでしたか、グローバル変数をうまく使えば出来そうです。
freeはコンポーネント配列を作ったときは必ずしなければなりませんか?
ツイート | ![]() |