- Комбинированные элементы управления
- Сплиттер.
Сплиттер. (timestamp not defined)
Как-то понадобился мне сплиттер, чтобы менять размеры двух связанных элементов относительно друг друга. Причем функциональность его требовалась достаточно высокая. Задумано - сделано, однако вопросы в форумах появлялись и была написана маленькая статейка об одном из возможных вариантов построения такого элемента. Привожу ее здесь с доработкой, учитывающей новые возможности Visual FoxPro.
Для построения требуемого элемента управления нужно три простых элемента:
- Textbox, используемый вместо метки
- Объект, динамически изменяемого типа связанный с текстбоксом (в зависимости от контекста им может быть текстбокс, комбобокс и т.п.)
- Shape - накладываемый поверх связанных объектов.
Вариант первый, примитивный.
Ограничения: класс помещается в контейнер, с четко заданными параметрами отступа справа и слева от границ. В качестве связанного с текстбоксом-меткой элемента ввода/выбора используется текстбокс. Суммарная ширина связанных элементов равняется ширине контейнера за вычетом отступов. Изначально оба элемента равны по ширине.
Теперь собственно о методе проектирования такого комбинированного элемента. Управляемым элементом является textbox-метка, управляющим элементом является shape и подчиненным - textbox ввода/выбора данных. Откроем новую форму в дизайнере форм и введем в нее перечисленные элементы. Оставляем, пока, названия по умолчанию.
Для начала определимся с элементом shape. Изначально его размер не должен превышать удвоенного значения свойства Margin подчиненного элемента + 2. Это сделано для того, чтобы исключить влияние объекта shape на нормальное поведение textbox'а, в случае, если он используется для ввода значения.
C появлением событий MouseEnter и MouseLeave жизнь значительно упростилась. Чтобы было легче "попадать" в диапазон реагирования, в методах, ассоциированных с этими событиями, можно соответственно немного увеличивать/уменьшать ширину объекта Shape. Очевидно, что нужно как-то фиксировать позицию разделительной линии, которая должно проходить через центр объекта Shape и совпадать по координате Х со совмещенными сторонами связанных объектов. Кроме того, нужно учитывать разницу в координатах этой линии, и координаты nXCoord, получаемой методом, ассоциированным с событием MouseDown. Для этого, присвоим нашему объекту Shape два пользовательских свойства - nSplitLine и nDeltaX. Памятуя о повышении точности попадания пользователем в границы реагирования, добавим еще одно свойство nExpOffset. Это можно сделать с помощью метода AddProperty в методе, ассоциированным с событием Init, примерно так, как это приведено ниже:
With This
.AddProperty("nExpOffset",4)
.AddProperty("nSplitLine",.Left+.Width/2)
.AddProperty("nDeltaX",0)
EndWith
Поскольку в новых версиях имеются события MouseEnter/MouseLeave, то в ассоциированных с ними методах будем увеличивать/уменьшать ширину объекта Shape
* code for MouseEnter
With This
.Width=.Width+.nExpOffset
.Left=.Left-.nExpOffset/2
EndWith
* code for MouseLeave
With This
.Width=.Width-.nExpOffset
.Left=.Left+.nExpOffset/2
EndWith
Осталось определить "неточность" попадания указателем мыши в разделительную линию, за что у нас отвечает свойство nDeltaX. Понятно, что это будет просто разница между значением свойства nSplitLine и значением координаты nXCoord, получаемой методом, ассоциированным с событием MouseDown. Код для этого метода может выглядеть так:
If nButton=1
With This
.nDeltaX=.nSplitLine-nXCoord
Endwith
Endif
Теперь собственно об игре с ширинами связанных объектов. Этим мы займемся в методе MouseMove все того же объекта Shape.
Во-первых, мы должны смешать сам объект Shape, что можно сделать с помощью изменения значения свойства Left. Во-вторых, мы должны переопределять значение введенного нами свойства nSplitLine И, в-третьих, изменять размер связанных элементов управления. Поскольку было оговорено, что суммарный размер связанных элементов постоянен, мы должны его также где-то зафиксировать. В данном примере мы сделаем это в методе, ассоциированным с событием Init формы. Код для этого метода приведен ниже
* код для метода, ассоциированного с событием Init формы
This.AddProperty(;
"nJoinedWidth",;
This.Text1.Width+This.Text2.Width;
)
Код для метода, ассоциированого с событием MouseMove объекта shape выглядит следующим образом:
* код для метода, ассоциированного с событием MouseMove объекта shape
If nButton=1
With This
.Left=nXCoord+.nDeltaX-.Width/2
.nSplitLine=.Left+.Width/2
.Parent.Text1.Width=.nSplitLine-.Parent.Text1.Left
.Parent.Text2.Left=.Parent.Text1.Width+.Parent.Text1.Left
.Parent.Text2.Width=.Parent.nJoinedWidth-.Parent.Text1.Width
Endwith
Endif
И это все! Внизу показан "живой" пример со сплиттером, в котором объект shape имеет гипертрофированные размеры, а значение свойства BorderStyle установлено в 1, тогда как в реальном приложении это значение должно быть равно нулю - 0.
Будет продолжено...
|