Tüm Platformlar için Hızlı Uygulama Geliştirme Kitabı... Delphi

Konuyu Paylaş : facebook gplus twitter

Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Nested Prosedürler Neden Event Handler Olamıyor?
#1
Merhaba değerli üyeler , 
DLL içinde bir fonksiyonum var, bu fonksiyon bazı nesneler oluşturuyor ve oluşan nesnelerin olaylarına da bir şeyler yapmam gerekiyor, ancak şöyle bir kullanım yapamıyorum ;

function GetPolicy( pWSUserName , pWSPass , pIP , pAgentCode , pUserName , pBegin , pEnd , pFileName , pProxy : PAnsiChar ;pDebug : Integer ) : PAnsiChar ; export ; stdcall;

           procedure RIO1AfterExecute(const MethodName: string;
           SOAPResponse: TStream);
              var
                 intList:TStringList;
               begin

                 try
                   intList := TStringList.Create;

                   SOAPResponse.Position := 0;

                   intList.LoadFromStream(SOAPResponse);
                   if pDebug = 1 then intList.SaveToFile(ExtractFilePath( GetModuleName( HInstance ) )+'response.xml');
                 finally
                   intList.Free;
                 end;

               end;






var
 rio1 : THTTPRIO;


 begin
 try
  CoInitialize(nil);
 Result := '';


 rio1 := THTTPRIO.Create(nil);





// alttaki gösterime müsaade etmiyor  derleme anı hatası oluşuyor   ([DCC Error] E2009 Incompatible types: 'method pointer and regular procedure')
  rio1.OnAfterExecute := RIO1AfterExecute;

Ancak aşağıdaki şekilde atama yapabiliyorum ve olay çalışıyor

 @rio1.OnAfterExecute  := @RIO1AfterExecute;

bu durumda da ilgili olayın "SOAPResponse" değişkeni her zaman NIL oluyor..

Her hangi bir kayba uğramadan nested bir kullanım yapabilmenin bir yolu var mı?
Cevapla
#2
Metodu dediğiniz gibi @ ile adresini çağırarak çalıştırabilirsiniz. Bir yöntemde reference to "method" dur. Bir dummy method tanımlayıp bu methoda sizin methodunuzu refere edersiniz sonra geri çağırırsınız. Eventlerin çalışma mantığıda buna benzerdir. 

Refenrece ile İlgili şu Linkleri Görebilmeniz İçin Giriş yap veya Üye Olbir göz atabilirsiniz.
WWW
Cevapla
#3
Bunun için bir sınıf oluşturup, onun içinde RIO1AfterExecute'ı tanımlayabilirsiniz.
TMyClass = class
 public
   class procedure RIO1AfterExecute(const MethodName: string, SOAPResponse: TStream);
 end;

implementation

class TMyClass.procedure RIO1AfterExecute(const MethodName: string, SOAPResponse: TStream);
var
 intList:TStringList;
begin
try
  intList := TStringList.Create;

  SOAPResponse.Position := 0;

  intList.LoadFromStream(SOAPResponse);
  if pDebug = 1 then intList.SaveToFile(ExtractFilePath( GetModuleName( HInstance ) )+'response.xml');
finally
  intList.Free;
end;

Sonra atama yaparken;
rio1.OnAfterExecute  := TMyClass.RIO1AfterExecute;
There's no place like 127.0.0.1
WWW
Cevapla
#4
(12-05-2017, Saat: 17:01)witalihakko Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlMetodu dediğiniz gibi @ ile adresini çağırarak çalıştırabilirsiniz. 

Adres ataması şeklinde kullandığımda derleniyor ve olay anında ilgili metod çalışıyor  ancak olay metoduna düşmesini beklediğim değişkenler NİL burda var bir püf noktası bence. linkteki diğer yöntemleri ayrıca vakit ayırıp inceleyeceğim teşekkürler.

@SimaWB örneklediğin yöntem tam olarak istediğim şekilde çalıştı çok teşekkür ederim.
Cevapla
#5
Delphi'nin olay mekanizması method pointerlar üzerine bina edilmiştir. Bu nedenle normal bir pointer'ı atarsanız istediğiniz sonuçları alamazsınız. TMethod yapısına bakacak olursanız, Code ve Data isimli iki ayrı pointer'a ihtiyaç duyulduğunu gözlemleyebilirsiniz. Bu pointer'lardan birisi ilgili metodun adresi, diğeri ise ilgili metodu bünyesinde barındıran sınıf instance'ının adresidir. Bu yapı sayesinde ilgili metod pointer'larına Self yani instance'ın kendisi de parametre olarak gönderilebilir.

Tabii ilgili sınıf instance'ına (Self) ihtiyacınız var ise. Eğer yok ise, bu durumda Delphi'nin kullandığı yapı üzerinde bazı ufak hileler kullanabilirsiniz. Örneğin bir sınıfın içine ilgili metodu static olarak (class metod) yazarak da kullanabilirsiniz. Ancak bu durumda ilgili sınıfın bir instance'ı olmadığı için elbette instance bilgisi elde edemezsiniz.

 Ya da TMethod yapısının Data pointer'ını nil'e eşitleyip, Code pointer'ına ilgili metodun adresini geçerek de Delphi'yi kandırabilirsiniz. Üçkağıdın sonu yok :-)
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#6
(15-05-2017, Saat: 14:36)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol Ya da TMethod yapısının Data pointer'ını nil'e eşitleyip, Code pointer'ına ilgili metodun adresini geçerek de Delphi'yi kandırabilirsiniz. Üçkağıdın sonu yok :-)

Tuğrul abi öncelikle ek önerin için teşekkürler. yukarıdaki kısım için minik bir örnek  karalarmısın kafamda tam oturtamadım.
Cevapla
#7
(16-05-2017, Saat: 14:58)vkamadan Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
(15-05-2017, Saat: 14:36)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol Ya da TMethod yapısının Data pointer'ını nil'e eşitleyip, Code pointer'ına ilgili metodun adresini geçerek de Delphi'yi kandırabilirsiniz. Üçkağıdın sonu yok :-)

Tuğrul abi öncelikle ek önerin için teşekkürler. yukarıdaki kısım için minik bir örnek  karalarmısın kafamda tam oturtamadım.

Rica ederim. Aşağıdaki basit kodu biraz inceleyebilirsin sevgili kardeşim. Umarım işine yarar Wink

procedure TForm1.DummyClick(Sender: TObject);
begin
  if not Assigned(Sender)
  then ShowMessage('Sender is nil')
  else ShowMessage(Sender.ClassName);

  ShowMessage('Dummy clicked');
end;

procedure DummyClick2(Sender: TObject);
begin
  if not Assigned(Sender)
  then ShowMessage('Sender is nil')
  else ShowMessage(Sender.ClassName);
  
  ShowMessage('Dummy clicked-2');
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  M : TMethod;
begin
  M.Code := @TForm1.DummyClick;
  M.Data := nil;

  Button4.OnClick := TNotifyEvent(M);
end;

// ya da 

procedure TForm1.Button3Click(Sender: TObject);
var
  M : TMethod;
begin
  M.Code := @DummyClick2;
  M.Data := Self;

  Button4.OnClick := TNotifyEvent(M);
end;
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#8
Tuğrul abi örneğin sayesinde "TMetod" un "Code" ve "Data" yapısını çok net anladım , özetlemek gerekirse "Code" metodun adresini tutarken "Data" metoda geçilecek parametreleri tutuyor (örn : Sender)
Emeğine sağlık iyi çalışmalar.
Cevapla

Konuyu Paylaş : facebook gplus twitter



Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  TCustomControl neden TRANSPARENT olmuyor? uparlayan 7 474 03-04-2018, Saat: 15:06
Son Yorum: uparlayan
  Rad Studio Neden Bu Kadar Hızlı? savasabd 14 1.501 27-09-2017, Saat: 19:21
Son Yorum: ismailkocacan
  Neden FMX ? Lord_Ares 19 2.071 04-04-2017, Saat: 11:46
Son Yorum: engerex



Konuyu Okuyanlar: 1 Ziyaretçi