2010-03-27 30 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

相关问题