Класс окна с автоматическим ресайзомПришлось мне как-то делать довольно крупное приложение на Power
Builder, у которого было много разных окон и почти на каждом было
порядка 60 всяких контролов (включая tab, datawindow и т.д.), причем
окна конечно должны быть resizable = true. Писать для каждого окна своё
событие resize дело утомительное и неинтересное. Мне захотелось сделать
такое окно, чтобы у контролов задаешь некие праметры, а окно само все
делало - a la свойства Anchors у визуальных объектов в C++ Builder или
Delphi.
Параметры прижима (я так их обозвал) у контролов я решил задавать в свойстве Tag:
- - сохранять расстояние между левым краем окна и левой границей контрола
- - сохранять расстояние между верхним краем окна и верхней границей контрола
- - сохранять расстояние между правым краем окна и правой границей контрола
- - сохранять расстояние между нижним краем окна и нижней границей контрола
В DataObject у контролов (столбцов, текстов ... ) в tag тоже можно
писать 1 или 3, тогда при изменении размеров DataWindow столбцы и т.д.
тоже будут раздвигаться или ездить, прижимаясь к краям
Больше от контролов мне ничего не надо
Реализация окна:
Выкладываю текст експортированного окна с комментариями
$PBExportHeader$w_autoalign.srw
forward
global type w_autoalign from window
end type
end forward
global type w_autoalign from window
integer width = 2500
integer height = 1500
boolean titlebar = true
boolean controlmenu = true
boolean minbox = true
boolean maxbox = true
boolean resizable = true
long backcolor = 67108864
string icon = "AppIcon!"
boolean center = true
end type
global w_autoalign w_autoalign
type variables
Private:
Integer ii_oldwidth, ii_oldheight // старые значения высоты и ширины
Boolean ib_isopen // открылось ли это окно (чтобы resize не выполнялось у потомков при открытии)
end variables
forward prototypes
private subroutine of_moveresizewo (readonly windowobject a_wo, readonly integer ai_dw, readonly integer ai_dh) // обрабатываем WindowObject
private subroutine of_moveresizedw (ref datawindow a_dw, readonly integer ai_dw, readonly integer ai_dh) // обрабатываем DataWindow
private subroutine of_moveresizetab (readonly tab a_tab, readonly integer ai_dw, readonly integer ai_dh) // обрабатываем Tab
end prototypes
private subroutine of_moveresizewo (readonly windowobject a_wo, readonly integer ai_dw, readonly integer ai_dh);
If Pos(a_wo.Tag, '3') = 0 And Pos(a_wo.Tag, '4') = 0 Then Return
// отдельно пришлось обрабатывать каждый DrawObject, т.к. у него нет свойств X, Y, Width, Height
Choose Case a_wo.TypeOf()
Case Line!
Line l_l; l_l = a_wo
If Pos(l_l.Tag, '3') > 0 Then
l_l.EndX += ai_dw
If Pos(l_l.Tag, '1') = 0 Then l_l.BeginX += ai_dw
End If
If Pos(l_l.Tag, '4') > 0 Then
l_l.EndY += ai_dh
If Pos(l_l.Tag, '2') = 0 Then l_l.BeginY += ai_dh
End If
Case Oval!
Oval l_o; l_o = a_wo
If Pos(l_o.Tag, '3') > 0 Then
If Pos(l_o.Tag, '1') > 0 Then l_o.Resize(l_o.Width + ai_dw, l_o.Height)
If Pos(l_o.Tag, '1') = 0 Then l_o.Move(l_o.x + ai_dw, l_o.y)
End If
If Pos(l_o.Tag, '4') > 0 Then
If Pos(l_o.Tag, '2') > 0 Then l_o.Resize(l_o.Width, l_o.Height + ai_dh)
If Pos(l_o.Tag, '2') = 0 Then l_o.Move(l_o.x, l_o.y + ai_dh)
End If
Case Rectangle!
Rectangle l_r; l_r = a_wo
If Pos(l_r.Tag, '3') > 0 Then
If Pos(l_r.Tag, '1') > 0 Then l_r.Resize(l_r.Width + ai_dw, l_r.Height)
If Pos(l_r.Tag, '1') = 0 Then l_r.Move(l_r.x + ai_dw, l_r.y)
End If
If Pos(l_r.Tag, '4') > 0 Then
If Pos(l_r.Tag, '2') > 0 Then l_r.Resize(l_r.Width, l_r.Height + ai_dh)
If Pos(l_r.Tag, '2') = 0 Then l_r.Move(l_r.x, l_r.y + ai_dh)
End If
Case RoundRectangle!
RoundRectangle l_rr; l_rr = a_wo
If Pos(l_rr.Tag, '3') > 0 Then
If Pos(l_rr.Tag, '1') > 0 Then l_rr.Resize(l_rr.Width + ai_dw, l_rr.Height)
If Pos(l_rr.Tag, '1') = 0 Then l_rr.Move(l_rr.x + ai_dw, l_rr.y)
End If
If Pos(l_rr.Tag, '4') > 0 Then
If Pos(l_rr.Tag, '2') > 0 Then l_rr.Resize(l_rr.Width, l_rr.Height + ai_dh)
If Pos(l_rr.Tag, '2') = 0 Then l_rr.Move(l_rr.x, l_rr.y + ai_dh)
End If
Case Else
DragObject l_do; l_do = a_wo
If Pos(l_do.Tag, '3') > 0 Then
If Pos(l_do.Tag, '1') > 0 Then l_do.Resize(l_do.Width + ai_dw, l_do.Height)
If Pos(l_do.Tag, '1') = 0 Then l_do.Move(l_do.x + ai_dw, l_do.y)
End If
If Pos(l_do.Tag, '4') > 0 Then
If Pos(l_do.Tag, '2') > 0 Then l_do.Resize(l_do.Width, l_do.Height + ai_dh)
If Pos(l_do.Tag, '2') = 0 Then l_do.Move(l_do.x, l_do.y + ai_dh)
End If
If l_do.TypeOf() = Tab! Then
Tab l_tab; l_tab = l_do
Of_MoveResizeTab(l_tab, ai_dw, ai_dh)
End If
If l_do.TypeOf() = DataWindow! Then
DataWindow l_dw; l_dw = l_do
Of_MoveResizeDW(l_dw, ai_dw, ai_dh)
End If
End Choose
end subroutine
private subroutine of_moveresizedw (ref datawindow a_dw, readonly integer ai_dw, readonly integer ai_dh);Int i = 1, li_value
String ls_temp, ls_objects[]
If IsNull(a_dw) Then Return
If Not IsValid(a_dw) Then Return
If Pos(a_dw.Tag, '1') = 0 Or Pos(a_dw.Tag, '3') = 0 Then Return
ls_temp = a_dw.Describe('DataWindow.visualobjects'); ls_temp += '~t'
Do While ls_temp <> ''
ls_objects[i] = Left(ls_temp, Pos(ls_temp, '~t') - 1)
ls_temp = Right(ls_temp, Len(ls_temp) - Pos(ls_temp, '~t'))
i++
Loop
ls_temp = ''
For i = 1 to UpperBound(ls_objects[])
If Pos(a_dw.Describe(ls_objects[i]+'.tag'),'3') = 0 Then
Continue
Else
If Pos(a_dw.Describe(ls_objects[i]+'.tag'),'1') = 0 Then
ls_temp += ls_objects[i]+'.x = ' + String(Integer(a_dw.Describe(ls_objects[i]+'.x')) + ai_dw) + '~r~n'
Else
ls_temp += ls_objects[i]+'.width = ' + String(Integer(a_dw.Describe(ls_objects[i]+'.width')) + ai_dw) + '~r~n'
End If
End If
Next
a_dw.Modify(ls_temp)
end subroutine
private subroutine of_moveresizetab (readonly tab a_tab, readonly integer ai_dw, readonly integer ai_dh);Integer i, j, li_tabpagecount, li_controlcountintabpage
li_tabpagecount = UpperBound(a_tab.Control[])
For i = 1 To li_tabpagecount
li_controlcountintabpage = UpperBound(a_tab.Control[i].Control)
For j = 1 To li_controlcountintabpage
Of_MoveResizeWO(a_tab.Control[i].Control[j], ai_dw, ai_dh)
Next
Next
end subroutine
on w_autoalign.create
end on
on w_autoalign.destroy
end on
event resize;If Not ib_isopen Then Return 0
Integer li_dw, li_dh, i, li_ControlCount
li_dw = width - ii_oldwidth // вычисляем приращение окна по горизантали
li_dh = height - ii_oldheight // вычисляем приращение окна по вертикали
ii_oldwidth = width
ii_oldheight = height
If li_dw = 0 And li_dh = 0 Then Return 0
li_ControlCount = UpperBound(This.Control[])
For i = 1 To li_ControlCount
Of_MoveResizeWO(This.Control[i], li_dw, li_dh)
Next
end event
event open;ib_isopen = True
ii_oldwidth = width
ii_oldheight = height
end event
|