Form

Почему созданный массив или переменную не “видно” в других методах формы

Проблема

В одном из методов формы или одного из ее объектов я создаю массив или переменную. Почему я не могу использовать этот массив или переменную в других методах и событиях, как самой формы, так и ее объектов. Например, как источник данных для ComboBox.

Причина

По умолчанию, если область видимости переменной памяти или массива не указана явно через команды PUBLIC, PRIVATE или LOCAL, то для такой переменной памяти или массива устанавливается область видимости PRIVATE. Т.е. команда DIMENSION (DECLARE) создаст массив с областью видимости PRIVATE.

Это значит, что созданный в методе формы или одного из ее объектов массив будет автоматически уничтожен по завершении того метода, в котором этот массив был создан.

Решение

Есть два принципиальных способа решения

  1. Установить область видимости массива PUBLIC
  2. Создать дополнительное свойство (Property) типа массив

По ряду причин, назначение локальному объекту области видимости PUBLIC - это не очень хорошая идея. В данном случае, под "локальным объектом" подразумевается массив, поскольку он нужен "локально", в пределах одной формы.

Наилучшим решением будет создание дополнительного свойства (Property) типа массив. Такое свойство можно создать как программно, используя метод AddProperty(), так и в дизайнере формы через пункт меню "Form", подпункт "New Property" или "Edit Property/Method".

Признаком того, что данное свойство является массивом, служит указание размерности. Например:

ThisForm.AddProperty("aArray[1,1]")

Размерность такого массива впоследствии можно изменять программно, через команду Dimension. Например:

DIMENSION ThisForm.aArray(10,2)

Теперь Вы можете из любого объекта формы обратиться к данному массиву, поскольку он является неотъемлемой частью самой формы.

Как перехватить нажатие на крестик в правом верхнем углу формы

Вопрос

Как перехватить нажатие на крестик в правом верхнем углу формы?

Ответ

При нажатии на крестик в правом верхнем углу формы срабатывает событие формы QueryUnload(). Если в этом событии дать команду

NODEFAULT

то закрытие формы будет отменено. Т.е. можно попросить пользователя подтвердить желание закрыть форму.

*** Событие формы QueryUnload  
  IF MessageBox("Вы действительно хотите закрыть форму",4+32+256,"Закрытие формы")=7  
 	* Нажали кнопку "Нет"  
  	NODEFAULT  
  ENDIF

Если у Вас на форме предусмотрена специальная кнопка "Выход", по нажатию на которую происходит закрытие формы, то, для того, чтобы не дублировать один и тот же код в несколких местах просто делайте вызов события нажатия данной кнопки при нажатии на крестик. Примерно так:

*** Событие формы QueryUnload  
  NODEFAULT  
  ThisForm.CmdExit.Click()

Здесь CmdExit - это имя кнопки "Выход".

Следует иметь в виду, что при вызове метода Release() или использовании команды RELEASE для закрытия формы событие QueryUnload() будет проигнорировано. Т.е. не сработает.

Почему параметры, переданные в форму “видно” только в INIT-формы

Вопрос
Я передаю параметры в форму. Они принимаются в событии INIT-формы и там они имеют переданные значения. Почему эти же переданные значения не "видно" из других методов формы?

Ответ

Дело в том, что параметр - это переменная памяти. Как и любая другая переменная памяти, она имеет область видимости. Если параметры принимаются через команду PARAMETERS, то область видимости PRIVATE. А если через команду LPARAMETRS, то область видимости LOCAL.

Кроме того, следует учитывать тот факт, что даже события, выполняющиеся при инициализации формы, выполняются не друг ИЗ друга, а друг ЗА другом. Т.е. это не вложенные друг в друга процедуры, а последовательность процедур.

Следовательно, в общем случае, даже переменная с областью видимости PRIVATE, объявленная в одном из событий или методов формы, не будет "видна", ни в каком другом событии или методе формы.

Чтобы обойти это ограничение, следует в том же событии INIT-формы присвоить переданные через параметры значения специально созданным свойствам (properties) формы. Как это сделать, подробно описано здесь

Почему созданный массив или переменную не "видно" в других методах формы

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

Вопрос:Запускаю модальную форму командой:

DO FORM MyForm.scx TO m.MyVar

В переменную m.MyVar будет записано одно возвращаемое значение. А как вернуть из модальной формы несколько значений? Как вернуть из модальной формы массив?

Ответ:

Идея решения принадлежит Юрию Шутенко (JS).

Суть идеи заключается в том, что хотя FoxPro ограничивается одним возвращаемым значением, но не накладывается никаких ограничений на тип этого возвращаемого значения. В данном случае, следует в качестве возвращаемого значения воспользоваться переменной типа "Object".

В событии UNLOAD формы пишется примерно такой код:

  
 * Создаем переменную типа "Object"  
  LOCAL loReturnValue   
  loReturnValue = CreateObject("Empty")  
    
 * Формируем в этой переменной нужное количество свойств  
 * и записываем в них нужные значения  
  AddProperty(m.loReturnValue,"Prop1")  
  m.loReturnValue.Prop1 = "Первое значение"  
    
  AddProperty(m.loReturnValue,"Prop2")  
  m.loReturnValue.Prop2 = "Второе значение"  
    
 * Добавляем свойство типа "массив"  
  AddProperty(m.loReturnValue,"PropArray[2,2]")  
  m.loReturnValue.PropArray[1,1] = 1  
  m.loReturnValue.PropArray[1,2] = 2  
  m.loReturnValue.PropArray[2,1] = 3  
  m.loReturnValue.PropArray[2,2] = 4  
    
  RETURN m.loReturnValue

Вызов такой формы и разбор возвращаемых параметров примет такой вид

  
  LOCAL loNewValue  
  loNewValue = NULL  
    
  DO FORM MyForm.scx TO m.loNewValue  
    
 * Переписываем возвращенные значения из свойств объекта в переменные памяти  
  LOCAL lcVal1, lcVal2, laArray(2,2)  
  lcVal1 = m.loNewValue.Prop1  
  lcVal2 = m.loNewValue.Prop2  
  =ACOPY(m.loNewValue.PropArray, m.laArray)

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

Замечание:

Объект класса "Empty" и функция AddProperty() были введены в FoxPro в версии Visual FoxPro 8. Для младших версий FoxPro в качестве возвращаемого объекта можно использовать объект класса "Custom", а для создания новых свойств его метод Custom.AdProperty().

  
 * Создаем переменную типа "Object"  
  LOCAL loReturnValue   
  loReturnValue = CreateObject("Custom")  
    
 * Формируем в этой переменной нужное количество свойств  
 * и записываем в них нужные значения  
  m.loReturnValue.AddProperty("Prop1")  
  m.loReturnValue.Prop1 = "Первое значение"  
    
  ...

Метод AddProperty() был введен в FoxPro в версии Visual FoxPro 6. Для младших версий FoxPro нужное количество свойств возвращаемого объекта, да и сам объект, необходимо сформировать заранее в соответствующей библиотеке классов.

Темы, связанные с данной:

Что означает префикс (буква) "m." перед именем

Как из модальной формы, открытой через Show(1) вернуть значение

Вопрос:

Я создал класс формы и создаю экземпляр модальной формы командой

  
  LOCAL loForm  
  loForm = CreateObject("MyFormClass")  
  m.loForm.Show(1)

Как из такой формы вернуть значение?

Ответ:

Идея решения принадлежит Вадиму Пирожкову (Piva).

Суть решения сводится к тому, что форма не может быть уничтожена, пока существует хотя бы одна ссылка на эту форму. Эта дополнительная ссылка создается при помощи объектных скобок WITH...ENDWITH.

Создание экземпляра такой формы примет вид:

  
  LOCAL loForm, lvProp1, lvProp2  
  loForm = CreateObject("MyFormClass")  
  WITH m.loForm  
  	.Show(1)  
  	m.lvProp1 = .Text1.Value  
  	m.lvProp2 = .Prop2  
  ENDWITH

Здесь Text1 – это объект, расположенный на форме, а Prop2 – свойство самой формы.

До тех пор, пока не будет закрыта объектная скобка "ENDWITH" форма не может быть удалена. Следовательно, будут доступны для прямого чтения все ее свойства и методы.

Но если форма не может быть удалена, то прямая команда ThisForm.Release() будет проигнорирована или же ее выполнение приведет к различным глюкам.

Чтобы все-таки удалить форму используется другая особенность модальных форм в FoxPro.

Модальной может быть только видимая форма. Как только модальная форма перестает быть видимой, она перестает быть модальной.

Другими словами, закрытие формы осуществляется не одной, а двумя командами:

  
  ThisForm.Hide()  
  ThisForm.Release()

Замечание:

В принципе, можно обойтись и без дополнительной объектной переменной для вызова формы. Примерно так:

  
  LOCAL lvProp1, lvProp2  
  WITH CreateObject("MyFormClass")  
  	.Show(1)  
  	m.lvProp1 = .Text1.Value  
  	m.lvProp2 = .Prop2  
  ENDWITH

Это как Вам покажется удобнее. Надо только не забыть присвоить "внешним" (по отношению к объектной скобке WITH...ENDWITH) переменным значения свойств модальной формы.

Темы, связанные с данной:

Что означает префикс (буква) "m." перед именем

//////////////// ///////////////
Авторизация
*
*
Генерация пароля