Просто не додумал еще. Должно свариться......
Этот топик читают: Гость
Ответов: 9906
Рейтинг: 351
|
|||
карма: 9 |
|
Администрация
Ответов: 15295
Рейтинг: 1519
|
|||
С внешним кодогенератором попроще будет
|
|||
карма: 27 |
|
Ответов: 9906
Рейтинг: 351
|
|||
В общем, есть такие предложения:
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 |
|
Администрация
Ответов: 15295
Рейтинг: 1519
|
|||
Полностью согласен
|
|||
карма: 27 |
|
Ответов: 9906
Рейтинг: 351
|
|||
Ну мысли по инерции продолжают катиться дальше (что свидетельствует о не полной управляемости мыслительным процессом
![]() Одна мелочь остается таки. Пустой метод 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 |
|
Главный модератор
Ответов: 2999
Рейтинг: 396
|
|||
WinEnum (b148 без патчей) перестал искать окна по заголовку. И вообще перечислять тоже отказывается.
![]() |
|||
карма: 6 |
|
Администрация
Ответов: 15295
Рейтинг: 1519
|
|||
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] Отсюда извечный вопрос: где пример, подтверждающий обратное :?: |
|||
карма: 27 |
|
Ответов: 9906
Рейтинг: 351
|
|||
Вроде ж, большенький уже
![]() ![]() ![]() |
|||
карма: 9 |
|
Ответов: 9906
Рейтинг: 351
|
|||
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 |
|
Ответов: 9906
Рейтинг: 351
|
|||
Ну блин
![]() Штука по п.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 |
|
Администрация
Ответов: 15295
Рейтинг: 1519
|
|||
Появилось ощущение, что InitMan надо делать отдельно для каждого контейнера. Тогда при создание контейнера он запоминает старый и заносит в InitMan свой указатель, а после вызова Init возвращает его на место. Тогда не нужно ничего чистить и удалять.
|
|||
карма: 27 |
|
Ответов: 9906
Рейтинг: 351
|
|||
Dilma, чистить надо всегда....
"Разогнал танки ? Положи гранату на место !!!" Пока что задача дальше обыкновенного буфера FIFO не идет вроде. А если создавать новый и исполнять его в процессе исполнения предыдущего - меняется порядок инициализаторов. И будет, кажется менее логично.... Работает, кстати.... |
|||
карма: 9 |
|
27