Настройка фокуса на .NET UserControl...?

Я создаю настраиваемый элемент управления, полученный из UserControl, на который я хотел бы установить фокус.

Пользовательский элемент управления содержит элемент управления ComboBox, и я рисую несколько строк рядом с ним.

ComboBox может получать фокус, но я хотел бы иметь возможность настроить фокус на сам UserControl. Мой обработчик OnPaint настроен на рисование элемента управления несколько по-другому, если он имеет фокус, но я вызываю CanFocus() из родительской формы, когда создаю свой настраиваемый элемент управления и возвращает false.

Есть ли свойство или что-то, что нужно установить?

Ответ 1

UserControl будет бороться с вами зуб и гвоздь, чтобы избежать фокуса. Он имеет код, который автоматически передает фокус на дочерний элемент управления (если он есть), если он получает фокус. Вы, как минимум, должны переопределить WndProc() и заблокировать сообщение WM_SETFOCUS. Могут потребоваться другие операции, такие как ControlStyles.Selectable и свойства TabStop и TabIndex.

Ваша следующая проблема заключается в том, что UserControl не будет реагировать осмысленно, скажем, на сообщения клавиатуры, если у него есть фокус. Вам нужно будет обнаружить клики на фоне UC для обработки сообщений мыши, а также переопределить картину, так что для пользователя очевидно, что UC имеет фокус (используйте ControlPaint.DrawFocusRectangle). Если это начинает казаться непривлекательным, это потому, что UC действительно предназначался для управления контейнером.

Ответ 2

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

Примечания

Для получения контроля фокус ввода, элемент управления должен иметь дескриптор, назначенный ему, и видимый и Enabled должны быть как установлено как true для управления и все его родительские элементы управления и контроль должен быть формой или контроль самого внешнего родителя должен быть форма.

Убедитесь, что вы выполнили эти предварительные запросы.

Ответ 3

слишком длинный для комментария, включает ссылку и код... но это комментарий...

Многие люди жаловались, что UserControl не запускает событие GotFocus(). Например: UserControl и GotFocus() fyi: LostFocus() будет срабатывать, как ожидалось, по моему опыту. Раньше в проекте с несколькими формами я экспериментировал с реализацией "Enter" и "Оставлять обработчики событий в UserControl для каждой формы" и обнаружил, что "Enter" вызывается только при загрузке формы один раз.

Очевидно, элементы управления на UserControl "сфокусированы" (в некотором смысле я не могу объяснить, но, возможно, один из гуру SO WinForms). Возможно, это связано с тем, что UserControl спускается из ContainerControl?

Я экспериментировал с написанием одного обработчика GotFocus():

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

И затем в событии LoadCertrol UserControl подключены все элементы управления в UserControl к этому обработчику событий. Я заметил, что элемент управления UserControl с самым низким TabIndex запускает событие GotFocus только при запуске приложения и при переключении между формами.

Единственное, что я видел в этой ситуации, это убедиться, что свойство IsTabStop для UserControl установлено на "True: это было от Shawn Wildermuth в MS в контексте вопроса SilverLight, поэтому нет идея, если это применимо в вашем случае.

Другое предложение, которое должно было написать обработчик событий MouseDown или MouseClick для UserControl, и в этом вызове: this.SetFocus(); никуда не менял.

Надеюсь, ты получишь ответ!

Ответ 4

В некоторых случаях также нежелательно не перемещать фокус на дочерние элементы UserControl.
В этом случае вам также необходимо установить ControlStyles.ContainerControl в значение false.

Public Sub New()
    InitializeComponent()

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

End Sub

Ответ 5

Скажем, у вас есть изображение в вашем пользовательском элементе управления, и вы хотите выделить его, подражая событию "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

Ответ 6

Если 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 - "0x0007".