数据窗口单击标题栏自动进行排序,并显示升降序/拖动行可以改变行顺序

     这是一个PB9写的数据窗口单击标题自动排序/拖动行可以改变行顺序的标准datawindow对象。

 

     自动排序:

单击标题栏排序

 

    拖动行改变行顺序:

数据窗口单击标题栏自动进行排序,并显示升降序/拖动行可以改变行顺序_第1张图片

 

    代码: 

     建立一个新的Standard Visual的datawindow对象,命名为uo_datawindow并保存,然后Edit Source,将代码替换为以下内容,再保存即可。

forward
global type uo_datawindow from datawindow
end type
end forward

global type uo_datawindow from datawindow
integer width = 686
integer height = 400
string dragicon = "Query5!"
string title = "none"
boolean hscrollbar = true
boolean vscrollbar = true
boolean livescroll = true
borderstyle borderstyle = stylelowered!
event key pbm_dwnkey
event lbuttondown pbm_lbuttondown
event mouseup pbm_dwnlbuttonup
event lbuttonup pbm_lbuttonup
event ue_win_mousemove pbm_mousemove
end type
global uo_datawindow uo_datawindow

type variables
Protected:
boolean 行指示 = true
boolean ib_first_row_countmove = false //第一行不可以移动,可扩展为指定行不可移动
string is_drag_col = 'xh' //单击后可以移动行的列(不同的dataobject对应的列不同,这里需要自己修改)
private:
long   il_drag_down, il_last_dragmove //被拖动的行、当前拖动移到的行
boolean ib_draging = false //是否正处于拖动状态下
boolean ib_draging_other = false //是否正在从其他数据窗口托数据行到这里
long   il_drag_down_other //其他数据窗口中被拖动的行
boolean ib_created = false
long il_line_color = -1

long il_text_color = 0

string is_ordercol, is_sorttype = 'A', is_lbuttondown_obj
boolean ib_clicked_header

constant string ASC_SIGN = '  △' //升序标示▲
constant string DESC_SIGN = '  ▽' //降序标示▼
end variables

forward prototypes
public subroutine of_sort ()
public subroutine of_clear_sort_sign ()
public function integer of_add_sort_sign_noredraw (string as_sort)
public function integer of_add_sort_sign (string as_sort)
public subroutine uf_create_drag_object ()
public function string of_describe (string as_describe, long row)
public function long of_get_dw_right_column (ref string as_col)
public subroutine uf_drag_end ()
public subroutine uf_drag_move_row ()
public function long of_get_row_bottom (long row)
end prototypes

event key;//key
end event

event lbuttondown;if left(getbandatpointer(),6) = 'header' then
	ib_clicked_header = true
	is_lbuttondown_obj = lower(trim(left(getobjectatpointer(),pos(getobjectatpointer(),"~t") - 1)))
end if



//====================================================================
//按下鼠标左键:如果数据窗口非只读(单据处于可编辑状态),且行数大于1,
//					 同时,存在is_drag_col列,并且鼠标单击的列是is_drag_col列,则可以
//					 进入拖动模式
//说明:ib_first_row_countmove 表示第一行不可以被移动,其他行也不可以
//										 移动到第一行
//====================================================================

if rowcount() > 0 then
	if of_Describe(is_drag_col + ".x", 1) <> '!' then //控件不存在,才新增 then
		if trim(left(getobjectatpointer(), pos(getobjectatpointer(), "~t") - 1)) = is_drag_col then
			il_drag_down = long(trim(mid(getobjectatpointer(), pos(getobjectatpointer(), "~t") + 1)))
			if il_drag_down > 0 and il_drag_down <= rowcount() then
				il_last_dragmove = il_drag_down
				if Object.DataWindow.ReadOnly = "no" then
					if rowcount() > 1 then
						if ib_first_row_countmove and il_drag_down = 1 then //第一行不可以移动
							uf_drag_end()
							return
						end if
						ib_draging = true
						il_text_color = 0
					end if
				end if
			end if
		end if
	end if
end if
end event

event mouseup;post of_sort()
end event

event lbuttonup;
//====================================================================
// 弹起鼠标左键:如果当前处于拖动模式,则结束拖动模式
//====================================================================
if ib_draging or ib_draging_other then
	uf_drag_end()
end if
end event

event ue_win_mousemove;//====================================================================================================
// 按下左键,拖动鼠标,且光标指向的行发生改变时(数据窗口行数需要大于1,且存在is_drag_col列),开始拖动模式
//====================================================================================================
if (ib_draging or ib_draging_other) and keydown(keyleftbutton!) then
	string	ls_col
	long ll_row, ll_drag_down
	if ib_draging then
		ll_drag_down = il_drag_down
	else
		ll_drag_down = il_drag_down_other
	end if
	ll_row = this.rowcount()
	if ((ll_row > 1 and ib_draging) or ib_draging_other) and not ib_created then //大于1行才有拖动的意义
		//当前鼠标移到被拖动行以外的行时,才开始进入拖动模式
		if ll_drag_down > 0 then //and long(trim(mid(getobjectatpointer(), pos(getobjectatpointer(), "~t") + 1))) <> ll_drag_down then
			this.Drag (begin!)
			uf_create_drag_object()
			int li_w
			li_w = nvll(long(this.describe(is_drag_col + ".width")), 130)
			if li_w <= 0 then li_w = 130
			int li_scw = 0
			if this.object.datawindow.firstrowonpage <> '1' or this.object.datawindow.lastrowonpage <> string(rowcount()) then li_scw = 80
			modify("t_for_Drag.text = '" + string(ll_drag_down) + "' t_for_Drag.width = '" + string(li_w) + "' rr_for_drag.width = '" + string(min(of_get_dw_right_column( ls_col), width - 35 - li_scw)) + "'")
			ib_created = true
		end if
	else
	end if
end if

end event

public subroutine of_sort ();if ib_clicked_header then
	ib_clicked_header = false
	string ls_curobj
	ls_curobj = lower(trim(left(getobjectatpointer(),pos(getobjectatpointer(),"~t") - 1)))
	if ls_curobj = is_lbuttondown_obj and is_lbuttondown_obj <> "" then
		string ls_curcol
		if this.describe(ls_curobj + ".text") <> "!" then
			ls_curcol = left(ls_curobj, len(ls_curobj) - 2)
			if is_ordercol <> ls_curcol then
				is_sorttype = 'A'
				is_ordercol = ls_curcol
			else
				if is_sorttype = 'A' then
					is_sorttype = 'D'
				ELSE
					is_sorttype = 'A'
				end if
			end if
			of_add_sort_sign( is_ordercol + " " + is_sorttype)
			setsort(is_ordercol + " " + is_sorttype)
			sort()
			groupcalc()
		end if
		
	end if
end if

is_lbuttondown_obj = ""
end subroutine

public subroutine of_clear_sort_sign ();
//========================================================================================================================
// 清除数据窗口的排序标示
//========================================================================================================================

string ls_sort, ls_tmp, ls_col, ls_a_d, ls_text
ls_sort = trim(this.describe("DataWindow.table.sort"))
if ls_sort = "" or ls_sort = "?" or ls_sort = "!" then return
if right(ls_sort, 1) <> ',' then ls_sort += ","
//"bm_sp a, barcode d, gg a,"
long i,j
i = pos(ls_sort, ',')
do while i > 0
	ls_tmp = trim(left(ls_sort, i - 1))
	j = pos(ls_tmp, ' ')
	if j > 0 then
		ls_col = trim(left(ls_tmp, j - 1))
		ls_a_d = lower(trim( mid(ls_tmp, j + 1)))
		if ls_a_d = 'd' or ls_a_d = 'desc' then //降序
			ls_a_d = DESC_SIGN
		else
			ls_a_d = ASC_SIGN
		end if
		if ls_col + ls_a_d <> '' then
			ls_text = this.describe(ls_col + "_t.text")
			if right(ls_text, len(ls_a_d)) = ls_a_d then 
				ls_text = left(ls_text, len(ls_text) - len(ls_a_d))
				this.modify(ls_col + "_t.text = '" + ls_text + "'")
			end if
		end if
	end if
	ls_sort = trim(mid(ls_sort, i + 1))
	i = pos(ls_sort, ',')
loop


end subroutine

public function integer of_add_sort_sign_noredraw (string as_sort);
//========================================================================================================================
// 根据as_sort字符串,设置数据窗口的排序标示
//========================================================================================================================
//排序规则没有发生改变则返回
if lower(as_sort) = lower(this.object.datawindow.table.sort) and this.describe("text_for_sort_only.text") <> '!' then return -1
//设置前先清除旧的排序
of_clear_sort_sign(this)
//新的排序规则为空,则不需要进行排序
if as_sort = "" then 
	return -1
end if
//设置新的排序
string ls_tmp, ls_col, ls_a_d, ls_text
if right(as_sort, 1) <> ',' then as_sort += ","
//"bm_sp a, barcode d, gg a,"
long i,j
i = pos(as_sort, ',')


//记录排序前的行顺序,以便将来还原用
string ls_sorttext
ls_sorttext = this.describe("text_for_sort_only.text")
if ls_sorttext = '!' or ls_sorttext = '?' then
	this.modify('create text(band=background alignment="2" text="未排序" border="0" color="16777215" x="0" y="0" height="0" width="0" html.valueishtml="0"  name=text_for_sort_only visible="0"  font.face="宋体" font.height="-9" font.weight="400"  font.family="2" font.pitch="2" font.charset="0" background.mode="1" background.color="536870912" )')
	ls_sorttext = '未排序'
end if
if ls_sorttext = '未排序' and this.rowcount() <= 1000 then //未排序,则记录当前的行id顺序
	ls_sorttext = ","
	for j = 1 to this.rowcount()
		yield()
		ls_sorttext += string(this.GetRowIdFromRow(j) ) + ','
	next
	this.modify("text_for_sort_only.text = '" + ls_sorttext + "'")
end if



do while i > 0
	ls_tmp = trim(left(as_sort, i - 1))
	j = pos(ls_tmp, ' ')
	if j > 0 then
		ls_col = trim(left(ls_tmp, j - 1))
		ls_a_d = lower(trim( mid(ls_tmp, j + 1)))
		
		if pos(',d,desc,descending,di,ds,', ',' + ls_a_d + ',') > 0 then //降序
			ls_a_d = DESC_SIGN
		else
			ls_a_d = ASC_SIGN
		end if
		if ls_col + ls_a_d <> '' then
			ls_text = this.describe(ls_col + "_t.text")
			if right(ls_text, len(ls_a_d)) <> ls_a_d then 
				ls_text = ls_text + ls_a_d
				this.modify(ls_col + "_t.text = '" + ls_text + "'")
			end if
		end if
	end if
	as_sort = trim(mid(as_sort, i + 1))
	i = pos(as_sort, ',')
loop
return 1


end function

public function integer of_add_sort_sign (string as_sort);
//========================================================================================================================
// 根据as_sort字符串,设置数据窗口的排序标示
//========================================================================================================================
//排序规则没有发生改变则返回
this.setredraw(false)
int li
li = of_add_sort_sign_noredraw(as_sort)
this.setredraw(true)

return li
end function

public subroutine uf_create_drag_object ();
//====================================================================
// 增加拖动控件t_for_drag
//====================================================================
if Describe("t_for_drag.x") = '!' then //控件不存在,才新增
	string ls_col
	if il_line_color = -1 then il_line_color = rgb(128,128,128)
	modify('create roundrectangle(band=foreground ellipseheight="36" ellipsewidth="41"x="0" y="0" height="12" width="' + string(min(width,of_get_dw_right_column(this, ls_col))) + '"  name=rr_for_drag visible="0" brush.hatch="6" brush.color="15793151" pen.style="0" pen.width="6" pen.color="' + string(il_line_color) + '"  background.mode="2" background.color="16711935" )')
	string ls_color
	ls_color = of_describe(is_drag_col + ".background.color", this.getrow())
	if not isnumber(ls_color) then ls_color = "67108864"
	modify('create text(band=foreground alignment="2" text="100" border="6" color="' + string(il_text_color) + '" x="0" y="0" height="' + this.Describe(is_drag_col + ".Height") + '" width="130" html.valueishtml="0"  name=t_for_drag visible="0"  font.face="Times New Roman" font.height="-9" font.weight="700"  font.family="1" font.pitch="2" font.charset="0" background.mode="2" background.color="' + ls_color + '"')
end if

end subroutine

public function string of_describe (string as_describe, long row);string str_return
str_return = this.describe(as_describe)
if pos(str_return, "~t") < 1 then return str_return
if left(str_return, 1) = '"' or left(str_return, 1) = "'" then str_return = mid(str_return, 2) 
if right(str_return, 1) = '"' or right(str_return, 1) = "'" then str_return = left(str_return, len(str_return) - 1) 
str_return = mid(str_return, pos(str_return, "~t") + len("~t"))
if row < 1 or row > this.rowcount() then row = this.getrow()
if row = 0 then return ''
return this.describe("evaluate(~"" + str_return + "~"," + string(row) + ")")


end function

public function long of_get_dw_right_column (ref string as_col);/*================================================
 *	功能:取得数据窗口最右边一对象(可能是column或computer或其他可视化dwobject)
 *	参数:datawindow 	as_dw
 *		  	string		as_col
 *	返回:最右边横坐标
 *===============================================*/

long ll_,ll_max=0
string ls_objects,ls_object,ls_ret
int li_pos
ls_objects = Describe("DataWindow.Objects") + "~t"
li_pos =pos(ls_objects,'~t')
do while li_pos>0
	ls_object = left(ls_objects,li_pos -1)
	if of_Describe(ls_object+".Visible", 1)='1' and of_describe(ls_object+".Band", 1)='detail' then
	ll_=integer(of_Describe(ls_object+".x", 1)) +integer(of_Describe(ls_object+".width", 1))
		if ll_>ll_max then
			ll_max=ll_
			ls_ret=ls_object		
		end if
	end if
	ls_objects = mid(ls_objects,li_pos+1)
	li_pos =pos(ls_objects,'~t')
loop

as_col =ls_ret
return ll_max
end function

public subroutine uf_drag_end ();
//====================================================================
// 结束拖动,还原
//====================================================================
//弹起鼠标左键
this.Drag (end!)
il_drag_down = 0
ib_draging = false
ib_draging_other = false
ib_created = false
modify("t_for_drag.visible = '0' rr_for_drag.visible = '0' ")
end subroutine

public subroutine uf_drag_move_row ();
//====================================================================
// 移动行,将行从row_from 移动 row_to
//====================================================================
if lower(Object.DataWindow.ReadOnly) = "yes" then return
long row_from, row_to
row_from = il_drag_down
row_to = il_last_dragmove
if row_from = 0 or row_from = row_to then return 

this.RowsMove(row_from, row_from, primary!, this, row_to + 1, Primary!)
if row_from > row_to then
	setrow(row_to + 1)
else
	setrow(row_to)
end if

end subroutine

public function long of_get_row_bottom (long row);
//====================================================================
// 根据行号取得该行的底部相对数据窗口的y值
//====================================================================
//if this.Object.DataWindow.Processing = '0' then return -1
long li_parenty, li_y, li_colheight, li_detailheight, li_coly, li_colheaderheight, li_rowsafterfirst,li_objheight
long li_vpos, li_dwy, li_dwborder, li_dwtitlebar, li_dwtitleborder
int li_counter
string ls_tempheaderheight, ls_colname
// Get exact pointers.
//	li_pointerx = this.PointerX()
//	li_pointery = this.PointerY()
//
//	// Get the DataWindow X/Y coordinates, Border width, and Title width. 
//	li_dwx = this.X
//	li_dwy = this.Y


// Get the X/Y point of the Left/Upper location for this column.


// Get the Height for this column and for the the Detail portion.

ls_colname = this.Describe("#1.name")
li_coly = Integer(this.Describe( ls_colname + ".Y"))
li_colheight = Integer(this.Describe(ls_colname+".Height"))
//ls_colname+".Height"
li_detailheight = Integer(this.Describe("DataWindow.Detail.Height")) 
// Get the height of the column header(s).
ls_tempheaderheight = this.Describe("DataWindow.Header.Height")
DO WHILE Pos(ls_tempheaderheight,"!") = 0
	li_colheaderheight += Integer(ls_tempheaderheight)
	li_counter ++
	ls_tempheaderheight = this.Describe("DataWindow.Header"+string(li_counter)+".Height")
LOOP

// 取得屏幕上显示的第一行数据的行号
li_rowsafterfirst = row - Long(this.Describe("DataWindow.FirstRowOnPage"))
//取得垂直滚动条的位置,freefrom 格式的数据窗口,才需要考虑
if integer(this.Describe("DataWindow.Processing")) = 0 then
	li_vpos = Integer (this.Describe("DataWindow.VerticalScrollPosition"))
else
	li_vpos = 0
end if
//li_vposMax = Integer (this.Describe("DataWindow.VerticalScrollMaximum"))
// Determine the Height of the column holding the dropdown.
li_objheight = li_colheight

// Calculate the X and Y Coordinates (check that it does not go past borders).
li_y = li_parenty + li_dwy + li_dwborder + li_dwtitleborder + li_dwtitlebar + &
li_colheaderheight +  (li_detailheight * li_rowsafterfirst ) + &
li_detailheight - li_vpos - 3
		

return li_y

end function

event clicked;setrow(row)
end event

event rowfocuschanged;selectrow(0 ,false)
selectrow(currentrow ,true)
end event

on uo_datawindow.create
end on

on uo_datawindow.destroy
end on

event constructor;if 行指示 = true then SetRowFocusIndicator(Hand!)
end event

event dragdrop;
//====================================================================
//释放拖动的行,结束拖动
//====================================================================
if ib_draging then
	//移动行
	uf_drag_move_row()
	//结束拖动模式
	uf_drag_end()
else
	//结束拖动模式
	uf_drag_end()
end if

end event

event dragleave;if source <> this then 
	il_drag_down_other = 0
	uf_drag_end()
end if
modify("t_for_drag.visible = '0' rr_for_drag.visible = '0' ")
end event

event dragwithin;
//====================================================================
// 拖动过程中,鼠标所指向的行发生改变时
//====================================================================
long ll_row
ll_row = row
if ib_draging or ib_draging_other then
	//如果第一行不可移动,则其他行被拖到第一行之前时,不做处理
	if ib_first_row_countmove and ll_row = 0 then return
	//行发生改变时,才进行的操作
	//setredraw( false)
	if il_last_dragmove <> ll_row then
		//取得当前光标下的数据带
		string ls_band
		ls_band = lower(GetBandAtPointer())
		//如果行号为0,且数据带为detail或summary,则表示光标当前在所有行的下面,需要默认为将行拖动到最后
		if (left(ls_band, 6) = 'detail' or left(ls_band, 7) = 'summary') and ll_row = 0 then //头部 'detail'header
			ll_row = rowcount()
		end if
		//设置新的行
		il_last_dragmove = ll_row
		//修改行插入位置
		modify("rr_for_drag.y = '" + string(of_get_row_bottom( ll_row)) + "' rr_for_drag.visible = '1'")
	end if
	//鼠标移动时,就发生的操作
	//修改用于指示被拖动行行号的控件的位置
	int li_w
	li_w = nvll(long(this.describe("t_for_drag.width")), 130)
	modify("t_for_Drag.color = '" + string(il_text_color) + "' t_for_drag.x = '" + string(pointerx() -35 - li_w) + "' t_for_drag.y = '" + string(pointery() + 38) + "' t_for_drag.visible = '1'")
	//setredraw( true)
end if
end event

event rbuttondown;if ib_draging or ib_draging_other then
	uf_drag_end()
end if
Return 1
end event


 

 

其中用到的一个全局函数nvll

global type nvll from function_object
end type

forward prototypes
global function any nvll (any ai, any an)
end prototypes

global function any nvll (any ai, any an);if isnull(ai) then return an
return ai
end function


 

你可能感兴趣的:(String,function,object,Integer,alignment,subroutine)