Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2015.12.20;
Скачать: CL | DM;

Вниз

Все события на одной процедуре   Найти похожие ветки 

 
Sakipiel   (2014-06-23 17:22) [0]

Есть идея всем событиям компонента присвоить одну процедуру, но возникает вопрос, как внутри этой процедуры понять, какое конкретно событие ее вызывало? (т.е. нужно узнать имя "OnClick", например)


 
Ega23 ©   (2014-06-23 17:34) [1]

Отвратительная идея.
Честно.


 
Юрий Зотов ©   (2014-06-23 17:38) [2]

А зачем? В чем смысл идеи?


 
Sakipiel   (2014-06-23 17:40) [3]

идея норм, т.к. в любом событии будет отрабатываться абсолютно одинаковый код, найти имя события в базе данных и найти текст процедуры и выполнить ее. Ну и зачем мне мучаться и на каждое событие создавать отдельную процедуру?


 
Sakipiel   (2014-06-23 17:45) [4]

смысл идеи в том, что в режиме разработки я в базу данных записываю имя события и имя процедуры которое ему соответствует. соответственно в режиме исполнения мне нужно при любом событии найти в базе для компонента имя события, посмотреть имя процедуры к нему и выполнить эту процедуру (которая на скриптовом языке написана)


 
KilkennyCat ©   (2014-06-23 19:35) [5]


> и на каждое событие создавать отдельную процедуру?

а вызвать в каждом одну единственную процедуру с параметром?


> Ну и зачем мне мучаться и на каждое событие

чтобы

> внутри этой процедуры понять, какое конкретно событие ее
> вызывало


 
Юрий Зотов ©   (2014-06-23 19:49) [6]

> Sakipiel

> Есть идея всем событиям компонента присвоить одну процедуру


Одну на все события, конечно, не получится, потому что у обработчиков разных событий могут быть разные заголовки. Но одну процедуру на все однотипные события - не проблема.

> как внутри этой процедуры понять, какое конкретно событие ее вызывало?

Процедуру вызывает код, а никакое не событие. Сам факт вызова процедуры - это и есть событие. В Вашем случае процедура всего одна, значит и событие всего одно. Одно на всех. Поэтому задача сводится к "определить, из какого места кода меня вызвали".

Если у события есть метод диспетчеризации, можно попробовать подняться вверх по стеку вызовов и определить имя этого метода, как это делает отладчик. Ну и потом уже из этого имени и исходить - в нем, как правило, присутствует имя события.

Но вообще, как-то странно выглядит такое решение. Я бы поискал другое. Тем более, что метод диспетчеризации есть не всегда, да и называется он не всегда одинаково.


 
Sha ©   (2014-06-24 00:57) [7]

Демо максимум на 10 событий,
все нужные события регистрируются при создании формы,
в дизайне ничего прописывать не надо.

ПРЕДОСТЕРЕЖЕНИЯ:
1. Работает только в 32-битной Delphi.
2. Работает только при включенной оптимизации.
3. Код сырой, предназначен только для демонстрации идеи,
    а не для использования в работе.


unit TheOnlyMethodForm;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;

type
 TForm1 = class(TForm)
   function EventHandlerRegister(pEvent: pointer; const Name: AnsiString): integer;
   procedure EventHandlerEntry(Sender: TObject);
   procedure EventHandlerExecute;
   procedure FormCreate(Sender: TObject);
 private
   FMyEventNames: array of AnsiString;
   FMyEventIndex: integer;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.EventHandlerRegister(pEvent: pointer; const Name: AnsiString): integer;
const
 SizeOfIncDwordPtr= 6;
var
 Offset: integer;
begin;
 Result:=-1;
 if FMyEventNames=nil then begin;
   EventHandlerEntry(nil);
   SetLength(FMyEventNames,FMyEventIndex+1);
   FMyEventIndex:=0;
   end;
 if Name<>"" then begin;
   Result:=Length(FMyEventNames)-1;
   while (Result>=0) and (FMyEventNames[Result]<>"") do dec(Result);
   if Result>=0 then begin;
     FMyEventNames[Result]:=Name;
     Offset:=((Length(FMyEventNames)-1)-Result)*SizeOfIncDwordPtr;
     TNotifyEvent(pEvent^):=EventHandlerEntry;
     inc(pAnsiChar(pEvent^),Offset);
     end;
   end;
 end;

procedure TForm1.EventHandlerEntry(Sender: TObject);
begin;
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 inc(FMyEventIndex);
 EventHandlerExecute;
 end;

procedure TForm1.EventHandlerExecute;
var
 i: integer;
begin;
 i:=FMyEventIndex;
 if (i>=0) and (i<Length(FMyEventNames)) then begin;
   FMyEventIndex:=0;
   if FMyEventNames[i]<>"" then ShowMessage(FMyEventNames[i]);
   end;
 end;

procedure TForm1.FormCreate(Sender: TObject);
begin;
 EventHandlerRegister(@@OnActivate, "OnActivate");
 EventHandlerRegister(@@OnClick, "OnClick");
 end;

end.


 
Германн ©   (2014-06-24 02:13) [8]


> Sha ©   (24.06.14 00:57) [7]

Это вообще что-то заумное из области "чистого искусства ради искусства". :)


 
KilkennyCat ©   (2014-06-24 03:01) [9]

а почему событий 10 а инков 9? :)


 
Sha ©   (2014-06-24 09:20) [10]

> KilkennyCat ©   (24.06.14 03:01) [9]

там 10 точек входа: по одной в каждый инк и одна в кол EventHandlerExecute


 
KilkennyCat ©   (2014-06-24 10:14) [11]

я так и подумал. а с оптимизацией почему? мне казалось, что оптимизация выдает некую непредсказуемость. по крайней мере, хайтечевский сишный компилятор  любит наоптимизировать каждый раз.


 
Sha ©   (2014-06-24 10:24) [12]

> KilkennyCat ©   (24.06.14 10:14) [11]

от степени оптимизации зависят "размеры" пролога-эпилога и отдельных операторов


 
oldman ©   (2014-06-24 11:09) [13]


> Sakipiel   (23.06.14 17:22) 
> Есть идея всем событиям компонента присвоить одну процедуру


Одна процедура на OnClick, на OnMouseMove и на OnResize?
Мдя........


 
Sha ©   (2014-06-24 11:31) [14]

> oldman ©   (24.06.14 11:09) [13]

Он этого не говорил.
Скорее всего, в скрипте требуется обработать только TNotifyEvent, что-нибудь вроде 100500 OnClick/OnCreate/OnClose.

В [6] уже было предложение относительно групповой обработки разнотипных событий. Разумеется, если у автора разнотипные события, то и в [7] каждому типу требуется свой групповой обработчик.


 
Sha ©   (2014-06-24 23:57) [15]

Более причесанный вариант.
Работает для разнотипных событий.
Оптимизация любая.
Дельфи 32-битная.


unit TheOnlyEventForm;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
 TMyEvent= packed record
   EventName: AnsiString;
   EventProc: pointer;
   end;
const
 SizeOfTMyEvent= SizeOf(TMyEvent);

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   Button2: TButton;
   procedure HandleNotifyEvent(Sender: TObject);
   procedure HandleMouseUpDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
   procedure EventHandlerEntry;
   function EventHandlerRegister(pEvent: pointer; const aName: AnsiString): integer;
   procedure FormCreate(Sender: TObject);
 private
   FMyFirstInc, FMyLastInc, FMyRealEntry, FMySaveArea: pointer;
   FMyEventIndex: integer;
   FMyEvents: packed array of TMyEvent;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.HandleNotifyEvent(Sender: TObject);
var
 i: integer;
 s: string;
begin;
 i:=FMyEventIndex;
 FMyEventIndex:=0;
 if (Sender<>nil) and (Sender is TComponent) then s:=TComponent(Sender).Name;
 if (0<=i) and (i<Length(FMyEvents)) then s:=s+FMyEvents[i].EventName;
 Memo1.Lines.Add(s);
 end;

procedure TForm1.HandleMouseUpDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin;
 HandleNotifyEvent(Sender);
 end;

procedure TForm1.EventHandlerEntry;
begin;
             asm
             lea ecx, @@FirstInc;   mov [eax + FMyFirstInc], ecx
             lea ecx, @@LastInc;    mov [eax + FMyLastInc], ecx
             lea ecx, @@RealEntry;  mov [eax + FMyRealEntry], ecx
             jmp @@End
@@FirstInc:   inc dword ptr [eax + FMyEventIndex]
             inc dword ptr [eax + FMyEventIndex]
             inc dword ptr [eax + FMyEventIndex]
             inc dword ptr [eax + FMyEventIndex]
             inc dword ptr [eax + FMyEventIndex]
             inc dword ptr [eax + FMyEventIndex]
             inc dword ptr [eax + FMyEventIndex]
             inc dword ptr [eax + FMyEventIndex]
@@LastInc:    inc dword ptr [eax + FMyEventIndex]
@@RealEntry:  mov [eax + FMySaveArea], ecx
             mov ecx, [eax + FMyEventIndex]
             imul ecx, ecx, SizeOfTMyEvent
             add ecx, [eax + FMyEvents]
             mov ecx, [ecx + TMyEvent.EventProc]
             call @@Next
@@Next:       mov [esp], ecx
             mov ecx, [eax + FMySaveArea]
             ret
@@End:        end;
 end;

function TForm1.EventHandlerRegister(pEvent: pointer; const aName: AnsiString): integer;
var
 IncSize, IncCount: integer;
begin;
 Result:=-1;
 if FMyEvents=nil then EventHandlerEntry;
 IncSize:=pAnsiChar(FMyRealEntry)-pAnsiChar(FMyLastInc);
 IncCount:=(pAnsiChar(FMyRealEntry)-pAnsiChar(FMyFirstInc)) div IncSize;
 if FMyEvents=nil then SetLength(FMyEvents,IncCount+1);
 if aName<>"" then begin;
   Result:=IncCount;
   while (Result>=0) and (FMyEvents[Result].EventName<>"") do dec(Result);
   if Result>=0 then begin;
     FMyEvents[Result].EventName:=aName;
     FMyEvents[Result].EventProc:=pointer(pEvent^);
     pointer(pEvent^):=pAnsiChar(FMyRealEntry)-Result*IncSize;
     end;
   end;
 end;

procedure TForm1.FormCreate(Sender: TObject);
begin;
 Self.OnActivate:=HandleNotifyEvent; EventHandlerRegister(@@Self.OnActivate, "OnActivate");
 Button1.OnClick:=HandleNotifyEvent; EventHandlerRegister(@@Button1.OnClick, "OnClick");
 Button2.OnClick:=HandleNotifyEvent; EventHandlerRegister(@@Button2.OnClick, "OnClick");
 Self.OnMouseUp:=HandleMouseUpDown;  EventHandlerRegister(@@Self.OnMouseUp, "МышкеБольно");
 end;

end.


 
oldman ©   (2014-06-25 12:17) [16]


> Sha ©   (24.06.14 11:31) [14]
> > oldman ©   (24.06.14 11:09) [13]
> Он этого не говорил.


да ну?


>  Все события на одной процедуре
>
> Sakipiel   (23.06.14 17:22) 
> Есть идея всем событиям компонента присвоить одну процедуру


 
Sha ©   (2014-06-25 12:35) [17]

Виноват, не заметил, наверно был слишком впечатлен этим:

Конференция для начинающих, а также для тех, кому сложно объяснить чего он хочет.



Страницы: 1 вся ветка

Текущий архив: 2015.12.20;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.012 c
2-1403498172
Sakipiel
2014-06-23 08:36
2015.12.20
не отрабатывает событие дабл клик для некоторых компонентов


15-1429825354
Rouse_
2015-04-24 00:42
2015.12.20
К девятому мая


15-1423150223
Дмитрий С
2015-02-05 18:30
2015.12.20
Midi 2 Beep-код


15-1429741804
Юрий
2015-04-23 01:30
2015.12.20
С днем рождения ! 23 апреля 2015 четверг


2-1403765627
Вася
2014-06-26 10:53
2015.12.20
Раскраска строк DBGrid относительно значения поля текущей строки