Я реализую пользовательский элемент управления, который наследовался Control
. Я хочу, чтобы это было focusable (это - своего рода поле списка).
В конструкторе я делаю
SetStyle(ControlStyles.Selectable, true);
Я могу теперь использовать Вкладку для навигации к управлению.
Однако, когда управление получает щелчок мышью, оно автоматически не требует фокуса. Я могу работать вокруг этого, конечно:
protected override void OnMouseDown(MouseEventArgs e)
{
Focus();
base.OnMouseDown(e);
}
Но это чувствует себя подобно клуджу, который не должен быть необходимым. Это - действительно способ пойти? Или есть ли некоторый способ сказать Control
требовать фокуса автоматически, когда это получает щелчок мышью?
Разборка спешит на помощь! Оказывается,
SetStyle(ControlStyles.UserMouse, true);
помогает.
По иронии судьбы, я прочитал в документации :
UserMouse
: Если это правда, элемент управления выполняет свою собственную обработку мыши, а события мыши не обрабатываются операционной системой.
Это казалось полной противоположностью того, что я хотел, поэтому я только попытался установить его на false
... Вперед, документация WinForms.
Да, это то, что вам следует делать.Есть много элементов управления, на которых нет значимого способа сосредоточиться. PictureBox, Panel - хорошие примеры. Все, что унаследовано от ContainerControl. Поэтому Control.OnMouseDown () не вызывает автоматически Focus () в OnMouseDown ().
Недостаточно просто переопределить метод OnMouseDown, вы также должны дать понять пользователю, что ваш элемент управления находится в фокусе. Так что она будет иметь представление о том, куда идут ходы на клавиатуре. Это требует переопределения OnPaint (), чтобы вы могли нарисовать прямоугольник фокуса. ControlPaint.DrawFocusRectangle () - это шаблонная реализация для этого.
Но фокус на самом деле полезен только в том случае, если вы делаете что-то значимое с сообщениями с клавиатуры. Таким образом, вам также придется переопределить OnKeyDown и / или OnKeyPressed. И покажите отзыв пользователю, чтобы он мог видеть, что напечатал. Если у вас нет для этого полезной реализации, не стоит сосредотачиваться. Вот почему PictureBox этого не делает.
компилируем в WinForms-проекте для FrameWork 3.5
перетаскиваем экземпляр Control1 из ToolBox на поверхность формы... убеждаемся, что его свойство TabStop установлено в 'true
размещаем на форме другие элементы управления.
убедитесь, что когда экземпляр Control1 находится на вкладке: он показывает прямоугольник выделения, который исчезает при отклонении от него.
проверьте, что при щелчке на экземпляре Control1 отображается прямоугольник выделения, а при щелчке на другом элементе управления он исчезает.
пространство имен testFocusableControl
{
// VS Studio 2010 RC1 : Проверено на FrameWork 3.5 Full (не '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, как предложил Томас.
Обратите внимание, что если вы сделаете контрол выше 'ContainerControl через 'SetStyle(ControlStyles.ContainerControl, true); и добавите к нему другой контрол, даже если вы установите свойство TabStop добавленного контрола в 'false : ... если он щелкнет ... он получит фокус, и вы потеряете прямоугольник фокуса, показанный на ContainerControl.