Comments 12
А всё-таки, почему не написать свой компонент? Ведь вы уже все сделали, осталось только собрать в пакет и инсталлировать.
+1
Довольно интересный подход с подменой компонента) В принципе, никаких чудес, но я даже не задумывался, что «так можно»)
0
Еще и не так можно. Все расскажу, дайте время. На самом деле все просто, если смотреть под иным углом зрения.
0
Как-то я имел дело с оперднем, в котором в зависимости от бизнес-логики у объектов в рантайме подменялась таблица виртуальных методов (VMT). Легким движением руки элементарные проводки становились выданными кредитами, лицевые счета — договорами и т.д. Глючило оно безбожно, пока не переписал на нормальное присвоение.
Я к тому, что иной угол зрения имеет право на жизнь, но не стоит увлекаться. В вашем примере вы имеете полный контроль над формой, а если форма чужая, то указатель на оригинальный TMemo мог быть где-то сохранен и использован позднее, а сам объект вы уже уничтожили.
Я к тому, что иной угол зрения имеет право на жизнь, но не стоит увлекаться. В вашем примере вы имеете полный контроль над формой, а если форма чужая, то указатель на оригинальный TMemo мог быть где-то сохранен и использован позднее, а сам объект вы уже уничтожили.
0
Не понял — в чем смысл использовать TMemo, а потом через одно место его подменять? Почему сразу не использовать ваш дочерний класс?
0
Есть более простой и менее опасный (в плане возможности наделать ошибок) способ «подмены». Хотя это уже совсем не подмена.
Единственное требование — такой класс должен быть объявлен перед объявлением класса формы. По идее, будет работать, если объявить в отдельном модуле, но в uses этот модуль должен быть указан обязательно после StdCtrls.
В результате в design-time ничего не меняется — там остается стандартный TMemo, а в run-time имеем доступ ко всем новым «фичам» нового класса.
Повторюсь — подмены тут никакой нет, компонент создается сразу с нужной функциональностью. Не надо создавать экземпляр нового класса, не надо ничего копировать. Отпадает необходимость писать метод TxIPMemo.SetMemo.
type
TMemo = class(StdCtrls.TMemo)
...
end;
Единственное требование — такой класс должен быть объявлен перед объявлением класса формы. По идее, будет работать, если объявить в отдельном модуле, но в uses этот модуль должен быть указан обязательно после StdCtrls.
В результате в design-time ничего не меняется — там остается стандартный TMemo, а в run-time имеем доступ ко всем новым «фичам» нового класса.
Повторюсь — подмены тут никакой нет, компонент создается сразу с нужной функциональностью. Не надо создавать экземпляр нового класса, не надо ничего копировать. Отпадает необходимость писать метод TxIPMemo.SetMemo.
0
В результате в design-time ничего не меняется — там остается стандартный TMemo, а в run-time имеем доступ ко всем новым «фичам» нового класса.
Зачем?
Почему просто не сделать свой компонент и размещать на форме его?
0
Вы абсолютно правы. Это красивое и элегантное решение, чтобы подменить в run-time все компоненты, созданные в дизайне, на свои. Только не всегда нужно заменять абсолютно все.
SetMemo имеет два параметра: указатель на TCustomMemo и AWithFree – уничтожать ли. Т.е. передать можно любого наследника TCustomMemo, не обязательно TMemo, компонент возьмет все необходимые ему свойства. И можно не уничтожать «донора», пусть живет как есть.
SetMemo имеет два параметра: указатель на TCustomMemo и AWithFree – уничтожать ли. Т.е. передать можно любого наследника TCustomMemo, не обязательно TMemo, компонент возьмет все необходимые ему свойства. И можно не уничтожать «донора», пусть живет как есть.
0
Вот, кстати, на кой чёрт там указатель?
var
параметры придумали миллиард лет назад. Ещё в Borland Pascal были.
0
Можно попробовать сделать такую запись:
Далее в коде вызвать хотя бы даже с «родным» наследником Memo1: TMemo
Компилятор будет не доволен.
function F1 (var m : TCustomMemo) : boolean;
Далее в коде вызвать хотя бы даже с «родным» наследником Memo1: TMemo
F1 (Memo1);
Компилятор будет не доволен.
0
Точно, вы правы.
Тогда можно сделать такой финт ушами:
Как минимум в Delphi XE8 должно уже работать.
Тут, как оказалось, ещё и проверка типов переменной ломается.
Тогда можно сделать такой финт ушами:
{$apptype console}
program Test;
uses
System.SysUtils;
type
TBase = class(TObject)
end;
TFoo = class(TBase)
end;
TBar = class(TBase)
end;
TXyz = class(TObject)
end;
TUtility = class(TObject)
public
class procedure SurpriseMe<T: TBase>(var AValue: T);
end;
class procedure TUtility.SurpriseMe<T>(var AValue: T);
begin
FreeAndNil(AValue);
AValue := T(TBar.Create());
end;
var
ObjFoo: TBase;
ObjXyz: TXyz;
begin
ObjFoo := TFoo.Create();
try
writeln('Before:'#9, ObjFoo.ClassName);
TUtility.SurpriseMe(ObjFoo);
writeln('After:'#9, ObjFoo.ClassName);
finally
FreeAndNil(ObjFoo);
end;
// Will fail to compile at SurpriseMe() call.
{
ObjXyz := TXyz.Create();
try
writeln('Before:'#9, ObjXyz.ClassName);
TUtility.SurpriseMe(ObjXyz);
writeln('After:'#9, ObjXyz.ClassName);
finally
FreeAndNil(ObjXyz);
end;
}
end.
Как минимум в Delphi XE8 должно уже работать.
Тут, как оказалось, ещё и проверка типов переменной ломается.
0
Sign up to leave a comment.
Как в TMemo сделать вертикальное выравнивание, отступы и TextHint