Juri Shutenko Personal Homepage. Visual FoxPro.

Из старого сундучка. Часть 4 (Начало)

От перестановки мест слагаемых сумма не изменяется...

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

Самый простой пример. Уже около 8 лет я использую в некоторых подобающих случаях динамическое построение форм. Иногда и сам не знаю, как будет выглядеть запущенная, создаваная "на лету" форма. Но над одной проблемой бился около часа. Ну "не выходит каменная ваза у Данилы-мастера"! Суть проблемы, высосанной в буквальном слове из пальца, заключалась в том, что при добавлении в контейнеры (форма, страница или контейнер, как экземляр одноименного класса) меток, они располагались явно не там, где им положено было показаться. Это касалось центрирования их относительно какого-то объекта. Ну казалось бы, правильное построение кода:

Lparameters lpcLabelZone
Local lcNewLabelName
Thisform.LockScreen=.T.

lcNewLabelName='lbl_'+lpcLabelZone+'Header'
This.AddObject(lcNewLabelName,'Label')

With This.&lcNewLabelName As Label
   .FontSize=6
   .Caption='HTML '+lpcLabelZone+' Header'
   .Alignment=0
   .AutoSize= .T.
   .Left=This.cvo_LayoutZones.Item(lpcLabelZone).nLeft+;
   ((This.cvo_LayoutZones.Item(lpcLabelZone).nWidth-.Width)/2)
   .Top =This.cvo_LayoutZones.Item(lpcLabelZone).nTop+5
   .Visible=.T.
ENDWITH

lcNewLabelName='lbl_'+lpcLabelZone+'Body'
This.AddObject(lcNewLabelName,'Label')

With This.&lcNewLabelName As Label
   .FontSize=6
   .Alignment=0
   .Caption='HTML '+lpcLabelZone+' Body'
   .Caption=ALLTRIM(.Caption)
   .AutoSize= .T.
   .Left=This.cvo_LayoutZones.Item(lpcLabelZone).nLeft+;
   ((This.cvo_LayoutZones.Item(lpcLabelZone).nWidth-.Width)/2)
   .Top =This.cvo_LayoutZones.Item(lpcLabelZone).nTop + ;
      (This.cvo_LayoutZones.Item(lpcLabelZone).nHeight-.Height)/2
   .Visible=.T.
Endwith

lcNewLabelName='lbl_'+lpcLabelZone+'Footer'
This.AddObject(lcNewLabelName,'Label')

With This.&lcNewLabelName As Label
   .FontSize=6
   .Caption='HTML '+lpcLabelZone+' Footer'
   .Alignment=0
   .AutoSize= .T.
   .Left=This.cvo_LayoutZones.Item(lpcLabelZone).nLeft+;
   ((This.cvo_LayoutZones.Item(lpcLabelZone).nWidth-.Width)/2)
   .Top=((This.cvo_LayoutZones.Item(lpcLabelZone).nTop + ;
      This.cvo_LayoutZones.Item(lpcLabelZone).nHeight)-.Height)-5
   .Visible=.T.

Endwith

Thisform.LockScreen=.F.

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

То есть правильный код для приведенного выше примера будет выглядет так:

Lparameters lpcLabelZone
Local lcNewLabelName
Thisform.LockScreen=.T.

lcNewLabelName='lbl_'+lpcLabelZone+'Header'
This.AddObject(lcNewLabelName,'Label')

With This.&lcNewLabelName As Label
   .FontSize=6
   .Caption='HTML '+lpcLabelZone+' Header'
   .Alignment=0
   .Visible=.T.
   .AutoSize= .T.
   .Left=This.cvo_LayoutZones.Item(lpcLabelZone).nLeft+;
   ((This.cvo_LayoutZones.Item(lpcLabelZone).nWidth-.Width)/2)
   .Top =This.cvo_LayoutZones.Item(lpcLabelZone).nTop+5
ENDWITH

lcNewLabelName='lbl_'+lpcLabelZone+'Body'
This.AddObject(lcNewLabelName,'Label')

With This.&lcNewLabelName As Label
   .FontSize=6
   .Alignment=0
   .Caption='HTML '+lpcLabelZone+' Body'
   .Caption=ALLTRIM(.Caption)
   .Visible=.T.
   .AutoSize= .T.
   .Left=This.cvo_LayoutZones.Item(lpcLabelZone).nLeft+;
   ((This.cvo_LayoutZones.Item(lpcLabelZone).nWidth-.Width)/2)
   .Top =This.cvo_LayoutZones.Item(lpcLabelZone).nTop + ;
      (This.cvo_LayoutZones.Item(lpcLabelZone).nHeight-.Height)/2
Endwith

lcNewLabelName='lbl_'+lpcLabelZone+'Footer'
This.AddObject(lcNewLabelName,'Label')

With This.&lcNewLabelName As Label
   .FontSize=6
   .Caption='HTML '+lpcLabelZone+' Footer'
   .Alignment=0
   .Visible=.T.
   .AutoSize= .T.
   .Left=This.cvo_LayoutZones.Item(lpcLabelZone).nLeft+;
   ((This.cvo_LayoutZones.Item(lpcLabelZone).nWidth-.Width)/2)
   .Top=((This.cvo_LayoutZones.Item(lpcLabelZone).nTop + ;
      This.cvo_LayoutZones.Item(lpcLabelZone).nHeight)-.Height)-5
Endwith

Thisform.LockScreen=.F.

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

А вот другой пример, связанный с рядом вопросов на форумах, которые можно объединить в суммарный:

Вот сделал форму, а потом потребовалось вставить элемент, который должен инициализироваться прежде всех остальных элементов, уже помещенных на форму. Как быть? Переписывать все заново?

Ну зачем же? Можно конечно поиграться со слоями - Bring To Front|Send To Back - но это может быть применимо при небольшом количестве элементов управления на форме. Да просто замучаетесь считать, сколько раз нужно нажать на соответствующую кнопку в панели инструментов Layout Предусмотрите это раз и навсегда в своих субклассах базовых классов. С помощью нескольких строк дополнительного кода, и объектов-компаньонов. Вот с них мы и начем. Правда в следующей части.

Cелектор для быстрого перехода на сайты, связанные с Visual FoxPro.