2010-03-27 34 views
9

我正在實施一個繼承自Control的自定義控件。我希望它是可以聚焦的(這是一種列表框)。我真的必須在我的自定義控件的OnMouseDown中調用Focus嗎?

在構造函數中,我做

SetStyle(ControlStyles.Selectable, true); 

我現在可以使用Tab鍵導航到控制。

但是,當控件收到鼠標點擊時,它不會自動聲明焦點。當然,我可以解決這個問題:

protected override void OnMouseDown(MouseEventArgs e) 
{ 
    Focus(); 
    base.OnMouseDown(e); 
} 

但是,這感覺就像一個不應該是必要的kludge。這真的是要走的路嗎?或者有什麼方法可以讓Control在接收到鼠標點擊時自動聲稱焦點?

+0

@Thomas:你提到「我已經有了焦點矩形到位」:你是通過覆蓋OnGotFocus和OnLostFocus並調用ControlPaint.DrawFocusRectangle來做到這一點?感謝任何迴應。 – BillW

+1

@BillW:是的,這就是我所做的。 「OnGotFocus」和「OnLostFocus」使包含焦點矩形的矩形失效; 'OnPaint'檢查'Focused'屬性並根據需要調用'ControlPaint.DrawFocusRectangle'。 – Thomas

+0

您的病人對我的問題的反應非常感謝!我發佈了一個更多答案,這是我可以在Visual Studio RC1中針對FrameWork 3.5(完整版)編譯的唯一方法。通過「工作」:我的意思是,當控件是「tabbed-to」時,它會顯示一個選擇矩形,當「tabbed-away-from」選擇矩形消失時:單擊Control時,將顯示選擇矩形。 – BillW

回答

4

拆解到救援!原來,

SetStyle(ControlStyles.UserMouse, true); 

是否有竅門。

諷刺的是,我曾經讀過的documentation

UserMouse:如果爲真,控制執行其自己的鼠標處理和鼠標活動不是由操作系統來處理。

這看起來與我想要的完全相反,所以我只嘗試將它設置爲false ...要走的路,WinForms文檔。

+2

這是不正確的。關閉UserMouse樣式應該只適用於實現其自己的鼠標消息處理的本地控件周圍的Control類包裝。由於您對輸入事件感興趣,因此您可以讓控件獲得焦點。故意關閉輸入事件處理沒有意義。 –

+0

根據您的說明,句子「控件執行自己的鼠標處理」會造成額外的混淆:* WinForms *控件是否執行其自己的鼠標處理(重寫'OnMouseDown'等)或* native *控件是否執行其自身的鼠標處理自己的鼠標處理(意味着WinForms控件應該遠離它)?無論如何,顯然'UserMouse'默認爲'false'。而且由於我沒有包裝一個本地控制,它應該是「真的」,對吧? – Thomas

+0

是的,它調用OnMouseDown方法。你可以重寫,以給你自己的控制鼠標行爲。就像給它關注。您的控件繼承自Control,沒有包裝本機Windows控件(如ListBox或TreeView)。這只是一個普通的窗口。 –

2

是的,你應該做什麼。有許多控制措施沒有一種有意義的方式來關注焦點。 PictureBox,Panel是很好的例子。任何派生自ContainerControl的東西。因此Control.OnMouseDown()不會自動調用OnMouseDown()中的Focus()。

僅覆蓋OnMouseDown方法是不夠的,您還應該向用戶明確說明您的控件具有焦點。所以她會知道鍵盤筆畫的位置。這需要重寫OnPaint(),以便您可以繪製焦點矩形。 ControlPaint.DrawFocusRectangle()是一個樣板實現。

但是,如果你對鍵盤消息做了一些有意義的事情,那麼重點確實非常有用。所以你必須重寫OnKeyDown和/或OnKeyPressed。並向用戶顯示反饋,以便她可以看到她輸入的內容。如果你沒有一個有用的實現,你不應該關注焦點。這就是PictureBox沒有的原因。

+0

好點,但你爲什麼認爲我想把控制權放在第一位呢?我已經有了焦點矩形,現在正在處理鍵盤處理程序。 – Thomas

+3

總是在問題中提到這些細節。 –

+0

我在括號裏提到它是一種列表框,它表明它應該處理按鍵;我不想通過提及所有這些細節來分散這個問題。但是你是對的:提供關於「你爲什麼要這樣做」的信息是很好的,因爲有時事實證明你實際上想要以完全不同的方式解決或規避潛在的問題! – Thomas

0
  1. 編譯的WinForms項目爲框架3.5

  2. 從工具箱拖動到曲面控制1的實例...確保其TabStop屬性設置爲「真

  3. 在窗體上放置一些其他控件。

  4. 驗證當Control1的實例被選中時:它將顯示一個選擇矩形,該選擇矩形會在您從中「選項卡離開」時消失。

  5. 驗證是否單擊Control1的實例以顯示選擇矩形,並且如果您單擊某個其他控件,它將消失。

    namespace testFocusableControl 
    { 
        // VS Studio 2010 RC1 : Tested against FrameWork 3.5 Full (not 'Client) 
    
        public class Control1 : Control 
        { 
         public Control1() 
         { 
          SetStyle(ControlStyles.UserMouse, true); 
         } 
    
         protected override void OnLostFocus(EventArgs e) 
         { 
          this.Invalidate(); 
          base.OnLostFocus(e); 
         } 
    
         protected override void OnGotFocus(EventArgs e) 
         { 
          this.Invalidate(); 
          base.OnGotFocus(e); 
         } 
    
         protected override void OnPaint(PaintEventArgs e) 
         { 
          if (this.Focused) 
          { 
           ControlPaint.DrawFocusRectangle(e.Graphics, this.ClientRectangle, Color.Red, Color.Blue); 
          } 
          base.OnPaint(e); 
         } 
        } 
    } 
    

唯一的「自由端」這裏對我來說,這個解決方案將顯示在鼠標單擊選擇矩形,但我並沒有實施任何的MouseDown代碼托馬斯建議。

請注意,如果您通過SetStyle(ControlStyles.ContainerControl,true)將控件置於'ContainerControl上方;併爲其添加一些其他控件,即使您將添加的控件的TabStop屬性設置爲'false:...'如果單擊它...它將獲得焦點,並且您將失去ContainerControl上顯示的焦點矩形。

+1

您標記爲'// no effect'的方法不起作用,因爲您將它們聲明爲「virtual」,而不是「override」。顯然'UserPaint'和'Selectable'默認爲'true'。至於#6:不理解你的代碼總是不好,不管它是否工作。但我認爲我們現在明白什麼是行不通的,而且爲什麼,對吧? :) – Thomas

+0

+1非常感謝,托馬斯你的見解。我已經修改了代碼以合併您的informatin。 ! – BillW

相關問題