2014-03-19 96 views
3

以下是我的代碼來處理窗體中可用的所有文本框的gotfocus和lostfocus事件。焦點和失去焦點兩個事件重複調用處理獲取和丟失多個文本框的焦點事件它進入無限循環

private void Form1_Load(object sender, EventArgs e) 
    { 

     foreach (Control c in this.Controls) 
     { 
      if (c is TextBox) 
      { 
       c.GotFocus += new System.EventHandler(this.txtGotFocus); 
       c.LostFocus += new System.EventHandler(this.txtLostfocus); 
      } 
     } 
    } 
    private void txtGotFocus(object sender, EventArgs e) 
    { 
     TextBox tb = (TextBox)sender; 
     if (tb != null) 
     { 
      tb.BackColor = Color.Silver; 
      tb.BorderStyle = BorderStyle.FixedSingle; 
     } 

    } 
    private void txtLostFocus(object sender, EventArgs e) 
    { 

     TextBox tb = (TextBox)sender; 
     if (tb != null) 
     { 
      tb.BackColor = Color.White; 
      tb.BorderStyle = BorderStyle.Fixed3D; 
     } 
    } 

它正常工作與第一個文本框,但是當我去到下一個文本框,按Tab鍵會重複調用的事件和文本框表現得像閃爍。像一些代碼時錯誤消息顯示後:

的回調被做了類型的垃圾收集委託「System.Windows.Forms的System.Windows.Forms.NativeMethods +的WndProc ::調用!」。這可能會導致應用程序崩潰,損壞和數據丟失。在將代理傳遞給非託管代碼時,它們必須由託管應用程序保持活動狀態,直到確保它們永遠不會被調用。

代碼有什麼問題?有沒有解決方法?

回答

18
c.LostFocus += new System.EventHandler(this.txtLostfocus); 

引發LostFocus是危險事件,在MSDN Library文章Control.LostFocus警告說這件事,強烈建議使用Leave事件來代替。這是您可以在設計器中看到的東西,在窗體上放置一個TextBox並在屬性窗口中單擊閃電圖標。請注意GotFocus和LostFocus事件如何顯示而不是。您必須改用Enter和Leave事件。

關於這裏發生了什麼的一些背景。由於您分配了BorderStyle屬性,因此程序爆炸。這是一個「困難」的屬性,它影響窗口的樣式標誌,這是傳遞給本地CreateWindowEx()函數的標誌。所以改變邊框樣式需要Winforms再次創建本地窗口。這是導致你看到的閃爍的原因,文本框被破壞並重新創建,然後重新繪製。你看到了。

但是,這具有超出閃爍的副作用,它也會導致低級GotFocus和LostFocus事件觸發。因爲被摧毀的窗戶當然也失去了重點。由於你的LostFocus事件處理程序再次改變了BorderStyle,所以這會在你的程序中交互很差,迫使Winforms再次重新創建窗口。並且觸發GotFocus事件,您再次更改BorderStyle。這一遍又一遍地重複,你看到文本框快速閃爍。這不會無休無止,在創建窗口10,000次之後,操作系統會拔出插件並且不會讓您的程序再創建一個。窗口程序的嚴重崩潰是結果。

輸入和離開事件沒有問題,它們不能從低級別Windows通知中工作,因此在重新創建文本框窗口時不會觸發。您只能通過不更改BorderStyle屬性來擺脫一次閃爍,如果它仍在困擾您。

+0

感謝您有用的信息。這件事幫助我。 –

3

發生這種情況會導致您更改邊框樣式。不要問我爲什麼,我不知道。如果你刪除tb.BorderStyle = XXX它將工作。我想改變的邊框使得控制失去其發展論壇(並再次得到它)

編輯(!):漢斯更快,更好的解釋:)

相關問題