Тайна потусторонних связей или Использование переадресованных вызовов

Как это теперь модно писать - Преамбула

В далеком, теперь уже, 1994 году, в свете развития всяких ООП технологий , в том же Turbo Vision, захотелось и мне в Фоксе придумать нечто такое же, пусть, хоть и отдаленно напоминающее сие новаторства. Собственно все сводилось к возможности получения результата функции из внешнего, по отношению к текущему, модуля. Если разработчики дали возможность использовать конструкции

 DO Func1 in Module1 

То почему-то не дали возможности хотя бы сделать так

 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, пишем

 DO P2 in MODULE1 

И получаем ошибку: 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
Опубликовал: Пирожков Вадим

Автор публикации

не в сети 20 лет

piva

Комментарии: 1Публикации: 11Регистрация: 24-03-2004
Материалы по теме
Оставить комментарий
//////////////// ///////////////
Авторизация
*
*
Генерация пароля