Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 聚焦于卷轴_C#_Winforms - Fatal编程技术网

C# 聚焦于卷轴

C# 聚焦于卷轴,c#,winforms,C#,Winforms,我有一个带有滚动条的用户控件(滚动条显示为包含的用户控件,从面板继承,太大)。当使用鼠标滚动时,一切正常,但尝试使用鼠标滚轮滚动不起作用 我的解决方案是在滚动的eventhandler中为我的子控件设置焦点。这很有效。现在是问题;这是否会导致大量对childControl.Focus()的不必要调用?有没有更简洁的方法 编辑:我想我的问题有点不清楚,所以重新表述问题: 是 设置焦点的坏方法?也就是说,每次滚动时焦点是否会设置多次?或者更确切地说,这会导致(微小的)性能问题。鼠标滚轮事件是一个“冒

我有一个带有滚动条的用户控件(滚动条显示为包含的用户控件,从面板继承,太大)。当使用鼠标滚动时,一切正常,但尝试使用鼠标滚轮滚动不起作用

我的解决方案是在
滚动的eventhandler中为我的子控件设置焦点。这很有效。现在是问题;这是否会导致大量对
childControl.Focus()
的不必要调用?有没有更简洁的方法

编辑:我想我的问题有点不清楚,所以重新表述问题:


设置焦点的坏方法?也就是说,每次滚动时焦点是否会设置多次?或者更确切地说,这会导致(微小的)性能问题。

鼠标滚轮事件是一个“冒泡”的事件。无论鼠标光标位于何处,Windows都会将其发送到具有焦点的控件。最典型的问题是您的控件无法接收焦点。例如,一个小组

当您在面板上放置控件时,会发生更改。现在,控件可以获得焦点并获得鼠标滚轮消息。它没有任何用处,因此消息将传递给其父级。它确实有它的用途,面板按预期滚动


您可以从中获得可聚焦的面板控件。来自

的通用“使其像浏览器或办公程序一样工作”解决方案如果childControl具有MouseEnter()事件,则使用该解决方案:

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

然后鼠标滚轮事件应该直接指向childControl。

这里有另一种方法,当单击SomeUserControl中panel1的滚动条区域时,可以获得焦点。它使用NativeWindow,因此您不必更改UserControl中的面板。这样,当鼠标在滚动条区域中向下移动时,Focus()只调用一次:

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);
        }

    }

}

对于您的场景来说,这可能有些过分,但它演示了一种捕获低级消息的方法。如前所述,您也可以从面板中派生,以实现相同的效果。您还可以使用IMessageFilter在应用程序级别捕获消息。

您的问题并不详细。你甚至没有提到你正在使用什么控件以及它们是如何放置的。更新了问题。也许你可以包含一些代码来演示这个问题?什么是
childControl
?再次更新了问题,如果有点模糊,很抱歉。谢谢你的解释!然而,我实际上能够设置焦点,我的问题是,在滚动时设置焦点是否有任何缺点或设计问题。我看不到连接。你的程序强制聚焦当然是一个坏主意,它应该总是留给用户。我宁愿不使用MouseEnter。。。仅当用户主动单击滚动条时设置此选项。(并尝试使用
Click
事件,但没有帮助。)要在滚动条区域上按住鼠标,可以从基类继承并在WndProc()中查找WM_nCluButtonDown消息。
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);
        }

    }

}