Вопрос пользователя касается управления событиями в компоненте, созданном в среде разработки Delphi. Пользователь хочет иметь возможность реагировать на событие подключения клиента, не прибегая к внешним обработчикам событий, а реализовав необходимую логику непосредственно в классе своего компонента. Проблема усложняется тем, что сокет клиента не создается компонентом, а назначается в runtime.
Проблема
Пользователь имеет пользовательский компонент TMyComponent, который содержит публичную процедуру ClientConnected. В текущем решении, при возникновении события подключения клиента для ClientSocket, вызывается процедура ClientConnected компонента TMyComponent. Однако, желательно избежать использования внешних обработчиков событий и реализовать нужное поведение внутри самого компонента.
Решение
Для успешного "перехвата" событий для дочернего ClientSocket, необходимо выполнить несколько шагов:
Не "мешать" обычному поведению во время дизайна: назначать свои обработчики событий только во время выполнения программы.
Сохранять обработчики событий, назначенные пользователем для дочернего компонента.
Обеспечить безопасный вызов сохраненных методов.
Позволить переназначение дочернего компонента во время выполнения.
Документировать, что происходит за кулисами, так как незнание разработчиков может привести к проблемам.
Пример реализации
TMyComponent = class(TComponent)
private
FClientSocket: TClientSocket;
FSavedClientConnected: TClientConnectedEvent; //Тип события, которое нужно сохранить
procedure ClientConnected(AValidFirm: TFirm); //Эта процедура должна иметь соответствующий тип события
procedure Hook; //Назначение своих обработчиков событий дочернему компоненту
procedure UnHook; //Отмена назначения своих обработчиков событий дочернему компоненту
protected
procedure Loaded; override; //Взаимодействие с дочерним компонентом после завершения загрузки контейнера
procedure Notification(AComponent: TComponent; Operation: TOperation); override; //Безопасность при удалении дочернего компонента
public
destructor Destroy; override; //Очистка дочернего компонента при удалении
published
property ClientSocket: TClientSocket read FClientSocket write SetClientSocket; //Публичное свойство для сокета
end;
procedure TMyComponent.SetClientSocket(Value: TClientSocket);
begin
if FClientSocket <> Value then
begin
UnHook;
FClientSocket := Value;
Hook;
end;
end;
procedure TMyComponent.Hook;
begin
if (csDesigning in ComponentState) or (csLoading in ComponentState) then Exit;
if Assigned(FClientSocket) then
begin
FSavedClientConnected := FClientSocket.OnClientConnected;
FClientSocket.OnClientConnected := ClientConnected;
end;
end;
procedure TMyComponent.UnHook;
begin
if Assigned(FClientSocket) then
begin
FClientSocket.OnClientConnected := FSavedClientConnected;
FSavedClientConnected := nil;
end;
end;
procedure TMyComponent.Loaded;
begin
Hook;
end;
destructor TMyComponent.Destroy;
begin
UnHook;
inherited;
end;
procedure TMyComponent.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (AComponent = FClientSocket) and (Operation = opRemove) then
UnHook;
FClientSocket := nil;
inherited;
end;
procedure TMyComponent.ClientConnected(AValidSocket: TCustomWinSocket);
begin
// Выполнение своих действий с сокетом
if Assigned(FSavedClientConnected) then
FSavedClientConnected(AValidSocket);
end;
В этом примере реализована возможность "перехвата" событий подключения клиента для назначенного ClientSocket, сохранения и последующего вызова пользовательских обработчиков событий. Обратите внимание, что в коде могут быть ошибки, так как он представлен в виде обобщенного примера, и его необходимо будет адаптировать под конкретные нужды и тип события, которое необходимо обработать.
Управление событиями дочерних компонентов в Delphi для обобщенного сохранения и вызова обработчиков, с возможностью 'перехвата' событий без внешних обработчиков.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.