2013-05-07 67 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