2013-05-07 109 views
0

我有一個滾動條的用戶控件(滾動條顯示爲一個包含的用戶控件,它繼承自Panel,太大)。當使用鼠標滾動一切都很好,但試圖用鼠標滾輪不工作。專注於滾動

我的解決方案是在Scroll的事件管理器中爲我的子控件設置焦點。這工作。現在的問題;這會導致很多不必要的電話childControl.Focus()?有沒有更簡潔的方法來做到這一點?

編輯:我想我是有點不清楚我的問題,從而改寫了一個問題:

private void ChildControl_OnScroll(object sender, ScrollEventArgs scrollEventArgs) 
{ 
    this.childControl.Focus(); 
} 

設置焦點的好方法?即每次滾動時,焦點會被設置爲多次?或者說,這會導致(微小的)性能問題。

+1

您的問題不詳細。你甚至沒有提到你使用的是什麼控件,以及它們是如何放置的。 – 2013-05-07 15:33:23

+0

更新了問題。 – Mystogan 2013-05-07 15:43:42

+0

也許你可以包含一些解決這個問題的代碼? – 2013-05-07 15:44:01

回答

1

下面是另一種在單擊SomeUserControl內panel1的滾動條區域時給予焦點的方法。它使用NativeWindow,因此您不必更改UserControl中的面板。這樣,焦點()纔會被調用一次,當鼠標在滾動條區域去

public partial class SomeUserControl : UserControl 
{ 
    private TrapMouseDownOnScrollArea trapScroll = null; 

    public SomeUserControl() 
    { 
     InitializeComponent(); 
     this.VisibleChanged += new EventHandler(SomeUserControl_VisibleChanged); 
    } 

    void SomeUserControl_VisibleChanged(object sender, EventArgs e) 
    { 
     if (this.Visible && trapScroll == null) 
     { 
      trapScroll = new TrapMouseDownOnScrollArea(this.panel1); 
     } 
    } 

    private class TrapMouseDownOnScrollArea : NativeWindow 
    { 
     private Control control = null; 
     private const int WM_NCLBUTTONDOWN = 0xA1; 

     public TrapMouseDownOnScrollArea(Control ctl) 
     { 
      if (ctl != null && ctl.IsHandleCreated) 
      { 
       this.control = ctl; 
       this.AssignHandle(ctl.Handle); 
      } 
     } 

     protected override void WndProc(ref Message m) 
     { 
      switch (m.Msg) 
      { 
       case WM_NCLBUTTONDOWN: 
        if (this.control != null) 
        { 
         Rectangle screenBounds = control.RectangleToScreen(new Rectangle(0, 0, control.Width, control.Height)); 
         if (screenBounds.Contains(Cursor.Position)) 
         { 
          control.Focus(); 
         } 
        } 

        break; 
      } 
      base.WndProc(ref m); 
     } 

    } 

} 

這可能是矯枉過正爲您的方案,但是它表明一種方法來捕獲低級別的消息。如前所述,您也可以從Panel中獲得相同的效果。您還可以使用IMessageFilter在應用程序級別捕獲消息。

+0

不錯!非常感謝! – Mystogan 2013-05-08 07:14:44

1

MouseWheel事件是一個「氣泡」事件。無論鼠標光標位於何處,Windows都會將它發送到具有焦點的控件。最典型的問題是您的控件無法獲得焦點。例如一個小組。

當您在面板上放置控件時會發生變化。現在,該控件可以獲得焦點並獲取MouseWheel消息。它不會有任何用處,所以消息傳遞給它的父代。其中確實有有用,面板按預期滾動。

您可以從this answer獲得可調焦的面板控制。一個普通的「使它像一個瀏覽器或Office程序中工作」,從this question

+0

感謝您的解釋!不過,我實際上可以設置焦點,我的問題是,如果在滾動時設置焦點有任何缺點或設計問題。 – Mystogan 2013-05-07 16:04:13

+0

我沒有看到連接。你的程序強調焦點肯定是一個壞主意,它應該始終留給用戶。 – 2013-05-07 16:06:23

0

解決方案如果childControl擁有的MouseEnter()事件,然後使用來代替:

private void childControl_MouseEnter(object sender, EventArgs e) 
    { 
     childControl.Focus(); 
    } 

然後將鼠標滾輪事件應該直接向childControl 。

+0

我寧願不使用MouseEnter ...只在用戶主動點擊滾動條時設置此項。 (並嘗試使用'Click'事件,但沒有幫助。) – Mystogan 2013-05-07 16:08:12

+0

要在滾動條區域上捕獲一個**鼠標**,您可以繼承基類並在WndProc()中查找WM_NCLBUTTONDOWN消息。 – 2013-05-07 16:28:00