Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Embarcadero RAD Studio

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
На первую страницук этому сообщениюк последнему сообщению

Открыть новую тему     Написать ответ в эту тему

xpin2013



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Код:
type
  TEventList = class(TComponent)
  private
    FList: array of TMethod;
    FLock: TRTLCriticalSection;
    FUnpackList: array of TMethod;
    procedure Delete(Index: Integer);
    function IndexOf(const AEvent: TMethod): Integer;
  protected
    function AddEvent(const AEvent: TMethod): Integer;
    function Count: Integer;
    function Event(Index: Integer): TMethod;
    function IsEmpty(Index: Integer): Boolean;
    procedure LockList;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure RemoveEvent(const AEvent: TMethod);
    procedure RemoveEventOf(AComponent: TObject);
    procedure UnlockList;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;
 
  TNotifyEventList = class(TEventList)
  public
    procedure Add(AEvent: TNotifyEvent);
    procedure Execute(Sender: TObject);
    procedure Remove(AEvent: TNotifyEvent);
  end;
 
{ TEventList }
 
function TEventList.AddEvent(const AEvent: TMethod): Integer;
var
  L: Integer;
begin
  if (AEvent.Code = nil) and (AEvent.Data = nil) then
    raise EListError.Create('Invalid method value');
  EnterCriticalSection(FLock);
  try
    Result := IndexOf(AEvent);
    if Result < 0 then
    begin
      L := Length(FList);
      SetLength(FList, Succ(L));
      FList[L] := AEvent;
      if TObject(AEvent.Data) is TComponent then
        TComponent(AEvent.Data).FreeNotification(Self);
    end;
  finally
    LeaveCriticalSection(FLock);
  end;
end;
 
function TEventList.Count: Integer;
begin
  Result := Length(FUnpackList);
end;
 
constructor TEventList.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  InitializeCriticalSection(FLock);
end;
 
procedure TEventList.Delete(Index: Integer);
var
  I: Integer;
  M: TMethod;
begin
  I := Length(FList);
  if (Index < 0) and (Index >= I) then
    raise EListError.CreateFmt('List index out of bounds (%d)', [Index]);
  Dec(I);
  M := FList[Index];
  if Index < I then
    System.Move(FList[Index + 1], FList[Index],
      (I - Index) * SizeOf(TMethod));
  SetLength(FList, I);
  for I := 0 to High(FUnpackList) do
    if (FUnpackList[I].Code = M.Code) and (FUnpackList[I].Data = M.Data) then
    begin
      FUnpackList[I].Code := nil;
      FUnpackList[I].Data := nil;
      Exit;
    end;
end;
 
destructor TEventList.Destroy;
begin
  SetLength(FList, 0);
  DeleteCriticalSection(FLock);
  inherited Destroy;
end;
 
function TEventList.Event(Index: Integer): TMethod;
begin
  if (Index < 0) or (Index >= Length(FUnpackList)) then
    FillChar(Result, Sizeof(Result), 0)
  else
    Result := FUnpackList[Index];
end;
 
function TEventList.IndexOf(const AEvent: TMethod): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := Pred(Length(FList)) downto 0 do
    if (FList[I].Code = AEvent.Code) and (FList[I].Data = AEvent.Data) then
    begin
      Result := I;
      Exit;
    end;
end;
 
function TEventList.IsEmpty(Index: Integer): Boolean;
begin
  if (Index < 0) and (Index >= Length(FUnpackList)) then
    raise EListError.CreateFmt('List index out of bounds (%d)', [Index]);
  Result := (FUnpackList[Index].Code = nil) and
    (FUnpackList[Index].Data = nil);
end;
 
procedure TEventList.LockList;
var
  L: Integer;
begin
  EnterCriticalSection(FLock);
  L := Length(FList);
  SetLength(FUnpackList, L);
  System.Move(FList[0], FUnpackList[0], L * SizeOf(TMethod));
end;
 
procedure TEventList.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  if Operation = opRemove then
    RemoveEventOf(AComponent);
  inherited Notification(AComponent, Operation);
end;
 
procedure TEventList.RemoveEvent(const AEvent: TMethod);
var
  I: Integer;
begin
  EnterCriticalSection(FLock);
  try
    for I := Pred(Length(FList)) downto 0 do
      if (FList[I].Code = AEvent.Code ) and (FList[I].Data = AEvent.Data) then
      begin
        Delete(I);
        Break;
      end;
  finally
    LeaveCriticalSection(FLock);
  end;
end;
 
procedure TEventList.RemoveEventOf(AComponent: TObject);
var
  I: Integer;
begin
  EnterCriticalSection(FLock);
  try
    for I := Pred(Length(FList)) downto 0 do
      if FList[I].Data = AComponent then
        Delete(I);
  finally
    LeaveCriticalSection(FLock);
  end;
end;
 
procedure TEventList.UnlockList;
begin
  SetLength(FUnpackList, 0);
  LeaveCriticalSection(FLock);
end;
 
{ TNotifyEventList }
 
procedure TNotifyEventList.Add(AEvent: TNotifyEvent);
begin
  AddEvent(TMethod(AEvent));
end;
 
procedure TNotifyEventList.Execute(Sender: TObject);
var
  I: Integer;
begin
  LockList;
  try
    for I := 0 to Count - 1 do if not IsEmpty(I) then
      TNotifyEvent(Event(I))(Sender);
  finally
    UnlockList;
  end;
end;
 
procedure TNotifyEventList.Remove(AEvent: TNotifyEvent);
begin
  RemoveEvent(TMethod(AEvent));
end;

Всего записей: 291 | Зарегистр. 16-01-2014 | Отправлено: 23:24 18-02-2015
Открыть новую тему     Написать ответ в эту тему

На первую страницук этому сообщениюк последнему сообщению

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Embarcadero RAD Studio


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru