Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2015.12.20;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.002 c
2-1403529768
Sakipiel
2014-06-23 17:22
2015.12.20
Все события на одной процедуре


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


15-1429879718
Andy BitOff
2015-04-24 15:48
2015.12.20
VCL кконтролы. Рушится шрифт.


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 четверг





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский