Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 10 декабря!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

БОЛЬШОЙ FAQ ПО DELPHI



Вот всю жизнь в TVision в итераторах _нужно_ было (параметром) передавать указатель на локальную процедуру, а тут задумал сделать свой итератор для обхода некоей древовидной структуры и на тебе - компилятор ругается. Да еще и в хелпе носом тыкают, что так мол в принципе нельзя делать... Гм. И как быть?

Конкретно по поводу локальных процедур - если нельзя, но очень хочется -
то можно. Я недавно искал способ. Как водится, сначала придумал свой,
а потом мне показали в исходниках VCL. Hо (как водится) мой красивее. Лови:

function LocalAddr(Proc :Pointer) :TMethod; assembler;
asm
mov Result.Data, EBP
mov Result.Code, Proc
end;


function TMyList.ForEach(Proc :TMethod) :Integer;
type
EnumProc = procedure(Index :Integer; Item :Pointer; var More :Boolean);
var
I :Integer;
More :Boolean;
Tmp :Pointer;
begin
Result := -1;
More := True;

for I := 0 to Count - 1 do begin

{Вызываем локальную процедуру...}
Tmp := Proc.Data; asm push Tmp end;
EnumProc(Proc.Code)(I, List^[I], More);
asm pop ECX end;

if not More then begin
Result := I;
Exit;
end;
end;

end;

В принципе, здесь можно без Tmp - сразу Push Proc.Data. о иногда - в
других enumertor'ах кодогенератор глючит. Так что, для надежности...

Использование:

function Present(AList :TList; AItem :Pointer) :Boolean;

procedure Compare(Index :Integer; Item :Pointer; var More :Boolean);
begin
More := Item <> AItem;
end;

begin
Result := AList.ForEach(LocalAddr(@Compare)) <> -1;
end;

(Для тех кто в танке: Это пример, IndexOf не предлагать!)



<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ



Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS