小議Focus 方法

2022-01-16 09:51:35 字數 2636 閱讀 5863

這裡說的是system.windows.forms.control.focus()方法,就是給桌面控制項設定焦點的方法。以前也曾無數次使用過該方法,沒有怎麼注意。偶然間我在msdn上發現focus方法的宣告是: public bool focus() 。也就是說focus()方法設定焦點有可能是會失敗的。

怎麼會呢? 我試了一下,在乙個form上放了乙個button和乙個textbox,tab順序是button:0 textbox:1如圖:

在form_load函式裡面寫下了下面的**:

private void form1_load(object sender, eventargs e)

並給button新增了乙個按鈕事件響應函式:

private void btntestbutton_click(object sender, eventargs e)

執行程式後,拍空格鍵。居然發現是彈出的"測試一下"提示框:

顯然,這是因為在form_load函式中的this.txttesttextbox.focus() 返回了false。那麼,為什麼會返回false呢?這就是我要研究的問題。追趕一下流行,使用了.net framework 3.5 源**除錯。

我先是將斷點停在了form_load函式的this.txttesttextbox.focus();行上。然後再call stack視窗上load system.windows.forms.dll的symbols(就是那個10m大的pdb檔案)。

然後按f11 step in……

[editorbrowsable(editorbrowsablestate.advanced)]

public bool focus()

**中執行了兩個方法乙個是intsecurity.modifyfocus.demand(),另乙個是focusinternal()。intsecurity.modifyfocus.demand()方法是判斷是否有相應的許可權的,屬於安全檢查,不去管他。focusinternal()方法是研究的重點,接著step in……

[resourceexposure(resourcescope.none)]

internal virtual bool focusinternal()

if (focused && this.parentinternal != null)

else }}

return focused;

}從上面的**看來,focus()方法返回的false,就是這個focusinternal方法給出的。這個方法的關鍵**是:

unsafenativemethods.setfocus(new handleref(this, handle));簡短截說,unsafenativemethods.setfocus()方法就是通過send乙個windows 的message讓控制項自己具有焦點的。f10單步執行,結果發現**執行路徑居然跳過了這行**,也就是說,這個訊息根本就沒有發出去!為啥呢?從**上看只有一種可能就是canfocus的值是false。

那canfocus是又是什麼呢?重新來過,執行到if(canfocus)一行時 f11 step in……

public bool canfocus

bool visible = safenativemethods.iswindowvisible(new handleref(window, handle));

bool enabled = safenativemethods.iswindowenabled(new handleref(window, handle));

return (visible && enabled); }} 

哈哈,原來是乙個可訪問的公共屬性,從**中我們可以看到決定乙個控制項是否可以被focus的條件有兩個:乙個是控制項可見(bool visible = safenativemethods.iswindowvisible(new handleref(window, handle));),另乙個是控制項是可用的(bool enabled = safenativemethods.iswindowenabled(new handleref(window, handle)); )。只有這兩個條件同時具備時,才能支援控制項設定焦點。

那麼為什麼form_load函式裡面執行focus()方法會失敗呢?控制項的enable屬性為true是肯定的,因為我從沒有修改過控制項的enable屬性,只有visible屬性有可能是false。也就是說在form_load方法在返回之前,程式的介面還沒有顯示呢。我們再做乙個實驗:

在按鈕的事件響應函式裡面填上this.txttesttextbox.focus();**,測試一下。

編譯,執行,此時焦點在button上,拍下空格鍵,彈出messagebox,確定之後,發現焦點已經轉移到textbox上了,如下圖:

這次是設定成功了。那麼我們能否在form_load中也設定成功呢?肯定能啊,只要在呼叫focus方法前讓控制項程式設計visible就可以了。我們可以在form_load方法中加入一行this.show();**,如下:

private void form1_load(object sender, eventargs e)

這下介面顯示出來時,焦點就在textbox上了。說了這麼多,其實就明白了一件事兒,乙個控制項要具有焦點,需要兩個條件:乙個是控制項是可見的,另乙個是控制項是enable狀態的。我用reflector看了一下,.net 1.1、2.0、3.0、3.5的相關**都是一樣的。

類似focus的定位

有時如明細表,需要點一下定位到明細表具體的item上,可以用 document.getelementbyid txtmeetingno scrollintoview 來實現 比scrolltop這些好用,不過沒有在ff等瀏覽器上測試過。if e.item.itemtype listitemtype....

js中apply使用方法小議

之一 函式的劫持與物件的複製 關於物件的繼承,一般的做法是用複製法 object.extend 見protpotype.js 的實現方法 function destination,source return destination script function person name,age fu...

js中apply使用方法小議

之一 函式的劫持與物件的複製 關於物件的繼承,一般的做法是用複製法 object.extend 見protpotype.js 的實現方法 我們先從 math.max 函式說起,math.max後面可以接任意個引數,最後返回所有引數中的最大值。比如 alert math.max 5,8 8 alert...