将焦点设置为.NET UserControl ......?

时间:2010-03-02 10:29:34

标签: c# .net winforms custom-controls

我正在创建一个从UserControl派生的自定义控件,我想将焦点设置为。

自定义控件包含一个ComboBox控件,我在它旁边绘制一些字符串。

ComboBox可以获得焦点,但我希望能够将焦点设置为UserControl本身。如果它有焦点,我的OnPaint处理程序被设置为稍微不同地绘制控件但我在创建自定义控件时从父窗体调用CanFocus()并返回false。

是否有财产或其他东西要设置?

7 个答案:

答案 0 :(得分:21)

UserControl将为您提供指甲,以避免获得焦点。它具有自动将焦点传递给子控件(如果有)的代码,如果它确实获得焦点。您至少必须覆盖WndProc()并捕获WM_SETFOCUS消息。可能还需要其他手术,例如ControlStyles.Selectable以及TabStop和TabIndex属性。

你的下一个问题是,当UserControl确实有焦点时,它不会对键盘消息作出有意义的响应。您需要检测UC背景上的点击以处理鼠标消息,并覆盖绘画,以便用户明白UC具有焦点(使用ControlPaint.DrawFocusRectangle)。如果这开始听起来没有吸引力,那是因为UC真的是一个容器控制。

答案 1 :(得分:1)

来自http://msdn.microsoft.com/en-us/library/system.windows.forms.control.canfocus.aspx

  

<强>说明

     

为了控制接收   输入焦点,控制必须有一个   分配给它的句柄和可见   和Enabled属性必须都是   对于控件和控件都设置为true   它的所有父控件和   控制必须是一种形式或   控制的最外层父母必须是a   形式。

确保您已满足这些先决条件。

答案 2 :(得分:1)

评论太长,包括链接和代码......但这是评论...

很多人抱怨UserControl没有触发'GotFocus()事件。例如:UserControl and GotFocus() fyi:根据我的经验,LostFocus()会按预期触发。过去,在一个多表单项目中,我尝试在每个表单上的UserControl上实现'Enter和'Leave事件处理程序,并发现'Enter仅在表单加载时调用一次。

显然,UserControl上的控件“聚焦”(以某种方式我无法解释,但也许是SO的WinForms专家之一)。也许这与UserControl来自ContainerControl的事实有关?

我尝试编写一个'GotFocus()处理程序:

    private void Control_GotFocus(object sender, EventArgs e)
    {
        Console.WriteLine("Control GotFocus : " + ((sender as Control).Name));
    }

然后,在UserControl的Load事件中,将UserControl上的所有控件连接到该事件处理程序:我观察到的是具有最低TabIndex的UserControl上的Control将在启动时触发'GotFocus事件应用程序,以及在表单之间切换。

我在这种情况下提到的唯一另一件事是确保UserControl的'IsTabStop属性设置为'True:这是来自Silver的Shawn Wildermuth,在SilverLight相关问题的上下文中,所以没有想法,如果这可能适用于您的情况。

另一个建议是为UserControl写一个MouseDown或MouseClick事件处理程序,并在那个调用中:this.SetFocus();让我无处可去。

希望你能得到答案!

答案 3 :(得分:1)

在某些情况下,也不希望焦点移动到UserControl的子元素。
在这种情况下,您还需要将ControlStyles.ContainerControl设置为false。

Public Sub New()
    InitializeComponent()

    Me.SetStyle(ControlStyles.ContainerControl, False)
    Me.SetStyle(ControlStyles.Selectable, True)

End Sub

答案 4 :(得分:0)

说,你的用户控件上有一张图片,你想要突出显示它模仿“GetFocus”事件(比如关注你的用户控件就会拍下这张照片)。将通过向PictureBox绘制轮廓虚线来处理对用户控件的关注。这是通过用户控件OnEnter和OnLeave事件完成的。这是突出的程序...

Public Sub highlightImage()
    Dim l As Single() = {2, 2, 2, 2}
    Dim p As New Pen(Color.Gray, 1)
    p.DashPattern = l
    Dim g As Graphics = picColor.CreateGraphics()
    g.DrawRectangle(p, 0, 0, picColor.Width - 1, picColor.Height - 1)
End Sub

这两个覆盖将完成这项工作。

Protected Overrides Sub OnEnter(e As EventArgs)
    MyBase.OnEnter(e)
    Me.highlightImage()
End Sub
Protected Overrides Sub OnLeave(e As EventArgs)
    MyBase.OnLeave(e)
    MyBase.Refresh()
End Sub

答案 5 :(得分:0)

如果UserControl获得焦点,它会在内部将焦点传递给其子控件。

因此,您需要跳过执行将焦点设置为子控件的代码。为此,您需要覆盖WndProc()跳过执行任何WM_SETFOCUS消息。

 public class FocusableUserControl : UserControl
 {
    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case (int)Win32Constants.WM_SETFOCUS:
            //Returning from here will skip setting focus to child controls.
            //It will not skip setting focus to this control.

                Console.WriteLine("FocusableUserControl is focused: " + Focused);
                return;
        }

        base.WndProc(ref m);
    }
}

WM_SETFOCUS是&#34; 0x0007&#34;。

答案 6 :(得分:0)

Hans是正确的,UserControl会尽一切可能将焦点移交给子控件,在这种偷偷摸摸的情况下,期望如此:

  • 所有孩子都已启用== false

这意味着只需做一些准备工作,UserControl就会勉强接受焦点。尝试一下以达到此效果:

  const headers = {
    "Content-Type": "application/json",
    Authorization: apiKey,
  };
  const url = "http://localhost:5000/api/expenses/get-expenses";

  axios.get(url, { headers });

  // WORKS FINE IF YOU HANDLED CORS CORRECTLY IN THE SERVER SIDE