Delphi dynamiczne tworzenia komponentu - problem z procedurą

0

Witam!
Korzystam z komponentu HTTPG i pobieram przez niego pliki. Teraz gdy tworzę go dynamicznie event onprogres przypisuje procedurze HTTPGetFileProgress, lecz procedura nie identyfikuje się z konkretnym plikiem i wykonanie podglądu stanu pobierania dla poszczególnego THTTPGet jest nie możliwe.
Moje jedyne rozwiązanie jakie udało mi się zrobić to ręczne napisanie 10 procedur (HTTPGetFileProgress_1, HTTPGetFileProgress_2 ... HTTPGetFileProgress_10) ale nawet nie potrafię ich przypisać

sdownload[licz].OnProgress := HTTPGetFileProgress_licz;

jest błędne. Rozwiązanie pozwala na obieranie tylko 10 plików więc jest kiepskie. Czy istnieje dynamiczna metoda tworzenia procedur?

kod fragmentu:

sdownload[licz]:=THTTPGet.Create(Self);
sdownload[licz].URL:='url';
sdownload[licz].FileName := 'nazwa';
sdownload[licz].BinaryData:=true;
sdownload[licz].UseCache:=false;
sdownload[licz].OnProgress := HTTPGetFileProgress;
sdownload[licz].GetFile;
0

HTTPGetFileProgress musi:

  • mieć identyczny format nagłówka co OnProgress (ofc).
  • nie może być "pływająca", tzn musi być składową jakiejkolwiek klasy. Od biedy może być nawet forma.
0

Nie musisz tworzyć 10 czy iluś tam procedur. Wykorzystaj właściwość Sender w metodzie OnProgress, w końcu do tego jest:

if Sender.Name = 'costam' ...

albo

if (Sender as THttpGet).Tag = ilestam

albo

cokolwiek Ci przyjdzie do głowy skojarzyć z Twoimi THttpGet.
0

gdy wywołuje (Sender as THttpGet).Name bądź (z dowolnym parametrem występującym w THttpGet) (Sender as THttpGet).Name za każdym razem
wyskakuje błąd "class EInvalidCast with message 'Invalid class typecast'

0
g4kpl napisał(a)

gdy wywołuje (Sender as THttpGet).Name bądź (z dowolnym parametrem występującym w THttpGet) (Sender as THttpGet).Name za każdym razem
wyskakuje błąd "class EInvalidCast with message 'Invalid class typecast'

Pełna konstrukcja:

If Sender is THttpGet then
  (Sender as THttpGet).CosTam...

lub

If Sender is THttpGet then
  THTTPGet(Sender).CosTam...

Dodatkowo możesz sprawdzić co wywołuje tę procedurę:

ShowMessage(Sender.ClassName)

lub

ShowMessage(TComponent(Sender).Name)
0

ShowMessage(Sender.ClassName) zwraca THTTPGetThread
THTTPGetThread nie identyfikuje się żadnym parametrem, po którym mogę rozpoznać HTTPGet
zamieszczam demo (źródło) programu, które ukazuje problem.
http://www.sendspace.com/file/8emlcw

0

No sam spójrz na definicję części publicznej klasy THttpThread:

THTTPGetThread = class(TThread)
private
{....}
public
constructor Create(aAcceptTypes, aAgent, aURL, aFileName, aUserName, aPassword, aPostQuery, aReferer: String;
aBinaryData, aUseCache: Boolean; aProgress: TOnProgressEvent; aToFile: Boolean);
end;

Tam faktycznie nie ma żadnej właściwości identyfikującej wątek.

Pokażę Ci jak to by wyglądało przy grzebaniu w kodzie (HTTPGet nie ma żadnych metod wirtualnych, więc dziedziczenie odpada, i tak musiałbyś zmieniać kod "główny" komponentu):

należy zrobić miejsce na zapamiętanie numeru komponentu tworzącego HttpThread

Należy dodać do metody Create jakiś parametr, np aComponentNo:

    constructor Create(aAcceptTypes, aAgent, aURL, aFileName, aUserName, aPassword, aPostQuery, aReferer: String;
                       aBinaryData, aUseCache: Boolean; aProgress: TOnProgressEvent; aToFile: Boolean; aComponentNo: integer = 0 );

(Dodanie dodatkowego parametru na końcu i zrobienie defaulta na 0 spowoduje że nie będzie wrzasków kompilatora gdybyś łączył to z kodem z innego źródła)

W ciele konstruktora zapamiętać go - np w prywatnej właściwości FComponentNo.

FComponentNo:= aComponentNo;

Tę właściwość należy oczywiście opublikować w sekcji public

property ComponentNo: integer read FComponentNo write FComponentNo;

(ja bym dał nawet read-only na wszelki wypadek :), czyli bez write)

I wreszcie - należy przerobić sam komponent HttpGet:

procedure THTTPGet.GetFile;
var
  Msg: TMsg;
begin
{...}
    FThread := THTTPGetThread.Create(FAcceptTypes, FAgent, FURL, FFileName, FUserName, FPassword, FPostQuery, FReferer,
                                     FBinaryData, FUseCache, FProgress, True, Self.Tag);
{...}
end;

I już masz (Sender as THTTPGetThread).Tag jako identyfikator :)

Oczywiście metod rozgrzebania tego kodu jest kilka - można do konstruktora wątku dodać np FOwner: TComponent. a metodę OnProgress wywoływać nie poprzez:

  FTProgress(Self, FTFileSize, BytesReaded);

tylko

  FTProgress(Self.FOwner, FTFileSize, BytesReaded);

itede. Powodzenia :)

0
TheBigStaticObject napisał(a)

I już masz (Sender as THTTPGetThread).Tag jako identyfikator :)

Sorry, walnąłem się. Oczywiście powinno być (przy tej konwencji jaką zaproponowałem)

(Sender as THTTPGetThread).ComponentNo
0

zrobiłem jak napisałeś - nie działało, dodałem własne poprawki i dalej nie działa =)
Nie wiem czy dobrze zrozumiałem FComponentNo:Integer? oi wporwadzeniu tych zmian delphi twierdzi, że ComponentNo nie został zdeklarowany. Masz może gg lub jabbera?

0
g4kpl napisał(a)

zrobiłem jak napisałeś - nie działało, dodałem własne poprawki i dalej nie działa =)
Nie wiem czy dobrze zrozumiałem FComponentNo:Integer? oi wporwadzeniu tych zmian delphi twierdzi, że ComponentNo nie został zdeklarowany. Masz może gg lub jabbera?

Wrzuć źródła i/lub swój nr gg na [email protected]

1 użytkowników online, w tym zalogowanych: 0, gości: 1