第二讲准备kodigo的排版服务n_svc_resize

来源:互联网 发布:nx8.0加工编程 编辑:程序博客网 时间:2024/06/05 02:01

第二讲准备kodigo的排版服务n_svc_resize

讲这个服务前,先介绍一下结构str_resize

global type str_resize from structure

       dragobject             control//待排对象的引用

       string             controlname//对象类名

       integer           sizeorder//排版序(即多个同级排版的先后序)

       boolean          dock//是否按停靠方式

       integer           docktype

//停靠类型:1 向顶靠 2 向左靠 3 向右靠 4 向底靠 5 填充全部

       integer           dockpadtop//向顶预留

       integer           dockpadleft//向左预留

       integer           dockpadright//向右预留

       integer           dockpadbottom//向底预留

       boolean          anchortop//是否向顶瞄定

       boolean          anchorleft//是否向左瞄定

       boolean          anchorright//是否向右瞄定

       boolean          anchorbottom//是否向度瞄定

//(注:除了动态建立的对象,PB的对象名,和类名一般一样)

       string             reftop//顶接对象类名

       string             refleft//左接对象类名

       string             refright//右接对象类名

       string             refbottom//底接对象类名

       rect                bounds//对象边界,实际上就是对象resize前的矩形

       string             ancestor//kodigo级祖先类名(cfbase中有定义)

       integer           reftopindex//顶接对象索引

       integer           refleftindex//左接对象索引

       integer           refrightindex//右接对象索引

       integer           refbottomindex//底接对象索引

       boolean          ignorevisible//虽然不显视,但是否预留空间

end type

 

再注意观查fcmainu打头的对象,是不是每个对象都有:

type variables

Public:

Long #SizeOrder

Boolean #AnchorTop

Boolean #AnchorLeft

Boolean #AnchorRight

Boolean #AnchorBottom

Boolean #Dock

Long #DockType, #DockPadTop, #DockPadLeft, #DockPadRight, #DockPadBottom

String #Dock_Control_Top, #Dock_Control_Left, #Dock_Control_Right, #Dock_Control_Bottom

Boolean #Tooltip

string #TooltipText

Boolean #BalloonTooltip

icon #TooltipIcon = none!

string #TooltipTitle

Private:

str_resize istr_resize

end variables

 

public function str_resize of_getresizeattrib ();istr_resize.Control = this

istr_resize.ControlName = ClassName(this)

istr_resize.SizeOrder = #SizeOrder

istr_resize.SizeOrder = #SizeOrder

istr_resize.Dock = #Dock

istr_resize.DockType = #DockType

istr_resize.DockPadTop = #DockPadTop

istr_resize.DockPadLeft = #DockPadLeft

istr_resize.DockPadRight = #DockPadRight

istr_resize.DockPadBottom = #DockPadBottom

istr_resize.AnchorTop = #AnchorTop

istr_resize.AnchorLeft = #AnchorLeft

istr_resize.AnchorRight = #Anchorright

istr_resize.AnchorBottom = #Anchorbottom

istr_resize.reftop = #Dock_Control_top

istr_resize.refleft = #Dock_Control_left

istr_resize.refright = #Dock_Control_right

istr_resize.refbottom = #Dock_Control_bottom

istr_resize.bounds.left = X

istr_resize.bounds.top = Y

istr_resize.bounds.right = width

istr_resize.bounds.bottom = height

RETURN istr_resize

end function

 

以上代码相信大家都可以看得懂,这里就不多作说明了,我将n_svc_resize的函数一个个的说明:

public subroutine of_initresize (ref n_svc_mgr anv_svc, powerobject apo, ref str_resize attrib[]);

/*

       功能:初使化对象的排版数组

*/

long lc, n, c, lc2

str_resize lstre[], lstr, lstrt

Boolean lb

n_svc_powerbuilder lnp

WindowObject lwo[]

w_main lw_base

u_base_container lu_base

Boolean IS_WBASE

string ls_classname

attrib = lstre

anv_svc.of_loadsvc(lnp, CSvc.POWERBUILDER)// n_svc_powerbuilder服务,以后再讲

TRY

       //apo是否是w_main的子类

       IF lnp.of_isdescendant(CFbase.WindowMain, apo.ClassDefinition) THEN

              lw_base = apo

              lwo = lw_base.Control         

              IS_WBASE = TRUE

//apo 是否是u_base_container的了类

       ELSEIF lnp.of_isdescendant(CFbase.UOContainer, apo.ClassDefinition) THEN

              //cast

              lu_base = apo

              lwo = lu_base.Control

       //否则该对象不是一个kodigo中的容器,不需要设定排版数组

       ELSE

              RETURN

       END IF

CATCH (n_x_svc ex)

       RETURN

END TRY

lc = UPPERBOUND(lwo)

FOR n = 1 to lc

       IF IS_WBASE THEN

              // 如果是mdiclient!窗口跳过

              IF lwo[n].TypeOf() = mdiclient! THEN CONTINUE

       END IF

       //如果不是kodigo系列对象跳过

       IF NOT lnp.of_isfcobject(lwo[n]) THEN CONTINUE

       //返回对象排版数组

       lstrt = lwo[n].DYNAMIC of_getresizeattrib()

//如果不显视

       IF NOT lstrt.control.visible THEN

              TRY

                     //如果不是工具条或容器标题栏跳过

                     IF (NOT lnp.of_isdescendant(CFbase.Toolbar, lstrt.Control.ClassDefinition)) AND (NOT lnp.of_isdescendant(CFbase.Rebar, lstrt.Control.ClassDefinition)) THEN CONTINUE

                     //是需要预留

                     lstrt.ignorevisible = TRUE

              CATCH (throwable e)

                     CONTINUE

              END TRY

       END IF

       // sizeorder<0的跳过

       IF lstrt.sizeorder < 0 THEN CONTINUE

       //加入待排序数组

       c ++

       attrib[c] = lstrt

NEXT

//sizeorder排序(冒泡法)

lc = UPPERBOUND(attrib)

lc2 = lc - 1

FOR n = 1 TO lc

       lb = FALSE

       FOR c = 1 TO lc2

              IF attrib[c].SizeOrder > attrib[c + 1].SizeOrder THEN

                     lb = TRUE

                     lstr = attrib[c]

                     attrib[c] = attrib[c + 1]

                     attrib[c + 1] = lstr

              END IF

       NEXT

       IF NOT lb THEN EXIT

NEXT

 

//更新四个方向的对接对象

lc = UPPERBOUND(attrib)

FOR n = 1 to lc

       attrib[n].reftopindex = this.of_getcontrolreference(attrib[n].reftop, attrib)

       attrib[n].refleftindex = this.of_getcontrolreference(attrib[n].refleft, attrib)

       attrib[n].refrightindex = this.of_getcontrolreference(attrib[n].refright, attrib)

       attrib[n].refbottomindex = this.of_getcontrolreference(attrib[n].refbottom, attrib)

NEXT

end subroutine

 

 

protected function long of_getcontrolreference (readonly string cls, readonly str_resize resize[]);

//在排版数组里查找类名为cls的对象的素引(即数组下标)

long lc, n

n_svc_powerbuilder lnp

n_svc_mgr lnv_Svc

 

lnv_svc.of_LoadSvc(lnp, CSvc.Powerbuilder)

 

lc = UPPERBOUND(resize)

 

//使用顺序查找,类名为cls,且可见或需预留空间的对象

FOR n = 1 to lc

       IF resize[n].controlname = cls THEN

              IF resize[n].control.Visible THEN

                     RETURN n

              ELSE

                     IF resize[n].ignorevisible THEN RETURN n

              END IF

       END IF

NEXT

RETURN CRet.FAILURE

end function

 

protected function str_resize of_dock (ref dragobject ado, readonly integer docktype, readonly integer x, readonly integer y, readonly integer width, readonly integer height, readonly str_resize astr);

//停靠的实现方法,并返回新的排版数组

//x,y,width,height 围起来的矩形为停靠区域

long ll_h//为对象可变高度

boolean lb

 

//如果是下拉列表框或下拉图形列表框,则高度不变。

IF astr.ancestor = CFbase.DropdownListBox OR astr.ancestor = CFbase.DropdownPictureListBox THEN

       ll_h = ado.height

       lb = TRUE

ELSE

       ll_h = height

END IF

 

CHOOSE CASE docktype

       CASE CDock.top

//向顶靠,则将坐标移至停靠区原点【即(x,y)坐标】

//且将宽设成和停靠区宽一样

              IF ado.x <> x OR ado.Y <> y THEN ado.Move(x, y)

              IF ado.width <> width THEN ado.width = width

       CASE CDock.left

//向左靠,则将坐标移至停靠区原点【即(x,y)坐标】

              //且将高设成和停靠区高一样

              IF ado.x <> x OR ado.Y <> y THEN ado.Move(x, y)

              IF ado.height <> ll_h THEN ado.height = ll_h

       CASE CDock.right

//向或靠,则将坐标移至(x + width - ado.width,y)坐标

// x + width - ado.width是我做的修正,原来是width - ado.width

              //且将高设成和停靠区高一样

 

              ado.Move(width - ado.width, y)

              IF ado.height <> ll_h THEN ado.height = ll_h                        

       CASE CDock.bottom

//向底靠,则将坐标移至(x, y + ll_h - ado.height)坐标

//且将宽设成和停靠区宽一样

 

              IF ado.x <> x OR ado.Y <> ll_h - ado.height THEN ado.Move(x, y + ll_h - ado.height)

              IF ado.width <> width THEN ado.width = width

       CASE CDock.fill

              //填充总个停靠区

              IF ado.x <> x OR ado.Y <> y THEN ado.Move(x, y)

              IF ado.width <> width OR ado.height <> ll_h THEN ado.Resize(width, ll_h)

END CHOOSE

//更新对象边界(实际上是当前变化后的矩形)

astr.bounds.left = ado.X

astr.bounds.top = ado.Y

astr.bounds.right = ado.Width

//dropdown exception

IF lb THEN

       astr.bounds.bottom = DROPDOWNHEIGHT

ELSE

       astr.bounds.bottom = ado.Height

END IF

 

RETURN astr

end function

 

 

public subroutine of_resize (readonly powerobject apo, readonly string classname, ref str_resize resize[], readonly integer oldwidth, readonly integer oldheight, readonly integer newwidth, readonly integer newheight);

//实现容器UO的对其规属的子对象的排版

long n, lc, c

long x, y, w, h, llt, llpw

rect lstr_rect

str_resize lstr

Boolean IS_WINDOW, lb

w_main lw

u_base_container lu

 

IF classname = CFbase.WindowMain THEN

       IS_WINDOW = TRUE

       lw = apo

ELSEIF classname = CFbase.UOContainer THEN

       lu = apo

ELSE

       RETURN

END IF

 

lc = UPPERBOUND(resize)

 

//得到容器矩形(即对象工作空间)

IF IS_WINDOW THEN

       lstr_rect = lw.of_getworkspace()

ELSE

       lstr_rect = lu.of_getworkspace()

END IF

 

FOR n = 1 to lc

       //如果排版按停靠,加上有了上面的of_dock

//那么停靠就只要计算该对象的可活动空间了

       IF resize[n].Dock THEN

              //求左接对象

              c = resize[n].refleftindex

              IF c = 0 THEN

                     c = this.of_getcontrolreference(resize[n].refleft, resize)

                     resize[n].refleftindex = c

              END IF

              //如果有左接对象,则预留出左接对象的x空间

              //如果没有左接对象,则从工作区的x开始(工作区的y 就是lstr_rect. left

)

 

              IF c > 0 THEN

                     x = resize[c].bounds.left + resize[c].bounds.right

              ELSE

                     x = lstr_rect.left

              END IF

              //求顶接对象

              c = resize[n].reftopindex

              IF c = 0 THEN

                     c = this.of_getcontrolreference(resize[n].reftop, resize)

                     resize[n].reftopindex = c

              END IF

              //如果有顶接对象,则预留出顶接对象的y空间

              //如果没有顶接对象,则从工作区的y开始

//(工作区的y 就是lstr_rect.top,不要变了个名字就不认得它了)

 

              IF c > 0 THEN

                     y = resize[c].bounds.top + resize[c].bounds.bottom

              ELSE

                     y = lstr_rect.top

              END IF

              //求右接对象

              c = resize[n].refrightindex

              IF c = 0 THEN

                     c = this.of_getcontrolreference(resize[n].refright, resize)

                     resize[n].refrightindex = c

              END IF

              //如果有右接对象,则预留出右接对象的widht空间

              //如果没有右接对象,则从w = newwidth – x

              // newwidth实际上就是lstr_rect的宽

 

              IF c > 0 THEN

                     w = resize[c].bounds.left - x

              ELSE

                     w = newwidth - x

              END IF

              //说了这么多,这个应该可以看懂了,就不多说了

              c = resize[n].refbottomindex

              IF c = 0 THEN

                     c = this.of_getcontrolreference(resize[n].refbottom, resize)

                     resize[n].refbottomindex = c

              END IF

              IF c > 0 THEN

                     h = resize[c].bounds.top - y

              ELSE

                     h = newheight - y

              END IF         

             

              //下面是四个方向预留设定的实现

              IF resize[n].dockpadleft <> 0 THEN

                     x += resize[n].dockpadleft

                     w -= resize[n].dockpadleft

              END IF

             

              IF resize[n].dockpadright <> 0 THEN

                     w -= resize[n].dockpadright

              END IF

             

              IF resize[n].dockpadtop <> 0 THEN

                     y += resize[n].dockpadtop

                     h -= resize[n].dockpadtop

              END IF

             

              IF resize[n].dockpadbottom <> 0 THEN

                     h -= resize[n].dockpadbottom

              END IF

              //实现停靠

              resize[n] = this.of_dock(resize[n].Control, resize[n].DockType, x, y, w, h, resize[n])

             

              CONTINUE         

       ELSE

              //init variables for anchor mode

              x = resize[n].bounds.left

              y = resize[n].bounds.top

              w = resize[n].bounds.right

              h = resize[n].bounds.bottom

              //这个对象,高是不可变的,变了就很难看

              IF resize[n].ancestor = CFbase.DropdownListBox OR resize[n].ancestor = CFbase.DropdownPictureListBox THEN

                     h = resize[n].control.height

                     lb = TRUE

              ELSE

                     lb = FALSE

              END IF         

              //向顶瞄定,即y值始终都不改变

              IF resize[n].AnchorTop THEN y = resize[n].bounds.top

              //向或瞄定,即x值始终都不改变

              IF resize[n].AnchorLeft THEN x = resize[n].bounds.left

              //向右瞄定,即与右边距离不变始终都不改变

              IF resize[n].AnchorRight THEN

                     llt = newwidth - oldwidth

                     IF NOT resize[n].AnchorLeft THEN

                                   x += llt

                     ELSE//若同时设定了左右瞄定,则拉宽对象

                                   w += llt

                     END IF

              END IF

//以下代码,同样的作操方法,不再多说了。

              IF resize[n].AnchorBottom THEN

                     llt = newheight - oldheight

                     IF NOT resize[n].AnchorTop THEN

                                   y += llt

                     ELSE

                                   h += llt

                     END IF

              END IF  

              //resize and move only if changed to prevent flicker

              IF resize[n].Control.width <> w OR resize[n].Control.height <> h THEN

                     resize[n].Control.Resize(w, h)

              END IF

              IF resize[n].Control.X <> x OR resize[n].Control.Y <> y THEN resize[n].Control.Move(x, y)

       END IF

       //update attributes

       resize[n].bounds.left = x

       resize[n].bounds.top = y

       resize[n].bounds.right = w

       //dropdown exception

       IF lb THEN

              resize[n].bounds.bottom = DROPDOWNHEIGHT

       ELSE

              resize[n].bounds.bottom = h

       END IF

NEXT

end subroutine

 

//排版对象就讲到这里,对于dwo的排版,原理是一样的,大家可以自己读读看

原创粉丝点击