Тайна потусторонних связей или
Использование переадресованных вызовов
Как это теперь модно писать -
Преамбула
В далеком, теперь уже, 1994 году, в свете развития
всяких ООП технологий , в том же Turbo Vision, захотелось и мне в Фоксе
придумать нечто такое же, пусть, хоть и отдаленно напоминающее сие новаторства.
Собственно все сводилось к возможности получения результата функции из внешнего,
по отношению к текущему, модуля. Если разработчики дали возможность использовать
конструкции
То
почему-то не дали возможности хотя бы сделать так
Do Func1 in Module1 to myVar |
Хотя
и такая конструкция, меня не устраивала. Хотелось сделать модуль отвечающий за
поведение определенного вида документа, но как получать результат функции их
этого модуля или другого без шаманского передергивания с использованием Set
Procedure To, которая тогда позволяла использовать только один общий процедурный
модуль. Тогда надо было выносить все мелкие общие функции из одного модуля и
раскладывать их на кучу мелких. Это мне тоже не нравилось. Оставалось одно –
пропадать. Надо было как-то заставить эти функции держать в связке стека
вызовов FoxPro иначе он никак их не хотел находить. И вот пришло решение, что
вызов функции нужно переадресовать тому модулю откуда он должен быть вызван, но
как? Да все оказалось проще простого. Пишем процедурный модуль MODULE1.PRG
с небольшим «довеском» , допустим в нем есть некая функция P1
* MODULE1.PRG
parameter m.__
if type(`m.__`)=`C`
return eval(m.__)
endif
Procedure P1
Return 1 |
Далее
пишем некий главный файл MAIN.PRG (Привет Владимиру
Максимову)
* MAIN.PRG
? MODULE1([P1()]) |
На
выходе получаем искомое значение 1 которое вернула функция P1 – Ура, у
нас получилось ! Изменяем модуль MAIN.PRG на такой
* MAIN.PRG
? MODULE1([P1()])
Procedure P1
Return 2 |
Проверим,
что вернет нам наша «шаманская» функция ? А в результате видим – 1.
Значит наша функция в MAIN.PRG не сработала ! И правильно, ибо вызов
функции идет в модуле MODULE1.PRG в строке EVAL(m.__) – фокс
находит функцию в текущем модуле и перестает ее искать где-то еще и возвращает
значение нужной нам функции. Ну пробовать, так пробовать. Еще раз меняем файл
MAIN.PRG
* MAIN.PRG
? MODULE1([P2()])
Procedure P2
Return 2 |
Прошу
заметить, что зайца в шляпе нет, то есть функции P2 в
MODULE1.PRG нет. Смотрим,что вернет функция. Оказывается
возвращает значение – 2. Пробуем штатными средствами FoxPro, пишем
И
получаем ошибку: Procedure “P2” not found –
чего собственно и ждали, но в нашем случае такой ошибки нет и функция вернула,
значение из модуля MODULE1 , это что же получается Фокс нас обманывает ?
Или все-таки мы его? . Давайте подумаем, а собственно откуда в MODULE1.PRG
взялось значение функции P2 ? Фокс в модуле MODUL1.PRG
пытается найти функцию P2 – не находит и переходит по стеку вызовов
на ранние вызовы, и что же, находит ее в модуле MAIN.PRG – соответственно
значение этой функции он нам и вернет. Проблема побеждена, и в том же 1994 году
за полторы недели на коленке был написан склад с использование
псевдо-объектности. Жаль исходники потерял, за давностью лет. Но было здорово и
быстро.
Ну вот, а теперь собственно - Амбула.
Был у
меня некий проект на VFP6 – размер исполняемого файла 3.5 метра – все в одном.
Решил я это дело порезать на куски. Ну общие процедурные модули и дополнительные
невизуальные классы вынести в отдельный модуль COMMON.APP – сказано – сделано –
исполняемый файл уменьшили на 1 метр, осталось 2.5 – из них картинок около 1.5
метров – на все случаи жизни, так сказать. А чего давай и их выкинем из
исполняемого файла – вынесем куда-нибудь в IMAGES.APP и пусть там валяются, все
равно этот модуль – ну очень редко будет изменяться. Ладно собираем все картинки
в новый IMAGES.APP в проекте им даем атрибут Excluded – собираем главный
исполняемый файл, предварительно в нем подключаем модуль IMAGES.APP. А вместо
картинок видим крестики, это что же теперь на картинках крест поставить ? Ладно
начнем думать. Если так картинки не подключаются, давай старым дедовским
шаманским способом – переадресуем подключение картинок в IMAGES.APP В
базовом классе Image дописываем в свойство Picture_Assing следующий
код
LPARAMETERS vNewVal
*To do: Modify this routine for the Assign method
THIS.Picture = m.vNewVal
if not empty(this.picture)
* Если файл не найдет в исполняемом файле или на диске – переадресуем вызов
if not file(this.picture)
if file(“IMAGES.APP”)
DO “IMAGES.APP” with (this),`picture`,this.picture
endif
endif
endif |
Соответственно
меняем главный файл для проекта IMAGES, а как без главного модуля ? Даже пустого
– APP не слепить. Процедура может принимать от 3 параметров 1 – ссылка
на объект к которому будем цеплять картинку 2 – имя свойства, в нашем случае
PICTURE 3 – собственно имя файла картинки 4 – параметр может
использоваться для ListBox или ComboBox для свойства Picture(N) – как
N
lparameter m.ObjRef, m.cProperty, m.xValue, m.nIndex
if pcount() < 3
MessageBox("Это модуль ресурсов",64,_screen.caption)
Return .F.
endif
if vartype(m.ObjRef)=`O` ;
and vartype(m.cProperty)=`C` ;
and PEMStatus(m.ObjRef,m.cProperty,5)
if vartype(m.nIndex)=`N`
if m.cProperty=`PICTURE`
ObjRef.Picture[m.nIndex]=m.xValue
else
Return ObjRef.WriteExpression(m.cProperty+`[m.nIndex]`,[m.xValue])
endif
else
Return ObjRef.WriteExpression(m.cProperty,[m.xValue])
endif
Return .T.
endif
Return .F. | Теперь
пересобираем APP для картинок – и главный исполняемый файл – и видим все
картинки на месте. Ну вот – наконец-то смогли уменьшить размер главного
исполняемого файла еще на 1.5 метра – остался метр «живого» кода – теперь можно
вздохнуть спокойно.
Используя «потусторонние связи» с переадресацией
вызова, оказывается можно много чего получить в Фоксе
Последние обновление: 2005-01-26 09:11 Опубликовал: Пирожков
Вадим
|