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

Вниз

Ссылка на метод класса   Найти похожие ветки 

 
Debug ©   (2007-08-11 09:46) [0]

Необходимо реализовать вызов метода класса по строковой команде. Проблема в том, что вызов метода происходит от объекта 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;


Подскажите, возможно ли организовать обработку комманд таким способом? Или каким-нибудь другим, но кроме кейса и кроме выделения каждой команды в отдельный класс.


 
Lacmus ©   (2007-08-11 10:00) [1]

Ошибка здесь


Handler := SomeStringIndexedArray[Command];


 
MetalFan ©   (2007-08-11 10:28) [2]


> SomeStringIndexedArray

это еще что за зверь????
нельзя в делфи использовать строку для индексации массива... только если свойство-массив


 
Debug ©   (2007-08-11 10:50) [3]

2Lacmus: в чем ошибка?
2MetalFan: это и есть свойство массив TObject"ов


 
Lacmus ©   (2007-08-11 11:04) [4]

>Debug ©   (11.08.07 10:50) [3]


TCommandHandler -

TMethod = record
 Code, Data: Pointer;
end;


 
Юрий Зотов ©   (2007-08-11 12:12) [5]

Отдельный менеджер команд плодить не стал, а сделал им саму форму. Сути это не меняет.

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 - на объект, инициировавший выполнение команды.


 
Юрий Зотов ©   (2007-08-11 12:16) [6]

Вдогонку: команды хранятся в ListBox"е лишь потому, что для демонстрашки это было удобнее. В реальном коде, видимо, удобнее будет TStringList.


 
Leonid Troyanovsky ©   (2007-08-11 12:40) [7]


> Debug ©   (11.08.07 09:46)  

> Необходимо реализовать вызов метода класса по строковой
> команде.


http://www.rsdn.ru/Forum/Message.aspx?mid=476748&only=1

Гм.. Кто здесь еще искал процедуру по имени.

--
Regards, LVT.


 
Debug ©   (2007-08-11 14:26) [8]

Огромное спасибо!



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

Форум: "Основная";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.044 c
15-1190408875
Kostafey
2007-09-22 01:07
2007.10.28
С днем рождения ! 22 сентября


5-1162483418
--= Eagle =--
2006-11-02 19:03
2007.10.28
Предотвратить удаление сабкомпонента в дизайнтайме


9-1162040068
Зм1й
2006-10-28 16:54
2007.10.28
Прозрачность и текстура


9-1154865892
Сан-саныч
2006-08-06 16:04
2007.10.28
Md2 модели


15-1191269789
Delphi User
2007-10-02 00:16
2007.10.28
VLK





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский