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

Вниз

задачка   Найти похожие ветки 

 
Polevi ©   (2004-04-19 19:10) [0]

написать ф-ию, возвращающую строку формата ClassName::PublishedProperty по параметру типа TClass

например для TControl должна вернуть
TComponent::Name
TComponent::Tag
TControl::Left
TControl::Top
TControl::Width
TControl::Height
TControl::Cursor
TControl::Hint
TControl::HelpType
TControl::HelpKeyword
TControl::HelpContext

интересено, у кого будет короче код :)


 
Vuk ©   (2004-04-19 19:25) [1]

Это... Так функцию, возвращающую строку или функцию, выдающую список строк?


 
Polevi ©   (2004-04-19 19:27) [2]

строку с разделителем #13#10


 
Jack128 ©   (2004-04-19 19:51) [3]

Примерно так, я думаю:

function GetPropListEx(AClass: TClass): string;
var
 TypeInfo: PTypeInfo;
 PropList: array[0..100] of PPropInfo;
 PropCount: Integer;
 i: Integer;
begin
 Result := "";
 TypeInfo := PTypeInfo(AClass.ClassInfo);
 if not Assigned(TypeInfo) then Exit;
 PropCount := GetTypeData(TypeInfo)^.PropCount;
 if PropCount = 0 then Exit;
 GetPropInfos(TypeInfo, @PropList);
 Result := "";
 for i := 0 to PropCount - 1 do
   Result := Result + AClass.ClassName + ": " + PropList[i].Name + #13#10;
end;

function GetAllProps(AClass: TClass): string;
var
 ClassArray: array of TClass;
 ClassCount: integer;
 i: Integer;
begin
 SetLength(ClassArray, 10);
 ClassCount := 0;
 while Assigned(AClass) do
 begin
   if Length(ClassArray) = ClassCount then
     SetLength(ClassArray, ClassCount + 10);
   ClassArray[ClassCount] := AClass;
   AClass := AClass.ClassParent;
   inc(ClassCount);
 end;
 SetLength(ClassArray, ClassCount);
 Result := "";
 for i := Length(ClassArray) - 1 downto 0 do
   Result := Result + GetPropListEx(ClassArray[i]);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Text := GetAllProps(TWinControl);
end;


 
Polevi ©   (2004-04-19 19:54) [4]

это очень длинно :)


 
Jack128 ©   (2004-04-19 19:56) [5]


>  [4] Polevi ©   (19.04.04 19:54)
К тому же не правельно :-(


> это очень длинно :)
А в чем длину оцениваем?? Или это предложение откопать в TypInfo стандартную функцию?


 
Polevi ©   (2004-04-19 20:02) [6]

длину оцениваем в строках кода
у меня 13, кто меньше ?
:)

кстати стандартной такой ф-ии я не знаю


 
Jack128 ©   (2004-04-19 20:05) [7]


> у меня 13, кто меньше ?
может поспорим, что я смогу ужать этот код до 13 строк???

По 250 символов каждая :-))


 
VMcL ©   (2004-04-19 20:06) [8]

>>Polevi ©  (19.04.04 20:02) [6]

Перепиши все свои 13 строк в одну - будет ваще обалдеть :)


 
Polevi ©   (2004-04-19 20:07) [9]

на строке допускается только не более одного знака ";"
:)


 
VMcL ©   (2004-04-19 20:09) [10]

>>Polevi ©  (19.04.04 20:07) [9]

Все равно многие составные операторы можно ужать :)

if a then
 b;

меняем на

if a then b;

и т. п.


 
VMcL ©   (2004-04-19 20:10) [11]

>>Polevi ©  (19.04.04 20:07) [9]

В общем, колись давай, а то такой flood разведём :))


 
Polevi ©   (2004-04-19 20:15) [12]

ладно, наслаждайтесь :)

function GetPublishedProps(AClass:TClass; var Value:string):integer;
var
 Props: PPropList;
 i:integer;
begin
 if AClass=TObject then exit;
 Result:=GetTypeData(AClass.ClassInfo)^.PropCount;
 GetMem(Props, Result * sizeof(Pointer));
 GetPropInfos(AClass.ClassInfo, Props);
 for i := GetPublishedProps(AClass.ClassParent,Value) to Result-1 do
   Value:=Value+Format("%s::%s",[AClass.ClassName,PPropInfo(Props^[I]).Name])+#13#10;
 FreeMem(Props);
end;


 
Jack128 ©   (2004-04-19 20:15) [13]


> VMcL ©   (19.04.04 20:10)
абсолютно согласен

Polevi - код на бочку!!! :-))


 
uny   (2004-04-19 20:17) [14]

Удалено модератором
Примечание: flood


 
VMcL ©   (2004-04-19 20:17) [15]

>>Polevi ©  (19.04.04 20:15) [12]

try..finally на GetMem/FreeMem
?


 
ламер ©   (2004-04-19 20:19) [16]

очень некрасиво. да и нет некоторых рекомендуемых проверок. но пока что работает.


function GetPublishedProperties(AClass: TClass): String;
var
 AParent: TClass;
 PropList: TPropList;
 I, PropCount: Integer;
begin
 Result := "";
 PropCount := GetPropList(AClass.ClassInfo, tkProperties, @PropList);
 for I := 0 to PropCount - 1 do
 begin
   AParent := AClass;
   while (AParent.ClassParent <> nil) and (AParent.ClassParent.ClassInfo <> nil) and IsPublishedProp(AParent.ClassParent, PropList[I]^.Name) do AParent := AParent.ClassParent;
   Result := Result + #13#10 + AParent.ClassName + "::" + PropList[I]^.Name;
 end;
end;



 
Polevi ©   (2004-04-19 20:19) [17]

>VMcL ©   (19.04.04 20:17) [15]
убрал в целях экономии :))


 
Jack128 ©   (2004-04-19 20:19) [18]

Ты это где GetPublishedProps откопал?? В Delphi5.TypInfo нету такого. Подлог!!! ;-))


 
Polevi ©   (2004-04-19 20:21) [19]

>Jack128 ©   (19.04.04 20:19) [18]
слово рекурсия видимо тебе не знакомо ?


 
VMcL ©   (2004-04-19 20:21) [20]

>>Polevi ©  (19.04.04 19:27) [2]

Кстати, твоя функция противоречит [2]. Она возвращает Integer, а не String. Ха!


 
Polevi ©   (2004-04-19 20:22) [21]

>ламер ©   (19.04.04 20:19) [16]
круто, только лист забыл освободить


 
VMcL ©   (2004-04-19 20:22) [22]

Sorry.
[20] = Re: [12]


 
Jack128 ©   (2004-04-19 20:23) [23]


> слово рекурсия видимо тебе не знакомо ?
сорри, не заметил..


 
Polevi ©   (2004-04-19 20:23) [24]

>VMcL ©   (19.04.04 20:21) [20]
не придирайся, и вообще, ты когда нибудь видел настолько красивый код, как у меня ? :)))))


 
VMcL ©   (2004-04-19 20:23) [25]

>>uny  (19.04.04 20:17) [14]

http://www.translate.ru/text.asp -> flood = наводнение


 
VMcL ©   (2004-04-19 20:24) [26]

>>Polevi ©  (19.04.04 20:23) [24]

Код на Delphi с GetMem/FreeMem и без try...finally я красивым не считаю :)))


 
uny   (2004-04-19 20:25) [27]

Удалено модератором
Примечание: Offtopic


 
VMcL ©   (2004-04-19 20:26) [28]

>>Polevi ©  (19.04.04 20:23) [24]

Да, у тебя еще и Warning. Фи! :)


 
Polevi ©   (2004-04-19 20:28) [29]

>VMcL ©   (19.04.04 20:26) [28]
новая версия, с учетом ранее неизвестных мне ф-ий от ламер ©   (19.04.04 20:19) [16]

function GetPublishedProps2(AClass:TClass; var Value:string):integer;
var
 Props: TPropList;
 i:integer;
begin
 Result:=GetPropList(AClass.ClassInfo, tkProperties, @Props);
 for i := GetPublishedProps2(AClass.ClassParent,Value) to Result-1 do
   Value:=Value+Format("%s::%s",[AClass.ClassName,PPropInfo(Props[I]).Name])+#13#10;
end;


 
Polevi ©   (2004-04-19 20:28) [30]

кул :)))


 
VMcL ©   (2004-04-19 20:34) [31]

>>Polevi ©  (19.04.04 20:28) [29]
>>Polevi ©  (19.04.04 20:28) [30]

Канешно, кул, дарагой.
AV, однако.


 
VMcL ©   (2004-04-19 20:35) [32]

>>Polevi ©  (19.04.04 20:28) [29]

Да и память кто будет очищать, дядя kernel?


 
VMcL ©   (2004-04-19 20:36) [33]

>>VMcL ©  (19.04.04 20:35) [32]

Sorry. С памятью поторопился. У тебя ж уже TPropList.


 
VMcL ©   (2004-04-19 20:37) [34]

>>Polevi ©  (19.04.04 20:28) [29]

Но всё равно: выделять по ~64 КБ на каждый из вызовов GetPublishedProps2 - это жирно. Гы.


 
Polevi ©   (2004-04-19 20:38) [35]

>VMcL ©   (19.04.04 20:36) [33]
да, проверочку зря убрал :)

function GetPublishedProps2(AClass:TClass; var Value:string):integer;
var
 Props: TPropList;
 i:integer;
begin
 if AClass=TObject then exit;
 Result:=GetPropList(AClass.ClassInfo, tkProperties, @Props);
 for i := GetPublishedProps2(AClass.ClassParent,Value) to Result-1 do
   Value:=Value+Format("%s::%s",[AClass.ClassName,PPropInfo(Props[I]).Name])+#13#10;
end;


 
Polevi ©   (2004-04-19 20:39) [36]

>VMcL ©   (19.04.04 20:37) [34]
что такое 64 к в наше время... тьфу :)


 
VMcL ©   (2004-04-19 20:41) [37]

>>Polevi ©  (19.04.04 20:38) [35]

Warning. Бу-га-га-га!!!


 
VMcL ©   (2004-04-19 20:42) [38]

>>Polevi ©  (19.04.04 20:39) [36]

Сказал бы ты мне это лет 5-6 назад, когда я на 386SX c 2MB RAM сидел :)


 
Polevi ©   (2004-04-19 20:43) [39]

вот пристал :))
function GetPublishedProps2(AClass:TClass; var Value:string):integer;
var
Props: TPropList;
i:integer;
begin
Result:=0;
if AClass=TObject then exit;
Result:=GetPropList(AClass.ClassInfo, tkProperties, @Props);
for i := GetPublishedProps2(AClass.ClassParent,Value) to Result-1 do
  Value:=Value+Format("%s::%s",[AClass.ClassName,PPropInfo(Props[I]).Name])+#13#10;
end


 
Polevi ©   (2004-04-19 20:45) [40]

>VMcL ©   (19.04.04 20:42) [38]
ты еще ZX Spectrum вспомни, там вместе с ОЗУ 65к было :-)


 
VMcL ©   (2004-04-19 20:50) [41]

>>Polevi ©  (19.04.04 20:43) [39]

Ну всё. Теперь у тебя суперпупергипермегафункция, куда там AvtoSheme :)


 
Юрий Зотов ©   (2004-04-19 21:07) [42]

Рекурсия с пожиранием 64 Кб стека на каждом уровне?
Из которых реально вряд ли и пара Кб потребуется?
Шалуны...
Stack Overflow на вас нет...
:о)

Ладно, вот задачка похитрее. Дана произвольная иерархия классов форм, отнаследованная от TForm. В каждом классе, возможно, есть произвольные обработчики событий произвольных компонентов. Задан класс TSomeForm, принадлежащий этой иерархии. Задача такая - сформировать список всех его обработчиков, включая и все унаследованные. Список нужно поместить в TStrings, по одному обработчику в строку, в виде:
Имя_класса.Имя_обработчика(Список_параметров)
причем список параметров должен быть синтаксически правильным. Пример:
TSomeFormAncestor.SomeMethod(Sender: TObject; Str: string)

Вот. Это похитрее будет, чем просто функции TypInfo вызывать. Пусть даже и рекурсивно.
:о)


 
VMcL ©   (2004-04-19 21:08) [43]

>>Юрий Зотов ©  (19.04.04 21:07) [42]

Да ну тебя. 8 вечера уже (Киев) :)


 
Yanis ©   (2004-04-19 21:12) [44]

<<<---Оффтопик--->>>

Этакий мастерский топик. Одни сливки собрались, ей богу :)


 
VMcL ©   (2004-04-19 21:16) [45]

>>Yanis ©  (19.04.04 21:12) [44]

Чтобы не портить "сливочность", твой пост и некоторые другие "лишние" удалят модераторы :D


 
Yanis ©   (2004-04-19 21:18) [46]

To [45]
Мне не привыкать :)

:)
:)


 
Юрий Зотов ©   (2004-04-19 21:18) [47]

> VMcL ©   (19.04.04 21:08) [43]

Нормально. Как раз до утра и выйдет.
:о)


 
VMcL ©   (2004-04-19 21:24) [48]

>>Юрий Зотов ©  (19.04.04 21:18) [47]

>Как раз до утра и выйдет.

Какого тысячелетия? :=D


 
Юрий Зотов ©   (2004-04-19 21:28) [49]

> VMcL ©   (19.04.04 21:24) [48]

Это уж как получится. Вообще-то, есть шанс стать Маклаудом.
:о)


 
VMcL ©   (2004-04-19 21:29) [50]

>>Юрий Зотов ©  (19.04.04 21:28) [49]

Уже стал. Меня так директор иногда называет.


 
VideoLord ©   (2004-04-19 22:24) [51]

Маклаудом... Хм ;-)
Ну если только нашим "бешенным", хотя мало кто может столько выпить.


 
Игорь Шевченко ©   (2004-04-19 23:33) [52]

Юрий Зотов ©   (19.04.04 21:07)

Задан класс или экземпляр класса ?


 
Igorek ©   (2004-04-20 11:11) [53]


> Юрий Зотов ©   (19.04.04 21:07) [42]
> Ладно, вот задачка похитрее. Дана произвольная иерархия
> классов форм, отнаследованная от TForm. В каждом классе,
> возможно, есть произвольные обработчики событий произвольных
> компонентов. Задан класс TSomeForm, принадлежащий этой иерархии.
> Задача такая - сформировать список всех его обработчиков,
> включая и все унаследованные. Список нужно поместить в TStrings,
> по одному обработчику в строку, в виде:
> Имя_класса.Имя_обработчика(Список_параметров)
> причем список параметров должен быть синтаксически правильным.
> Пример:
> TSomeFormAncestor.SomeMethod(Sender: TObject; Str: string)


Если дан класс, то невозможно, по определению, определить обработчики, а только события. На этот раз вам уже точно 2 за вопрос.


 
Игорь Шевченко ©   (2004-04-20 11:28) [54]


> Если дан класс, то невозможно, по определению, определить
> обработчики, а только события


Если можно, перевод этой фразы дай пожалуйста.


 
Igorek ©   (2004-04-20 11:30) [55]


> Игорь Шевченко ©   (20.04.04 11:28) [54]
>
> > Если дан класс, то невозможно, по определению, определить
>
> > обработчики, а только события
>
>
> Если можно, перевод этой фразы дай пожалуйста.

На какой язык?


 
Игорь Шевченко ©   (2004-04-20 11:34) [56]

Igorek ©   (20.04.04 11:30)

На понятный


 
Igorek ©   (2004-04-20 11:37) [57]


> Игорь Шевченко ©   (20.04.04 11:34) [56]
> Igorek ©   (20.04.04 11:30)
>
> На понятный

А что конкретно непонятно? Неужели все?


 
Igorek ©   (2004-04-20 11:40) [58]

Вообще чем дальше, тем больше меня поражают так называемые "мастера".


 
pasha_golub ©   (2004-04-20 11:44) [59]

Igorek ©   (20.04.04 11:40) [58]
Зря ты так. Зависть плохое чувство.


 
Игорь Шевченко ©   (2004-04-20 11:46) [60]

Igorek ©   (20.04.04 11:37)

Тебе трудно объяснить свою фразу ?


 
Igorek ©   (2004-04-20 11:49) [61]

Ок, поясняю попу-лярно.
"Если дан класс" - дано скажем TForm, TObject, TCoolGrid..., а не Form1: TForm...
"то невозможно, по определению, определить обработчики, а только события." - обработчики - это фактически указатели на функции. Эти указатели являются полями класса. А поля, как известно имеют значение только при наличии обьекта, а не класса (за исключением статических полей, которые не знаю есть ли в Паскале).
Таким образом, поскольку мы имеем класс, а не обьект, то мы не можем по-определению узнать значения полей (читай обработчики событий).


 
Igorek ©   (2004-04-20 11:50) [62]


> pasha_golub ©   (20.04.04 11:44) [59]
> Igorek ©   (20.04.04 11:40) [58]
> Зря ты так. Зависть плохое чувство.

С чего ты взял, что я кому-то завидую?


 
pasha_golub ©   (2004-04-20 11:52) [63]

Igorek ©   (20.04.04 11:50) [62]
Я не сказал, что ты завидуешь :-)

Просто, констатировал факт, что "Зависть - плохое чувство". ;-)


 
Igorek ©   (2004-04-20 11:53) [64]

оффтоп, цитата:
"
       Мама, мы все тяжело больны...
       Мама, я знаю, мы все сошли с ума...
"
В.Цой


 
Юрий Зотов ©   (2004-04-20 11:55) [65]

> Игорь Шевченко ©   (19.04.04 23:33) [52]

Дана иерархия классов и входящий в нее класс. Допустим, иерархия сидит в каком-то BPL, или прямо в EXE - неважно.

Задачу можно упростить (суть останется та же, просто код будет менее громоздким за счет меньшего количества рутины) - будем строить список вообще любых published-методов. То есть - всех доступных данному классу, включая и унаследованные.

> Igorek ©   (20.04.04 11:11) [53]

Оценки будете выставлять, когда решите задачу (если вообще сможете). А до тех пор - LMD. Сначала разберитесь, чему принадлежит код, а чему - данные.


 
Igorek ©   (2004-04-20 11:56) [66]


> pasha_golub ©   (20.04.04 11:52) [63]
> Igorek ©   (20.04.04 11:50) [62]
> Я не сказал, что ты завидуешь :-)
>
> Просто, констатировал факт, что "Зависть - плохое чувство".
> ;-)

Ты сказал "зря ты так". Что именно зря? И почему зависть плохое чувство? Я например очень сильно завидую уму и знаниям некоторых программистов с этого форума, и из форумов rsdn.ru. И некоторых из них я искренне уважаю.


 
Igorek ©   (2004-04-20 11:57) [67]


> Юрий Зотов ©   (20.04.04 11:55) [65]
> Оценки будете выставлять, когда решите задачу (если вообще
> сможете). А до тех пор - LMD. Сначала разберитесь, чему
> принадлежит код, а чему - данные.

Да я собственно уже решил в [61]


 
Игорь Шевченко ©   (2004-04-20 12:04) [68]

Igorek ©   (20.04.04 11:49)

Именно это я и хотел услышать.

hint: привязка обработчиков к событиям формы и ее компонентов является общей для всех экземпляров класса формы и располагается в .dfm


 
Igorek ©   (2004-04-20 12:12) [69]


> Игорь Шевченко ©   (20.04.04 12:04) [68]
> Igorek ©   (20.04.04 11:49)
> Именно это я и хотел услышать.
> hint: привязка обработчиков к событиям формы и ее компонентов
> является общей для всех экземпляров класса формы и располагается
> в .dfm


Что-то я нервный сегодня (из-за вчерашних событий). Еще "мастера" достают.

По сути:
In Delphi, almost all the code you write is executed, directly or indirectly, in response to events. An event is a special kind of property that represents a runtime occurrence, often a user action. The code that responds directly to an event—called an event handler—is an Object Pascal procedure. Все пошел работать.
---
"Кто имеет уши, тот услышит"


 
Игорь Шевченко ©   (2004-04-20 12:24) [70]

Юрий Зотов ©   (20.04.04 11:55)

Тогда уточним задачу:

Есть класс TForm1, у него есть published метод OnCreate. Обработчик его события чаще всего называется TForm1.FormCreate, если его имя не меняется руками.

В задаче требуется для произвольного класса, входящего в иерархию, вывести этот обработчик в виде
procedure TForm1.FormCreate(Sender: TObject);
или в виде
procedure TForm1.OnCreate(Sender: TObject);

?


 
Юрий Зотов ©   (2004-04-20 12:54) [71]

> Игорь Шевченко ©   (20.04.04 12:24) [70]

В виде
procedure TForm1.FormCreate(Sender: TObject);

То есть - реальное имя метода. Вообще, можно упростить задачу и просто построить список доступных классу методов (а то тут с понятиями "событие" и "обработчик" не у всех все в порядке - зато с самомнением нет проблем).

Рассмотрим пример. Пусть есть такая иерархия:

TForm1 = class(TForm)
 procedure Proc1(...);
 procedure Proc2(...);
end;

TForm2 = class(TForm1)
 procedure Proc2(...);
 procedure Proc3(...);
end;

TForm3 = class(TForm2)
 procedure Proc3(...);
 procedure Proc4(...);
end;

Для класса TForm3 должен получиться такой список:

TForm3.Proc3(...);
TForm3.Proc4(...);
TForm2.Proc2(...);
TForm1.Proc1(...);


 
Игорь Шевченко ©   (2004-04-20 13:08) [72]

Юрий Зотов ©   (20.04.04 12:54)

Тогда я наверное чего-то не понимаю. Список методов я могу достать, список свойств-методов с синтаксисом - тоже. Но привязать их одни к другим без dfm я не могу :)


 
Igorek ©   (2004-04-20 13:59) [73]

2 Юрий Зотов
Протрите значок мастера и бегом учить азы ObjectPascal.


 
Игорь Шевченко ©   (2004-04-20 14:02) [74]

Igorek ©   (20.04.04 12:12)


> The code that responds directly to an event—called an event
> handler—is an Object Pascal procedure


Точнее, метод объекта.

И эта...завязывай перепалку, плз


 
Igorek ©   (2004-04-20 15:08) [75]


> Игорь Шевченко ©   (20.04.04 14:02) [74]
> И эта...завязывай перепалку, плз

Ок. Но истина тебя интересует? Ответь на вопрос "Задача, заданная в (Юрий Зотов ©   (19.04.04 21:07) [42]), имеет решение?" Да или нет?


 
Игорь Шевченко ©   (2004-04-20 15:25) [76]

Igorek ©   (20.04.04 15:08)


> Ответь на вопрос


Пока я вижу решение, связанное с разбором .dfm или с созданием экземпляра класса. Но хочу надеятся, что существует более элегантное. То есть, решение имеется в любом случае.


 
MBo ©   (2004-04-20 15:28) [77]

> [71]
приспособлено из старых извращений:


procedure ListMethods(Cls: TClass; Strings: TStrings);
var
 PVMT: Pointer;
 i, Num, len: Integer;
 MName: string;
begin
 if Cls = nil then Exit;
 PVMT := Pointer(Cls);
 Inc(PByte(PVMT), vmtMethodtable);
 PVMT := Pointer(PVMT^);
 if PVMT = nil then Exit;
 Num := PWord(PVMT)^;
 Strings.Add(Format("класс %s, методов: %d ", [Cls.ClassName, Num]));
 Inc(PWord(PVMT));
 for i := 0 to Num - 1 do begin
   len := PWord(PVMT)^;
   Inc(PByte(PVMT),7);
   SetLength(MName, len - 7);
   Move(PVMT^, MName[1], len - 7);
   Strings.Add(Format("%d: %d %s", [i, len, MName]));
   Inc(PByte(PVMT), len - 7);
 end;
 ListMethods(Cls.ClassParent, Strings);
end;


 
Игорь Шевченко ©   (2004-04-20 15:31) [78]

MBo ©   (20.04.04 15:28)

А параметры ? :))))


 
MBo ©   (2004-04-20 15:33) [79]

>Игорь Шевченко
>А параметры ? :))))
Это еще думать надо, а с обходом VMT уже когда-то копался ;))


 
Vuk ©   (2004-04-20 15:38) [80]

to Игорь Шевченко ©   (20.04.04 15:31) [78]:
>А параметры ? :))))
Если мне мой склероз не изменяет, нету их тама. :o)
Параметры методов, как они объявлены, можно вытащить только для RTTI-enabled интерфейсов начиная с D6.


 
Игорь Шевченко ©   (2004-04-20 15:38) [81]

MBo ©   (20.04.04 15:33)

Подобный код я тоже вчера вечером написал, а вот сопоставление TypeData от свойств с конкретными именами/адресами методов у меня не вышло без одного из тех двух способов в [76] :)


 
Игорь Шевченко ©   (2004-04-20 15:42) [82]

Vuk ©   (20.04.04 15:38)


> Параметры методов, как они объявлены


Можно вытащить из TypeInfo/TypeData свойства, как это делает DeDe


 
Vuk ©   (2004-04-20 15:47) [83]

Ну это только по факту привязки метод-свойство выявляется, за счет предположения, что заголовок метода совпадает с заголовком типа для свойства. У интерфейсов можно вытащить вообще все. Я, помнится, чуть ли не исходный текст интерфейса восстанавливал.
:o)


 
Игорь Шевченко ©   (2004-04-20 15:49) [84]

Vuk ©   (20.04.04 15:47)

С интерфейсами я не пробовал, ничего не могу сказать, а вот синтаксис свойства-метода с незапамятных времен в RTTI живет, и даже в TypInfo описан :)


 
Vuk ©   (2004-04-20 15:51) [85]

И я про то, что описаны параметры свойства-метода, но не параметры published метода.


 
Igorek ©   (2004-04-20 16:11) [86]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   procedure FormCreate(Sender: TObject);
   procedure FormShow1(Sender: TObject);
 private
   procedure FormShow2(Sender: TObject);
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}
procedure ListMethods(Cls: TClass; Strings: TStrings);
var
PVMT: Pointer;
i, Num, len: Integer;
MName: string;
begin
if Cls = nil then Exit;
PVMT := Pointer(Cls);
Inc(PByte(PVMT), vmtMethodtable);
PVMT := Pointer(PVMT^);
if PVMT = nil then Exit;
Num := PWord(PVMT)^;
Strings.Add(Format("класс %s, методов: %d ", [Cls.ClassName, Num]));
Inc(PWord(PVMT));
for i := 0 to Num - 1 do begin
  len := PWord(PVMT)^;
  Inc(PByte(PVMT),7);
  SetLength(MName, len - 7);
  Move(PVMT^, MName[1], len - 7);
  Strings.Add(Format("%d: %d %s", [i, len, MName]));
  Inc(PByte(PVMT), len - 7);
end;
ListMethods(Cls.ClassParent, Strings);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 OnShow := FormShow2;
end;

procedure TForm1.FormShow1(Sender: TObject);
begin
//  dummy
end;

procedure TForm1.FormShow2(Sender: TObject);
begin
 ListMethods(TForm1, Memo1.Lines);
end;

end.

Кто что думает насчет этого кода?


 
Igorek ©   (2004-04-20 16:32) [87]

А насчет этого:
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TDummy = class(TComponent)
   procedure FormShow1(Sender: TObject);
 end;

 TForm1 = class(TForm)
   Memo1: TMemo;
   procedure FormCreate(Sender: TObject);
 private
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}
procedure ListMethods(Cls: TClass; Strings: TStrings);
var
PVMT: Pointer;
i, Num, len: Integer;
MName: string;
begin
if Cls = nil then Exit;
PVMT := Pointer(Cls);
Inc(PByte(PVMT), vmtMethodtable);
PVMT := Pointer(PVMT^);
if PVMT = nil then Exit;
Num := PWord(PVMT)^;
Strings.Add(Format("класс %s, методов: %d ", [Cls.ClassName, Num]));
Inc(PWord(PVMT));
for i := 0 to Num - 1 do begin
  len := PWord(PVMT)^;
  Inc(PByte(PVMT),7);
  SetLength(MName, len - 7);
  Move(PVMT^, MName[1], len - 7);
  Strings.Add(Format("%d: %d %s", [i, len, MName]));
  Inc(PByte(PVMT), len - 7);
end;
ListMethods(Cls.ClassParent, Strings);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 with TDummy.Create(Self) do
   OnShow := FormShow1;
end;

{ TDummy }

procedure TDummy.FormShow1(Sender: TObject);
begin
 ListMethods(TForm1, Form1.Memo1.Lines);
end;

end.


 
Игорь Шевченко ©   (2004-04-20 18:18) [88]

Для экземпляра класса что-то получилось - не судите строго:
unit main;

interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, TypInfo;

type
 TfMain = class(TForm)
   ListBox1: TListBox;
   Button3: TButton;
   procedure Button3Click(Sender: TObject);
 private
   procedure SpyMethods(AClass: TClass; Strings: TStrings);
   procedure SpyRootComponentMethods(AClass: TObject; Strings: TStrings);
   procedure SpyComponentMethods(AClass: TObject; Strings, Methods: TStrings);
   procedure SpyInstanceMethods(AClass: TObject; Strings, Methods: TStrings);
   function ParseMethodProp(AProp: PPropInfo;
     const MethodName: string): string; overload;
   function ParseMethodProp(AProp: PPropInfo): string; overload;
 end;

var
 fMain: TfMain;

implementation
uses
 ChildForm;

{$R *.dfm}

{ TfMain }

type
 TMethodDesc = packed record
   MethodDescSize: Word;
   MethodAddress: Pointer;
   MethodName: ShortString;
 end;
 PMethodDesc = ^TMethodDesc;

 TMethodTable = packed record
   MethodCount: Word;
   Data: TMethodDesc;
 end;
 PMethodTable = ^TMethodTable;
 PPMethodTable = ^PMethodTable;

procedure TfMain.SpyMethods(AClass: TClass; Strings: TStrings);
var
 Methods: PMethodTable;
 MethodDesc: PMethodDesc;
 I: Integer;
begin
 Methods := PPMethodTable(PChar(AClass) + vmtMethodTable)^;
 if Assigned(Methods) then begin
   MethodDesc := @Methods^.Data;
   for I:=0 to Pred(Methods^.MethodCount) do begin
     Strings.AddObject(
       Format("%s.%s", [AClass.ClassName, MethodDesc^.MethodName]),
         TObject(MethodDesc^.MethodAddress));
     MethodDesc := PMethodDesc(PChar(MethodDesc) + MethodDesc^.MethodDescSize);
   end;
 end;
 if AClass.ClassParent <> nil then
   SpyMethods(AClass.ClassParent, Strings);
end;

function MethodKindToString (const Value: TMethodKind): string;
const
 MethodKindNames: array[TMethodKind] of string = ("procedure", "function",
   "constructor", "destructor", "class procedure", "class function",
   "procedure", "function");
begin
 Result := MethodKindNames[Value];
end;

type
 TParamDesc = packed record
   Flags: TParamFlags;
   ParamName: ShortString;
   TypeName: ShortString;
 end;
 PParamDesc = ^TParamDesc;

function TfMain.ParseMethodProp(AProp: PPropInfo;
 const MethodName: string): string;
var
 MethodTypeData: PTypeData;
 ParamCount: Integer;
 ParamDesc: PParamDesc;
 Param, Params: string;
 ResultType: PShortString;
 I: Integer;
 TypeName: PShortString;
begin
 MethodTypeData := GetTypeData(AProp^.PropType^);
 ParamCount := MethodTypeData^.ParamCount;
 ParamDesc := @MethodTypeData^.ParamList;
 ResultType := PShortString(ParamDesc);
 for I:=0 to Pred(ParamCount) do begin
   if pfVar in ParamDesc^.Flags then
     Param := "var "
   else if pfConst in ParamDesc^.Flags then
     Param := "const "
   else
     Param := "";
   TypeName := PShortString(PChar(ParamDesc) + SizeOf(TParamFlags) +
     Length(ParamDesc^.ParamName) + SizeOf(Char));
   if pfArray in ParamDesc^.Flags then
     Param := Param + Format("%s: array of %s", [ParamDesc^.ParamName,
       TypeName^])
   else
     Param := Param + Format("%s: %s", [ParamDesc^.ParamName,
       TypeName^]);
   if I <> 0 then
     Params := Params + "; ";
   Params := Params + Param;
   ParamDesc := PParamDesc(PChar(ParamDesc) + SizeOf(TParamFlags) +
     Length(ParamDesc^.ParamName) + Length(TypeName^) +
     SizeOf(Char) * 2);
   ResultType := PShortString(ParamDesc);
 end;
 if Length(Params) <> 0 then
   Params := "(" + Params + ")";
 if MethodTypeData^.MethodKind in
     [mkFunction, mkClassFunction, mkSafeFunction] then
   Params := Format("%s: %s;", [Params, ResultType^])
 else
   Params := Params + ";";
 if MethodTypeData^.MethodKind in [mkSafeProcedure, mkSafeFunction] then
   Params := Params + "safecall;";
 Result := Format("%s %s: %s", [
   MethodKindToString(MethodTypeData^.MethodKind), MethodName, Params]);
end;

function TfMain.ParseMethodProp(AProp: PPropInfo): string;
begin
 Result := ParseMethodProp(AProp, AProp^.Name);
end;

procedure TfMain.SpyInstanceMethods(AClass: TObject;
 Strings, Methods: TStrings);

 function GetFullMethodName(const Methods: TStrings; Address: Pointer): string;
 var
   I: Integer;
 begin
   for I:=0 to Pred(Methods.Count) do
     if Pointer(Methods.Objects[I]) = Address then begin
       Result := Methods[I];
       Break;
     end;
 end;

var
 Props: TPropList;
 I: Integer;
 NumMethods: Integer;
 Method: TMethod;
 FullMethodName: string;
begin
 NumMethods := GetPropList(AClass.ClassInfo, tkMethods, @Props);
 for I:=0 to Pred(NumMethods) do begin
   Method := GetMethodProp(AClass, Props[I]);
   if Assigned(Method.Code) then begin
     FullMethodName := GetFullMethodName(Methods, Method.Code);
     if Length(FullMethodName) <> 0 then
       Strings.Add (ParseMethodProp(Props[I], FullMethodName));
   end;
 end;
end;

procedure TfMain.Button3Click(Sender: TObject);
var
 Strings: TStrings;
begin
 Strings := TStringList.Create;
 try
   SpyRootComponentMethods(fChild, Strings);
   ListBox1.Items.Assign(Strings);
 finally
   Strings.Free;
 end;
end;

procedure TfMain.SpyComponentMethods(AClass: TObject;
 Strings, Methods: TStrings);
var
 I: Integer;
begin
 SpyInstanceMethods(AClass, Strings, Methods);
 if AClass is TComponent then
   for I:=0 to Pred(TComponent(AClass).ComponentCount) do
     SpyComponentMethods(TComponent(AClass).Components[I], Strings, Methods);
end;

procedure TfMain.SpyRootComponentMethods(AClass: TObject;
 Strings: TStrings);
var
 MethodStrings: TStrings;
begin
 MethodStrings := TStringList.Create;
 try
   SpyMethods(AClass.ClassType, MethodStrings);
   SpyComponentMethods(AClass, Strings, MethodStrings);
 finally
   MethodStrings.Free;
 end;
end;

end.


 
Игорь Шевченко ©   (2004-04-20 18:20) [89]

В проекте созданы три формы: главная (текст в студии),
и две формы для иерархии
unit ChildForm;

interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
 Dialogs, ParentForm, ExtCtrls;

type
 TfChild = class(TfParent)
   Timer: TTimer;
   procedure TimerTimer(Sender: TObject);
 end;

var
 fChild: TfChild;

implementation

{$R *.dfm}

procedure TfChild.TimerTimer(Sender: TObject);
begin
 Beep;
end;

end.


и ее родитель:
unit ParentForm;

interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
 Dialogs;

type
 TfParent = class(TForm)
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure FormActivate(Sender: TObject);
 end;

var
 fParent: TfParent;

implementation

{$R *.dfm}

procedure TfParent.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree;
end;

procedure TfParent.FormActivate(Sender: TObject);
begin
 ShowMessage("I am activated");
end;

end.


Все формы создаются в AutoCreate


 
Игорь Шевченко ©   (2004-04-20 18:21) [90]

Как тоже самое сделать не для экземпляра класса, а для класса, легко и просто - не знаю :)


 
-SeM-   (2004-04-21 09:50) [91]

[88] Игорь Шевченко ©   (20.04.04 18:18)

А может еще добавить?


>  for I:=0 to Pred(ParamCount) do begin
>    if pfVar in ParamDesc^.Flags then
>      Param := "var "
>    else if pfConst in ParamDesc^.Flags then
>      Param := "const "


    if pfOut in ParamDesc^.Flags then
      Param:="out ";


>    else
>      Param := "";


 
Игорь Шевченко ©   (2004-04-21 10:17) [92]

-SeM-   (21.04.04 09:50)

Да, спасибо, можно добавить. Может, я его просмотрел. А вот как отображаются в исходном виде параметры pfAddress и pfReference я даже не представляю :)


 
Igorek ©   (2004-04-21 10:38) [93]

Я тут подумал, что в принципе какая-то логика (хотя и имхо неправильная) в постановке Ю.З. есть. Скажем "вывести все методы класса, которые могут выступать в качестве обработчиков". Вот если в форме есть 100 методов, по сигнатуре подходящих для события напр. OnFormCreate, то все их вывести. Но вы же понимаете что только один в конкретный момент может выступать обработчиком. Более того, строго говоря, даже то что на метод указывает поле, хранящее обработчик, этот метод еще не есть обработчиком. Он станет таковым в момент вызова. А до того момента значение поля может сто раз поменяться (что и было продемонстрировано в приведенном мною коде). :-)


 
-SeM-   (2004-04-21 10:44) [94]

[92] Игорь Шевченко ©   (21.04.04 10:17)
А это где, в интерфейсах?


 
Игорь Шевченко ©   (2004-04-21 10:45) [95]

-SeM-   (21.04.04 10:44)

В описании TParamFlag :)


 
Игорь Шевченко ©   (2004-04-21 10:45) [96]


> Вот если в форме есть 100 методов, по сигнатуре подходящих
> для события напр. OnFormCreate, то все их вывести.


А сигнатуру как узнать ? :))


 
-SeM-   (2004-04-21 10:55) [97]


> [93] Igorek ©   (21.04.04 10:38)


> Он станет таковым в момент вызова.


Правильно, но задача то "строить список вообще любых published-методов. То есть - всех доступных данному классу, включая и унаследованные", как я понимаю, на момент исследования.


 
-SeM-   (2004-04-21 10:57) [98]


> [95] Игорь Шевченко ©   (21.04.04 10:45)

Не, я в смысле используется :)


 
Igorek ©   (2004-04-21 13:01) [99]


> Игорь Шевченко ©   (21.04.04 10:45) [96]
> А сигнатуру как узнать ? :))

 TForm1 = class(TForm)
   Memo1: TMemo;
   procedure FormCreate(Sender: TObject);
 private
 public
 published
   procedure FormShow1(Sender: TObject);
   procedure FormShow2(Sender: TObject);
   procedure FormShow3(Sender: TObject);
 end;

А потом RTTI, если не ошибаюсь.


 
Игорь Шевченко ©   (2004-04-21 13:55) [100]

Igorek ©   (21.04.04 13:01)

Дело в том, что по условию задачи сигнатура мне неизвестна. Произвольный обработчик может иметь произвольный процедурный тип.


 
Igorek ©   (2004-04-21 14:25) [101]


> Игорь Шевченко ©   (21.04.04 13:55) [100]
> Igorek ©   (21.04.04 13:01)
>
> Дело в том, что по условию задачи сигнатура мне неизвестна.
> Произвольный обработчик может иметь произвольный процедурный
> тип.

Как? Тип обработчика определяется типом события.
Т.е. или нам надо вывести все публикуемые методы данного класса, которые могут выступать в роли обработчиков для событий обьектов данного класса. Или нам надо вывести сигнатуры (без названий методов) обработчиков которые подходят для всех событий (иными словами типы событий).


 
Игорь Шевченко ©   (2004-04-21 14:28) [102]

Igorek ©   (21.04.04 14:25)

Вроде, я попытался решить задачу, правда, с несколько измененными начальными условиями, используя не класс (VMT), а экземпляр класса (TObject). Я не совсем понимаю, какой смысл в дополнениях к условиям ?


 
Igorek ©   (2004-04-21 14:39) [103]


> Игорь Шевченко ©   (21.04.04 14:28) [102]
Я не совсем понимаю, какой смысл в дополнениях
> к условиям ?

Просто я привык перед решением четко сформулировать задачу. Что и стараюсь после вчерашнего (а то остался неприятный осадок, и думаю не только у меня). Без формулировки у меня лично нету ни малейшего желания даже браться за задачу.


 
Юрий Зотов ©   (2004-04-21 15:15) [104]

Все же исходная постановка задачи в [42] была правильной - без привязки к TypeData можно построить список параметров для методов RTTI-интерфейсов (см. [80]), а для методов произвольных объектов, как сказал Игорь, нужно либо сканировать ресурсы ручками, либо создавать экземпляр - иначе привязаться к TypeData и получить параметры не удается.

Тем не менее, обоими методами можно получить решение именно для класса, а не для объекта. Естественно, параметры будут получены только для тех методов, которые в этом классе являются обработчиками событий (о чем, собственно, сразу и говорилось в [42]).

Привожу свое решение для обоих вариантов (переключаются опцией ParseDfmIndirect). Чтобы не загромождать код непринципиальными деталями, сканируются только события самих форм. Опция AutoRegisterForms указывает, должна ли быть использована автоматическая регистрация форм (можно либо отключить эту опцию, либо взять пример кода авторегистрации в "Кладовке").

================ Код см. в продолжении ================


 
Юрий Зотов ©   (2004-04-21 15:16) [105]

================ Продолжение ================

Проект состоит из стандартного DPR, модуля главной формы и трех модулей форм, входящих в иерархию. Модуль главной формы такой:

unit Main;

interface

uses
 Classes, Controls, Forms, StdCtrls;

type
 TAppMainForm = class(TForm)
   ListBox1: TListBox;
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 end;

var
 AppMainForm: TAppMainForm;

implementation

{$R *.dfm}

{$DEFINE ParseDfmIndirect}
// {$DEFINE AutoRegisterForms}

uses
 Windows, SysUtils, TypInfo, First, Third,
{$IFDEF AutoRegisterForms}
 ClassReg;
{$ELSE AutoRegisterForms}
 Second;
{$ENDIF AutoRegisterForms}

var
 FormsModule: Cardinal;

procedure GetAllHandlers(Strings: TStrings; AClass: TClass);

 function GetHandlers(Strings: TStrings; AClass: TClass): Boolean;

   procedure IncPtr(var P: Pointer; Value: integer);
   begin { IncPtr }
     P := Pointer(Integer(P) + Value)
   end; { IncPtr }

   function ExtractShortString(var P: Pointer): string;
   begin { GetShortString }
     Result := ShortString(P^);
     IncPtr(P, Byte(P^) + 1)
   end; { GetShortString }

   function GetMethodParams(MethodName: string; AClass: TClass): string;

{$IFDEF ParseDfmIndirect}
     function GetHandlerName(PropName: string; AClass: TClass): string;
     var
       ResourceStream: TResourceStream;
       StringStream: TStringStream;
       Fmt: TStreamOriginalFormat;
       i: integer;
     begin
       Result := "";
       if (AClass = nil) or (FindResource(FormsModule, PChar(AClass.ClassName + #0), RT_RCDATA) = 0) then
         Exit;
       StringStream := TStringStream.Create("");
       try
         ResourceStream := TResourceStream.Create(FormsModule, AClass.ClassName, RT_RCDATA);
         try
           Fmt := sofText;
           ObjectResourceToText(ResourceStream, StringStream, Fmt)
         finally
           ResourceStream.Free
         end;
         i := Length(PropName) + 2;
         with StringStream do
         begin
           Position := Pos(PropName, DataString) + i;
           if Position > i then
           begin
             i := Position;
             while DataString[i] in ["_", "0".."9", "A".."Z", "a".."z"] do Inc(i);
             Result := Copy(DataString, Position, i - Position)
           end
           else Result := GetHandlerName(PropName, AClass.ClassParent)
         end
       finally
         StringStream.Free
       end
     end;
{$ELSE ParseDfmIndirect}
     function GetHandlerAddress(PropInfo: PPropInfo): Pointer;
     var
       Component: TComponent;
     begin { GetHandlerAddress }
       Component := ReadComponentRes(AClass.ClassName, nil);
       try
         Result := GetMethodProp(Component, PropInfo).Code
       finally
         Component.Free
       end
     end; { GetHandlerAddress }
{$ENDIF ParseDfmIndirect}
   var
     PropList: PPropList;
     PropCount, i, ParamCount, j: integer;
     P: Pointer;
   begin { GetMethodParams }
     Result := "";
     PropCount := GetPropList(AClass.ClassInfo, tkMethods, nil);
     if PropCount = 0 then Exit;
     GetMem(PropList, PropCount * SizeOf(PPropInfo));
     try
       GetPropList(AClass.ClassInfo, tkMethods, PropList);
       for i := 0 to PropCount - 1 do
{$IFDEF ParseDfmIndirect}
         if SameText(MethodName, GetHandlerName(PropList^[i].Name, AClass)) then
{$ELSE ParseDfmIndirect}
         if AClass.MethodAddress(MethodName) = GetHandlerAddress(PropList^[i]) then
{$ENDIF ParseDfmIndirect}
         begin
           P := GetTypeData(PropList^[i]^.PropType^);
           IncPtr(P, SizeOf(TMethodKind));
           ParamCount := Byte(P^);
           IncPtr(P, 1);
           for j := 0 to ParamCount - 1 do
           begin
             if pfVar in TParamFlags(P^) then
               Result := Result + "var "
             else
               if pfConst in TParamFlags(P^) then
                 Result := Result + "const "
               else
                 if pfOut in TParamFlags(P^) then
                   Result := Result + "out ";
             IncPtr(P, SizeOf(TParamFlags));
             Result := Format("%s%s: %s; ", [Result, ExtractShortString(P), ExtractShortString(P)])
           end;
           SetLength(Result, Length(Result) - 2);
           Exit
         end
     finally
       FreeMem(PropList)
     end
   end; { GetMethodParams }

 var
   P: Pointer;
   MethodCount, i: Word;
   MethodName: string;
 begin { GetHandlers }
   Result := False;
   P := AClass;
   IncPtr(P, vmtMethodTable);
   P := Pointer(P^);
   if P = nil then Exit;
   MethodCount := Word(P^);
   if MethodCount = 0 then Exit else Result := True;
   IncPtr(P, SizeOf(Word));
   for i := 0 to MethodCount - 1 do
   begin
     IncPtr(P, SizeOf(Word) + SizeOf(Pointer));
     MethodName := ExtractShortString(P);
     if Pos(MethodName, Strings.Text) = 0 then
       Strings.Add(Format("%s.%s(%s);", [AClass.ClassName, MethodName,
         GetMethodParams(MethodName, AClass)]))
   end
 end; { GetHandlers }

begin { GetAllHandlers }
 Strings.BeginUpdate;
 try
   Strings.Clear;
   while AClass <> nil do
   begin
     GetHandlers(Strings, AClass);
     AClass := AClass.ClassParent
   end
 finally
   Strings.EndUpdate
 end
end; { GetAllHandlers }

{$IFDEF AutoRegisterForms}
function RegisterForms(AClass: TClass; Data: Pointer): Boolean;
begin
 Result := True;
 if AClass.InheritsFrom(TFirstForm) then Classes.RegisterClass(TPersistentClass(AClass))
end;
{$ENDIF AutoRegisterForms}

{ TForm1 }

procedure TAppMainForm.FormCreate(Sender: TObject);
begin
 FormsModule := FindClassHInstance(TFirstForm);
{$IFDEF AutoRegisterForms}
 EnumClasses(FormsModule, RegisterForms, nil)
{$ELSE AutoRegisterForms}
 RegisterClasses([TFirstForm, TSecondForm, TThirdForm])
{$ENDIF AutoRegisterForms}
end;

procedure TAppMainForm.Button1Click(Sender: TObject);
begin
 GetAllHandlers(ListBox1.Items, TThirdForm)
end;

end.


================ Модули с формами иерархии см. в окончании ================


 
Юрий Зотов ©   (2004-04-21 15:18) [106]

================ Окончание ================

unit First;

interface

uses
 Forms;

type
 TFirstForm = class(TForm)
   procedure FormCreate(Sender: TObject);
   procedure FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean);
 end;

implementation

{$R *.dfm}

procedure TFirstForm.FormCreate(Sender: TObject);
begin
 Width := 500
end;

procedure TFirstForm.FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean);
begin
 Resize := True
end;

end.

unit Second;

interface

uses
 Forms, First;

type
 TSecondForm = class(TFirstForm)
   procedure FormCreate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 end;

implementation

{$R *.dfm}

procedure TSecondForm.FormCreate(Sender: TObject);
begin
 Width := 500
end;

procedure TSecondForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree
end;

end.

unit Third;

interface

uses
 Classes, Forms, Second;

type
 TThirdForm = class(TSecondForm)
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
 end;

implementation

{$R *.dfm}

procedure TThirdForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree
end;

procedure TThirdForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
 Key := 0
end;

end.


 
Игорь Шевченко ©   (2004-04-21 15:33) [107]

Юрий Зотов ©   (21.04.04 15:16)

Respect!

Про ReadComponentRes я не додумал, спасибо за науку :)


 
euru ©   (2004-04-21 15:58) [108]

Вопрос не по теме, а по коду.

Почему для определения собственных условий компиляции используется конструкция


{$DEFINE condition}

{$IFDEF condition}
{$ENDIF}


вместо


const
  condition = True;

{$IF condition}
{$IFEND}


 
Vuk ©   (2004-04-21 16:20) [109]

to euru ©   (21.04.04 15:58) [108]:
>Почему для определения собственных условий компиляции
>используется конструкция
Потому, что то, что определяется через $DEFINE можно компилятору с командной строки передать.


 
euru ©   (2004-04-21 16:55) [110]

>Vuk ©   (21.04.04 16:20) [109]
А как через командную строку можно определить условие типа

{$IF condition > 5}


 
Игорь Шевченко ©   (2004-04-21 17:05) [111]

euru ©   (21.04.04 16:55)

А у меня компилятор выдает Invalid compiler directive $IF. Отгадайте с трех раз, почему ?


 
Vuk ©   (2004-04-21 17:15) [112]

to euru ©   (21.04.04 16:55) [110]:
>А как через командную строку можно определить условие типа
>{$IF condition > 5}
Для {$IF condition > 5} - никак. Для {$IF Defined(VARIABLE)} и {$IFDEF VARIABLE} - при помощи -D

И вообще, dcc32.exe


 
euru ©   (2004-04-21 17:24) [113]

>Игорь Шевченко ©   (21.04.04 17:05) [111]
Думаю, у вас Delphi v1-v6.

>Игорь Шевченко ©   (21.04.04 17:05) [111]
>Vuk ©   (21.04.04 17:15) [112]
Спасибо за предоставленную информацию.


 
VMcL ©   (2004-04-21 17:32) [114]

>>euru ©  (21.04.04 17:24) [113]

В D6 уже появилась {$IF}.


 
Igorek ©   (2004-04-21 17:45) [115]


2 Юрий Зотов ©   (21.04.04 15:18) [106]

Однако я смотрю этот вопрос для Вас стал принципиальным. :-)
Не умаляя достоинств приведенного кода, позволю себе не согласиться, что это решение задачи в постановке [42]. Там ничего не говорилось про RTTI. Соотв. был и мой пост [53].
Повторю касательно постановки 42. В роли обработчиков могут выступать и не публикуемые методы.
Поймите меня правильно. Я не придираюсь, а просто, отбросив обиды, пытаюсь обьективно найти истину.


 
Игорь Шевченко ©   (2004-04-21 18:00) [116]


> В роли обработчиков могут выступать и не публикуемые методы.


Вот теперь я понял всю глубину задачи:)

Юрий Зотов в задаче и в дополнениях к ней специально сделал акцент на класс, а не на экземпляр. У класса формы в роли обработчиков событий компонент(ов) могут выступать только published-методы.


 
Igorek ©   (2004-04-21 18:30) [117]


> Игорь Шевченко ©   (21.04.04 18:00) [116]
> У класса формы в роли
> обработчиков событий компонент(ов) могут выступать только
> published-методы.

Ты не прав. Не публикуемые методы тоже могут выступать в такой роли. Просто присвоить их событиям можно только динамически.


 
McSimm ©   (2004-04-21 18:34) [118]


> Просто присвоить их событиям можно только динамически.

классу ?


 
Игорь Шевченко ©   (2004-04-21 18:34) [119]


> Просто присвоить их событиям можно только динамически.


Ты сказал (с) Евангелие.

В момент разбора VMT нету экземпляров класса, следовательно о динамическом присвоении речи быть не может :)


 
Игорь Шевченко ©   (2004-04-21 18:37) [120]

Игорь Шевченко ©   (21.04.04 18:34)

Следует читать: При разборе VMT не имеет значения, есть ли экземпляры класса или нет.


 
Igorek ©   (2004-04-21 18:58) [121]

Еще раз давайте разберемся с понятиями. На самом деле тут легко запутаться. Итак:
1) обработчик события - это процедура Паскаля, которая вызывается при наступлении события;
2) событие наступает только тогда, когда есть обьект, и соотв. код обьекта вызывает обработчик, который записан в поле обьекта;
3) с этого вытекает, что процедура становится обработчиком только тогда, когда ссылка на нее содержится в поле обьекта; до этого момента (допустим обьекта еще нет) процедура (если подходит по сигнатуре) может выступать в роли обработчика события конкретного обьекта
4) обработчиком событий данного класса могут выступать процедуры любого класса, подходящие по сигнатуре;

Теперь ответы:

> McSimm ©   (21.04.04 18:34) [118]
>
> > Просто присвоить их событиям можно только динамически.
>
> классу ?

Исходя из вышесказанного мы присваиваем метод какого-то класса событию какого-то обьекта;


> Игорь Шевченко ©   (21.04.04 18:34) [119]
> В момент разбора VMT нету экземпляров класса, следовательно
> о динамическом присвоении речи быть не может :)

Какая разница, как мы реализуем задачу? Повторю, что задача была "вывести все обработчики класса". Надо было сказать "вывести все методы класса А, которые есть потенциальные обработчики событий обьектов класса В". А может быть равно В. Но даже в такой постановке задача неразрешима, поскольку возможно в классе А есть приватные методы, которые есть потенциальные обработчики событий обьектов класса В (могут стать таковыми в результате динамического присваивания).


 
Юрий Зотов ©   (2004-04-21 19:31) [122]

> Igorek ©   (21.04.04 17:45) [115, 117, 121]

> Однако я смотрю этот вопрос для Вас стал принципиальным.

Почему стал? Он таким и был. Только Вы тут ни при чем - снизьте самооценку, Джо. Дело просто-напросто в том, что, раз уж я в [42] предложил задачу (да еще и с "подковыркой" - вот, мол, попробуйте), то считаю, что должен был дать и свой вариант решения (не сразу, естественно). Оно и раньше всегда было так же, ничего нового.

> Не умаляя достоинств приведенного кода

Браво. Тронут. Плачу. Вы не поверите, насколько для были важна именно ВАША оценка. Сбылось...
"Слеза... стекает... по щеке... на клаву..."
Хотите еще одну задачку - персонально для Вас? В коде, если рассматривать его не как просто пример, а как рабочий код, есть довольно серьезный недостаток. Он был сделан специально, и не просто так, а была на то причина. Надо найти этот недостаток и указать его причину. В идеале - доработать одну из процедур, устранив в ней тот самый недостаток (кстати, объем кода после этого даже уменьшится).

> позволю себе не согласиться, что это решение задачи в
> постановке [42]. Там ничего не говорилось про RTTI.

Там про МЕТОД решения не было сказано вообще НИ-ЧЕ-ГО. Что и естественно. Потому что метод решения задачи оставляется на усмотрение разработчика. Хотите - RTTI юзайте, хотите - выкапывайте Debug Info, хотите - еще как хотите. Дело хозяйское.

> Соотв. был и мой пост [53].

Не будем о грустном.

> Повторю касательно постановки 42. В роли обработчиков могут
> выступать и не публикуемые методы.

Высоко ценю Ваши знания. Однако же, в [42] речь шла о классах, и ТОЛЬКО о классах - а теперь перечитайте [116] и, как знаток основ Паскаля, устыдитесь за [117].

Таким образом, постановку [42] Вы просто элементарно не поняли. Готов согласиться, что формулировка действительно была слишком скупой, но кто хотел уточнить - тот задал вопросы. И в своем посте [53], как и в последующих, Вам ничто не мешало сделать то же самое, а не устраивать очередную склоку.

Вообще, Игорек, Вы уж извините, но если моя персона так патологически раздражающе на Вас действует - то задумайтесь, наконец, почему это так? Кстати, в затеяной Вами же откровенно склочной ветке Вам об этом сказали практически открытым текстом (причем даже и не один человек) - так что есть что перечитать и о чем подумать.

Что касается [121], то вот Вам наводящая задачка. Пусть мы имеем вот такой DFM:
object Form1: TForm1
 OnClose = FormClose
end

и еще не создано ни одного экземпляра TForm1. Теперь ответьте:
1. Является ли этот DFM принадлежностью класса TForm1?
2. Метод FormClose уже существует, или еще нет?
3. Если существует, то чему (кому) он принадлежит?
4. В какой секции он объявлен?
5. Может ли он быть объявлен в другой секции?
6. Назначает ли этот DFM событию OnClose обработчик FormClose?
7. Можно ли назначить событию OnClose другой обработчик, не создавая при этом экземпляра TForm1?


 
Юрий Зотов ©   (2004-04-21 19:58) [123]

> Pasha Golub & other

Помнится, в ветке про тесты по поводу вопроса 1.1 было написано примерно следующее - вопрос чисто теоретический, потому что в реальных разработках подобный код встретиться не может. На что я тогда ответил что-то вроде того, что вопрос этот теоретический до тех пор, пока он не встретится на практике.

Так вот - выше MBo, Игорем и мною приведены вполне практические примеры использования такого кода (скажем, процедура ExtractShortString). Могу еще добавить, что подобныйй код реально использовался при написании одного редактора свойства (собственно, откуда и родилась сама эта задачка - она ведь не только из головы была придумана). И подобный код можно встретить и в VCL, и в других пакетах - например, посмотрите код в "Кладовке", о котором уже упоминалось.

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


 
Igorek ©   (2004-04-22 10:17) [124]


> Хотите еще одну задачку - персонально для Вас? ...

Нет, не хочу. Неинтересная задача. Куда интереснее такая: "сформулировать корректное условие задачи, для которой приведенный код будет решением и в нем не будет ничего лишнего"

> Готов согласиться, что формулировка действительно была слишком
> скупой

Имхо она была некорректной как минимум. А при корректировке к наиболее близкой корректной - неразрешимой.

> Что касается [121], то вот Вам наводящая задачка. Пусть
> мы имеем вот такой DFM: ...

Отвечаю: задача поставлена некорректно и не полно. Кроме того некоторые пункты сами по себе не имеют смысла.


 
Игорь Шевченко ©   (2004-04-22 10:48) [125]


> Отвечаю: задача поставлена некорректно и не полно. Кроме
> того некоторые пункты сами по себе не имеют смысла.


В чем именно некорректность и неполнота ?


 
Igorek ©   (2004-04-22 10:52) [126]

Прикольный пример:
1) создаем новое приложение в Дельфи
2) создаем обработчик главной формы на событие OnShow такой:
procedure TForm1.FormShow(Sender: TObject);
begin
 with TForm1.CreateNew(Application) do
   Show;
end;
3) запускаем...


 
Igorek ©   (2004-04-22 11:04) [127]


>
> Игорь Шевченко ©   (22.04.04 10:48) [125]
> В чем именно некорректность и неполнота ?

Неполнота:
- не приведен код формы, имя модуля, имя файла dfm, проекта
Короче в идеале надо или иметь все исходники или пошаговую инструкцию воспроизведения условия.
- не указан момент, касательно которого вопросы (designtime, точка останова)
Следовательно некорректности:
> 1. Является ли этот DFM принадлежностью класса TForm1?
Какого класса TForm1?
> 2. Метод FormClose уже существует, или еще нет?
Вообще бред.
> 3. Если существует, то чему (кому) он принадлежит?
Бред.
> 4. В какой секции он объявлен?
> 5. Может ли он быть объявлен в другой секции?
Хрен его знает. О каких секциях вообще речь?
> 6. Назначает ли этот DFM событию OnClose обработчик FormClose?
DFM ничего не назначает. Назначает VCL.
> 7. Можно ли назначить событию OnClose другой обработчик,
> не создавая при этом экземпляра TForm1?
Бред.

Не сочтите за грубость - это просто чесно мои мысли.


 
Игорь Шевченко ©   (2004-04-22 11:16) [128]

Igorek ©   (22.04.04 11:04)

Sapienti sat


 
Юрий Зотов ©   (2004-04-22 11:40) [129]

> Igorek © (22.04.04 11:04) [127]

И Вы еще беретесь о чем-то там спорить?

> Игорь Шевченко, McSimm & other

По-моему, бесполезно. Ламер - он как раз потому и ламер, что считает себя знатоком. Воинствующий ламер - хуже втройне. А воинствующий ламер, не сомневающийся в собственных выводах, да еще и с ярко выраженным талантом флудера... страшнеее, наверное, может быть только пулемет.

Поэтому предлагаю оставить этого Анику-воина в покое. Все равно он даже и не пытается понять того, что ему тут хором пытаются объяснить. Да и не только тут.

P.S.
"Не сочтите за грубость - это просто чесно мои мысли".
(с) Igorek © (22.04.04 11:04) [127]


 
Igorek ©   (2004-04-22 11:52) [130]


> Игорь Шевченко ©   (22.04.04 11:16) [128]
> Sapienti sat

Здесь вроде надо только русском.

> Юрий Зотов ©   (22.04.04 11:40) [129]

Мне глубоко пофиг, что говорит толпа, когда нет аргументов. Исключение составляют люди, которых я уважаю. К любому мнению таковых я сразу прислушаюсь даже без аргументов. На этом форуме таковыми для себя считаю: MBo и Е-мое Имя.


 
Юрий Зотов ©   (2004-04-22 12:04) [131]

> Igorek ©   (22.04.04 11:52) [130]

> Мне глубоко пофиг, что говорит толпа, когда нет аргументов.

А также когда они есть, но некто в упор не желает их видеть. О чем и было сказано выше.

> Исключение составляют люди, которых я уважаю. К любому мнению
> таковых я сразу прислушаюсь даже без аргументов. На этом
> форуме таковыми для себя считаю: MBo и Е-мое Имя.

Это заметно. Уже хотя бы по тому, что у одного Вы заимствовали код, а у другого - ведра.

P.S.
"И это все о нем"
(с) То ли книга, то ли фильм, то ли все вместе.


 
Игорь Шевченко ©   (2004-04-22 12:23) [132]

Igorek ©   (22.04.04 11:52)


> Здесь вроде надо только русском.


Хорошо, я переведу: умному достаточно.

---
LMD


 
Cobalt ©   (2004-04-23 12:42) [133]

Надеюсь, я всё правильно понял:

object Form1: TForm1
OnClose = FormClose
end
и еще не создано ни одного экземпляра TForm1. Теперь ответьте:
1. Является ли этот DFM принадлежностью класса TForm1?
-  Да, судя по тому, что при создании формы читается её описание из ресурсов (TCustomForm.Create)
2. Метод FormClose уже существует, или еще нет?
-  Да, он уже описан в VMT (сама процедура)
3. Если существует, то чему (кому) он принадлежит?
-  Он является методом формы (? насколько я знаю)
4. В какой секции он объявлен?
-  В Published.
5. Может ли он быть объявлен в другой секции?
-  При объявлении его в private или public при создании формы  EReadError - "Invalid property value"
6. Назначает ли этот DFM событию OnClose обработчик FormClose?
-   При создании.
7. Можно ли назначить событию OnClose другой обработчик, не создавая при этом экземпляра TForm1?
-  Нет.


 
IGOREK ©   (2004-04-23 18:53) [134]

Вот мои ответы с домысленным условием:
> 1. Является ли этот DFM принадлежностью класса TForm1?
В любом случае не является - ВНИМАТЕЛЬНО см. [126]
> 2. Метод FormClose уже существует, или еще нет?
> -  Да, он уже описан в VMT (сама процедура)
А в виде текста в designtime метод не существует?
> 3. Если существует, то чему (кому) он принадлежит?
Во первых в моем понятии метод не может принадлежать классу, он может только быть его членом. Вот про обьект я могу сказать, что он пренадлежит классу, ибо есть елементом множества, которое класс описывает
> 4. В какой секции он объявлен?
> -  В Published.
При условии, что код компилируется.
> 5. Может ли он быть объявлен в другой секции?
> -  При объявлении его в private или public при создании
> формы  EReadError - "Invalid property value"
Может, тогда код не будет выполняться.
> 6. Назначает ли этот DFM событию OnClose обработчик FormClose?
> -   При создании.
В принципе можно и так выразится, хотя имхо неточно.
> 7. Можно ли назначить событию OnClose другой обработчик,
> не создавая при этом экземпляра TForm1?
Не только нельзя другой, нельзя любой. Нету обьекта - нету обработчика. Есть только методы, которые могут выступать в такой роли. Тоже в принципе буквоедство, но как видим иногда небесполезное.


 
Cobalt ©   (2004-04-24 01:17) [135]

2 IGOREK ©   (23.04.04 18:53) [134]
Ну что, обсудим? Предлагаю конструктивный диалог:

>> 1. Является ли этот DFM принадлежностью класса TForm1?
>В любом случае не является - ВНИМАТЕЛЬНО см. [126]
Тогда как ты прокомментируешь тот факт, что форма при создании (см. TCustomForm.Create) читает себя из ресурсов?
имеется в виду именно Тип класса TForm1 (будем считать, что ресурс с описанием класса в ехе-ке менять не будем).

>> 2. Метод FormClose уже существует, или еще нет?
>> -  Да, он уже описан в VMT (сама процедура)
>А в виде текста в designtime метод не существует?
Хм, не понял :(


 
nikkie ©   (2004-04-24 03:03) [136]

дайте я попробую, что ли...
1. Является ли этот DFM принадлежностью класса TForm1?
имхо - нет. DFM хранится в ресурсах и может быть легко изменена без изменения кода класса.
2. Метод FormClose уже существует, или еще нет?
да.
3. Если существует, то чему (кому) он принадлежит?
классу TForm1.
4. В какой секции он объявлен?
ну там же, где объявлены сами компоненты, в начале класса без ключевого слова private/protected/public/published. поскольку к компонентам формы можно обращаться из вне TForm1 без проблем, значит, это либо public, либо published. хелп данную ситуацию комментирует так:
Members at the beginning of a class declaration that don’t have a specified visibility are by default published, provided the class is compiled in the {$M+} state or is derived from a class compiled in the {$M+} state; otherwise, such members are public.
кроме того, в другом месте написано
A class cannot have published members unless it is compiled in the {$M+} state or descends from a class compiled in the {$M+} state. Most classes with published members derive from TPersistent, which is compiled in the {$M+} state, so it is seldom necessary to use the $M directive.
значит, published. эксперимент показывает, что попытка объявить их как public приводит в ран-тайме к ошибке создания формы. а с published все в порядке. кроме того, если чуть еще подумать и посмотреть, как хранятся ссылки на обработчики событий в откомпилированном DFM, то видно, что они хранятся как имена. значит при загрузке формы используется RTTI и это должна быть published секция.
5. Может ли он быть объявлен в другой секции?
нет.
6. Назначает ли этот DFM событию OnClose обработчик FormClose?
ну не то, чтобы назначает. скорее описывает, что назначить. реальное назначение происходит при загрузке формы, где-то внутрях TReader, наверное.
7. Можно ли назначить событию OnClose другой обработчик, не создавая при этом экземпляра TForm1?
ну если отбросить непосредственное исправление ресурса, то вероятно можно (в том же смысле, в каком DFM "назначает") - для этого надо вклиниться в процесс создания формы, переписав TReader, наверное.


 
Sha ©   (2004-04-24 12:49) [137]

Хорошая получилась ветка.
Могла бы быть еще лучше, если бы, субъекты, препарирующие Delphi, обсуждали только ее внутренности.
Да и число участников было бы больше, если бы градус обсуждения был пониже.


 
Игорь Шевченко ©   (2004-04-24 18:33) [138]


> 1. Является ли этот DFM принадлежностью класса TForm1?
> имхо - нет. DFM хранится в ресурсах и может быть легко изменена
> без изменения кода класса.


Является. Имя ресурса совпадает с именем класса формы. Если изменить имя ресурса извне форма будет являться принадлежностью другого класса.


 
Sha ©   (2004-04-24 19:18) [139]

Игорь Шевченко ©   (24.04.04 18:33) [138]
> 1. Является ли этот DFM принадлежностью класса TForm1?
> имхо - нет. DFM хранится в ресурсах и может быть легко изменена
> без изменения кода класса.

Не является. Что мешает зачитать ресурс с именем класса формы из потока, созданного в runtime?


 
Юрий Зотов ©   (2004-04-24 19:34) [140]

> Sha ©   (24.04.04 19:18) [139]

Ничто не мешает. Но и ничего не меняет. Ресурс класса формы так и останется ресурсом класса формы. Хоть вообще его не читай, хоть читай как угодно и для чего угодно.


 
Игорь Шевченко ©   (2004-04-24 19:50) [141]

Sha ©   (24.04.04 19:18)


> Не является. Что мешает зачитать ресурс с именем класса
> формы из потока, созданного в runtime?


Глупый вопрос: а зачем ?


 
Sha ©   (2004-04-24 20:11) [142]

Еще можно спросить: "является ли компонент Button1 принадлежностью класса TForm1?". Ясное дело, нет. Компонент с таким именем может быть в любом DFM и даже в том, которого еще нет в design time и который будет создан в run time.
Таким образом, классу TForm1 принадлежат все существующие и будущие DFM, содержащие ресурс с таким именем, а также все созданные в run time потоки, содержащие ресурс с таким именем.
А это значит, что этому классу никакой конкретный DFM не принадлежит, а только может принадлежать, после того, как будет прочитан TReader"ом.


 
Игорь Шевченко ©   (2004-04-24 20:28) [143]


> классу TForm1 принадлежат все существующие и будущие DFM,
> содержащие ресурс с таким именем


Тут такой момент - ресурс может быть только один :)


 
Юрий Зотов ©   (2004-04-24 20:28) [144]

> Sha © (24.04.04 20:11) [142]

А еще можно говорить, что файл kernel32.dll библиотекой ядра не является, а только МОЖЕТ ею являться.

Но стоит ли?


 
Sha ©   (2004-04-24 20:41) [145]

> Игорь Шевченко ©   (24.04.04 20:28) [143]
> Тут такой момент - ресурс может быть только один :)

Ничто не мешает хранить ресурсы в отдельных файлах или создавать динамически.

> Юрий Зотов ©   (24.04.04 20:28) [144]
> А еще можно говорить, что файл kernel32.dll библиотекой ядра не является, а только МОЖЕТ ею являться.
> Но стоит ли?

Спор чисто терминологический: что значит "принадлежит"?
Если это означает совпадение имен и возможность загрузки ресурса, то принадлежит.
Если же это означает собственно загрузку ресурса, то не принадлежит.
Мне больше симпатична вторая точка зрения, потому что окончательный вид формы в run time определяется только после загрузки ресурса. До этого формы просто не существует.

В общем, стоит сначала определиться с терминами. Каждая из этих точек зрения может оказаться верной при соответствующей трактовке терминов.


 
Юрий Зотов ©   (2004-04-24 20:51) [146]

> Sha © (24.04.04 20:11) [142]

Наверное, нужно пояснить, что я имел в виду в [144]. Конечно, можно понасоздавать 100 потоков, а в них программно нагенерить 100 одноименных ресурсов. Можно сделать еще вообще что угодно, хоть ОС переписать.

Однако же, когда задача ставится, например, так "Найти сумму углов треугольника", то мы понимаем, что речь идет о геометрии Эвклида, а не Лобачевского. Причем на плоскости, а не на сфере или еще на чем-то.

И подобного рода дефолты имеют место всегда. То есть - если явно не оговорено ничего другого, то подразумевается некий стандарт. В нашем случае таким стандартом является единственный ресурс с именем TForm1, находящийся в теле EXE и из него же загружаемый.

Помните анекдот, как программист ходил в магазин? Жена сказала ему: "Купи батон хлеба и если есть яйца, то десяток". Далее произошел такой диалог с продавцом:
- У Вас яйца есть?
- Есть.
- Тогда десяток батонов хлеба.

В словах жены подразумевался тот самый дефолт, но программист поступил, как машина, а не как человек.

Мы будем поступать так же? Будем придираться к словам друг друга, или все же будем понимать, что если что-то не оговорено явно, то имеется и виду стандарт?

Вот что имелось в виду в [144].


 
Sha ©   (2004-04-24 20:57) [147]

Я не придирался, а просто решал задачу в общей постановке.
Теперь понятно, что имелось ввиду :)


 
IGOREK ©   (2004-04-26 13:00) [148]

> >> 1. Является ли этот DFM принадлежностью класса TForm1?
> >В любом случае не является - ВНИМАТЕЛЬНО см. [126]
> Тогда как ты прокомментируешь тот факт, что форма при создании
> (см. TCustomForm.Create) читает себя из ресурсов?
Да не знаю что и сказать. Читает себе и все.
А как Вы прокомментируете [126]?

> >> 2. Метод FormClose уже существует, или еще нет?
> >> -  Да, он уже описан в VMT (сама процедура)
> >А в виде текста в designtime метод не существует?
> Хм, не понял :(
Ну вот я решаю задачу по программированию. Надо написать метод. И вот я уже знаю, как решить задачу - весь метод у меня в голове. Вопрос: этот метод существует?


 
Polevi ©   (2004-04-26 13:08) [149]

несомненно


 
Sha ©   (2004-04-26 14:37) [150]

Сначала надо дать определение: "Говорят, что метод существует, если выполнены следующие условия: ...", а после этого начинаем проверять, выполнены ли указанные условия.
Весь сыр-бор в конце концов сводится к тому, чьи определения лучше.


 
pasha_golub ©   (2004-04-26 15:35) [151]

2ЮЗ
Я прошу прощения, но я не нашел куска Вашего кода, который под чистую совпадает с примером 1.1

Лично для меня, пожалуйста, запостите его. Спасибо.


 
Юрий Зотов ©   (2004-04-26 18:01) [152]

> pasha_golub ©   (26.04.04 15:35) [151]

Подчистую - конечно, не совпадает. А вот по смыслу (адресная арифметика) и по использованным приемам ("хитрое" получение данных по адресу) - совпадает. См., например, функцию ExtractShortString.

> Sha ©   (26.04.04 14:37) [150]

Условия очевидны - исходный текст программы содержит данный метод, программа откомпилирована и запущена, но ни один объект класса TForm1 в ней еще не создан.


 
Sha ©   (2004-04-26 18:09) [153]

Юрий Зотов ©   (26.04.04 18:01) [152]

Ну, тогда метод существует, пока программа работает в ОП, но ни один объект класса TForm1 в ней еще не создан :))



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

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

Наверх




Память: 0.95 MB
Время: 0.033 c
9-1072024759
dRake
2003-12-21 19:39
2004.05.16
Рендер на текстуру под PowerDraw!


1-1083422566
Leos
2004-05-01 18:42
2004.05.16
"Нестандартная форма"


3-1082555269
}|{yk
2004-04-21 17:47
2004.05.16
Master-detail в FIBPlus


8-1076946984
Grinder
2004-02-16 18:56
2004.05.16
Проиграть мелодию 10 раз


1-1083440703
APXi
2004-05-01 23:45
2004.05.16
Как передать строку другой копии моего приложения.





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