Форум: "Начинающим";
Текущий архив: 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