我是否真的必须在自定义控件的OnMouseDown中调用Focus?

时间:2010-03-27 12:29:01

标签: c# .net winforms focus

我正在实现一个继承自Control的自定义控件。我希望它是可聚焦的(它是一种列表框)。

在构造函数中,我做

SetStyle(ControlStyles.Selectable, true);

我现在可以使用Tab导航到控件。

但是,当控件收到鼠标单击时,它不会自动声明焦点。当然,我可以解决这个问题:

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

但这感觉就像一个不应该是必需的kludge。这真的是要走的路吗?或者有没有办法告诉Control在收到鼠标点击时自动声明焦点?

3 个答案:

答案 0 :(得分:4)

拆卸救援!事实证明

SetStyle(ControlStyles.UserMouse, true);

诀窍。

具有讽刺意味的是,我读过documentation

  

UserMouse:如果为true,则控件执行自己的鼠标处理,操作系统不处理鼠标事件。

这似乎与我想要的完全相反,所以我只尝试将其设置为false ...方式去,WinForms文档。

答案 1 :(得分:2)

是的,你应该做什么。有许多控件没有一个有意义的方法来获得焦点。 PictureBox,Panel就是很好的例子。任何派生自ContainerControl的东西。因此,Control.OnMouseDown()不会在OnMouseDown()中自动调用Focus()。

仅仅重写OnMouseDown方法是不够的,您还应该向用户说明您的控件具有焦点。所以她会知道键盘敲击的位置。这需要重写OnPaint(),以便您可以绘制焦点矩形。 ControlPaint.DrawFocusRectangle()是一个样板实现。

但是,如果您使用键盘消息做一些有意义的事情,那么获得焦点真的很有用。因此,您还必须重写OnKeyDown和/或OnKeyPressed。并向用户显示反馈,以便她可以看到她输入的内容。如果您没有有用的实现,则不应该关注焦点。这就是PictureBox没有的原因。

答案 2 :(得分:0)

  1. 在FrameWork 3.5的WinForms项目中编译

  2. 将Control1的实例从ToolBox拖到Form Surface ...确保其TabStop属性设置为'true

  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);
            }
        }
    }
    
  6. 这里唯一的“松散结束”是这个解决方案会在鼠标点击时显示选择矩形,但我没有像Thomas建议的那样实现任何MouseDown代码。

    注意,如果你将Control控制在'ContainerControl via'SetStyle(ControlStyles.ContainerControl,true)之上;并添加一些其他控件,即使你将添加的控件的TabStop属性设置为'false:...如果它被点击...它将获得焦点,你将失去ContainerControl上显示的焦点矩形。 / p>