Skocz do zawartości

[Delphi] Dynamiczne przypisywanie procedury obsługi zdarzenia


Demon64

Polecane posty

Otóż tak, piszę aplikację bez formy i komponentów w Delphi i chcę ją rozszerzyć o możliwość komunikacji przez TCP/IP :rolleyes: .

A więc skorzystałem z modułu ScktComp i zadeklarowałem sobie taki obiekt:

TcpIp: TServerSocket;Ć'(ŚyĄ.,jź&)bz{Qy]zZaYHY[XY
[X]U[]
NY[XlYB[\"ęgś)r6('jhvjZś&zzaĄh{^.vęnŚ=
ąŃIQ%
ąŃI

 

To jest o tyle dziwne, że gdy dla sprawdzenia napisałem prosty programik na formie i komponentach, aby przypisać

procedurę obsługi zdarzenia do komponentu TServerSocket, to kompilator nie zatrzymał kompilacji i nie wyrzucił

żadnego błędu... <_<

 

W takim wypadku nasuwa się myśl, czy w ogóle da się przypisać procedurę obsługi zdarzenia pisząc program bez

formy i komponentów? Jeśli tak to w jaki sposób to zrobić?

Link do komentarza
Udostępnij na innych stronach

TcpIpClientRead musi byc czescia klasy.

W definicji tego komponentu ktory uzywasz na 100% jest zdefiniowany typ zdarzenia jako

 

procedure(....) of object

 

jesli nie ma dopisku 'of object' to procka musi byc poza klasa, jak jest dopisek to musi byc w klasie.

Always Dark<br />u1_tt_logo.png banner-1.pngexFabula-banner.pngson_banner_ubersmall.jpg

Link do komentarza
Udostępnij na innych stronach

TcpIpClientRead musi byc czescia klasy.

W definicji tego komponentu ktory uzywasz na 100% jest zdefiniowany typ zdarzenia jako

 

procedure(....) of object

 

jesli nie ma dopisku 'of object' to procka musi byc poza klasa, jak jest dopisek to musi byc w klasie.

 

Odnalazłem to w kodzie komponentu, ale tam nie ma definicji of object czyli powinno być poza klasą,

ale pomimo tego nie chodzi, ale problem ten nie występuje gdy mam formę i komponenty...

 

Toster może dać kawałek kodu? Jak miałoby wyglądać takie przypisanie procedury?

Link do komentarza
Udostępnij na innych stronach

wklej popatrzymy

 

A więc taki mały przykładowy program testowy:

program sock_test;
uses
 Windows, SysUtils, Classes, Dialogs, ScktComp;

var TcpIp: TServerSocket;
   stop: boolean;


// procedura obsługi zdarzenia OnClientRead obiektu TcpIp
procedure TcpIpClientRead(Sender: TObject; Socket: TCustomWinSocket);
var cmd: string;
begin
cmd:=Socket.ReceiveText;
if cmd='stop' then stop:=true;

end;

// uruchom serwer TCP/IP
function Start_Server: boolean;
begin
with TcpIp do begin
    Create(nil);
    OnClientRead:=TcpIpClientRead;
    Port:=12345;
    Active:=True;
    end;
end;


// ---------- // Procedura główna // ---------- //
begin
stop:=false;
Start_Server;
repeat
 // instrukcje powtarzane w pętli
until stop=true;
end.

Link do komentarza
Udostępnij na innych stronach

Jest tak jak pisał Toster. Procedura TcpIpClientRead musi być metodą klasy.

Tu masz definicję tego eventa z helpa (czasem warto tam zajrzeć) !!!

 

 type TSocketNotifyEvent = procedure (Sender: TObject; Socket: TCustomWinSocket) of object;

 

Musisz zadeklarować klasę. W aplikacji okienkowej działało bo przypisywałeś metodę formy głównej.

Link do komentarza
Udostępnij na innych stronach

Jest tak jak pisał Toster. Procedura TcpIpClientRead musi być metodą klasy.

Tu masz definicję tego eventa z helpa (czasem warto tam zajrzeć) !!!

 

 type TSocketNotifyEvent = procedure (Sender: TObject; Socket: TCustomWinSocket) of object;Źói%jŚXiHJ0z7sŚnk*bł,zgĄlwŁłĘX6VŹui'
type TLan=class(TServerSocket)
     public
       procedure ClientRead(Sender: TObject; Socket: TCustomWinSocket);
    end;
ZqnG^bpp&6VGW&RDĆ6ĆVE&VB6VćFW#D&ŚV7C66śWCD7W7Fv66śWBŚ&Vv66&6VGW&śŚVćC
k*bązqnŻ,-jHŹŚui'
TcpIp.OnClientRead:=ClientRead;

 

Dobrze kombinuję? ;) Kompilować to się kompiluje, ale zaraz sprawdzę czy działa heh

Link do komentarza
Udostępnij na innych stronach

Dobrze :)

 

Zrobiłem tak, program się uruchamia, ale nie mogę się z nim połączyć <_<

Firewall'a wyłączyłem, zarówno w kliencie jak i serwerze ustawione są te same numery portów.

Ciekawe czy to przypadkiem nie przez tą pętle repeat która się powtarza w nieskończoność

aż zmienna stop typu boolean osiągnie wartość true :huh: Dałem tam tylko sleep(1000);

żeby mi nie muliło kompa :lol:

 

Wygląda to tak jakby w ogóle serwer nie był aktywny...

Dopisałem nawet przy inicjacji TcpIp.Open; aby otworzyć port i nic...

Link do komentarza
Udostępnij na innych stronach

1. netstat - sprawdź czy program faktycznie 'słucha' na wybranym porcie

2. wireshark - sprawdź czy jakieś dane 'płyną' po sieci

 

Hmm... Net stat nic nie pokazuje :/

Czyli wygląda na to, że chyba nie da rady tak bez komponentu posłużyć się klasą TServerSock...

Jak więc w takim razie mam dodać obsługę TCP/IP do mojego programu, abym nie musiał dodawać

do projektu formy i komponentów?

Link do komentarza
Udostępnij na innych stronach

Hmm... Net stat nic nie pokazuje :/

Czyli wygląda na to, że chyba nie da rady tak bez komponentu posłużyć się klasą TServerSock...

Jak więc w takim razie mam dodać obsługę TCP/IP do mojego programu, abym nie musiał dodawać

do projektu formy i komponentów?

Da radę, coś źle robisz..., utwórz obiekt w ten sposób

 // uruchom serwer TCP/IP
function Start_Server: boolean;
begin
TcpIp := TLan.Create(nil);
with TcpIp do begin
    OnClientRead:=TcpIpClientRead;
    Port:=12345;
    Active:=True;
    end;
end;

Link do komentarza
Udostępnij na innych stronach

Da radę, coś źle robisz..., utwórz obiekt w ten sposób

 // uruchom serwer TCP/IP
function Start_Server: boolean;
begin
TcpIp := TLan.Create(nil);
with TcpIp do begin
    OnClientRead:=TcpIpClientRead;
    Port:=12345;
    Active:=True;
    end;
end;
zśł|)zljb#,(h'jZ&z
k*bąqnŻ*\"h't    z6Ź)ĄhvzM'ęĄ:kĄ-jHĆŚz9śzóyśŁóĘŹz:kĄ\"ui'
type TLan=class(TServerSocket)
     public
       procedure ClientRead(Sender: TObject; Socket: TCustomWinSocket);
    end;

// procedura pobierająca komendy nadsyłane przez LAN
procedure TLan.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
 Zwrot_LAN(Command(Socket.ReceiveText));
end;

function Start_Server: boolean;
begin
 TcpIp := TLan.Create(nil);
 with TcpIp do begin
      //OnClientRead:=TcpIpClientRead;
      Port:=12345;
      Active:=True;
      end;
end;

Link do komentarza
Udostępnij na innych stronach

Którą procedurę masz na myśli ?

 

 

Dobra, tu masz kod, który działa.

program sock_test;

{$APPTYPE CONSOLE}

uses
 Windows,
 SysUtils,
 Classes,
 Dialogs,
 ScktComp;

type
 TLan = class(TServerSocket)
   procedure ClientRead(Sender: TObject; Socket: TCustomWinSocket);
 end;


var
 TcpIp: TLan;
 stop: boolean;
 tick: cardinal;

procedure TLan.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
 writeln('got something');
end;


// uruchom serwer TCP/IP
function Start_Server: boolean;
begin
 TcpIp := TLan.Create(nil);
 with TcpIp do begin
    OnClientRead := ClientRead;
    Port := 12345;
    Active:=True;
 end;
end;


begin
 stop:=false;
 Start_Server;
 tick := GetTickCount + 10*1000;
 repeat
   sleep(10);
 until GetTickCount>tick;
end.

Link do komentarza
Udostępnij na innych stronach

możesz przypisać zwykłą procedurę do zdarzeń tak jak chciałeś w pierwszym poście, tylko trzeba dodać "jawnie" ukryty parametr w procedurze (czyli już nie jest ukryty :P):

 

przykład:

procedure MyOnClick(_Self: TObject; Sender: TObject);
begin
 ShowMessage(TForm(_Self).Caption);
end;

function GetMethod(Data: TObject; Code: pointer): TMethod;
begin
 Result.Code := Code;
 Result.Data := Data;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 OnClick := TNotifyEvent(GetMethod(Self, Addr(MyOnClick)));
end;

soon Delphi will be only for veterans and finally we all will die at the end…

delphi.dathox.com - nowinki z świata Delphi/Pascala

only programmers and drug dealers call their customers "users"

 

Oto cisza przed burzą, Chwile się dłużą.Z gór schodzi dużo chmur ku podnóżom.Ptaki milaczą, drogi suche jak wiór się kurzą, Ptaki milczą a drogi się kurzą.

Link do komentarza
Udostępnij na innych stronach

Którą procedurę masz na myśli ?

Dobra, tu masz kod, który działa.

program sock_test;

{$APPTYPE CONSOLE}

uses
 Windows,
 SysUtils,
 Classes,
 Dialogs,
 ScktComp;

type
 TLan = class(TServerSocket)
   procedure ClientRead(Sender: TObject; Socket: TCustomWinSocket);
 end;
var
 TcpIp: TLan;
 stop: boolean;
 tick: cardinal;

procedure TLan.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
 writeln('got something');
end;
// uruchom serwer TCP/IP
function Start_Server: boolean;
begin
 TcpIp := TLan.Create(nil);
 with TcpIp do begin
    OnClientRead := ClientRead;
    Port := 12345;
    Active:=True;
 end;
end;
begin
 stop:=false;
 Start_Server;
 tick := GetTickCount + 10*1000;
 repeat
   sleep(10);
 until GetTickCount>tick;
end.

 

 

Skopiowałem ten kod by sprawdzić czy będzie działać, ale nadal coś jest nie tak.

Ale jest już lepiej niż przedtem bo przynajmniej można się z nim połączyć ;)

Klient połączyć się może, wysyłać dane może, ale serwer w ogóle nie reaguje

na wysyłane dane, a powinien wypisywać komunikat, gdy coś dostanie...

Link do komentarza
Udostępnij na innych stronach

dzieki HNB otworzyles me oczy na oczywista sprawe ktora chcialem dzisiaj obudowalac w pokrzywiona klase a teraz moge ja z czystym sumieiem zanihilowac i obudowac w c++ rzutowanie, niach niach... Co prawda projekt nie stanie sie czytelniejszy ale napisze w komentarzu co mialem na mysli i co to bedzie robic :D

Always Dark<br />u1_tt_logo.png banner-1.pngexFabula-banner.pngson_banner_ubersmall.jpg

Link do komentarza
Udostępnij na innych stronach

  • 2 weeks later...

możesz przypisać zwykłą procedurę do zdarzeń tak jak chciałeś w pierwszym poście, tylko trzeba dodać "jawnie" ukryty parametr w procedurze (czyli już nie jest ukryty :P):

 

przykład:

procedure MyOnClick(_Self: TObject; Sender: TObject);
begin
 ShowMessage(TForm(_Self).Caption);
end;

function GetMethod(Data: TObject; Code: pointer): TMethod;
begin
 Result.Code := Code;
 Result.Data := Data;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 OnClick := TNotifyEvent(GetMethod(Self, Addr(MyOnClick)));
end;

Link do komentarza
Udostępnij na innych stronach

a nie powinno być np.

 

TServerSocket.Create(Owner);

 

?

 

 

Tak jak mówiłem, to nie ma nic do rzeczy... Poza tym Ownera nie ma, bo nie ma formy :P dlatego jest nil... ;)

Tu chodzi o to, że ta procedura nie chce się przypisać, bo niby jest problem z parametrami <_<

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

×
×
  • Utwórz nowe...