我們在數據窗口中需要進行行選擇操作,如用戶爲了修改數據或看到更詳細的內容而選擇了某一行;在另一些情況下,用戶可能要同時刪除或修改多行,這時,我們需要有使用戶在一個數據窗口中同時選擇多行的功能。這在PowerBuilder中是相當容易做到的,但是,如果在一個數據窗口祖先中沒有標準的函數來處理這些,而在每個窗口中重複編程,就非常麻煩。 |
我們首先來看一看進行行選擇的不同方法。 |
·所有行都不加亮通常情況下數據窗口不加亮任何行。這對於那些只允許用戶進行滾動和查看的數據列表或那些單行的數據窗口是合適的。 |
·單行選擇單行選擇意味着用戶在同一時間只能選擇一行來執行一些動作,如刪除或在主從關係的列表中顯示詳細信息,這是非常有用的。下面是實現單行選擇功能的代碼: |
Event: RowFocusChangedif GetRow() > 0 then |
SelectRow( 0, FALSE ) |
SelectRow( GetRow(), TRUE )end if·多行的自動選擇多行的自動選擇表現爲:當用戶點擊一個未加亮的行時,該行將變亮;反之,用戶點擊一個加亮行,該行將不加亮。爲了實現上述功能,在RowFocusChanged事件中加入如下代碼: |
Event:RowFocusChangedObject: Any DataWindowif GetRow() > 0 then |
if IsSelected( GetRow() ) then |
SelectRow( GetRow(), FALSE ) |
else |
SelectRow( GetRow(), TRUE ) |
end ifend if或者簡化成爲下面的一行代碼: |
if GetRow() > 0 then SelectRow( GetRow(), NOT IsSelected( GetRow()))·shift、control或control+shift+鼠標的使用Windows的文件管理器或其它Windows程序中,您可以使用Shift、Control或Control+Shift這種鍵盤與鼠標的組合來選擇。PowerBuilder在數據窗口中沒有提供這樣的能力,我們必須自己實現。 |
我們應當實現的組合功能是: |
要建立這樣的功能,數據窗口必須記錄當前的起始行。我們聲明這樣一個實例變量: |
protected long il_ anchor _ row當用戶點擊鼠標或進行了鍵盤操作時,我們要測試用戶是否同時按下了Shift或Control鍵,方法是用KeyDown()函數,檢查有沒有KeyShift!和KeyControl!,如有這樣的鍵按下則記錄起始行。 |
編寫行選擇函數 |
爲了在用戶點擊鼠標或進行鍵盤操作時使上述行爲發生作用,我們必須在Clicked事件和一個映射到Pbm _ dwnkey事件的自定義用戶事件中調用我們自己的行選擇函數。這樣,不管用戶是點擊鼠標還是擊中鍵盤,選擇行爲都會發生。我們也可以將這個功能放入RowFocusChanged事件中。 |
爲了使這個行選擇功能可重用,這裏我們建立兩個函數。一個函數設置我們希望的選擇行爲類型,另外一個真正執行該選擇行爲。首先我們使用一個實例變量來設定選擇行爲的值: |
protected integer ii _ select_ behavior這個變量中將存放下面的一些值。 |
可能發生的選擇行爲 |
值 行爲 |
0 不允許選擇行爲 |
1 只允許有一行選中 |
2 自動實現多行選擇 |
3 允許使用鼠標和鍵盤組合選擇 |
99 不允許選擇,將鼠標變成手型 |
如果使用的是保護變量或私有變量,這就意味着本對象以外的程序無法訪問,因此必須爲其他程序員建立對這些變量賦值和獲取這些變量值的函數。 |
另外,還需要一些函數來執行基於該變量的過程。 |
函數:uf_SetSelect(Select_behavior)我們要寫的第一個函數將允許程序員設置選擇行爲。 |
函數: public integer uf_ SetSelect( integer ai_ select_ behavior)/* 本函數設置數據窗口的選擇行爲值 |
下列爲有效的選擇行爲值 */CHOOSE CASE ai_select_behavior CASE 0, 1, 2, 3, 99 |
ii_ select_ behavior = ai_ select_ behavior |
// 至少一行將被選中 |
if ai_ select_ behavior = 1 then |
uf_ process_ select( GetRow(), "Keyboard" ) |
end if |
if ai_ select_ behavior = 99 then |
SetRowFocusIndicator(Hand!) |
else |
SetRowFocusIndicator(OFF!) |
end if |
return 0 CASE ELSE |
return -1 |
END CHOOSE |
一旦選擇類型被設置,所有的行都必須被處理。我們把這部分代碼放入一個叫作uf_ ProcessSelect的函數中。這個函數處理選擇行爲。我們需要告訴該函數要處理的行和該請求是通過鼠標還是鍵盤發出的。下面是該函數代碼: |
函數:uf_ ProcessSelect(long al_ row, string as_ input_ type) |
long l_ row |
boolean b_ reset_ anchor |
boolean b_ keyboard, b_ mouse |
// 鼠標動作還是鍵盤動作? |
if Upper(left(as_input_type,1)) = "K" then |
b_ keyboard = TRUEelse |
b_ mouse = TRUEend if/* 確認鼠標點在了數據窗口的記錄上*/if al_ row < 1 Then Return -1/* 是否要確定起始行 */b_ reset_ anchor = TRUESetRedraw(FALSE)CHOOSE CASE ii_ select_ behavior CASE 0, 99 // 無 CASE 1 // 單行選中 |
SelectRow(0,FALSE) |
SelectRow(al_row,TRUE) CASE 2 // 多行選中 |
if b_ mouse then |
SelectRow(al_ row, NOT IsSelected( al_ row )) |
end if CASE 3 |
if keyDown(KeyShift!) and KeyDown(KeyControl!) then |
if il_anchor_row > al_row then |
FOR l_ row = il_ anchor_ row TO al_ row STEP -1 |
this.selectrow(l_row,TRUE) |
NEXT |
else |
FOR l_ row = il_ anchor_ row TO al_ row |
this.selectrow(l_row,TRUE) |
NEXT |
end if elseif KeyDown(KeyShift!) then |
SelectRow(0,FALSE) |
IF il_ anchor_ row > al_ row then |
FOR l_ row = il_ anchor_ row TO al_ row STEP -1 |
this.selectrow(l_ row,TRUE) |
NEXT |
else |
FOR l_ row = il_ anchor_ row TO al_ row |
this.selectrow(l_row,TRUE) |
NEXT |
end if |
b_ reset_ anchor = FALSE |
elseif Keydown(KeyControl!) then |
SelectRow( al_row, NOT IsSelected( al_row ) ) else |
SelectRow(0,FALSE) |
SelectRow(al_ row,TRUE) end ifEND CHOOSESetRedraw(TRUE)if b_ reset_ anchor then il_ anchor_ Row = al_ rowreturn 0現在,要執行行選擇時,只需調用uf_ProcessSelect()函數。一般當用戶在一個數據窗口中點擊了鼠標或是按下了上、下箭頭鍵時,調用這個函數。另外還有捕獲home和end鍵的代碼。下面是we_keydown用戶事件映射到Pbm_dwnkey事件中的代碼: |
Event: we_ keydown (pbm_dwnkey) Object: Any DataWindow |
if KeyDown(KeyDownArrow!) and GetRow() <> RowCount() then |
uf_ processSelect( GetRow() + 1 , "Keyboard") elseif KeyDown(KeyUpArrow!) and GetRow() <> 1 then |
uf_ processSelect( GetRow() - 1 , "Keyboard") elseif KeyDown(KeyHome!) and RowCount() > 0 then |
uf_ processSelect( 1, "KeyBoard") elseif KeyDown(KeyEnd!) and RowCount() > 0 then |
uf_ processSelect( RowCount(), "Keyboard") end if最後,我們需要在clicked事件中加入: |
uf_ processSelect(GetClickedRow(), "Mouse")在這個祖先函數中編寫這樣一個行選擇的函數只是作爲一個簡單的實例,相信讀者一定能因此受到啓發,編寫出更多的函數,以拓展數據窗口的基本功能。 |