![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ссылка на метод класса [D6, WinXP]
Debug © (2007-08-11 09:46:00)Необходимо реализовать вызов метода класса по строковой команде. Проблема в том, что вызов метода происходит от объекта nil, а не от вызывающего.
type
TCommandHandler = procedure (I: Integer) of object;
TCommandManager = class (TObject)
protected
procedure SetCommandHandler(Command: string; Handler: TCommandHandler);
procedure DoCommand1(I: Integer);
procedure DoCommand2(I: Integer);
...
public
procedure ProcessCommand(Command: string);
end;
procedure TCommandManager.SetCommandHandler(Command: string; Handler: TCommandHandler);
begin
SomeStringIndexedArray[Command] := Handler;
end;
procedure TCommandManager.ProcessCommand(Command: string; I: Integer);
var
Handler: TCommandHandler;
begin
@Handler := Pointer(SomeStringIndexedArray[Command]);
if Assigned(Handler) then
Handler(I);
end;
procedure TCommandManager.DoCommand1(I: Integer);
begin
// Здесь при вызове метода Self = nil!
end;
Подскажите, возможно ли организовать обработку комманд таким способом? Или каким-нибудь другим, но кроме кейса и кроме выделения каждой команды в отдельный класс.
Debug (2007-08-11 14:26:00) [1]Огромное спасибо!
Leonid Troyanovsky (2007-08-11 12:40:00) [2]
> Debug © (11.08.07 09:46)
> Необходимо реализовать вызов метода класса по строковой
> команде.
http://www.rsdn.ru/Forum/Message.aspx?mid=476748&only=1
Гм.. Кто здесь еще искал процедуру по имени.
--
Regards, LVT.
Юрий Зотов (2007-08-11 12:16:00) [3]Вдогонку: команды хранятся в ListBox'е лишь потому, что для демонстрашки это было удобнее. В реальном коде, видимо, удобнее будет TStringList.
Юрий Зотов (2007-08-11 12:12:00) [4]Отдельный менеджер команд плодить не стал, а сделал им саму форму. Сути это не меняет.
unit Unit6;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TCommandHandler = procedure(I: Integer) of object;
TForm1 = class(TForm)
ListBox1: TListBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
protected
procedure SetCommandHandler(Command: string; Handler: TCommandHandler);
procedure DoCommand1(I: Integer);
procedure DoCommand2(I: Integer);
public
procedure ProcessCommand(Command: string; Sender: TObject; Param: Integer);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.DoCommand1(I: Integer);
begin
ShowMessage(Format('DoCommand1: Self = %s, Parameter = %d', [TComponent(Self).Name, I]))
end;
procedure TForm1.DoCommand2(I: Integer);
begin
ShowMessage(Format('DoCommand2: Self = %s, Parameter = %d', [TComponent(Self).Name, I]))
end;
procedure TForm1.ProcessCommand(Command: string; Sender: TObject; Param: Integer);
var
Index: integer;
Method: TMethod;
begin
Index := ListBox1.Items.IndexOf(Command);
if Index < 0 then
raise Exception.CreateFmt('Unknown command "%s"', [Command]);
Method.Code := ListBox1.Items.Objects[Index];
Method.Data := Sender;
TCommandHandler(Method)(Param)
end;
procedure TForm1.SetCommandHandler(Command: string; Handler: TCommandHandler);
begin
ListBox1.Items.AddObject(Command, TObject(TMethod(Handler).Code))
end;
// ========================================
procedure TForm1.FormCreate(Sender: TObject);
begin
SetCommandHandler('Command1', DoCommand1);
SetCommandHandler('Command2', DoCommand2);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Index: integer;
Obj: TObject;
begin
Index := ListBox1.ItemIndex;
if Index < 0 then
raise Exception.Create('Command not selected');
if Index = 0 then
Obj := Self
else
Obj := Sender;
ProcessCommand(ListBox1.Items[Index], Obj, Index)
end;
end.
Но лучше не корежить Self, а вввести параметр Sender:
type
TCommandHandler = procedure(Sender: TObject; I: Integer) of object;
Тогда в ProcessCommand нужно будет изменить 2 строчки:
Method.Data := Self;
TCommandHandler(Method)(Sender, Param)
Соответственно изменятся заголовки всех DoCommandX.
Что получим: Self, как ему и положено, будет указывать на менеджер команд, а Sender - на объект, инициировавший выполнение команды.
Lacmus (2007-08-11 11:04:00) [5]>Debug © (11.08.07 10:50) [3]
TCommandHandler -
TMethod = record
Code, Data: Pointer;
end;
Debug (2007-08-11 10:50:00) [6]2Lacmus: в чем ошибка?
2MetalFan: это и есть свойство массив TObject'ов
MetalFan (2007-08-11 10:28:00) [7]
> SomeStringIndexedArray
это еще что за зверь????
нельзя в делфи использовать строку для индексации массива... только если свойство-массив
Lacmus (2007-08-11 10:00:00) [8]Ошибка здесь
Handler := SomeStringIndexedArray[Command];