Visual Basic, .NET, ASP, VBScript
 

   
 

За период изучения данной СУБД мною накоплено большое количество программного кода, советов, трюков и хитростей в создании баз данных средствами MS Access.

 
     
   
 
Ресайзинг форм

Ресайзинг форм Access - это просто!

Способов ресайзинга (Resize) форм много. Даже очень много. У каждого свой ;)

До я и сам решил создать форму с ресайзингом и.... создал совершенно "ломовой" способ ;): просто в событии Form_Resize тупо передвигаем каждый контрол, управляя его атрибутами .Top, .Left. Width и .Heigth. Код получается простым, длинным и малоэффективным. Следовательно, некрасивым....бррр.....

Если что-то некрасиво, то я спокойно смотреть на это не могу ;). Начал искать по этой теме сэмплы, коды, исходники.... и совершенно случайно, можно сказать, машинально, скачал с сайта CodeGuru пример http://www.codeguru.com/code/legacy/vb_forms/FlexiForms_Src.zip . Пример меня просто поразил своей простотой и элегантностью исполнения. Правда, он был для VB6, пришлось повозиться с адаптацией под Access. В процессе возни я много чего упростил из примера (для повышения скорости ;) и уменьшения кода. И вот представляю Вам вариант под Access:

 

Создаем два класса - первый clsControl:

 

Option Compare Database
Option Explicit

Public LeftIndent As Long
Public RightIndent As Long
Public TopIndent As Long
Public BottomIndent As Long
Public Width As Long
Public Height As Long
Public style As enLayoutStyle
Public ctrl As Control


и вт
орой класс clsLayOut:

 

Option Compare Database
Option Explicit

Public Enum enLayoutStyle
lsNone = 0 ' Позиция и размер зафиксированы (нет необходимости в использовании)
lsLeft = 1 ' контрол привязан к левой границе формы (нет необходимости в использовании)
lsRight = 2 ' контрол привязан к правой стороне формы
lsHorizontal = 3 ' зафиксирован между правыми и левыми границами формы (растягивается горизонтально)
lsTop = 4 ' привязка к верхей границе формы (нет необходимости в использовании)
lsBottom = 8 ' привязка к нижней границе формы
lsVertical = 12 'зафиксирован между верхней и нижней границами формы (растягивается вертикально)
lsFull = 15 ' контрол растягивается вертикально и горизонтально по правой и нижней границе
lsXProp = 16 ' позиция зависит от ширины формы (распределение по ширине)
lsYProp = 32 ' позиция зависит от высоты формы (распределение по высоте)
lsWprop = 64 ' ширина пропорциональна ширине формы
lsDprop = 128 ' высота пропорциональна высоте формы
End Enum
' комбинация условий дает дополнительные преимущества - так, например 160 (128+32) позволяет
' распределять контролы по высоте, одновременно их растягивая
' 80 (64+16) распределяет контролы по ширине формы, одновременно растягивая их, например:

' выровненные друг к другу поля или кнопки которые просто расширяются, сохраняя строй ;)

' 10 (8+2) привязывает контрол к правому нижнему углу формы


Private m_Controls As Collection ' of clsControl objects
Private m_minWidth As Long
Private m_minHeight As Long

Private Function AddControl(ctrl As Control, style As Long)
On
Error GoTo errortrap
Dim udt As New clsControl

udt.style = style
Set udt.ctrl = ctrl
udt.LeftIndent = ctrl.Left
udt.TopIndent = ctrl.Top
udt.RightIndent = ctrl.Parent.InsideWidth - (ctrl.Width + ctrl.Left)
udt.BottomIndent = ctrl.Parent.InsideHeight - (ctrl.Height + ctrl.Top)
udt.Width = ctrl.Width
udt.Height = ctrl.Height
m_Controls.Add udt

Exit Function
errortrap:
' there are some controls that have no visual element in run time (ie timer, image list etc)
End Function

Private Function NotNeg(x As Long)
NotNeg = IIf(x < 0, 0, x)
End Function

Public Function RedrawLayout()
Dim Width As Long
Dim
Height As Long
Dim ctrl As clsControl

For Each ctrl In m_Controls
    With ctrl
        If Width = 0 Then
            Width = .ctrl.Parent.InsideWidth
            If Width < m_minWidth Then Width = m_minWidth
        End If
        If Height = 0 Then
            Height = .ctrl.Parent.InsideHeight
            If Height < m_minHeight Then Height = m_minHeight
        End If

        If (.style And lsXProp) = lsXProp Then
            .ctrl.Left = (.LeftIndent * Width) / m_minWidth
        End If
        If (.style And lsHorizontal) = lsHorizontal Then
            .ctrl.Width = NotNeg((Width - .RightIndent) - .LeftIndent)
        Else
            If (.style And lsWprop) = lsWprop Then
                .ctrl.Width = (.Width * Width) / m_minWidth
            End If
            If (.style And lsRight) = lsRight Then
                .ctrl.Left = NotNeg((Width - .RightIndent) - .ctrl.Width)
            End If
        End If
        If (.style And lsYProp) = lsYProp Then
            .ctrl.Top = (.TopIndent * Height) / m_minHeight
        End If
        If (.style And lsVertical) = lsVertical Then
            .ctrl.Height = NotNeg((Height - .BottomIndent) - .TopIndent)
        Else
            If (.style And lsDprop) = lsDprop Then
                .ctrl.Height = (.Height * Height) / m_minHeight
            End If
            If (.style And lsBottom) = lsBottom Then
                .ctrl.Top = NotNeg((Height - .BottomIndent) - .ctrl.Height)
            End If
        End If
    End With
Next
End Function

Public Function SetLayout(frm As Form)
m_minWidth = frm.InsideWidth
m_minHeight = frm.InsideHeight

Set m_Controls = New Collection ' of clsControl objects
Dim con As Control
For Each con In frm.Controls
    ' проверим Tag на цифру
    If IsNumeric(con.Tag) Then
        AddControl con, con.Tag
    End If
Next
End Function

 

После добавления классов в приложение достаточно в любой форме вставить такой простой код:

 

Option Compare Database
Option Explicit

Private myLayout As New clsLayOut

Private Sub Form_Load()
myLayout.SetLayout Me
End Sub

Private Sub Form_Resize()
myLayout.RedrawLayout
End Sub


Для любого контрола (кнопка, поле, надпись, список, подчиненная форма и т.п.) в дополнительных параметрах
(Tag) укажите номер (цифру) стиля (перечислен в
Public Enum enLayoutStyle) и, в зависимости от указанного номера стиля, контрол будет изменять свое положение и (или) размер.

Для подчиненных форм: также вставьте код для формы в подчиненной форме и укажите для контролов подчиненной формы (и для самого контейнера подчиненной формы!) номера стилей в дополнительных параметрах (Tag) - всё также будет ресайзиться вместе с главной формой.

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

 

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

 

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

 

Option Compare Database
Option Explicit

Private myLayout As New clsLayOut
Private mInsideHeight As Long
Private mInsideWidth As Long
Private mIsMovedAfterOpen As Boolean

Private Sub Form_Current()
' можно запоминать размер формы при закрытии, чтобы восстанавливать при открытии
If Not mIsMovedAfterOpen Then

    ' "ломовое" восстановление размеров
    DoCmd.MoveSize 1500, 1500, 15000, 8000
    mIsMovedAfterOpen = True
End If
End Sub

Private Sub Form_Load()
' запомним первоначальный "минимальный" размер формы
mInsideHeight = Me.InsideHeight
mInsideWidth = Me.InsideWidth
myLayout.SetLayout Me
Me.ОбластьДанных.Height = 30000 'чтобы не ограничивало перемещение элементов по вертикали

' Me.Detail.Height = 30000
End Sub

Private Sub Form_Resize()
' ограничиваем размер формы по "минимальным" размерам
If Me.InsideHeight < mInsideHeight Then Me.InsideHeight = mInsideHeight
If Me.InsideWidth < mInsideWidth Then Me.InsideWidth = mInsideWidth
myLayout.RedrawLayout
End Sub


На кнопку закрытия формы или события Form_Unload полезно повесить процедуру сохранения размеров и положения формы, например, в реестре, чтобы при
следующем открытии сразу ресайзить ее по сохраненному размеру.

(Например: в Access 2002-2003: Me.WindowLeft, Me.WindowTop, Me.WindowWidth, Me.WindowHeight, хотя для универсальности (и совместимости с Access 2000) я бы рекомендовал использовать API)

 

Весь опубликованный код работает в Access 2000 и в .MDE без проблем....

 

Осторожно!: при правке кода в модуле формы с ресайзингом всегда сначала переключайте форму в режим конструктора. Иначе при сохранении формы измененные размеры контролов (если Вы растягивали их) также сохранятся! - будете потом чертыхаться и руками восстанавливать первоначальные размеры ;)

 

Мои мысли, мои скакуны

 
     

   
   
     
  VBNet рекомендует