Вверх ↑
Этот топик читают: Гость
Ответов: 9906
Рейтинг: 351
#16: 2005-06-21 21:07:58 ЛС | профиль | цитата
Просто не додумал еще. Должно свариться......
карма: 9

0
Администрация
Ответов: 15295
Рейтинг: 1519
#17: 2005-06-21 23:27:27 ЛС | профиль | цитата
С внешним кодогенератором попроще будет
карма: 26
0
Ответов: 9906
Рейтинг: 351
#18: 2005-06-22 00:31:04 ЛС | профиль | цитата
В общем, есть такие предложения:

1) CreateInstance для мультика сделать ф-ей:
[code:1]function THIMultiElementEx.CreateInstance:THIEditMultiEx; begin
Result := FOnCreate(FControl);
Result.Parent := Self;
Result.MainClass.Init;
end;[/code:1]
Это от того, что у нас в мультике сегодня есть такие коды:
[code:1] ............ F := FOnCreate(FControl);
F.Parent := Self;
............[/code:1]
и не очень хочется, чтобы они раздувались от нововведений...
Т.е., что бы стало не больше, а меньше:
[code:1] F := CreateInstance;[/code:1]
2) вместо [b]property [/b]OnCreate сделать два раздельных, для статического и динамического случаев, оставив кодогенератору возможность выбрать нужный. Например:
[code:1] property SaticCreate:TOnCreate write SetStaticProc; property DynamicCreate:TOnCreate write FOnCreate;
......................
procedure THIMultiElementEx.SetStaticProc;
begin
FOnCreate := Value;
FChild := FOnCreate(FControl);
FChild.Parent := Self;
end;[/code:1]

3) ну а дальше все ясно: кодогенератор, разобравшись со св-м Mode, в статическом случае генерирует строку:
[code:1] StaicCreate := Create_UnitName;[/code:1]и ДОБАВЛЯЕТ в метод Init генерируемого контейнера вызов Init-метода обрабатывамого (если тот не пустой, конечно). А в динамическом случае - ТОЛЬКО генерирует строку:
[code:1] DynamicCreate := Create_UnitName;[/code:1]и все.
Вроде....
карма: 9

0
Администрация
Ответов: 15295
Рейтинг: 1519
#19: 2005-06-22 13:14:01 ЛС | профиль | цитата
Полностью согласен
карма: 26
0
Ответов: 9906
Рейтинг: 351
#20: 2005-06-22 19:21:27 ЛС | профиль | цитата
Ну мысли по инерции продолжают катиться дальше (что свидетельствует о не полной управляемости мыслительным процессом )

Одна мелочь остается таки. Пустой метод Init для контейнера делать надо, и вызывать его будут. Неправильно (только в философском смысле, конечно ) это потому, что это напрягает тех кто не пользовался фичей InitMan (как у буржуинов - потенциальное наличие фичей увеличивает ресурсы, потребляемые одной и той же простой задачей ). Хорошо, хоть есть возможность не строить полное дерево из пустышек (не включать в Init пустышки вложенных контейнеров).

Логически рассуждая, приходим к выводу, что НЕ ВЫЗЫВАТЬ пустой (или отсутствующий Init) может только код, сделанный кодогенератором. А это опять же ф-ия Create_hi<Name>.......

Все это состыковать все-таки можно, несколько большим напряжением (для кодогенератора).
[code:1]function Create_hi<Name>(Sender:THIMultiElementEx):THiEditMultiEx; begin
Result := TClass<Name>.Create(Sender.Control).Child;
Result.Parent := Sender;
Result.MainClass.Init; //Ура! Именно это может отсутствовать (если пустой Init)
end;[/code:1]
В статическом случае, у кодогенератора (в отличии от кодов мультика) есть возможность прописать конструктор типа inline:
[code:1] ........ OnCreate := Create_hi<Name>;
Child := TClass<Name>.Create(<Name>.Control).Child // впрочем, parent кодогенератору и так должен быть известен
Child.Parent := <Name>;
........[/code:1]И, как и раньше, дополнить Init конструируемого контейнера.
А в динамическом, только:
[code:1] ........ OnCreate := Create_<Name>;
........[/code:1]При этом в мультике: CreateInstance, SetStaticProc, DynamicCreate и SaticCreate перестают существовать, но нужно открыть доступ:
[code:1] property Child write FChild; property Control read FControl;
property OnCreate write FOnCreate;[/code:1]
ну и еще кое-какие назначительные исправления в кодах мультика из-за этого....
карма: 9

0
Главный модератор
Ответов: 2997
Рейтинг: 395
#21: 2005-07-04 13:45:46 ЛС | профиль | цитата
WinEnum (b148 без патчей) перестал искать окна по заголовку. И вообще перечислять тоже отказывается.
карма: 6
Дорогу осилит идущий. Install/Update HiAsm.NET
0
Администрация
Ответов: 15295
Рейтинг: 1519
#22: 2005-07-04 14:12:04 ЛС | профиль | цитата
Nic, ну поехали:
1) Запустил windowswintools.sha - все выводит, все работает
2) Набросал небольшую схемку(!)
[code:1]Add(WinEnum,5778871,147,112) {
link(onFindWindow,15524729:doMessage,[])
}
Add(Button,13465496,84,119)
{
Left=80
Top=115
Data=String(Program Manager)
link(onClick,5778871:doFind,[])
}
Add(Message,15524729,210,112)
{
}
[/code:1]
при нажатие на кнопку выдает "Program Manager" - т.е. заголовок [b]найденного окна[/b]

Отсюда извечный вопрос: где пример, подтверждающий обратное :?:
карма: 26
0
Ответов: 9906
Рейтинг: 351
#23: 2005-07-04 19:05:50 ЛС | профиль | цитата
Вроде ж, большенький уже
карма: 9

0
Ответов: 9906
Рейтинг: 351
#24: 2006-02-08 23:35:59 ЛС | профиль | цитата
Dilma, вот чего до меня доехало:

Чтобы поправить это дело можно не лезть ни в среду, ни в кодогенератор.
Проще все:
1)
[code:1]procedure THIEditMultiEx.SetParent; begin
FParent := Value;
if THIMultiElementEx(FParent)._prop_Mode <> 0 then
InitMan.Init;
end;[/code:1]
2) А вот в InitMan.Init необходима чистка списка после запуска, ну например:
[code:1]procedure TInitMan.Init; var i:word;
begin
if Count = 0 then exit;
for i := 0 to Count-1 do
Items[i];
Count := 0;
SetLength(Items,0);
end;[/code:1]

BTW: если иметь ввиду возможность обладания различными зкземплярами одного класса разными же значениями св-ва Mode, то на этапе компиляции, запуск или нет InitMan.Init сразу после отработки конструктора - не разрешишь....
Только на этапе исполнения....
карма: 9

0
Ответов: 9906
Рейтинг: 351
#25: 2006-02-27 15:53:59 ЛС | профиль | цитата
Ну блин
Штука по п.2 предыдущего поста не всегда срабатывает.
А именно: При выполнении InitMan.Init может оказаться, что в него добавляются новые инициализаторы, и снова вызывается он же...

Такая смертельная рекурсия. Примеры: exampleDrawMove2.sha, exampleDrawMove3.sha

Переделал совсем TInitMan:
[code:1]unit Share; ..................
TInitMan = object
private
Items:array of TInitProc;
Run:boolean;
public
procedure Add(Proc:TInitProc);
procedure Init;
end;
..................
var Null:THI_Event;
GHandle:cardinal;
InitMan:TInitMan;
_data_Empty:TData;
..................
procedure TInitMan.Add;
begin
SetLength(Items,length(Items)+1);
Items[high(Items)] := Proc;
end;

procedure TInitMan.Init;
begin
if Run then exit;
Run := true;
while length(Items)>0 do
begin
Items[0];
Items:=Copy(Items,1,high(Items));
end;
Run := False;
end;[/code:1]

Вроде работает.............
карма: 9

0
Администрация
Ответов: 15295
Рейтинг: 1519
#26: 2006-03-01 03:37:59 ЛС | профиль | цитата
Появилось ощущение, что InitMan надо делать отдельно для каждого контейнера. Тогда при создание контейнера он запоминает старый и заносит в InitMan свой указатель, а после вызова Init возвращает его на место. Тогда не нужно ничего чистить и удалять.
карма: 26
0
Ответов: 9906
Рейтинг: 351
#27: 2006-03-01 03:59:59 ЛС | профиль | цитата
Dilma, чистить надо всегда....

"Разогнал танки ? Положи гранату на место !!!"

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

Работает, кстати....
карма: 9

0
27
Сообщение
...
Прикрепленные файлы
(файлы не залиты)