![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Возможно ли имея имя класса в переменной обратится
dmk © (2015-03-16 16:53:00)к строке как к классу в рантайм не делая кучу условий?
Например:
s := 'TEdit';
s.text := 'something';
(2015-10-20 19:37:00) [1]Удалено модератором
(2015-10-20 19:26:00) [2]Удалено модератором
dmk (2015-03-24 12:09:00) [3]У себя тоже нашел ошибку. Она вообще в другом месте была. По крайней мере получил опыт с переназначением методов :)
Leonid Troyanovsky (2015-03-24 09:22:00) [4]
> dmk © (23.03.15 16:17) [42]
> Вот так заработало:
Ну, и как хотелось:
type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Button1: TButton;
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
TypInfo;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Sender is TLabel then
Caption := Format( '%s.%s: %d %d',
[Name, TLabel(Sender).Caption, X, Y]);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ppi: PPropInfo;
AMethod: TMethod;
i : Longint;
begin
ppi := GetPropInfo(TLabel, 'OnMouseUp');
if ppi = nil then
raise Exception.Create('Property not exist');
AMethod.Code := MethodAddress('FormMouseUp');
AMethod.Data := Self;
for i := 0 to ControlCount-1 do
if Controls[i] is TLabel then
SetMethodProp(Controls[i], ppi, AMethod);
end;
--
Regards, LVT.
dmk (2015-03-23 16:17:00) [5]Вот так заработало:
unit test1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.TypInfo,
Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
FInt: integer;
FStr: string;
procedure AssignNewMethod;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function ObjPropInfo(AObject: TObject; const PropName: String): PPropInfo;
begin
Result := GetPropInfo(AObject.ClassInfo, PropName);
if Result = nil then raise Exception.Create('Property not exist');
end;
procedure SetMethodProperty(AObject: TObject; const PropName: string; const Value: Pointer; const ASelf: pointer);
var
AMethod: TMethod;
begin
AMethod.Code := Value;
if ASelf = nil then AMethod.Data := AObject else AMethod.Data := ASelf;
SetMethodProp(AObject, ObjPropInfo(AObject, PropName), AMethod);
end;
procedure TForm1.AssignNewMethod;
var
i: integer;
c: TWinControl;
p1: pointer;
begin
for i := 0 to ControlCount - 1 do
begin
if Controls[i] is TWinControl then
begin
c := TWinControl(Controls[i]);
p1 := @Self.OnMouseDown;
if IsPublishedProp(c, 'OnMouseDown') then SetMethodProperty(c, 'OnMouseDown', p1, Self);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FInt := 10;
FStr := 'Правильно';
AssignNewMethod;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
s1, s2: string;
begin
//Только оконные объекты
if (Sender is TWinControl) then
begin
Self.Caption := FStr;
s1 := TWinControl(Sender).Name;
s2 := 'No parent';
if TWinControl(Sender).Parent <> nil then s2 := TWinControl(Sender).Parent.Name;
ShowMessage('Mouse down from (' + s1 + ') FInt: ' + IntToStr(FInt) + ' Caption: ' + FStr + #13 + 'Parent form is (' + s2 + ')');
end;//if sender
end;
end.
Видимо у меня там где 50к кода ошибка где-то. будем разбираться. Спасибо!
Leonid Troyanovsky (2015-03-22 19:09:00) [6]
> dmk © (22.03.15 16:21) [40]
> Работает только такой вариант.
Не верю.
--
Regards, LVT.
dmk (2015-03-22 16:21:00) [7]>Ну, тогда б предпочел GetParentForm.
Работает только такой вариант.
Leonid Troyanovsky (2015-03-22 09:29:00) [8]
> Leonid Troyanovsky © (22.03.15 09:20) [38]
Поторопился, sorry.
procedure TForm1.SetMethodProperty( AObject: TObject; const PropName:String; const Value: Pointer);
var
AMethod: TMethod;
begin
AMethod.Code := Value;
AMethod.Data := Self;
SetMethodProp(AObject, ObjPropInfo(AObject, PropName), AMethod);
end;
Все работает как обычно.
--
Regards, LVT.
Leonid Troyanovsky (2015-03-22 09:20:00) [9]
> dmk © (22.03.15 01:18) [36]
> не работает.
А... Понял.
Ну, тогда б предпочел GetParentForm.
--
Regards, LVT.
Leonid Troyanovsky (2015-03-22 09:04:00) [10]
> dmk © (22.03.15 01:18) [36]
> AMethod.Data := AObject; написать AMethod.Data := Self.Так
> не работает. Вызова не происходит.
Код в студию.
Сдается мне, что не в _методе_ пытаешься.
--
Regards, LVT.
dmk (2015-03-22 01:18:00) [11]>Еже ли хочется того самого Self из методов формы, то
>procedure SetMethodProperty надо сделать методом формы,
>где вместо AMethod.Data := AObject; написать AMethod.Data := Self.
Так не работает. Вызова не происходит.
Сделал пока обращение напрямую к полям формы, но выглядит не очень. Будем разбираться. Спасибо за помощь!
Leonid Troyanovsky (2015-03-20 17:29:00) [12]
> dmk © (20.03.15 16:45) [34]
> один и тот же метод: http://s15.postimg.org/swpyqo1ob/dump1.jpg
@Self.OnMouseUp - поубивав бы.
> когда назначается метод, то self от TForm1, а когда он вызывается,
> то self становится указателем на Edit1
Он становится Edit1 при AMethod.Data := AObject.
> Видимо надо родителя проверять или не обращаться к self.
Еже ли хочется того самого Self из методов формы, то
procedure SetMethodProperty надо сделать методом формы,
где вместо AMethod.Data := AObject; написать AMethod.Data := Self.
--
Regards, LVT.
dmk (2015-03-20 16:45:00) [13]>> Даже если назначить от TForm1, а не от self, то разницы нет.
>Обоснуй.
без проблем, переменные p1 и p2 ссылаются на один и тот же метод:
http://s15.postimg.org/swpyqo1ob/dump1.jpg
>> Доступ к полям ошибочный.
>Показывай.
когда назначается метод, то self от TForm1, а когда он вызывается, то self становится указателем на Edit1 у которого таких полей как у TForm нет.
http://s21.postimg.org/4yu3q8mkn/dump2.jpg
Видимо надо родителя проверять или не обращаться к self.
Leonid Troyanovsky (2015-03-20 15:54:00) [14]
> что известно в оном форме, на который его положат.
что известно в оном о форме, на которую его положат.
Sorry.
--
Regards, LVT.
Leonid Troyanovsky (2015-03-20 15:45:00) [15]
> dmk © (20.03.15 15:30) [30]
> Заменять метод небезопасно.
и загадочно.
--
Regards, LVT.
Leonid Troyanovsky (2015-03-20 15:40:00) [16]
> dmk © (20.03.15 15:26) [29]
> Даже если назначить от TForm1, а не от self, то разницы нет.
Обоснуй.
> Доступ к полям ошибочный.
Показывай.
> Поля от TForm1 в случае вызова из TEdit не видны.
Предположим, что у Edit есть обработчик OnMouseUp,
скажем, EditMouseUp.
Спросим, что известно в оном форме, на который его положат.
Ну, или, не положат.
Где-то сгодится GetParentForm, а где-то - нет. Всё как в жизни.
--
Regards, LVT.
dmk (2015-03-20 15:30:00) [17]я про это и писал выше, что self, что TForm1 разницы нет. Заменять метод небезопасно.
dmk (2015-03-20 15:26:00) [18]Даже если назначить от TForm1, а не от self, то разницы нет. Доступ к полям ошибочный. Поля от TForm1 в случае вызова из TEdit не видны.
Leonid Troyanovsky (2015-03-20 14:59:00) [19]
> @Self.OnMouseUp
Поубивав бы.
Leonid Troyanovsky (2015-03-20 14:54:00) [20]
> dmk © (20.03.15 13:46) [26]
> В последнем случае возникает AV.
Внезапно?
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
ShowMessage(TWinControl(Sender).Name);
ShowMessage(Self.Name + '>' +Name); // wow
ShowMessage(FStr); // surprise
end;
--
Regards, LVT.